Merge "Cleanup remote execution of perf tests." into ics-mr1

This commit is contained in:
Dianne Hackborn
2011-11-08 11:52:58 -08:00
committed by Android (Google) Code Review
2 changed files with 92 additions and 20 deletions

View File

@ -20,6 +20,7 @@ import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
@ -45,6 +46,7 @@ import java.util.ArrayList;
public class FrameworkPerfActivity extends Activity public class FrameworkPerfActivity extends Activity
implements AdapterView.OnItemSelectedListener { implements AdapterView.OnItemSelectedListener {
static final String TAG = "Perf"; static final String TAG = "Perf";
static final boolean DEBUG = false;
Spinner mFgSpinner; Spinner mFgSpinner;
Spinner mBgSpinner; Spinner mBgSpinner;
@ -67,22 +69,47 @@ public class FrameworkPerfActivity extends Activity
TestService.Op mBgTest; TestService.Op mBgTest;
int mCurOpIndex = 0; int mCurOpIndex = 0;
TestConnection mCurConnection; TestConnection mCurConnection;
boolean mConnectionBound;
final ArrayList<RunResult> mResults = new ArrayList<RunResult>(); final ArrayList<RunResult> mResults = new ArrayList<RunResult>();
class TestConnection implements ServiceConnection { class TestConnection implements ServiceConnection, IBinder.DeathRecipient {
Messenger mService; Messenger mService;
boolean mLinked;
@Override public void onServiceConnected(ComponentName name, IBinder service) { @Override public void onServiceConnected(ComponentName name, IBinder service) {
try {
if (!(service instanceof Binder)) {
// If remote, we'll be killing ye.
service.linkToDeath(this, 0);
mLinked = true;
}
mService = new Messenger(service); mService = new Messenger(service);
dispatchCurOp(this); dispatchCurOp(this);
} catch (RemoteException e) {
// Whoops, service has disappeared... try starting again.
Log.w(TAG, "Test service died, starting again");
startCurOp();
}
} }
@Override public void onServiceDisconnected(ComponentName name) { @Override public void onServiceDisconnected(ComponentName name) {
} }
@Override public void binderDied() {
cleanup();
connectionDied(this);
} }
static final int MSG_CONTINUE = 1000; void cleanup() {
if (mLinked) {
mLinked = false;
mService.getBinder().unlinkToDeath(this, 0);
}
}
}
static final int MSG_DO_NEXT_TEST = 1000;
final Handler mHandler = new Handler() { final Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) { @Override public void handleMessage(Message msg) {
@ -93,11 +120,7 @@ public class FrameworkPerfActivity extends Activity
RunResult res = (RunResult)bundle.getParcelable("res"); RunResult res = (RunResult)bundle.getParcelable("res");
completeCurOp(res); completeCurOp(res);
} break; } break;
case TestService.RES_TERMINATED: { case MSG_DO_NEXT_TEST: {
// Give a little time for things to settle down.
sendMessageDelayed(obtainMessage(MSG_CONTINUE), 500);
} break;
case MSG_CONTINUE: {
startCurOp(); startCurOp();
} break; } break;
} }
@ -235,7 +258,7 @@ public class FrameworkPerfActivity extends Activity
try { try {
conn.mService.send(msg); conn.mService.send(msg);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.i(TAG, "Failure communicating with service", e); Log.w(TAG, "Failure communicating with service", e);
} }
} }
@ -273,29 +296,55 @@ public class FrameworkPerfActivity extends Activity
} }
void disconnect() { void disconnect() {
if (mCurConnection != null) { final TestConnection conn = mCurConnection;
unbindService(mCurConnection); if (conn != null) {
if (mCurConnection.mService != null) { if (DEBUG) {
Message msg = Message.obtain(null, TestService.CMD_TERMINATE); RuntimeException here = new RuntimeException("here");
msg.replyTo = mMessenger; here.fillInStackTrace();
try { Log.i(TAG, "Unbinding " + conn, here);
mCurConnection.mService.send(msg);
} catch (RemoteException e) {
Log.i(TAG, "Failure communicating with service", e);
} }
if (mConnectionBound) {
unbindService(conn);
mConnectionBound = false;
}
if (conn.mLinked) {
Message msg = Message.obtain(null, TestService.CMD_TERMINATE);
try {
conn.mService.send(msg);
return;
} catch (RemoteException e) {
Log.w(TAG, "Test service aleady died when terminating");
}
}
conn.cleanup();
}
connectionDied(conn);
}
void connectionDied(TestConnection conn) {
if (mCurConnection == conn) {
// Now that we know the test process has died, we can commence
// the next test. Just give a little delay to allow the activity
// manager to know it has died as well (not a disaster if it hasn't
// yet, though).
if (mConnectionBound) {
unbindService(conn);
} }
mCurConnection = null; mCurConnection = null;
mHandler.sendMessageDelayed(Message.obtain(null, MSG_DO_NEXT_TEST), 100);
} }
} }
void startCurOp() { void startCurOp() {
if (DEBUG) Log.i(TAG, "startCurOp: mCurConnection=" + mCurConnection);
if (mCurConnection != null) { if (mCurConnection != null) {
disconnect(); disconnect();
return;
} }
if (mStarted) { if (mStarted) {
mHandler.removeMessages(TestService.RES_TEST_FINISHED); mHandler.removeMessages(TestService.RES_TEST_FINISHED);
mHandler.removeMessages(TestService.RES_TERMINATED); mHandler.removeMessages(TestService.RES_TERMINATED);
mHandler.removeMessages(MSG_CONTINUE); mHandler.removeMessages(MSG_DO_NEXT_TEST);
mCurConnection = new TestConnection(); mCurConnection = new TestConnection();
Intent intent; Intent intent;
if (mLocalCheckBox.isChecked()) { if (mLocalCheckBox.isChecked()) {
@ -303,7 +352,13 @@ public class FrameworkPerfActivity extends Activity
} else { } else {
intent = new Intent(this, TestService.class); intent = new Intent(this, TestService.class);
} }
if (DEBUG) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Log.i(TAG, "Binding " + mCurConnection, here);
}
bindService(intent, mCurConnection, BIND_AUTO_CREATE|BIND_IMPORTANT); bindService(intent, mCurConnection, BIND_AUTO_CREATE|BIND_IMPORTANT);
mConnectionBound = true;
} }
} }

