diff options
10 files changed, 417 insertions, 15 deletions
diff --git a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml index ec5a9c63e9c8..23a151c0350a 100644 --- a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml +++ b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml @@ -32,5 +32,8 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> + <service + android:name=".TestService" + android:exported="true" /> </application> </manifest> 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/TestActivity.java index 1f061218a10c..4e7bb4cc101e 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/TestActivity.java @@ -18,7 +18,6 @@ package com.android.frameworks.perftests.amteststestapp; import android.app.Activity; import android.os.Looper; -import android.os.MessageQueue; import com.android.frameworks.perftests.am.util.Constants; import com.android.frameworks.perftests.am.util.Utils; diff --git a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestService.java b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestService.java new file mode 100644 index 000000000000..b6534fc87ae3 --- /dev/null +++ b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestService.java @@ -0,0 +1,38 @@ +/* + * 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.amteststestapp; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +import com.android.frameworks.perftests.am.util.Constants; +import com.android.frameworks.perftests.am.util.Utils; + +public class TestService extends Service { + @Override + public IBinder onBind(Intent intent) { + return new Binder(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Utils.sendTime(intent, Constants.TYPE_SERVICE_START); + return super.onStartCommand(intent, flags, startId); + } +} 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 661abe91337f..cf175e00b217 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,8 +16,11 @@ 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; @@ -26,13 +29,17 @@ 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; @@ -52,14 +59,70 @@ public class BasePerfTest { TargetPackageUtils.killTargetPackage(mContext); } - protected Intent createIntent(String action) { + protected void addReceivedTimeNs(String type) { + mTimeReceiver.addTimeForTypeToQueue(type, System.nanoTime()); + } + + protected Intent createServiceIntent() { + final Intent intent = new Intent(); + intent.setClassName(TargetPackageUtils.PACKAGE_NAME, + TargetPackageUtils.SERVICE_NAME); + putTimeReceiverBinderExtra(intent); + 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( Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - intent.putExtras(mTimeReceiver.createReceiveTimeExtraBinder()); + putTimeReceiverBinderExtra(intent); return intent; } + protected void putTimeReceiverBinderExtra(Intent intent) { + intent.putExtras(mTimeReceiver.createReceiveTimeExtraBinder()); + } + private void setUpIteration() { mTimeReceiver.clear(); TargetPackageUtils.killTargetPackage(mContext); diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java index 795f49866f84..f7dab03f10ee 100644 --- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java @@ -33,7 +33,8 @@ public class BroadcastPerfTest extends BasePerfTest { runPerfFunction(() -> { startTargetPackage(); - final Intent intent = createIntent(Constants.ACTION_BROADCAST_MANIFEST_RECEIVE); + final Intent intent = createBroadcastIntent( + Constants.ACTION_BROADCAST_MANIFEST_RECEIVE); final long startTime = System.nanoTime(); @@ -48,7 +49,8 @@ public class BroadcastPerfTest extends BasePerfTest { @Test public void manifestBroadcastNotRunning() { runPerfFunction(() -> { - final Intent intent = createIntent(Constants.ACTION_BROADCAST_MANIFEST_RECEIVE); + final Intent intent = createBroadcastIntent( + Constants.ACTION_BROADCAST_MANIFEST_RECEIVE); final long startTime = System.nanoTime(); @@ -65,7 +67,8 @@ public class BroadcastPerfTest extends BasePerfTest { runPerfFunction(() -> { startTargetPackage(); - final Intent intent = createIntent(Constants.ACTION_BROADCAST_REGISTERED_RECEIVE); + final Intent intent = createBroadcastIntent( + Constants.ACTION_BROADCAST_REGISTERED_RECEIVE); final long startTime = System.nanoTime(); 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 new file mode 100644 index 000000000000..6d2935a148fd --- /dev/null +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java @@ -0,0 +1,162 @@ +/* + * 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.tests; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.frameworks.perftests.am.util.Constants; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ServiceBindPerfTest extends BasePerfTest { + /** + * Create and return a ServiceConnection that will add the current time with type + * Constants.TYPE_SERVICE_CONNECTED. + */ + private ServiceConnection createServiceConnectionReportTime() { + return new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + addReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + } + }; + } + + /** + * Try to bind to the service with the input parameters, throwing a RuntimeException with the + * errorMessage on failure. + */ + private void bindService(Intent intent, ServiceConnection serviceConnection, int flags) { + final boolean success = mContext.bindService(intent, serviceConnection, flags); + Assert.assertTrue("Could not bind to service", success); + } + + /** + * Benchmark time from Context.bindService() to Service.onBind() when target package is not + * running. + */ + @Test + public void bindServiceNotRunning() { + runPerfFunction(() -> { + final Intent intent = createServiceIntent(); + final ServiceConnection serviceConnection = createServiceConnectionReportTime(); + + final long startTimeNs = System.nanoTime(); + bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + try { + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); + return endTimeNs - startTimeNs; + } finally { + unbindFromService(serviceConnection); + } + }); + } + + /** + * Benchmark time from Context.bindService() to Service.onBind() when target package is running. + */ + @Test + public void bindServiceRunning() { + runPerfFunction(() -> { + startTargetPackage(); + + final Intent intent = createServiceIntent(); + final ServiceConnection serviceConnection = createServiceConnectionReportTime(); + + final long startTimeNs = System.nanoTime(); + bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + try { + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); + return endTimeNs - startTimeNs; + } finally { + unbindFromService(serviceConnection); + } + }); + } + + /** + * Benchmark time from Context.bindService() to Service.onBind() when service is already bound + * to. + */ + @Test + public void bindServiceAlreadyBound() { + runPerfFunction(() -> { + startTargetPackage(); + + final Intent intent = createServiceIntent(); + final ServiceConnection alreadyBoundServiceConnection = bindAndWaitForConnectedService(); + + try { + final ServiceConnection serviceConnection = createServiceConnectionReportTime(); + + final long startTimeNs = System.nanoTime(); + try { + bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); + return endTimeNs - startTimeNs; + } finally { + unbindFromService(serviceConnection); + } + } finally { + unbindFromService(alreadyBoundServiceConnection); + } + }); + } + + /** + * Benchmark time from Context.bindService() (without BIND_ALLOW_OOM_MANAGEMENT) to + * Service.onBind() when service is already bound to with BIND_ALLOW_OOM_MANAGEMENT. + */ + @Test + public void bindServiceAllowOomManagement() { + runPerfFunction(() -> { + final Intent intentNoOom = createServiceIntent(); + final ServiceConnection serviceConnectionOom = bindAndWaitForConnectedService( + Context.BIND_ALLOW_OOM_MANAGEMENT); + + try { + final ServiceConnection serviceConnectionNoOom = + createServiceConnectionReportTime(); + try { + final long startTimeNs = System.nanoTime(); + bindService(intentNoOom, serviceConnectionNoOom, Context.BIND_AUTO_CREATE); + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED); + + return endTimeNs - startTimeNs; + } finally { + unbindFromService(serviceConnectionNoOom); + } + } finally { + unbindFromService(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 new file mode 100644 index 000000000000..626ee020542d --- /dev/null +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java @@ -0,0 +1,127 @@ +/* + * 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.tests; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.frameworks.perftests.am.util.Constants; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ServiceStartPerfTest extends BasePerfTest { + + /** + * Tries to start the service with the given intent, throwing a RuntimeException with the + * errorMessage on failure. + */ + private void startService(Intent intent) { + final ComponentName componentName = mContext.startService(intent); + Assert.assertNotNull("Could not start service", componentName); + } + + /** + * Benchmark time from Context.startService() to Service.onStartCommand() when target process is + * not running. + */ + @Test + public void startServiceNotRunning() { + runPerfFunction(() -> { + final Intent intent = createServiceIntent(); + + final long startTimeNs = System.nanoTime(); + + startService(intent); + + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START); + return endTimeNs - startTimeNs; + }); + } + + /** + * Benchmark time from Context.startService() to Service.onStartCommand() when target process is + * running. + */ + @Test + public void startServiceProcessRunning() { + runPerfFunction(() -> { + startTargetPackage(); + + final Intent intent = createServiceIntent(); + + final long startTimeNs = System.nanoTime(); + startService(intent); + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START); + + return endTimeNs - startTimeNs; + }); + } + + /** + * Benchmark time from Context.startService() to Service.onStartCommand() when service is + * already bound to. + */ + @Test + public void startServiceAlreadyBound() { + runPerfFunction(() -> { + final ServiceConnection alreadyBoundServiceConnection = + bindAndWaitForConnectedService(); + try { + final Intent intent = createServiceIntent(); + + final long startTimeNs = System.nanoTime(); + startService(intent); + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START); + + return endTimeNs - startTimeNs; + } finally { + unbindFromService(alreadyBoundServiceConnection); + } + }); + } + + /** + * Benchmark time from Context.startService() with FLAG_GRANT_READ_URI_PERMISSION to + * Service.onStartCommand() when target process is running. + */ + @Test + public void startServiceProcessRunningReadUriPermission() { + runPerfFunction(() -> { + final ServiceConnection alreadyBoundServiceConnection = + bindAndWaitForConnectedService(); + try { + final Intent intent = createServiceIntent(); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + final long startTimeNs = System.nanoTime(); + startService(intent); + final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_START); + + return endTimeNs - startTimeNs; + } finally { + unbindFromService(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 26a8e7b8945e..3db8abce90da 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 @@ -27,6 +27,7 @@ public class TargetPackageUtils { 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 long WAIT_TIME_MS = 100L; diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java index 9cf6ee7c91d5..a86a5c7ac3d4 100644 --- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java +++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java @@ -45,20 +45,23 @@ public class TimeReceiver { } } + public void addTimeForTypeToQueue(String type, long timeNs) { + if (type == null) { + throw new IllegalArgumentException("type is null when adding time to queue"); + } + if (timeNs < 0) { + throw new RuntimeException( + "time is negative/non-existant (" + timeNs + ") when adding time to queue"); + } + mQueue.add(new ReceivedMessage(type, timeNs)); + } + public Bundle createReceiveTimeExtraBinder() { Bundle extras = new Bundle(); extras.putBinder(Constants.EXTRA_RECEIVER_CALLBACK, new ITimeReceiverCallback.Stub() { @Override public void sendTime(String type, long timeNs) throws RemoteException { - if (type == null) { - throw new RuntimeException("receivedType is null"); - } - if (timeNs < 0) { - throw new RuntimeException( - "receivedTime is negative/non-existant: " + timeNs); - } - Log.i(TAG, type + " " + timeNs); - mQueue.add(new ReceivedMessage(type, timeNs)); + addTimeForTypeToQueue(type, timeNs); } }); return extras; 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 f35c2fd38dbc..ffb3f84cee51 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 @@ -19,6 +19,9 @@ package com.android.frameworks.perftests.am.util; public class Constants { public static final String TYPE_TARGET_PACKAGE_START = "target_package_start"; public static final String TYPE_BROADCAST_RECEIVE = "broadcast_receive"; + public static final String TYPE_SERVICE_BIND = "service_bind"; + public static final String TYPE_SERVICE_START = "service_start"; + public static final String TYPE_SERVICE_CONNECTED = "service_connection_connect"; public static final String ACTION_BROADCAST_MANIFEST_RECEIVE = "com.android.frameworks.perftests.ACTION_BROADCAST_MANIFEST_RECEIVE"; |