diff options
9 files changed, 163 insertions, 94 deletions
diff --git a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml index 23a151c0350a..32905a96ae14 100644 --- a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml +++ b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml @@ -19,7 +19,6 @@ android:minSdkVersion="21" android:targetSdkVersion="27" /> <application android:name=".TestApplication"> - <activity android:name=".TestActivity" android:exported="true"/> <provider android:authorities="com.android.frameworks.perftests.amteststestapp" android:name=".TestContentProvider" @@ -33,6 +32,9 @@ </intent-filter> </receiver> <service + android:name=".StartProcessService" + android:exported="true" /> + <service android:name=".TestService" android:exported="true" /> </application> diff --git a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/StartProcessService.java index 4e7bb4cc101e..054097ec207a 100644 --- a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java +++ b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/StartProcessService.java @@ -16,19 +16,26 @@ package com.android.frameworks.perftests.amteststestapp; -import android.app.Activity; +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; import android.os.Looper; +import android.util.Log; -import com.android.frameworks.perftests.am.util.Constants; import com.android.frameworks.perftests.am.util.Utils; -public class TestActivity extends Activity { +/** + * Service used to start up the target package and make sure it's running. + * Should be bound to, then wait for it to call the ILooperIdleCallback. + */ +public class StartProcessService extends Service { @Override - protected void onResume() { - super.onResume(); - Looper.myQueue().addIdleHandler(() -> { - Utils.sendTime(getIntent(), Constants.TYPE_TARGET_PACKAGE_START); + public IBinder onBind(Intent intent) { + Looper.getMainLooper().getQueue().addIdleHandler(() -> { + Utils.sendLooperIdle(intent); return false; }); + return new Binder(); } } diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java index cf175e00b217..58fb136ae9b3 100644 --- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java @@ -16,11 +16,9 @@ package com.android.frameworks.perftests.am.tests; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.IBinder; import android.perftests.utils.ManualBenchmarkState; import android.perftests.utils.PerfManualStatusReporter; import android.support.test.InstrumentationRegistry; @@ -28,20 +26,16 @@ import android.support.test.InstrumentationRegistry; import com.android.frameworks.perftests.am.util.TargetPackageUtils; import com.android.frameworks.perftests.am.util.TimeReceiver; -import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import java.util.function.LongSupplier; public class BasePerfTest { private static final String TAG = BasePerfTest.class.getSimpleName(); - private static final long AWAIT_SERVICE_CONNECT_MS = 2000; private TimeReceiver mTimeReceiver; + private ServiceConnection mAliveServiceConnection; @Rule public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter(); @@ -54,11 +48,6 @@ public class BasePerfTest { mTimeReceiver = new TimeReceiver(); } - @After - public void tearDown() { - TargetPackageUtils.killTargetPackage(mContext); - } - protected void addReceivedTimeNs(String type) { mTimeReceiver.addTimeForTypeToQueue(type, System.nanoTime()); } @@ -71,46 +60,6 @@ public class BasePerfTest { return intent; } - protected ServiceConnection bindAndWaitForConnectedService() { - return bindAndWaitForConnectedService(0); - } - - protected ServiceConnection bindAndWaitForConnectedService(int flags) { - CountDownLatch countDownLatch = new CountDownLatch(1); - final ServiceConnection serviceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - countDownLatch.countDown(); - } - - @Override - public void onServiceDisconnected(ComponentName name) { - } - }; - - final Intent intent = createServiceIntent(); - final boolean success = mContext.bindService(intent, serviceConnection, - Context.BIND_AUTO_CREATE | flags); - Assert.assertTrue("Could not bind to service", success); - - try { - boolean connectedSuccess = countDownLatch.await(AWAIT_SERVICE_CONNECT_MS, - TimeUnit.MILLISECONDS); - Assert.assertTrue("Timeout when waiting for ServiceConnection.onServiceConnected()", - connectedSuccess); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - return serviceConnection; - } - - protected void unbindFromService(ServiceConnection serviceConnection) { - if (serviceConnection != null) { - mContext.unbindService(serviceConnection); - } - } - protected Intent createBroadcastIntent(String action) { final Intent intent = new Intent(action); intent.addFlags( @@ -125,11 +74,14 @@ public class BasePerfTest { private void setUpIteration() { mTimeReceiver.clear(); - TargetPackageUtils.killTargetPackage(mContext); + } + + private void tearDownIteration() { + TargetPackageUtils.killTargetPackage(mContext, mAliveServiceConnection); } protected void startTargetPackage() { - TargetPackageUtils.startTargetPackage(mContext, mTimeReceiver); + mAliveServiceConnection = TargetPackageUtils.startTargetPackage(mContext); } protected long getReceivedTimeNs(String type) { @@ -142,6 +94,7 @@ public class BasePerfTest { while (benchmarkState.keepRunning(elapsedTimeNs)) { setUpIteration(); elapsedTimeNs = func.getAsLong(); + tearDownIteration(); } } } diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java index 6d2935a148fd..e1263db61b8b 100644 --- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java @@ -25,6 +25,7 @@ import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; import com.android.frameworks.perftests.am.util.Constants; +import com.android.frameworks.perftests.am.util.TargetPackageUtils; import org.junit.Assert; import org.junit.Test; @@ -75,7 +76,7 @@ public class ServiceBindPerfTest extends BasePerfTest { final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); return endTimeNs - startTimeNs; } finally { - unbindFromService(serviceConnection); + TargetPackageUtils.unbindFromService(mContext, serviceConnection); } }); } @@ -97,7 +98,7 @@ public class ServiceBindPerfTest extends BasePerfTest { final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); return endTimeNs - startTimeNs; } finally { - unbindFromService(serviceConnection); + TargetPackageUtils.unbindFromService(mContext, serviceConnection); } }); } @@ -112,7 +113,8 @@ public class ServiceBindPerfTest extends BasePerfTest { startTargetPackage(); final Intent intent = createServiceIntent(); - final ServiceConnection alreadyBoundServiceConnection = bindAndWaitForConnectedService(); + final ServiceConnection alreadyBoundServiceConnection = + TargetPackageUtils.bindAndWaitForConnectedService(mContext, intent); try { final ServiceConnection serviceConnection = createServiceConnectionReportTime(); @@ -123,10 +125,10 @@ public class ServiceBindPerfTest extends BasePerfTest { final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); return endTimeNs - startTimeNs; } finally { - unbindFromService(serviceConnection); + TargetPackageUtils.unbindFromService(mContext, serviceConnection); } } finally { - unbindFromService(alreadyBoundServiceConnection); + TargetPackageUtils.unbindFromService(mContext, alreadyBoundServiceConnection); } }); } @@ -139,8 +141,9 @@ public class ServiceBindPerfTest extends BasePerfTest { public void bindServiceAllowOomManagement() { runPerfFunction(() -> { final Intent intentNoOom = createServiceIntent(); - final ServiceConnection serviceConnectionOom = bindAndWaitForConnectedService( - Context.BIND_ALLOW_OOM_MANAGEMENT); + final ServiceConnection serviceConnectionOom = + TargetPackageUtils.bindAndWaitForConnectedService(mContext, intentNoOom, + Context.BIND_ALLOW_OOM_MANAGEMENT); try { final ServiceConnection serviceConnectionNoOom = @@ -152,10 +155,10 @@ public class ServiceBindPerfTest extends BasePerfTest { return endTimeNs - startTimeNs; } finally { - unbindFromService(serviceConnectionNoOom); + TargetPackageUtils.unbindFromService(mContext, serviceConnectionNoOom); } } finally { - unbindFromService(serviceConnectionOom); + TargetPackageUtils.unbindFromService(mContext, serviceConnectionOom); } }); } diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java index 626ee020542d..f05f32382e53 100644 --- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java @@ -23,6 +23,7 @@ import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; import com.android.frameworks.perftests.am.util.Constants; +import com.android.frameworks.perftests.am.util.TargetPackageUtils; import org.junit.Assert; import org.junit.Test; @@ -86,7 +87,8 @@ public class ServiceStartPerfTest extends BasePerfTest { public void startServiceAlreadyBound() { runPerfFunction(() -> { final ServiceConnection alreadyBoundServiceConnection = - bindAndWaitForConnectedService(); + TargetPackageUtils.bindAndWaitForConnectedService(mContext, + createServiceIntent()); try { final Intent intent = createServiceIntent(); @@ -96,20 +98,21 @@ public class ServiceStartPerfTest extends BasePerfTest { return endTimeNs - startTimeNs; } finally { - unbindFromService(alreadyBoundServiceConnection); + TargetPackageUtils.unbindFromService(mContext, alreadyBoundServiceConnection); } }); } /** * Benchmark time from Context.startService() with FLAG_GRANT_READ_URI_PERMISSION to - * Service.onStartCommand() when target process is running. + * Service.onStartCommand() when target service is already running. */ @Test public void startServiceProcessRunningReadUriPermission() { runPerfFunction(() -> { final ServiceConnection alreadyBoundServiceConnection = - bindAndWaitForConnectedService(); + TargetPackageUtils.bindAndWaitForConnectedService(mContext, + createServiceIntent()); try { final Intent intent = createServiceIntent(); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); @@ -120,7 +123,7 @@ public class ServiceStartPerfTest extends BasePerfTest { return endTimeNs - startTimeNs; } finally { - unbindFromService(alreadyBoundServiceConnection); + TargetPackageUtils.unbindFromService(mContext, alreadyBoundServiceConnection); } }); } diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java index 3db8abce90da..046dd6bb7dce 100644 --- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java @@ -17,19 +17,33 @@ package com.android.frameworks.perftests.am.util; import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.ResultReceiver; import android.os.SystemClock; +import org.junit.Assert; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + public class TargetPackageUtils { private static final String TAG = TargetPackageUtils.class.getSimpleName(); public static final String PACKAGE_NAME = "com.android.frameworks.perftests.amteststestapp"; public static final String ACTIVITY_NAME = PACKAGE_NAME + ".TestActivity"; public static final String SERVICE_NAME = PACKAGE_NAME + ".TestService"; + private static final String START_SERVICE_NAME = PACKAGE_NAME + ".StartProcessService"; private static final long WAIT_TIME_MS = 100L; + private static final long AWAIT_SERVICE_CONNECT_MS = 10000L; // Cache for test app's uid, so we only have to query it once. private static int sTestAppUid = -1; @@ -37,11 +51,13 @@ public class TargetPackageUtils { /** * Kills the test package synchronously. */ - public static void killTargetPackage(Context context) { - ActivityManager activityManager = context.getSystemService(ActivityManager.class); + public static void killTargetPackage(Context context, ServiceConnection serviceConnection) { + unbindFromService(context, serviceConnection); + + final ActivityManager activityManager = context.getSystemService(ActivityManager.class); activityManager.forceStopPackage(PACKAGE_NAME); while (targetPackageIsRunning(context)) { - sleep(); + SystemClock.sleep(WAIT_TIME_MS); } Utils.drainBroadcastQueue(); @@ -50,21 +66,24 @@ public class TargetPackageUtils { /** * Starts the test package synchronously. It does so by starting an Activity. */ - public static void startTargetPackage(Context context, TimeReceiver timeReceiver) { - // "am start-activity -W PACKAGE_NAME/ACTIVITY_CLASS_NAME" still requires a sleep even - // though it should be synchronous, so just use Intent instead + public static ServiceConnection startTargetPackage(Context context) { + final CountDownLatch countDownLatch = new CountDownLatch(1); final Intent intent = new Intent(); - intent.putExtras(timeReceiver.createReceiveTimeExtraBinder()); - intent.setClassName(PACKAGE_NAME, ACTIVITY_NAME); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); + intent.putExtra(Intent.EXTRA_RESULT_RECEIVER, new CountDownResultReceiver(countDownLatch)); + intent.setClassName(PACKAGE_NAME, START_SERVICE_NAME); + final ServiceConnection serviceConnection = bindAndWaitForConnectedService(context, intent); - while (!targetPackageIsRunning(context)) { - sleep(); + try { + final boolean targetPackageIdleSuccess = countDownLatch.await(AWAIT_SERVICE_CONNECT_MS, + TimeUnit.MILLISECONDS); + Assert.assertTrue("Timeout when waiting for ILooperIdleCallback.Stub.looperIdle()", + targetPackageIdleSuccess); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - // make sure Application has run - timeReceiver.getReceivedTimeNs(Constants.TYPE_TARGET_PACKAGE_START); + Utils.drainBroadcastQueue(); + return serviceConnection; } private static boolean targetPackageIsRunning(Context context) { @@ -74,10 +93,6 @@ public class TargetPackageUtils { return !result.contains("(NONEXISTENT)"); } - private static void sleep() { - SystemClock.sleep(WAIT_TIME_MS); - } - private static int getTestAppUid(Context context) { if (sTestAppUid == -1) { final PackageManager pm = context.getPackageManager(); @@ -90,5 +105,45 @@ public class TargetPackageUtils { return sTestAppUid; } + public static ServiceConnection bindAndWaitForConnectedService(Context context, Intent intent) { + return bindAndWaitForConnectedService(context, intent, 0); + } + + public static ServiceConnection bindAndWaitForConnectedService(Context context, Intent intent, + int bindFlags) { + final CountDownLatch countDownLatch = new CountDownLatch(1); + final ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + countDownLatch.countDown(); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + } + }; + + final boolean success = context.bindService(intent, serviceConnection, + Context.BIND_AUTO_CREATE | bindFlags); + Assert.assertTrue("Could not bind to service", success); + + try { + final boolean connectedSuccess = countDownLatch.await(AWAIT_SERVICE_CONNECT_MS, + TimeUnit.MILLISECONDS); + Assert.assertTrue("Timeout when waiting for ServiceConnection.onServiceConnected()", + connectedSuccess); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + return serviceConnection; + } + + public static void unbindFromService(Context context, ServiceConnection serviceConnection) { + if (serviceConnection != null) { + context.unbindService(serviceConnection); + } + } + } diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java index ffb3f84cee51..9b076c507ff8 100644 --- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java +++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java @@ -29,4 +29,5 @@ public class Constants { "com.android.frameworks.perftests.ACTION_BROADCAST_REGISTERED_RECEIVE"; public static final String EXTRA_RECEIVER_CALLBACK = "receiver_callback_binder"; + public static final String EXTRA_LOOPER_IDLE_CALLBACK = "looper_idle_callback_binder"; } diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/CountDownResultReceiver.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/CountDownResultReceiver.java new file mode 100644 index 000000000000..6c032c45e751 --- /dev/null +++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/CountDownResultReceiver.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 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 com.android.frameworks.perftests.am.util; + +import android.os.Bundle; +import android.os.ResultReceiver; + +import java.util.concurrent.CountDownLatch; + +public class CountDownResultReceiver extends ResultReceiver { + private CountDownLatch mCountDownLatch; + + public CountDownResultReceiver(CountDownLatch countDownLatch) { + super(null); + mCountDownLatch = countDownLatch; + } + + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + mCountDownLatch.countDown(); + } +} diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java index 493d8cdd0803..67071d204eff 100644 --- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java +++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java @@ -18,6 +18,7 @@ package com.android.frameworks.perftests.am.util; import android.content.Intent; import android.os.RemoteException; +import android.os.ResultReceiver; import android.support.test.InstrumentationRegistry; import android.support.test.uiautomator.UiDevice; import android.util.Log; @@ -56,4 +57,12 @@ public class Utils { Log.e(TAG, e.getMessage()); } } + + /** + * Notify the listener that the main Looper queue is idle. + */ + public static void sendLooperIdle(Intent intent) { + ResultReceiver resultReceiver = intent.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER); + resultReceiver.send(0, null); + } } |