View File

@ -139,6 +139,9 @@ public class TestService extends Service {
static final int CMD_START_TEST = 1; static final int CMD_START_TEST = 1;
static final int CMD_TERMINATE = 2; static final int CMD_TERMINATE = 2;
static final int MSG_REALLY_START = 1000;
static final int MSG_REALLY_TERMINATE = 1001;
static final int RES_TEST_FINISHED = 1; static final int RES_TEST_FINISHED = 1;
static final int RES_TERMINATED = 2; static final int RES_TERMINATED = 2;
@ -146,6 +149,13 @@ public class TestService extends Service {
@Override public void handleMessage(Message msg) { @Override public void handleMessage(Message msg) {
switch (msg.what) { switch (msg.what) {
case CMD_START_TEST: { case CMD_START_TEST: {
// Give a little time for things to settle down.
Message newMsg = Message.obtain(null, MSG_REALLY_START);
newMsg.obj = msg.obj;
newMsg.replyTo = msg.replyTo;
sendMessageDelayed(newMsg, 500);
} break;
case MSG_REALLY_START: {
Bundle bundle = (Bundle)msg.obj; Bundle bundle = (Bundle)msg.obj;
bundle.setClassLoader(getClassLoader()); bundle.setClassLoader(getClassLoader());
final TestArgs args = (TestArgs)bundle.getParcelable("args"); final TestArgs args = (TestArgs)bundle.getParcelable("args");
@ -166,6 +176,13 @@ public class TestService extends Service {
}); });
} break; } break;
case CMD_TERMINATE: { case CMD_TERMINATE: {
// Give a little time for things to settle down.
Message newMsg = Message.obtain(null, MSG_REALLY_TERMINATE);
newMsg.obj = msg.obj;
newMsg.replyTo = msg.replyTo;
sendMessageDelayed(newMsg, 50);
} break;
case MSG_REALLY_TERMINATE: {
if (msg.replyTo != null) { if (msg.replyTo != null) {
Message reply = Message.obtain(null, RES_TERMINATED); Message reply = Message.obtain(null, RES_TERMINATED);
try { try {
@ -174,7 +191,7 @@ public class TestService extends Service {
} }
} }
terminate(); terminate();
} } break;
} }
} }
}; };
@ -187,7 +204,7 @@ public class TestService extends Service {
} }
void terminate() { void terminate() {
Process.killProcess(Process.myPid()); Runtime.getRuntime().exit(0);
} }
enum BackgroundMode { enum BackgroundMode {