blob: a451445530cd98b43186ff7aceef0147d883808c [file] [log] [blame]
package com.google.android.experimental.svcmonitor;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.lang.Runnable;
import java.lang.Thread;
import java.util.Set;
public class SvcMonitor extends Service {
public static final String TAG = "svcmonitor";
String javaProc, halProc;
volatile Thread tMonitor;
int period;
public SvcMonitor() {};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
stopSelf();
return 0;
}
Log.d(TAG, "Starting SvcMonitor");
if ("stop".equals(intent.getAction())) {
stopService();
} else if ("start".equals(intent.getAction())) {
startMonitor(intent);
} else if ("change".equals(intent.getAction())) {
changeConfig(intent);
} else {
Log.d(TAG, "unknown action: + " + intent.getAction());
}
return 0;
}
private void changeConfig(Intent intent) {
if (tMonitor == null) {
Log.d(TAG, "Service not active. Start service first");
return;
}
stopThread();
startMonitor(intent);
}
private void startMonitor(Intent intent) {
if (tMonitor != null) {
Log.d(TAG, "thread already active");
return;
}
javaProc = intent.getStringExtra("java");
halProc = intent.getStringExtra("hal");
period = intent.getIntExtra("period", 1000);
if (javaProc == null || halProc == null || period < 100) {
Log.d(TAG, "Failed starting monitor, invalid arguments.");
stopSelf();
return;
}
Runnable monitor = new MonitorRunnable(this);
tMonitor = new Thread(monitor);
tMonitor.start();
}
private void stopService() {
stopThread();
stopSelf();
Log.d(TAG, "SvcMonitor stopped");
}
private void stopThread() {
if (tMonitor == null) {
Log.d(TAG, "no active thread");
return;
}
Log.d(TAG, "interrupting monitor thread");
tMonitor.interrupt();
try {
tMonitor.join();
} catch (InterruptedException e) {
Log.d(TAG, "Unable to finish monitor thread");
}
tMonitor = null;
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
public static class MonitorRunnable implements Runnable {
long java_time_old, hal_time_old, cpu_time_old = -1;
String javaPID, halPID;
SvcMonitor svcmonitor;
static String javaProcTAG;
int period;
public MonitorRunnable(SvcMonitor svcmonitor) {
this.svcmonitor = svcmonitor;
this.period = svcmonitor.period;
javaPID = getPIDof(svcmonitor.javaProc);
halPID = getPIDof(svcmonitor.halProc);
java_time_old = getPsTime(javaPID);
hal_time_old = getPsTime(halPID);
cpu_time_old = getPsTime("");
javaProcTAG = String.valueOf(svcmonitor.javaProc.toCharArray());
}
@Override
public void run() {
if (halPID.isEmpty() || javaPID.isEmpty()) {
Log.d(javaProcTAG, "No such process: " +
(halPID.isEmpty() ? svcmonitor.halProc : svcmonitor.javaProc));
return;
}
while (!Thread.interrupted()) {
calculateUsage();
SystemClock.sleep(period);
}
Log.d(TAG, "Stopping monitor thread");
}
private void calculateUsage() {
long java_time = getPsTime(javaPID);
long hal_time = getPsTime(halPID);
long cpu_time = getPsTime("");
if (cpu_time_old >= 0) {
float java_diff = (float) (java_time - java_time_old);
float hal_diff = (float) (hal_time - hal_time_old);
float cpu_diff = (float) (cpu_time - cpu_time_old);
Log.w(javaProcTAG, "\n----------------\n");
Log.w(javaProcTAG, "JAVA level CPU: "
+ (java_diff * 100.0 / cpu_diff) + "%\n");
Log.w(javaProcTAG, " HAL level CPU: "
+ (hal_diff * 100.0 / cpu_diff) + "%\n");
Log.w(javaProcTAG, " SYS level CPU: "
+ ((java_diff + hal_diff) * 100.0 / cpu_diff) + "%\n");
} else {
Log.w(TAG, "Waiting for status\n");
}
java_time_old = java_time;
hal_time_old = hal_time;
cpu_time_old = cpu_time;
}
private String getPIDof(String psName) {
String pid = "";
try {
String[] cmd = {"/system/bin/sh", "-c", "ps | grep " + psName};
Process ps = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(
new InputStreamReader(ps.getInputStream()));
String temp = in.readLine();
if (temp == null || temp.isEmpty())
throw new IOException("No such process: " + psName);
pid = temp.split(" +")[1];
in.close();
} catch (IOException e) {
Log.d(javaProcTAG, "Error finding PID of process: " + psName + "\n", e);
}
return pid;
}
private long getPsTime(String pid) {
String psStat = getPsStat("/" + pid);
String[] statBreakDown = psStat.split(" +");
long psTime;
if (pid.isEmpty()) {
psTime = Long.parseLong(statBreakDown[1])
+ Long.parseLong(statBreakDown[2])
+ Long.parseLong(statBreakDown[3])
+ Long.parseLong(statBreakDown[4]);
} else {
psTime = Long.parseLong(statBreakDown[13])
+ Long.parseLong(statBreakDown[14]);
}
return psTime;
}
private String getPsStat(String psname) {
String stat = "";
try {
FileInputStream fs = new FileInputStream("/proc" + psname + "/stat");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
stat = br.readLine();
fs.close();
} catch (IOException e) {
Log.d(TAG, "Error retreiving stat. \n");
}
return stat;
}
}
}