Home | History | Annotate | Download | only in svcmoniter
      1 package com.google.android.experimental.svcmonitor;
      2 
      3 import android.app.Service;
      4 import android.content.Intent;
      5 import android.os.IBinder;
      6 import android.os.SystemClock;
      7 import android.util.Log;
      8 
      9 import java.io.IOException;
     10 import java.io.InputStreamReader;
     11 import java.io.BufferedReader;
     12 import java.io.FileInputStream;
     13 import java.lang.Runnable;
     14 import java.lang.Thread;
     15 import java.util.Set;
     16 
     17 public class SvcMonitor extends Service {
     18     public static final String TAG = "svcmonitor";
     19     String javaProc, halProc;
     20     volatile Thread tMonitor;
     21     int period;
     22 
     23     public SvcMonitor() {};
     24 
     25     @Override
     26     public int onStartCommand(Intent intent, int flags, int startId) {
     27         if (intent == null) {
     28             stopSelf();
     29             return 0;
     30         }
     31         Log.d(TAG, "Starting SvcMonitor");
     32         if ("stop".equals(intent.getAction())) {
     33             stopService();
     34         } else if ("start".equals(intent.getAction())) {
     35             startMonitor(intent);
     36         } else if ("change".equals(intent.getAction())) {
     37             changeConfig(intent);
     38         } else {
     39             Log.d(TAG, "unknown action: + " + intent.getAction());
     40         }
     41         return 0;
     42     }
     43 
     44     private void changeConfig(Intent intent) {
     45         if (tMonitor == null) {
     46             Log.d(TAG, "Service not active. Start service first");
     47             return;
     48         }
     49         stopThread();
     50         startMonitor(intent);
     51     }
     52 
     53     private void startMonitor(Intent intent) {
     54         if (tMonitor != null) {
     55             Log.d(TAG, "thread already active");
     56             return;
     57         }
     58         javaProc = intent.getStringExtra("java");
     59         halProc = intent.getStringExtra("hal");
     60         period = intent.getIntExtra("period", 1000);
     61         if (javaProc == null || halProc == null || period < 100) {
     62             Log.d(TAG, "Failed starting monitor, invalid arguments.");
     63             stopSelf();
     64             return;
     65         }
     66         Runnable monitor = new MonitorRunnable(this);
     67         tMonitor = new Thread(monitor);
     68         tMonitor.start();
     69     }
     70 
     71     private void stopService() {
     72         stopThread();
     73         stopSelf();
     74         Log.d(TAG, "SvcMonitor stopped");
     75     }
     76 
     77     private void stopThread() {
     78         if (tMonitor == null) {
     79             Log.d(TAG, "no active thread");
     80             return;
     81         }
     82         Log.d(TAG, "interrupting monitor thread");
     83         tMonitor.interrupt();
     84         try {
     85             tMonitor.join();
     86         } catch (InterruptedException e) {
     87             Log.d(TAG, "Unable to finish monitor thread");
     88         }
     89         tMonitor = null;
     90     }
     91 
     92     @Override
     93     public void onDestroy() {
     94         super.onDestroy();
     95     }
     96 
     97     @Override
     98     public IBinder onBind(Intent intent) {
     99         throw new UnsupportedOperationException("Not yet implemented");
    100     }
    101 
    102     public static class MonitorRunnable implements Runnable {
    103         long java_time_old, hal_time_old, cpu_time_old = -1;
    104         String javaPID, halPID;
    105         SvcMonitor svcmonitor;
    106         static String javaProcTAG;
    107         int period;
    108 
    109         public MonitorRunnable(SvcMonitor svcmonitor) {
    110             this.svcmonitor = svcmonitor;
    111             this.period = svcmonitor.period;
    112             javaPID = getPIDof(svcmonitor.javaProc);
    113             halPID = getPIDof(svcmonitor.halProc);
    114             java_time_old = getPsTime(javaPID);
    115             hal_time_old = getPsTime(halPID);
    116             cpu_time_old = getPsTime("");
    117             javaProcTAG = String.valueOf(svcmonitor.javaProc.toCharArray());
    118         }
    119 
    120         @Override
    121         public void run() {
    122             if (halPID.isEmpty() || javaPID.isEmpty()) {
    123                 Log.d(javaProcTAG, "No such process: " +
    124                         (halPID.isEmpty() ? svcmonitor.halProc : svcmonitor.javaProc));
    125                 return;
    126             }
    127             while (!Thread.interrupted()) {
    128                 calculateUsage();
    129                 SystemClock.sleep(period);
    130             }
    131             Log.d(TAG, "Stopping monitor thread");
    132         }
    133 
    134         private void calculateUsage() {
    135             long java_time = getPsTime(javaPID);
    136             long hal_time = getPsTime(halPID);
    137             long cpu_time = getPsTime("");
    138 
    139             if (cpu_time_old >= 0) {
    140                 float java_diff = (float) (java_time - java_time_old);
    141                 float hal_diff = (float) (hal_time - hal_time_old);
    142                 float cpu_diff = (float) (cpu_time - cpu_time_old);
    143                 Log.w(javaProcTAG, "\n----------------\n");
    144                 Log.w(javaProcTAG, "JAVA level CPU: "
    145                         + (java_diff * 100.0 / cpu_diff) + "%\n");
    146                 Log.w(javaProcTAG, " HAL level CPU: "
    147                         + (hal_diff * 100.0 / cpu_diff) + "%\n");
    148                 Log.w(javaProcTAG, " SYS level CPU: "
    149                         + ((java_diff + hal_diff) * 100.0 / cpu_diff) + "%\n");
    150             } else {
    151                 Log.w(TAG, "Waiting for status\n");
    152             }
    153 
    154             java_time_old = java_time;
    155             hal_time_old = hal_time;
    156             cpu_time_old = cpu_time;
    157         }
    158 
    159         private String getPIDof(String psName) {
    160             String pid = "";
    161 
    162             try {
    163                 String[] cmd = {"/system/bin/sh", "-c", "ps | grep " + psName};
    164                 Process ps = Runtime.getRuntime().exec(cmd);
    165                 BufferedReader in = new BufferedReader(
    166                         new InputStreamReader(ps.getInputStream()));
    167                 String temp = in.readLine();
    168                 if (temp == null || temp.isEmpty())
    169                     throw new IOException("No such process: " + psName);
    170                 pid = temp.split(" +")[1];
    171                 in.close();
    172             } catch (IOException e) {
    173                 Log.d(javaProcTAG, "Error finding PID of process: " + psName + "\n", e);
    174             }
    175             return pid;
    176         }
    177 
    178         private long getPsTime(String pid) {
    179             String psStat = getPsStat("/" + pid);
    180             String[] statBreakDown = psStat.split(" +");
    181             long psTime;
    182 
    183             if (pid.isEmpty()) {
    184                 psTime = Long.parseLong(statBreakDown[1])
    185                         + Long.parseLong(statBreakDown[2])
    186                         + Long.parseLong(statBreakDown[3])
    187                         + Long.parseLong(statBreakDown[4]);
    188             } else {
    189                 psTime = Long.parseLong(statBreakDown[13])
    190                         + Long.parseLong(statBreakDown[14]);
    191             }
    192 
    193             return psTime;
    194         }
    195 
    196         private String getPsStat(String psname) {
    197             String stat = "";
    198             try {
    199                 FileInputStream fs = new FileInputStream("/proc" + psname + "/stat");
    200                 BufferedReader br = new BufferedReader(new InputStreamReader(fs));
    201                 stat = br.readLine();
    202                 fs.close();
    203             } catch (IOException e) {
    204                 Log.d(TAG, "Error retreiving stat. \n");
    205             }
    206             return stat;
    207         }
    208     }
    209 }
    210