1 / 18

Tracking T asks and Processes

Tracking T asks and Processes. GET_TASK. Make a new app, WatchProcesses Add permission GET_TASK This permission allows the app to collect lots of information about other tasks Add permission KILL_BACKGROUND_PROCESSES Not as cool as you might think. getRunningAppProcesses.

maree
Download Presentation

Tracking T asks and Processes

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Tracking Tasks and Processes

  2. GET_TASK • Make a new app, WatchProcesses • Add permission GET_TASK • This permission allows the app to collect lots of information about other tasks • Add permission KILL_BACKGROUND_PROCESSES • Not as cool as you might think

  3. getRunningAppProcesses • In onCreate, add • Context context = this.getApplicationContext(); • ActivityManager mgr = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); • List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses(); • Log.e("DEBUG", "Running processes:"); • for(Iteratori = processes.iterator(); i.hasNext(); ) • { • RunningAppProcessInfo p = (RunningAppProcessInfo)i.next(); • Log.e("DEBUG", " process name: "+p.processName); • Log.e("DEBUG", " pid: "+p.pid); // process id • }

  4. Importance • In onCreate, add • Context context = this.getApplicationContext(); • ActivityManager mgr = (ActivityManager)context.getSystemService(ACTIVITY_SERVICE); • List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses(); • Log.e("DEBUG", "importance:"); • for(Iteratori = processes.iterator(); i.hasNext(); ) • { • RunningAppProcessInfo p = (RunningAppProcessInfo)i.next(); • Log.e("DEBUG", " process name: "+p.processName); • Log.e("DEBUG", " importance value: "+p.importance); • switch (p.importance) { • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND: Log.e("DEBUG"," is IMPORTANCE_FOREGROUND"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE: Log.e("DEBUG"," is IMPORTANCE_VISIBLE"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE: Log.e("DEBUG"," is IMPORTANCE_SERVICE"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND: Log.e("DEBUG"," is IMPORTANCE_BACKGROUND"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY: Log.e("DEBUG"," is IMPORTANCE_EMPTY"); break; • default: Log.e("DEBUG"," should not happend"); break; • } • Log.e("DEBUG", " importance reason code: "+p.importanceReasonCode); • switch (p.importanceReasonCode) { • case ActivityManager.RunningAppProcessInfo.REASON_PROVIDER_IN_USE : Log.e("DEBUG"," is REASON_PROVIDER_IN_USE "); break; • case ActivityManager.RunningAppProcessInfo.REASON_SERVICE_IN_USE : Log.e("DEBUG"," is REASON_SERVICE_IN_USE "); break; • case ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN : Log.e("DEBUG"," is REASON_UNKNOWN "); break; • default : Log.e("DEBUG"," should not happen "); break; • } • Log.e("DEBUG", " fine grain importance: "+p.lru); • }

  5. importance • When resources run out, Android will kill some processes. It uses importance to decide which can be killed • Five categories of importance • IMPORTANCE_BACKGROUND – expendable • IMPORTANCE_FOREGROUND – currently in the foreground • IMPORTANCE_PERCEPTIBLE - an app that the user is actively perceptible to the user. An example would be an application performing background music playback. (but not a service) • IMPORTANCE_SERVICE – a service that should remain running • IMPORTANCE_VISIBLE – is visible, but not in the foreground • IMPORTANCE_EMPTY - no actively running code • Other, but in this case, importanceReasonCodemigth have more in details • Three reasons for the importance, given by importanceReasonCode • REASON_PROVIDER_IN_USE • REASON_SERVICE_IN_USE • REASON_UNKNOWN • lru gives relative importance within a category • Only determined for IMPORTANCE_BACKGROUND category

  6. Package list • Context context = this.getApplicationContext(); • ActivityManager mgr = (ActivityManager)context.getSystemService(ACTIVITY_SERVICE); • List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses(); • Log.e("DEBUG", "packages:"); • for(Iteratori = processes.iterator(); i.hasNext(); ) • { • RunningAppProcessInfo p = (RunningAppProcessInfo)i.next(); • Log.e("DEBUG", " process name: "+p.processName); • Log.e("DEBUG", " user id: "+p.uid); • for( String str : p.pkgList) • { • Log.e("DEBUG", " package: "+str); • } • }

  7. Collecting memory usage • In onCreate, add • Context context = this.getApplicationContext(); • ActivityManager mgr = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); • List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses(); • Log.e("DEBUG", "Running processes:"); • for(Iteratori = processes.iterator(); i.hasNext(); ) • { • RunningAppProcessInfo p = (RunningAppProcessInfo)i.next(); • Log.e("DEBUG", " process name: "+p.processName); • Log.e("DEBUG", " pid: "+p.pid); // process id • int[] pids = new int[1]; • pids[0] = p.pid; • android.os.Debug.MemoryInfo[] MI = mgr.getProcessMemoryInfo(pids); • Log.e("memory"," dalvik private: " + MI[0].dalvikPrivateDirty); • Log.e("memory"," dalvik shared: " + MI[0].dalvikSharedDirty); • Log.e("memory"," dalvik pss: " + MI[0].dalvikPss); • Log.e("memory"," native private: " + MI[0].nativePrivateDirty); • Log.e("memory"," native shared: " + MI[0].nativeSharedDirty); • Log.e("memory"," native pss: " + MI[0].nativePss); • Log.e("memory"," other private: " + MI[0].otherPrivateDirty); • Log.e("memory"," other shared: " + MI[0].otherSharedDirty); • Log.e("memory"," other pss: " + MI[0].otherPss); • Log.e("memory"," total private dirty memory (KB): " + MI[0].getTotalPrivateDirty()); • Log.e("memory"," total shared (KB): " + MI[0].getTotalSharedDirty()); • Log.e("memory"," total pss: " + MI[0].getTotalPss()); • } • run

  8. Memory usage • In modern OS, app use shared libraries. • Hence, some memory is used by multiple apps, complicating determining an apps memory usage • dalvikPrivateDirty is the memory that would be freed by the java virtual machine if the process is killed • nativePrivateDirty is the same for native code • otherPrivateDirty is the same for some other code (not sure what else there is) • dalvikSharedDirty is the shared memory used by the java virtual machine • But this would not be freed if this app is killed • dalvikPss – an estimate of how much memory is used by the app. • This includes all the private memory, and a fraction of the shared memory • Check that pss >= private • The reason that only a fraction of shared memory is used is so that reasonability of the shared memory usage across all responsible apps • This value is used to estimate the memory load of the app and is used when considering whether to kill the app. • The totals are the sum over the dalvik, native, and other

  9. Recent activities • In onCreate, add • Context context = this.getApplicationContext(); • ActivityManager mgr = (ActivityManager)context.getSystemService(ACTIVITY_SERVICE); • List<ActivityManager.RecentTaskInfo> recentTasks = mgr.getRecentTasks(100,ActivityManager.RECENT_WITH_EXCLUDED ); • Log.e("DEBUG", "Recently started tasks"); • for(Iteratori = recentTasks.iterator(); i.hasNext(); ) • { • RecentTaskInfo p = (RecentTaskInfo)i.next(); • Log.e("DEBUG", " package name: "+p. .baseIntent.getComponent().getPackageName()); • }

  10. Recent activities • Does it show the same activity if the activity has repeatedly restarted? • What about if the activity was used intermittently? • Note that the intent gives some information

  11. Running services • In onCreate, add • Context context = this.getApplicationContext(); • ActivityManager mgr = (ActivityManager)context.getSystemService(ACTIVITY_SERVICE); • List<RunningServiceInfo> services = mgr.getRunningServices(100); • Log.e("DEBUG", "services:"); • for(Iterator<RunningServiceInfo> i = services.iterator(); i.hasNext(); ) • { • RunningServiceInfo p = (RunningServiceInfo)i.next(); • Log.e("DEBUG", " process name: "+p.process); • Log.e("DEBUG", " user id of owner: "+p.uid); • Log.e("DEBUG", " number of clients: "+p.clientCount); • Log.e("DEBUG", " client package name: "+p.clientPackage); • Log.e("DEBUG", " activeSince started (secs): "+p.activeSince/1000.0); • Log.e("DEBUG", " last active: "+p.lastActivityTime/1000.0); • }

  12. killBackgroundProcesses • Add user permission, kill background processes • Context context = this.getApplicationContext(); • ActivityManager mgr = (ActivityManager)context.getSystemService(ACTIVITY_SERVICE); • List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses(); • Log.e("DEBUG", "Running processes:"); • for(Iteratori = processes.iterator(); i.hasNext(); ) • { • RunningAppProcessInfo p = (RunningAppProcessInfo)i.next(); • Log.e("DEBUG", " process name: "+p.processName); • Log.e("DEBUG", " pid: "+p.pid); // process id • switch (p.importance) { • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND: Log.e("DEBUG"," is IMPORTANCE_FOREGROUND"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE: Log.e("DEBUG"," is IMPORTANCE_VISIBLE"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE: Log.e("DEBUG"," is IMPORTANCE_SERVICE"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND: Log.e("DEBUG"," is IMPORTANCE_BACKGROUND"); break; • case ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY: Log.e("DEBUG"," is IMPORTANCE_EMPTY"); break; • default: Log.e("DEBUG"," should not happend"); break; • } • } • Log.e("debug","killingcom.android.browser"); • mgr.killBackgroundProcesses("com.android.browser"); • Log.e("debug","processes again"); • for(Iteratori = processes.iterator(); i.hasNext(); ) • { • RunningAppProcessInfo p = (RunningAppProcessInfo)i.next(); • Log.e("DEBUG", " process name: "+p.processName); • Log.e("DEBUG", " pid: "+p.pid); // process id • } • Does not really kill it. It just restarts

  13. runningTasks (activities) • For this, you must have GET_TASKS permission • List<RunningServiceInfo> services = mgr.getRunningServices(100); • List<ActivityManager.RunningTaskInfo> tasks = mgr.getRunningTasks(100); • for(Iteratori = tasks.iterator(); i.hasNext(); ) • { • RunningTaskInfo task = (RunningTaskInfo)i.next(); • Log.e("debug","name: "+task.baseActivity.getPackageName()); • Log.e("debug","num of activities"+task.numActivities); • Log.e("debug","top activity: "+task.topActivity.getPackageName()); • Log.e("debug","top activity: "+task.topActivity.getClassName()); • } • To test this, run our very first app, HelloWorld. Recall that this app has two views. Go to the second view • Now run the get tasks app • Notice that helloWorld has two views • Notice that our app is first, and helloworld is second • Unfortunately, this does not exact tell us if either app is actually comsuming CPU time

  14. Determine which processes are running (using the CPU) • Overview • Read /proc/[pid]/stat to get the total amount of CPU time used by process • We don’t actually get the CPU time, but jiffies, which can be converted to time. But usually we only need the relative amount of time, some jiffies is good enough • Read /proc/[pid]/stat and compute the current rate • To do • Read and parse /proc/[pid]/stat • Make a class to store the list of processes and jiffies • New app, TrackProcessCPULoad • Add member variable • ActivityManager mgr; • In onCreate, add • mgr = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);

  15. Determining jiffies • Add these functions to activity • public intgetJiffies(intpid) { • return getJiffiesFromProcStat(getProcStat(pid)); • } • public String getProcStat(intpid) { • String str = new String(); • str += "cat /proc/"+pid+"/stat"; • //Log.e("track process","running cat proc: "+str); • Process p; • try { • p = Runtime.getRuntime().exec(str); • BufferedReaderbri = new BufferedReader(new InputStreamReader(p.getInputStream())); • String line; • while ((line = bri.readLine()) != null) { • return line; • } • bri.close(); • } catch (IOException e) { • e.printStackTrace(); • } • return new String(); • } • public intgetJiffiesFromProcStat(String str) { • if (str==null) { • return -1; • } • inti = str.indexOf(")"); • if (i==-1) • return -1; • intlastI = i; • for(int j=0; j<13; j++) { • lastI = i; • i = str.indexOf(" ", i+1); • if (i==-1) • return -1; • } • return Integer.parseInt(str.substring(lastI+1, i)); • }

  16. Class to hold jiffie info • Need to compute current time. • JodaTime – standard class for time in java • Get and decompress the latest jar file from http://joda-time.sourceforge.net/installation.html • Add as external jar file • Right click on app, select Build Path->Configure Build Path • In dialog • select Libraries tab • Add external JARs button • Browse to jodatime.jar • Select Order and Export tab • Click joda-time check box • public class ProcessState { • DateTimelastTimeUpdated= null; • intlastJiffies = 0; • booleanflag = true; • public double updateState(intcurrentJiffies, boolean flag) { • this.flag = flag; • DateTimecurrentTime = new DateTime(); // sets to current time • double jiffieRate; • if (lastTimeUpdated==null) { • jiffieRate = -1; • lastTimeUpdated = currentTime; • } else • jiffieRate = ((double)(currentJiffies - lastJiffies))/(0.001*(double)(currentTime.getMillis() - lastTimeUpdated.getMillis())); • lastJiffies = currentJiffies; • lastTimeUpdated = currentTime; • return jiffieRate; • } • } • // Activity variable object to hold process name and jiffies • Map<String, ProcessState> processMap = new HashMap<String, ProcessState>();

  17. Function to get the jiffie rate • boolean flag = true; • public void updateProcesses() { • flag = !flag; • List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses(); • for (inti=0; i<processes.size(); i++) { • String name = processes.get(i).processName; • intpid = processes.get(i).pid; • ProcessState entry = processMap.get(name); • if (entry==null) { • Log.e("process tracker","new process: "+name); • ProcessStateps = new ProcessState(); • ps.updateState(getJiffies(pid),flag); • processMap.put(name, ps); • } else { • double rate = entry.updateState(getJiffies(pid),flag); • if (rate>0) • Log.e("process tracker",name+" has rate "+entry.updateState(getJiffies(pid),flag)); • } • } • // delete processes that are no longer running • // the flag is used to detect which processes were not updated and hence did not appear in getRunningAppProcess • Set s = processMap.entrySet(); • Iteratorit=s.iterator(); • Map.Entry entry; • if (it.hasNext()) { • entry = (Entry) it.next(); • while (entry!=null) { • IteratorlastIt = it; • ProcessStateps = (ProcessState)entry.getValue(); • if (it.hasNext()) • entry = (Entry) it.next(); • else • entry = null; • if (ps.flag != flag) { • Log.e("process tracker",(String)entry.getKey()+"is no longer active"); • processMap.remove(lastIt); • } • } • } • }

  18. Calling updateProcesses • updateProcesses needs to be called at least twice • Not updateProcesses(); updateProcesses(); • Handlers are good scheduling tasks • Note: AlarmManager can wake up the CPU at a scheduled time. Handler does not wake up the cpu • Add member variable to Activity • Handler handler; • Make function that the handler will run • RunnablerepeatTracker = new Runnable() { • @Override • public void run() { • updateProcesses(); • handler.postDelayed(repeatTracker, 5000); // runs again in 5 seconds • } • }; • At the end of onCreate, add • handler = new Handler(); // handler create in UI thread, and so it will always run in the UI thread • repeatTracker.run(); • Run • Try running the browser

More Related