summaryrefslogtreecommitdiffstats
path: root/core/tests
diff options
context:
space:
mode:
authorYuchao Zhou <superzhou@google.com>2015-09-16 22:53:10 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-09-16 22:53:10 +0000
commit88daa997fc609fdcbd1376657e3f18de4ca37193 (patch)
treee06c6f556df5452b7c5f5a912500d30c4ddbebe8 /core/tests
parent4873c549f7f4c45237a6f1185dd29216157965df (diff)
parentc38ffecc348687ae30c5fa2dc1761d9138b406b6 (diff)
downloadframeworks_base-88daa997fc609fdcbd1376657e3f18de4ca37193.zip
frameworks_base-88daa997fc609fdcbd1376657e3f18de4ca37193.tar.gz
frameworks_base-88daa997fc609fdcbd1376657e3f18de4ca37193.tar.bz2
am c38ffecc: Merge "Moving BTtraffic from experiment location to here" into cw-d-mr1-dev
* commit 'c38ffecc348687ae30c5fa2dc1761d9138b406b6': Moving BTtraffic from experiment location to here
Diffstat (limited to 'core/tests')
-rw-r--r--core/tests/BTtraffic/Android.mk16
-rw-r--r--core/tests/BTtraffic/AndroidManifest.xml22
-rw-r--r--core/tests/BTtraffic/README45
-rw-r--r--core/tests/BTtraffic/res/values/strings.xml3
-rw-r--r--core/tests/BTtraffic/src/com/android/google/experimental/bttraffic/BTtraffic.java328
-rw-r--r--core/tests/SvcMonitor/Android.mk16
-rw-r--r--core/tests/SvcMonitor/AndroidManifest.xml21
-rw-r--r--core/tests/SvcMonitor/README27
-rw-r--r--core/tests/SvcMonitor/res/values/strings.xml3
-rw-r--r--core/tests/SvcMonitor/src/com/android/google/experimental/svcmoniter/SvcMonitor.java209
10 files changed, 690 insertions, 0 deletions
diff --git a/core/tests/BTtraffic/Android.mk b/core/tests/BTtraffic/Android.mk
new file mode 100644
index 0000000..7d83527
--- /dev/null
+++ b/core/tests/BTtraffic/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR := \
+ $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := bttraffic
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/BTtraffic/AndroidManifest.xml b/core/tests/BTtraffic/AndroidManifest.xml
new file mode 100644
index 0000000..00d9707
--- /dev/null
+++ b/core/tests/BTtraffic/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.experimental.bttraffic" >
+
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+
+ <uses-sdk
+ android:minSdkVersion="18"
+ android:targetSdkVersion="18"
+ />
+ <application
+ android:allowBackup="false"
+ android:label="@string/app_name" >
+ <service
+ android:name=".BTtraffic"
+ android:enabled="true"
+ android:exported="true" >
+ </service>
+ </application>
+
+</manifest>
diff --git a/core/tests/BTtraffic/README b/core/tests/BTtraffic/README
new file mode 100644
index 0000000..430488f
--- /dev/null
+++ b/core/tests/BTtraffic/README
@@ -0,0 +1,45 @@
+This is a tool to generate classic Bluetooth traffic with specified period and package size.
+Together with the SvcMonitor, which will be called automatically in this android service, can be
+used to measure the CPU usage from the Java layer Bluetooth code and the underlying system service
+com.android.bluetooth.
+
+1. Server (Listener) - Client (Sender) model. Both run as an Android service.
+2. No pairing needed. Communicate via unsecured RFcomm. Client establishes the connection by
+providing the MAC addr of the server.
+3. Bluetooth has to be turned on on both side.
+4. Client can configure the traffic by specifying the transfer period and package size.
+5. A separate monitor process will be automatically forked and will be reading from /proc file
+system to calculate the cpu usage. The measurement is updated once per second.
+6. The monitor process (com.google.android.experimental.svcmonitor/.ScvMonitor) can be run as an
+independent service to measure cpu usage on any similarly configured tests (e.g. wifi, BLE). Refer
+to SvcMonitor's README for usage and details.
+
+Usage:
+To instal the test:
+On both the server and client device, install the 2 apk:
+$ adb install $OUT/system/app/bttraffic/bttraffic.apk
+$ adb install $OUT/system/app/svcmonitor/svcmonitor.apk
+
+To start the service on the SERVER side:
+$ adb shell am startservice -a start --ez ack true \
+com.google.android.experimental.bttraffic/.BTtraffic
+
+To start the service on the CLIENT side:
+$ adb shell am startservice -a start \
+-e addr "F8:A9:D0:A8:74:8E" --ei size 1000 --ei period 15 \
+com.google.android.experimental.bttraffic/.BTtraffic
+
+To stop the test:
+On either the server or client:
+$ adb shell am startservice -a stop \
+com.google.android.experimental.bttraffic/.BTtraffic
+
+To look at the data:
+$ adb logcat | grep bttraffic
+
+Options:
+-e addr: MAC addr of the server, in uppercase letter.
+--ei size: package size, unit: byte; default: 1024, MAX: 20MB
+--ei period: system sleep time between sending each package, unit: ms, default: 5000
+ ** if -1 is provided, client will only send the package once.
+--ez ack: whether acknowledge is required (true/false)
diff --git a/core/tests/BTtraffic/res/values/strings.xml b/core/tests/BTtraffic/res/values/strings.xml
new file mode 100644
index 0000000..e70276e
--- /dev/null
+++ b/core/tests/BTtraffic/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">Bluetooth Test</string>
+</resources>
diff --git a/core/tests/BTtraffic/src/com/android/google/experimental/bttraffic/BTtraffic.java b/core/tests/BTtraffic/src/com/android/google/experimental/bttraffic/BTtraffic.java
new file mode 100644
index 0000000..286c0aa
--- /dev/null
+++ b/core/tests/BTtraffic/src/com/android/google/experimental/bttraffic/BTtraffic.java
@@ -0,0 +1,328 @@
+package com.google.android.experimental.bttraffic;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothServerSocket;
+import android.bluetooth.BluetoothSocket;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.Exception;
+import java.lang.Runtime;
+import java.lang.RuntimeException;
+import java.lang.Process;
+import java.nio.ByteBuffer;
+import java.util.Random;
+import java.util.Set;
+import java.util.UUID;
+
+public class BTtraffic extends Service {
+ public static final String TAG = "bttraffic";
+ static final String SERVICE_NAME = "bttraffic";
+ static final String SYS_SERVICE_NAME = "com.android.bluetooth";
+ static final UUID SERVICE_UUID = UUID.fromString("5e8945b0-1234-5432-a5e2-0800200c9a67");
+ volatile Thread mWorkerThread;
+ volatile boolean isShuttingDown = false;
+ volatile boolean isServer = false;
+
+ public BTtraffic() {}
+
+ static void safeClose(Closeable closeable) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ Log.d(TAG, "Unable to close resource.\n");
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent == null) {
+ stopSelf();
+ return 0;
+ }
+ if ("stop".equals(intent.getAction())) {
+ stopService();
+ } else if ("start".equals(intent.getAction())) {
+ startWorker(intent);
+ } else {
+ Log.d(TAG, "unknown action: + " + intent.getAction());
+ }
+ return 0;
+ }
+
+ private void startWorker(Intent intent) {
+ if (mWorkerThread != null) {
+ Log.d(TAG, "worker thread already active");
+ return;
+ }
+ isShuttingDown = false;
+ String remoteAddr = intent.getStringExtra("addr");
+ Log.d(TAG, "startWorker: addr=" + remoteAddr);
+ Runnable worker =
+ remoteAddr == null
+ ? new ListenerRunnable(this, intent)
+ : new SenderRunnable(this, remoteAddr, intent);
+ isServer = remoteAddr == null ? true: false;
+ mWorkerThread = new Thread(worker, "BTtrafficWorker");
+ try {
+ startMonitor();
+ Log.d(TAG, "Monitor service started");
+ mWorkerThread.start();
+ Log.d(TAG, "Worker thread started");
+ } catch (Exception e) {
+ Log.d(TAG, "Failed to start service", e);
+ }
+ }
+
+ private void startMonitor()
+ throws Exception {
+ if (isServer) {
+ Log.d(TAG, "Start monitor on server");
+ String[] startmonitorCmd = {
+ "/system/bin/am",
+ "startservice",
+ "-a", "start",
+ "-e", "java", SERVICE_NAME,
+ "-e", "hal", SYS_SERVICE_NAME,
+ "com.google.android.experimental.svcmonitor/.SvcMonitor"
+ };
+ Process ps = new ProcessBuilder()
+ .command(startmonitorCmd)
+ .redirectErrorStream(true)
+ .start();
+ } else {
+ Log.d(TAG, "No need to start SvcMonitor on client");
+ }
+ }
+
+ private void stopMonitor()
+ throws Exception {
+ if (isServer) {
+ Log.d(TAG, "StopMonitor on server");
+ String[] stopmonitorCmd = {
+ "/system/bin/am",
+ "startservice",
+ "-a", "stop",
+ "com.google.android.experimental.svcmonitor/.SvcMonitor"
+ };
+ Process ps = new ProcessBuilder()
+ .command(stopmonitorCmd)
+ .redirectErrorStream(true)
+ .start();
+ } else {
+ Log.d(TAG, "No need to stop Svcmonitor on client");
+ }
+ }
+
+ public void stopService() {
+ if (mWorkerThread == null) {
+ Log.d(TAG, "no active thread");
+ return;
+ }
+
+ isShuttingDown = true;
+
+ try {
+ stopMonitor();
+ } catch (Exception e) {
+ Log.d(TAG, "Unable to stop SvcMonitor!", e);
+ }
+
+ if (Thread.currentThread() != mWorkerThread) {
+ mWorkerThread.interrupt();
+ Log.d(TAG, "Interrupting thread");
+ try {
+ mWorkerThread.join();
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Unable to join thread!");
+ }
+ }
+
+ mWorkerThread = null;
+ stopSelf();
+ Log.d(TAG, "Service stopped");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public static class ListenerRunnable implements Runnable {
+ private final BTtraffic bttraffic;
+ private final boolean sendAck;
+ private Intent intent;
+ private final int maxbuffersize = 20 * 1024 * 1024;
+
+ public ListenerRunnable(BTtraffic bttraffic, Intent intent) {
+ this.bttraffic = bttraffic;
+ this.sendAck = intent.getBooleanExtra("ack", true);
+ this.intent = intent;
+ }
+
+ @Override
+ public void run() {
+ BluetoothServerSocket serverSocket;
+
+ try {
+ Log.d(TAG, "getting server socket");
+ serverSocket = BluetoothAdapter.getDefaultAdapter()
+ .listenUsingInsecureRfcommWithServiceRecord(
+ SERVICE_NAME, SERVICE_UUID);
+ } catch (IOException e) {
+ Log.d(TAG, "error creating server socket, stopping thread");
+ bttraffic.stopService();
+ return;
+ }
+
+ Log.d(TAG, "got server socket, starting accept loop");
+ BluetoothSocket socket = null;
+ try {
+ Log.d(TAG, "accepting");
+ socket = serverSocket.accept();
+
+ if (!Thread.interrupted()) {
+ Log.d(TAG, "accepted, listening");
+ doListening(socket.getInputStream(), socket.getOutputStream());
+ Log.d(TAG, "listen finished");
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "error while accepting or listening", e);
+ } finally {
+ Log.d(TAG, "Linster interruped");
+ Log.d(TAG, "closing socket and stopping service");
+ safeClose(serverSocket);
+ safeClose(socket);
+ if (!bttraffic.isShuttingDown)
+ bttraffic.stopService();
+ }
+
+ }
+
+ private void doListening(InputStream inputStream, OutputStream outputStream)
+ throws IOException {
+ ByteBuffer byteBuffer = ByteBuffer.allocate(maxbuffersize);
+
+ while (!Thread.interrupted()) {
+ readBytesIntoBuffer(inputStream, byteBuffer, 4);
+ byteBuffer.flip();
+ int length = byteBuffer.getInt();
+ if (Thread.interrupted())
+ break;
+ readBytesIntoBuffer(inputStream, byteBuffer, length);
+
+ if (sendAck)
+ outputStream.write(0x55);
+ }
+ }
+
+ void readBytesIntoBuffer(InputStream inputStream, ByteBuffer byteBuffer, int numToRead)
+ throws IOException {
+ byteBuffer.clear();
+ while (true) {
+ int position = byteBuffer.position();
+ int remaining = numToRead - position;
+ if (remaining == 0) {
+ break;
+ }
+ int count = inputStream.read(byteBuffer.array(), position, remaining);
+ if (count < 0) {
+ throw new IOException("read the EOF");
+ }
+ byteBuffer.position(position + count);
+ }
+ }
+ }
+
+ public static class SenderRunnable implements Runnable {
+ private final BTtraffic bttraffic;
+ private final String remoteAddr;
+ private final int pkgsize, period;
+ private final int defaultpkgsize = 1024;
+ private final int defaultperiod = 5000;
+ private static ByteBuffer lengthBuffer = ByteBuffer.allocate(4);
+
+ public SenderRunnable(BTtraffic bttraffic, String remoteAddr, Intent intent) {
+ this.bttraffic = bttraffic;
+ this.remoteAddr = remoteAddr;
+ this.pkgsize = intent.getIntExtra("size", defaultpkgsize);
+ this.period = intent.getIntExtra("period", defaultperiod);
+ }
+
+ @Override
+ public void run() {
+ BluetoothDevice device = null;
+ try {
+ device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr);
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Invalid BT MAC address!\n");
+ }
+ if (device == null) {
+ Log.d(TAG, "can't find matching device, stopping thread and service");
+ bttraffic.stopService();
+ return;
+ }
+
+ BluetoothSocket socket = null;
+ try {
+ Log.d(TAG, "connecting to device with MAC addr: " + remoteAddr);
+ socket = device.createInsecureRfcommSocketToServiceRecord(SERVICE_UUID);
+ socket.connect();
+ Log.d(TAG, "connected, starting to send");
+ doSending(socket.getOutputStream());
+ Log.d(TAG, "send stopped, stopping service");
+ } catch (Exception e) {
+ Log.d(TAG, "error while sending", e);
+ } finally {
+ Log.d(TAG, "finishing, closing thread and service");
+ safeClose(socket);
+ if (!bttraffic.isShuttingDown)
+ bttraffic.stopService();
+ }
+ }
+
+ private void doSending(OutputStream outputStream) throws IOException {
+ Log.w(TAG, "doSending");
+ try {
+ Random random = new Random(System.currentTimeMillis());
+
+ byte[] bytes = new byte[pkgsize];
+ random.nextBytes(bytes);
+ while (!Thread.interrupted()) {
+ writeBytes(outputStream, bytes.length);
+ outputStream.write(bytes, 0, bytes.length);
+ if (period < 0)
+ break;
+ if (period == 0)
+ continue;
+
+ SystemClock.sleep(period);
+ }
+ Log.d(TAG, "Sender interrupted");
+ } catch (IOException e) {
+ Log.d(TAG, "doSending got error", e);
+ }
+ }
+
+ private static void writeBytes(OutputStream outputStream, int value) throws IOException {
+ lengthBuffer.putInt(value);
+ lengthBuffer.flip();
+ outputStream.write(lengthBuffer.array(), lengthBuffer.position(), lengthBuffer.limit());
+ }
+ }
+
+}
diff --git a/core/tests/SvcMonitor/Android.mk b/core/tests/SvcMonitor/Android.mk
new file mode 100644
index 0000000..2b80455
--- /dev/null
+++ b/core/tests/SvcMonitor/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR := \
+ $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := svcmonitor
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/SvcMonitor/AndroidManifest.xml b/core/tests/SvcMonitor/AndroidManifest.xml
new file mode 100644
index 0000000..de5a9bd
--- /dev/null
+++ b/core/tests/SvcMonitor/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.experimental.svcmonitor" >
+
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+
+ <uses-sdk
+ android:minSdkVersion="18"
+ android:targetSdkVersion="18"
+ />
+ <application
+ android:allowBackup="false"
+ android:label="@string/app_name" >
+ <service
+ android:name=".SvcMonitor"
+ android:enabled="true"
+ android:exported="true" >
+ </service>
+ </application>
+
+</manifest>
diff --git a/core/tests/SvcMonitor/README b/core/tests/SvcMonitor/README
new file mode 100644
index 0000000..13a4380
--- /dev/null
+++ b/core/tests/SvcMonitor/README
@@ -0,0 +1,27 @@
+This Android service measures CPU usage of a program and an underlying system service it relies on.
+An example of this would be an android app XYZ communicates to some other device via Bluetooth. The
+SvcMonitor service can monitor the CPU usage of XYZ and com.android.bluetooth.
+
+Usage:
+
+To start the service:
+$ adb shell am startservice -a start \
+-e java XYZ -e hal com.android.bluetooth \
+com.google.android.experimental.svcmonitor/.SvcMonitor
+
+To stop the service:
+$ adb shell am startservice -a stop \
+com.google.android.experimental.svcmonitor/.SvcMonitor
+
+To stop the service config:
+$ adb shell am startservice -a change \
+-e java NewName -e hal NewService \
+com.google.android.experimental.svcmonitor/.SvcMonitor
+
+To monitor the data:
+$ adb logcat | grep XYZ
+
+Options:
+-e java NameOfProgram: any running process’s name.
+-e hal NameOfSysService: name of the system service the previous process relies on.
+--ei period: period between each measurement (frequency). Unit: ms, Default:1000, Min: 100
diff --git a/core/tests/SvcMonitor/res/values/strings.xml b/core/tests/SvcMonitor/res/values/strings.xml
new file mode 100644
index 0000000..e70276e
--- /dev/null
+++ b/core/tests/SvcMonitor/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">Bluetooth Test</string>
+</resources>
diff --git a/core/tests/SvcMonitor/src/com/android/google/experimental/svcmoniter/SvcMonitor.java b/core/tests/SvcMonitor/src/com/android/google/experimental/svcmoniter/SvcMonitor.java
new file mode 100644
index 0000000..a451445
--- /dev/null
+++ b/core/tests/SvcMonitor/src/com/android/google/experimental/svcmoniter/SvcMonitor.java
@@ -0,0 +1,209 @@
+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;
+ }
+ }
+}