| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.app.activity; |
| |
| import android.app.Activity; |
| import android.content.BroadcastReceiver; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.os.Binder; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.IBinder; |
| import android.os.Message; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.test.PerformanceTestCase; |
| import android.util.Log; |
| |
| class MyBadParcelable implements Parcelable { |
| public MyBadParcelable() { |
| } |
| |
| public void writeToParcel(Parcel out, int flags) { |
| out.writeString("I am bad"); |
| } |
| |
| public int describeContents() { |
| return 0; |
| } |
| |
| public static final Parcelable.Creator<MyBadParcelable> CREATOR |
| = new Parcelable.Creator<MyBadParcelable>() { |
| public MyBadParcelable createFromParcel(Parcel in) { |
| return new MyBadParcelable(in); |
| } |
| |
| public MyBadParcelable[] newArray(int size) { |
| return new MyBadParcelable[size]; |
| } |
| }; |
| |
| public MyBadParcelable(Parcel in) { |
| String nm = in.readString(); |
| } |
| } |
| |
| public class LaunchpadActivity extends Activity { |
| public interface CallingTest extends PerformanceTestCase.Intermediates { |
| public void startTiming(boolean realTime); |
| public void addIntermediate(String name); |
| public void addIntermediate(String name, long timeInNS); |
| public void finishTiming(boolean realTime); |
| public void activityFinished(int resultCode, Intent data, |
| RuntimeException where); |
| } |
| |
| // Also used as the Binder interface descriptor string in these tests |
| public static final String LAUNCH = "com.android.frameworks.coretests.activity.LAUNCH"; |
| |
| public static final String FORWARD_RESULT = |
| "com.android.frameworks.coretests.activity.FORWARD_RESULT"; |
| public static final String RETURNED_RESULT = |
| "com.android.frameworks.coretests.activity.RETURNED_RESULT"; |
| |
| public static final String BAD_PARCELABLE = |
| "comcom.android.frameworks.coretests.activity.BAD_PARCELABLE"; |
| |
| public static final int LAUNCHED_RESULT = 1; |
| public static final int FORWARDED_RESULT = 2; |
| |
| public static final String LIFECYCLE_BASIC = |
| "com.android.frameworks.coretests.activity.LIFECYCLE_BASIC"; |
| public static final String LIFECYCLE_SCREEN = |
| "com.android.frameworks.coretests.activity.LIFECYCLE_SCREEN"; |
| public static final String LIFECYCLE_DIALOG = |
| "com.android.frameworks.coretests.activity.LIFECYCLE_DIALOG"; |
| public static final String LIFECYCLE_FINISH_CREATE = |
| "com.android.frameworks.coretests.activity.LIFECYCLE_FINISH_CREATE"; |
| public static final String LIFECYCLE_FINISH_START = |
| "com.android.frameworks.coretests.activity.LIFECYCLE_FINISH_START"; |
| |
| public static final String BROADCAST_REGISTERED = |
| "com.android.frameworks.coretests.activity.BROADCAST_REGISTERED"; |
| public static final String BROADCAST_LOCAL = |
| "com.android.frameworks.coretests.activity.BROADCAST_LOCAL"; |
| public static final String BROADCAST_REMOTE = |
| "com.android.frameworks.coretests.activity.BROADCAST_REMOTE"; |
| public static final String BROADCAST_ALL = |
| "com.android.frameworks.coretests.activity.BROADCAST_ALL"; |
| public static final String BROADCAST_REPEAT = |
| "com.android.frameworks.coretests.activity.BROADCAST_REPEAT"; |
| public static final String BROADCAST_MULTI = |
| "com.android.frameworks.coretests.activity.BROADCAST_MULTI"; |
| public static final String BROADCAST_ABORT = |
| "com.android.frameworks.coretests.activity.BROADCAST_ABORT"; |
| |
| public static final String BROADCAST_STICKY1 = |
| "com.android.frameworks.coretests.activity.BROADCAST_STICKY1"; |
| public static final String BROADCAST_STICKY2 = |
| "com.android.frameworks.coretests.activity.BROADCAST_STICKY2"; |
| |
| public static final String RECEIVER_REG = "receiver-reg"; |
| public static final String RECEIVER_LOCAL = "receiver-local"; |
| public static final String RECEIVER_REMOTE = "receiver-remote"; |
| public static final String RECEIVER_ABORT = "receiver-abort"; |
| |
| public static final String DATA_1 = "one"; |
| public static final String DATA_2 = "two"; |
| |
| public static final String ON_START = "onStart"; |
| public static final String ON_RESTART = "onRestart"; |
| public static final String ON_RESUME = "onResume"; |
| public static final String ON_FREEZE = "onSaveInstanceState"; |
| public static final String ON_PAUSE = "onPause"; |
| public static final String ON_STOP = "onStop"; |
| public static final String ON_DESTROY = "onDestroy"; |
| |
| public static final String DO_FINISH = "finish"; |
| public static final String DO_LOCAL_SCREEN = "local-screen"; |
| public static final String DO_LOCAL_DIALOG = "local-dialog"; |
| |
| private boolean mBadParcelable = false; |
| |
| private boolean mStarted = false; |
| private long mStartTime; |
| |
| private int mResultCode = RESULT_CANCELED; |
| private Intent mData = (new Intent()).setAction("No result received"); |
| private RuntimeException mResultStack = null; |
| |
| private String[] mExpectedLifecycle = null; |
| private int mNextLifecycle; |
| |
| private String[] mExpectedReceivers = null; |
| private int mNextReceiver; |
| |
| private String[] mExpectedData = null; |
| private boolean[] mReceivedData = null; |
| |
| boolean mReceiverRegistered = false; |
| |
| private static CallingTest sCallingTest = null; |
| |
| public static void setCallingTest(CallingTest ct) { |
| sCallingTest = ct; |
| } |
| |
| public LaunchpadActivity() { |
| mStartTime = System.currentTimeMillis(); |
| } |
| |
| @Override |
| protected void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| String action = getIntent().getAction(); |
| if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "CREATE lauchpad " |
| + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); |
| if (LIFECYCLE_BASIC.equals(action)) { |
| setExpectedLifecycle(new String[]{ON_START, ON_RESUME, |
| DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); |
| } else if (LIFECYCLE_SCREEN.equals(action)) { |
| setExpectedLifecycle(new String[]{ON_START, ON_RESUME, |
| DO_LOCAL_SCREEN, ON_FREEZE, ON_PAUSE, ON_STOP, |
| ON_RESTART, ON_START, ON_RESUME, |
| DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); |
| } else if (LIFECYCLE_DIALOG.equals(action)) { |
| setExpectedLifecycle(new String[]{ON_START, ON_RESUME, |
| DO_LOCAL_DIALOG, ON_FREEZE, ON_PAUSE, ON_RESUME, |
| DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); |
| } else if (LIFECYCLE_FINISH_CREATE.equals(action)) { |
| // This one behaves a little differently when running in a group. |
| if (getParent() == null) { |
| setExpectedLifecycle(new String[]{ON_DESTROY}); |
| } else { |
| setExpectedLifecycle(new String[]{ON_START, ON_STOP, ON_DESTROY}); |
| } |
| finish(); |
| } else if (LIFECYCLE_FINISH_START.equals(action)) { |
| setExpectedLifecycle(new String[]{ON_START, DO_FINISH, |
| ON_STOP, ON_DESTROY}); |
| } |
| } |
| |
| @Override |
| protected void onStart() { |
| super.onStart(); |
| if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "START lauchpad " |
| + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); |
| checkLifecycle(ON_START); |
| } |
| |
| @Override |
| protected void onRestart() { |
| super.onStart(); |
| checkLifecycle(ON_RESTART); |
| } |
| |
| @Override |
| protected void onResume() { |
| super.onResume(); |
| |
| if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "RESUME lauchpad " |
| + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); |
| checkLifecycle(ON_RESUME); |
| |
| if (!mStarted) { |
| mStarted = true; |
| |
| mHandler.postDelayed(mTimeout, 5 * 1000); |
| |
| String action = getIntent().getAction(); |
| |
| sCallingTest.startTiming(true); |
| |
| if (LAUNCH.equals(action)) { |
| Intent intent = getIntent(); |
| intent.setFlags(0); |
| intent.setComponent((ComponentName) |
| intent.getParcelableExtra("component")); |
| //System.out.println("*** Launchpad is starting: comp=" + intent.component); |
| startActivityForResult(intent, LAUNCHED_RESULT); |
| } else if (FORWARD_RESULT.equals(action)) { |
| Intent intent = getIntent(); |
| intent.setFlags(0); |
| intent.setClass(this, LocalScreen.class); |
| startActivityForResult(intent, FORWARDED_RESULT); |
| } else if (BAD_PARCELABLE.equals(action)) { |
| mBadParcelable = true; |
| Intent intent = getIntent(); |
| intent.setFlags(0); |
| intent.setClass(this, LocalScreen.class); |
| startActivityForResult(intent, LAUNCHED_RESULT); |
| } else if (BROADCAST_REGISTERED.equals(action)) { |
| setExpectedReceivers(new String[]{RECEIVER_REG}); |
| registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED)); |
| sCallingTest.addIntermediate("after-register"); |
| sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED)); |
| } else if (BROADCAST_LOCAL.equals(action)) { |
| setExpectedReceivers(new String[]{RECEIVER_LOCAL}); |
| sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL)); |
| } else if (BROADCAST_REMOTE.equals(action)) { |
| setExpectedReceivers(new String[]{RECEIVER_REMOTE}); |
| sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE)); |
| } else if (BROADCAST_ALL.equals(action)) { |
| setExpectedReceivers(new String[]{ |
| RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL}); |
| registerMyReceiver(new IntentFilter(BROADCAST_ALL)); |
| sCallingTest.addIntermediate("after-register"); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); |
| } else if (BROADCAST_MULTI.equals(action)) { |
| setExpectedReceivers(new String[]{ |
| RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, |
| RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, |
| RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, |
| RECEIVER_LOCAL, RECEIVER_REMOTE, |
| RECEIVER_LOCAL, RECEIVER_REMOTE, |
| RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, |
| RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, |
| RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, |
| RECEIVER_REMOTE, RECEIVER_LOCAL, |
| RECEIVER_REMOTE, RECEIVER_LOCAL}); |
| registerMyReceiver(new IntentFilter(BROADCAST_ALL)); |
| sCallingTest.addIntermediate("after-register"); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT), null); |
| } else if (BROADCAST_ABORT.equals(action)) { |
| setExpectedReceivers(new String[]{ |
| RECEIVER_REMOTE, RECEIVER_ABORT}); |
| registerMyReceiver(new IntentFilter(BROADCAST_ABORT)); |
| sCallingTest.addIntermediate("after-register"); |
| sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT), null); |
| } else if (BROADCAST_STICKY1.equals(action)) { |
| setExpectedReceivers(new String[]{RECEIVER_REG}); |
| setExpectedData(new String[]{DATA_1}); |
| registerMyReceiver(new IntentFilter(BROADCAST_STICKY1)); |
| sCallingTest.addIntermediate("after-register"); |
| } else if (BROADCAST_STICKY2.equals(action)) { |
| setExpectedReceivers(new String[]{RECEIVER_REG, RECEIVER_REG}); |
| setExpectedData(new String[]{DATA_1, DATA_2}); |
| IntentFilter filter = new IntentFilter(BROADCAST_STICKY1); |
| filter.addAction(BROADCAST_STICKY2); |
| registerMyReceiver(filter); |
| sCallingTest.addIntermediate("after-register"); |
| } |
| } |
| } |
| |
| @Override |
| protected void onSaveInstanceState(Bundle icicle) { |
| super.onSaveInstanceState(icicle); |
| checkLifecycle(ON_FREEZE); |
| if (mBadParcelable) { |
| icicle.putParcelable("baddy", new MyBadParcelable()); |
| } |
| } |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "PAUSE lauchpad " |
| + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); |
| checkLifecycle(ON_PAUSE); |
| } |
| |
| @Override |
| protected void onStop() { |
| super.onStop(); |
| if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "STOP lauchpad " |
| + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); |
| checkLifecycle(ON_STOP); |
| } |
| |
| @Override |
| protected void onActivityResult(int requestCode, int resultCode, |
| Intent data) { |
| switch (requestCode) { |
| case LAUNCHED_RESULT: |
| sCallingTest.finishTiming(true); |
| finishWithResult(resultCode, data); |
| break; |
| case FORWARDED_RESULT: |
| sCallingTest.finishTiming(true); |
| if (RETURNED_RESULT.equals(data.getAction())) { |
| finishWithResult(resultCode, data); |
| } else { |
| finishWithResult(RESULT_CANCELED, (new Intent()).setAction( |
| "Bad data returned: " + data)); |
| } |
| break; |
| default: |
| sCallingTest.finishTiming(true); |
| finishWithResult(RESULT_CANCELED, (new Intent()).setAction( |
| "Unexpected request code: " + requestCode)); |
| break; |
| } |
| } |
| |
| @Override |
| protected void onDestroy() { |
| super.onDestroy(); |
| if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "DESTROY lauchpad " |
| + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); |
| checkLifecycle(ON_DESTROY); |
| sCallingTest.activityFinished(mResultCode, mData, mResultStack); |
| } |
| |
| private void setExpectedLifecycle(String[] lifecycle) { |
| mExpectedLifecycle = lifecycle; |
| mNextLifecycle = 0; |
| } |
| |
| private void checkLifecycle(String where) { |
| if (mExpectedLifecycle == null) return; |
| |
| if (mNextLifecycle >= mExpectedLifecycle.length) { |
| finishBad("Activity lifecycle incorrect: received " + where |
| + " but don't expect any more calls"); |
| mExpectedLifecycle = null; |
| return; |
| } |
| if (!mExpectedLifecycle[mNextLifecycle].equals(where)) { |
| finishBad("Activity lifecycle incorrect: received " + where |
| + " but expected " + mExpectedLifecycle[mNextLifecycle] |
| + " at " + mNextLifecycle); |
| mExpectedLifecycle = null; |
| return; |
| } |
| |
| mNextLifecycle++; |
| |
| if (mNextLifecycle >= mExpectedLifecycle.length) { |
| setTestResult(RESULT_OK, null); |
| return; |
| } |
| |
| String next = mExpectedLifecycle[mNextLifecycle]; |
| if (where.equals(ON_DESTROY)) { |
| finishBad("Activity lifecycle incorrect: received " + where |
| + " but expected more actions (next is " + next + ")"); |
| mExpectedLifecycle = null; |
| return; |
| } else if (next.equals(DO_FINISH)) { |
| mNextLifecycle++; |
| if (mNextLifecycle >= mExpectedLifecycle.length) { |
| setTestResult(RESULT_OK, null); |
| } |
| if (!isFinishing()) { |
| finish(); |
| } |
| } else if (next.equals(DO_LOCAL_SCREEN)) { |
| mNextLifecycle++; |
| Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH); |
| intent.setClass(this, LocalScreen.class); |
| startActivity(intent); |
| } else if (next.equals(DO_LOCAL_DIALOG)) { |
| mNextLifecycle++; |
| Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH); |
| intent.setClass(this, LocalDialog.class); |
| startActivity(intent); |
| } |
| } |
| |
| private void setExpectedReceivers(String[] receivers) { |
| mExpectedReceivers = receivers; |
| mNextReceiver = 0; |
| } |
| |
| private void setExpectedData(String[] data) { |
| mExpectedData = data; |
| mReceivedData = new boolean[data.length]; |
| } |
| |
| private Intent makeBroadcastIntent(String action) { |
| Intent intent = new Intent(action, null); |
| intent.putExtra("caller", mCallTarget); |
| return intent; |
| } |
| |
| private void finishGood() { |
| finishWithResult(RESULT_OK, null); |
| } |
| |
| private void finishBad(String error) { |
| finishWithResult(RESULT_CANCELED, (new Intent()).setAction(error)); |
| } |
| |
| private void finishWithResult(int resultCode, Intent data) { |
| setTestResult(resultCode, data); |
| finish(); |
| } |
| |
| private void setTestResult(int resultCode, Intent data) { |
| mHandler.removeCallbacks(mTimeout); |
| unregisterMyReceiver(); |
| mResultCode = resultCode; |
| mData = data; |
| mResultStack = new RuntimeException("Original error was here"); |
| mResultStack.fillInStackTrace(); |
| } |
| |
| private void registerMyReceiver(IntentFilter filter) { |
| mReceiverRegistered = true; |
| //System.out.println("Registering: " + mReceiver); |
| registerReceiver(mReceiver, filter); |
| } |
| |
| private void unregisterMyReceiver() { |
| if (mReceiverRegistered) { |
| mReceiverRegistered = false; |
| //System.out.println("Unregistering: " + mReceiver); |
| unregisterReceiver(mReceiver); |
| } |
| } |
| |
| private Handler mHandler = new Handler() { |
| public void handleMessage(Message msg) { |
| } |
| }; |
| |
| static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; |
| static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; |
| |
| private Binder mCallTarget = new Binder() { |
| public boolean onTransact(int code, Parcel data, Parcel reply, int flags) { |
| data.setDataPosition(0); |
| data.enforceInterface(LaunchpadActivity.LAUNCH); |
| if (code == GOT_RECEIVE_TRANSACTION) { |
| String name = data.readString(); |
| gotReceive(name, null); |
| return true; |
| } else if (code == ERROR_TRANSACTION) { |
| finishBad(data.readString()); |
| return true; |
| } |
| return false; |
| } |
| }; |
| |
| private final void gotReceive(String name, Intent intent) { |
| synchronized (this) { |
| |
| //System.out.println("Got receive: " + name); |
| //System.out.println(mNextReceiver + " in " + mExpectedReceivers); |
| //new RuntimeException("stack").printStackTrace(); |
| |
| sCallingTest.addIntermediate(mNextReceiver + "-" + name); |
| |
| if (mExpectedData != null) { |
| int n = mExpectedData.length; |
| int i; |
| boolean prev = false; |
| for (i = 0; i < n; i++) { |
| if (mExpectedData[i].equals(intent.getStringExtra("test"))) { |
| if (mReceivedData[i]) { |
| prev = true; |
| continue; |
| } |
| mReceivedData[i] = true; |
| break; |
| } |
| } |
| if (i >= n) { |
| if (prev) { |
| finishBad("Receive got data too many times: " |
| + intent.getStringExtra("test")); |
| } else { |
| finishBad("Receive got unexpected data: " |
| + intent.getStringExtra("test")); |
| } |
| return; |
| } |
| } |
| |
| if (mNextReceiver >= mExpectedReceivers.length) { |
| finishBad("Got too many onReceiveIntent() calls!"); |
| // System.out.println("Too many intents received: now at " |
| // + mNextReceiver + ", expect list: " |
| // + Arrays.toString(mExpectedReceivers)); |
| } else if (!mExpectedReceivers[mNextReceiver].equals(name)) { |
| finishBad("Receive out of order: got " + name + " but expected " |
| + mExpectedReceivers[mNextReceiver] + " at " |
| + mNextReceiver); |
| } else { |
| mNextReceiver++; |
| if (mNextReceiver == mExpectedReceivers.length) { |
| mHandler.post(mUnregister); |
| } |
| } |
| |
| } |
| } |
| |
| private Runnable mUnregister = new Runnable() { |
| public void run() { |
| if (mReceiverRegistered) { |
| sCallingTest.addIntermediate("before-unregister"); |
| unregisterMyReceiver(); |
| } |
| sCallingTest.finishTiming(true); |
| finishGood(); |
| } |
| }; |
| |
| private Runnable mTimeout = new Runnable() { |
| public void run() { |
| Log.i("foo", "**** TIMEOUT"); |
| String msg = "Timeout"; |
| if (mExpectedReceivers != null |
| && mNextReceiver < mExpectedReceivers.length) { |
| msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver]; |
| } |
| finishBad(msg); |
| } |
| }; |
| |
| private BroadcastReceiver mReceiver = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| //System.out.println("Receive in: " + this + ": " + intent); |
| gotReceive(RECEIVER_REG, intent); |
| } |
| }; |
| } |
| |