/** * */ package com.asksven.android.common.kernelutils; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileReader; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import com.asksven.andoid.common.contrib.Util; import com.asksven.android.common.CommonLogSettings; import com.asksven.android.common.privateapiproxies.NetworkUsage; import com.asksven.android.common.privateapiproxies.StatElement; import com.asksven.android.common.shellutils.Exec; import com.asksven.android.common.shellutils.ExecResult; import com.asksven.android.common.utils.StringUtils; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.content.Context; import android.content.pm.PackageManager; import android.os.SystemClock; import android.util.Log; /** * @author sven * Parser for wakeup_sources * ********************************** * From pm_wakeup.h * struct wakeup_source - Representation of wakeup sources * * @total_time: Total time this wakeup source has been active. * @max_time: Maximum time this wakeup source has been continuously active. * @last_time: Monotonic clock when the wakeup source's was touched last time. * @prevent_sleep_time: Total time this source has been preventing autosleep. * @event_count: Number of signaled wakeup events. * @active_count: Number of times the wakeup sorce was activated. * @relax_count: Number of times the wakeup sorce was deactivated. * @expire_count: Number of times the wakeup source's timeout has expired. * @wakeup_count: Number of times the wakeup source might abort suspend. * @active: Status of the wakeup source. * @has_timeout: The wakeup source has been activated with a timeout. * struct wakeup_source { * const char *name; * struct list_head entry; * spinlock_t lock; * struct timer_list timer; * unsigned long timer_expires; * ktime_t total_time; * ktime_t max_time; * ktime_t last_time; * ktime_t start_prevent_time; * ktime_t prevent_sleep_time; * unsigned long event_count; * unsigned long active_count; * unsigned long relax_count; * unsigned long expire_count; * unsigned long wakeup_count; * bool active:1; * bool autosleep_enabled:1; * }; * */ public class WakeupSources extends Wakelocks { private final static String TAG ="WakeupSources"; private static String FILE_PATH = "/sys/kernel/debug/wakeup_sources"; //private static String FILE_PATH = "/sdcard/wakeup_sources.txt"; public static ArrayList<StatElement> parseWakeupSources(Context context) { Log.i(TAG, "Parsing " + FILE_PATH); String delimiter = String.valueOf('\t'); delimiter = delimiter + "+"; ArrayList<StatElement> myRet = new ArrayList<StatElement>(); // format // new [name active_count event_count wakeup_count expire_count active_since total_time max_time last_change prevent_suspend_time] ArrayList<String[]> rows = parseDelimitedFile(FILE_PATH, delimiter); long msSinceBoot = SystemClock.elapsedRealtime(); // list the running processes ActivityManager actvityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> procInfos = actvityManager.getRunningAppProcesses(); // start with 1 for (int i=1; i < rows.size(); i++ ) { try { // times in file are milliseconds String[] data = (String[]) rows.get(i); String name = data[0].trim(); // name int count = Integer.valueOf(data[1]); // active_count int expire_count = Integer.valueOf(data[4]); // expire_count int wake_count = Integer.valueOf(data[3]); // wakeup_count long active_since = Long.valueOf(data[5]); // active_since long total_time = Long.valueOf(data[6]); // total_time long sleep_time = Long.valueOf(data[9]); // prevent_suspend_time long max_time = Long.valueOf(data[7]); // max_time long last_change = Long.valueOf(data[8]); // last_change // post-processing of eventX-YYYY processes String details = ""; // we start with a " here as that is the way the data comes from /proc if (name.startsWith("\"event")) { String process = name.replaceAll("\"", ""); if (CommonLogSettings.DEBUG) { Log.d(TAG, "Pattern 'event' found in " + process); } int proc = 0; String[] parts = process.split("-"); if (parts.length == 2) { try { proc = Integer.valueOf(parts[1]); if (CommonLogSettings.DEBUG) { Log.d(TAG, "Resolving proc name for 'event' " + proc); } } catch (Exception e) { Log.e(TAG, "Cound not split process name " + process); } } if (proc != 0) { // search for the process in the task list for (int psCount = 0; psCount < procInfos.size(); psCount++) { int id = procInfos.get(psCount).pid; if ( id == proc) { String processName = procInfos.get(psCount).processName; details= processName; String appName = ""; String[] pkgList = procInfos.get(count).pkgList; for (int j=0; j < pkgList.length; j++) { if (details.length() > 0) { details += ", "; } details += pkgList[j]; } if (CommonLogSettings.DEBUG) { Log.d(TAG, "Pattern 'event' resolved to " + details); } } } } } NativeKernelWakelock wl = new NativeKernelWakelock( name, details, count, expire_count, wake_count, active_since, total_time, sleep_time, max_time, last_change, msSinceBoot); myRet.add(wl); } catch (Exception e) { // go on } } return myRet; } }