12de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhoupackage com.google.android.experimental.svcmonitor; 22de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 32de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport android.app.Service; 42de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport android.content.Intent; 52de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport android.os.IBinder; 62de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport android.os.SystemClock; 72de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport android.util.Log; 82de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 92de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport java.io.IOException; 102de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport java.io.InputStreamReader; 112de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport java.io.BufferedReader; 122de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport java.io.FileInputStream; 132de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport java.lang.Runnable; 142de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport java.lang.Thread; 152de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhouimport java.util.Set; 162de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 172de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhoupublic class SvcMonitor extends Service { 182de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public static final String TAG = "svcmonitor"; 192de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String javaProc, halProc; 202de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou volatile Thread tMonitor; 212de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou int period; 222de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 232de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public SvcMonitor() {}; 242de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 252de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou @Override 262de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public int onStartCommand(Intent intent, int flags, int startId) { 272de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (intent == null) { 282de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou stopSelf(); 292de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return 0; 302de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 312de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "Starting SvcMonitor"); 322de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if ("stop".equals(intent.getAction())) { 332de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou stopService(); 342de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } else if ("start".equals(intent.getAction())) { 352de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou startMonitor(intent); 362de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } else if ("change".equals(intent.getAction())) { 372de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou changeConfig(intent); 382de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } else { 392de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "unknown action: + " + intent.getAction()); 402de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 412de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return 0; 422de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 432de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 442de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private void changeConfig(Intent intent) { 452de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (tMonitor == null) { 462de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "Service not active. Start service first"); 472de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return; 482de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 492de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou stopThread(); 502de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou startMonitor(intent); 512de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 522de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 532de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private void startMonitor(Intent intent) { 542de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (tMonitor != null) { 552de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "thread already active"); 562de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return; 572de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 582de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou javaProc = intent.getStringExtra("java"); 592de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou halProc = intent.getStringExtra("hal"); 602de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou period = intent.getIntExtra("period", 1000); 612de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (javaProc == null || halProc == null || period < 100) { 622de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "Failed starting monitor, invalid arguments."); 632de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou stopSelf(); 642de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return; 652de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 662de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Runnable monitor = new MonitorRunnable(this); 672de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou tMonitor = new Thread(monitor); 682de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou tMonitor.start(); 692de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 702de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 712de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private void stopService() { 722de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou stopThread(); 732de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou stopSelf(); 742de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "SvcMonitor stopped"); 752de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 762de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 772de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private void stopThread() { 782de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (tMonitor == null) { 792de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "no active thread"); 802de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return; 812de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 822de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "interrupting monitor thread"); 832de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou tMonitor.interrupt(); 842de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou try { 852de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou tMonitor.join(); 862de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } catch (InterruptedException e) { 872de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "Unable to finish monitor thread"); 882de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 892de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou tMonitor = null; 902de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 912de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 922de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou @Override 932de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public void onDestroy() { 942de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou super.onDestroy(); 952de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 962de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 972de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou @Override 982de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public IBinder onBind(Intent intent) { 992de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou throw new UnsupportedOperationException("Not yet implemented"); 1002de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1012de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1022de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public static class MonitorRunnable implements Runnable { 1032de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou long java_time_old, hal_time_old, cpu_time_old = -1; 1042de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String javaPID, halPID; 1052de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou SvcMonitor svcmonitor; 1062de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou static String javaProcTAG; 1072de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou int period; 1082de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1092de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public MonitorRunnable(SvcMonitor svcmonitor) { 1102de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou this.svcmonitor = svcmonitor; 1112de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou this.period = svcmonitor.period; 1122de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou javaPID = getPIDof(svcmonitor.javaProc); 1132de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou halPID = getPIDof(svcmonitor.halProc); 1142de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou java_time_old = getPsTime(javaPID); 1152de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou hal_time_old = getPsTime(halPID); 1162de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou cpu_time_old = getPsTime(""); 1172de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou javaProcTAG = String.valueOf(svcmonitor.javaProc.toCharArray()); 1182de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1192de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1202de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou @Override 1212de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou public void run() { 1222de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (halPID.isEmpty() || javaPID.isEmpty()) { 1232de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(javaProcTAG, "No such process: " + 1242de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou (halPID.isEmpty() ? svcmonitor.halProc : svcmonitor.javaProc)); 1252de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return; 1262de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1272de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou while (!Thread.interrupted()) { 1282de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou calculateUsage(); 1292de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou SystemClock.sleep(period); 1302de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1312de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "Stopping monitor thread"); 1322de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1332de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1342de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private void calculateUsage() { 1352de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou long java_time = getPsTime(javaPID); 1362de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou long hal_time = getPsTime(halPID); 1372de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou long cpu_time = getPsTime(""); 1382de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1392de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (cpu_time_old >= 0) { 1402de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou float java_diff = (float) (java_time - java_time_old); 1412de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou float hal_diff = (float) (hal_time - hal_time_old); 1422de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou float cpu_diff = (float) (cpu_time - cpu_time_old); 1432de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.w(javaProcTAG, "\n----------------\n"); 1442de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.w(javaProcTAG, "JAVA level CPU: " 1452de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou + (java_diff * 100.0 / cpu_diff) + "%\n"); 1462de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.w(javaProcTAG, " HAL level CPU: " 1472de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou + (hal_diff * 100.0 / cpu_diff) + "%\n"); 1482de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.w(javaProcTAG, " SYS level CPU: " 1492de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou + ((java_diff + hal_diff) * 100.0 / cpu_diff) + "%\n"); 1502de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } else { 1512de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.w(TAG, "Waiting for status\n"); 1522de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1532de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1542de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou java_time_old = java_time; 1552de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou hal_time_old = hal_time; 1562de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou cpu_time_old = cpu_time; 1572de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1582de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1592de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private String getPIDof(String psName) { 1602de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String pid = ""; 1612de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1622de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou try { 1632de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String[] cmd = {"/system/bin/sh", "-c", "ps | grep " + psName}; 1642de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Process ps = Runtime.getRuntime().exec(cmd); 1652de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou BufferedReader in = new BufferedReader( 1662de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou new InputStreamReader(ps.getInputStream())); 1672de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String temp = in.readLine(); 1682de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (temp == null || temp.isEmpty()) 1692de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou throw new IOException("No such process: " + psName); 1702de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou pid = temp.split(" +")[1]; 1712de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou in.close(); 1722de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } catch (IOException e) { 1732de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(javaProcTAG, "Error finding PID of process: " + psName + "\n", e); 1742de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1752de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return pid; 1762de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1772de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1782de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private long getPsTime(String pid) { 1792de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String psStat = getPsStat("/" + pid); 1802de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String[] statBreakDown = psStat.split(" +"); 1812de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou long psTime; 1822de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1832de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou if (pid.isEmpty()) { 1842de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou psTime = Long.parseLong(statBreakDown[1]) 1852de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou + Long.parseLong(statBreakDown[2]) 1862de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou + Long.parseLong(statBreakDown[3]) 1872de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou + Long.parseLong(statBreakDown[4]); 1882de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } else { 1892de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou psTime = Long.parseLong(statBreakDown[13]) 1902de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou + Long.parseLong(statBreakDown[14]); 1912de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1922de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1932de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return psTime; 1942de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 1952de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou 1962de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou private String getPsStat(String psname) { 1972de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou String stat = ""; 1982de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou try { 1992de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou FileInputStream fs = new FileInputStream("/proc" + psname + "/stat"); 2002de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou BufferedReader br = new BufferedReader(new InputStreamReader(fs)); 2012de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou stat = br.readLine(); 2022de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou fs.close(); 2032de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } catch (IOException e) { 2042de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou Log.d(TAG, "Error retreiving stat. \n"); 2052de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 2062de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou return stat; 2072de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 2082de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou } 2092de4b74d80edd8a8ee063980c6eb608369c5f81aYuchao Zhou} 210