Presentation is loading. Please wait.

Presentation is loading. Please wait.

Tracking Tasks and Processes. GET_TASK Make a new app, WatchProcesses – Add permission GET_TASK This permission allows the app to collect lots of information.

Similar presentations


Presentation on theme: "Tracking Tasks and Processes. GET_TASK Make a new app, WatchProcesses – Add permission GET_TASK This permission allows the app to collect lots of information."— 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 processes = mgr.getRunningAppProcesses(); – Log.e("DEBUG", "Running processes:"); – for(Iterator i = 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 processes = mgr.getRunningAppProcesses(); – Log.e("DEBUG", "importance:"); – for(Iterator i = 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, importanceReasonCode migth 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 processes = mgr.getRunningAppProcesses(); – Log.e("DEBUG", "packages:"); – for(Iterator i = 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 processes = mgr.getRunningAppProcesses(); – Log.e("DEBUG", "Running processes:"); – for(Iterator i = 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 recentTasks = mgr.getRecentTasks(100,ActivityManager.RECENT_WITH_EXCLUDED ); – Log.e("DEBUG", "Recently started tasks"); – for(Iterator i = 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 services = mgr.getRunningServices(100); – Log.e("DEBUG", "services:"); – for(Iterator 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 processes = mgr.getRunningAppProcesses(); Log.e("DEBUG", "Running processes:"); for(Iterator i = 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","killing com.android.browser"); mgr.killBackgroundProcesses("com.android.browser"); Log.e("debug","processes again"); for(Iterator i = 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 services = mgr.getRunningServices(100); List tasks = mgr.getRunningTasks(100); for(Iterator i = 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 int getJiffies(int pid) { return getJiffiesFromProcStat(getProcStat(pid)); – } – public String getProcStat(int pid) { 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); – BufferedReader bri = 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 int getJiffiesFromProcStat(String str) { if (str==null) { – return -1; } int i = str.indexOf(")"); if (i==-1) – return -1; int lastI = 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.htmlhttp://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 { – DateTime lastTimeUpdated = null; – int lastJiffies = 0; – boolean flag = true; – public double updateState(int currentJiffies, boolean flag) { this.flag = flag; DateTime currentTime = 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 processMap = new HashMap ();

17 Function to get the jiffie rate boolean flag = true; public void updateProcesses() { – flag = !flag; – List processes = mgr.getRunningAppProcesses(); – for (int i=0; i<processes.size(); i++) { String name = processes.get(i).processName; int pid = processes.get(i).pid; ProcessState entry = processMap.get(name); if (entry==null) { – Log.e("process tracker","new process: "+name); – ProcessState ps = 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(); – Iterator it=s.iterator(); – Map.Entry entry; – if (it.hasNext()) { entry = (Entry) it.next(); while (entry!=null) { – Iterator lastIt = it; – ProcessState ps = (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 – Runnable repeatTracker = 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


Download ppt "Tracking Tasks and Processes. GET_TASK Make a new app, WatchProcesses – Add permission GET_TASK This permission allows the app to collect lots of information."

Similar presentations


Ads by Google