summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Eubanks <aeubanks@google.com>2017-12-18 13:46:59 -0800
committerArthur Eubanks <aeubanks@google.com>2018-01-12 09:54:13 -0800
commit263d674d598f77a1f91bdfc73be808efd3446133 (patch)
treee61a0b9e50b4d85512a3ec13d06c42d3caef8982
parent8da513e8bfedae0316939768a826c55d34f123e0 (diff)
Add performance test for BroadcastReceiver
This is intended to be the first of multiple performance tests around ActivityManager. This also refactors some of the existing performance utils so that a BenchmarkState which accepts the elapsed time rather than measures it can be added (ManualBenchmarkState). This test measures the current time, sends a Broadcast, the target APK receives it, measures the current time, and sends its measured time back to the test APK. Test: m ActivityManagerPerfTestsTestApp ActivityManagerPerfTests Test: adb install $OUT/data/app/ActivityManagerPerfTestsTestApp/ActivityManagerPerfTestsTestApp.apk Test: adb install $OUT/data/app/ActivityManagerPerfTests/ActivityManagerPerfTests.apk Test: adb shell am instrument -w -e class \ com.android.frameworks.perftests.am.tests.BroadcastPerfTest \ com.android.frameworks.perftests.amtests/android.support.test.runner.AndroidJUnitRunner Bug: 67460485 Change-Id: Ib1606ff60c6a845088bde5bd1a33294765b88b36
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java46
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java157
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java73
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/Stats.java76
-rw-r--r--tests/ActivityManagerPerfTests/README.txt34
-rw-r--r--tests/ActivityManagerPerfTests/test-app/Android.mk28
-rw-r--r--tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml29
-rw-r--r--tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java32
-rw-r--r--tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestApplication.java51
-rw-r--r--tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestBroadcastReceiver.java32
-rw-r--r--tests/ActivityManagerPerfTests/tests/Android.mk33
-rw-r--r--tests/ActivityManagerPerfTests/tests/AndroidManifest.xml27
-rw-r--r--tests/ActivityManagerPerfTests/tests/AndroidTest.xml29
-rw-r--r--tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java84
-rw-r--r--tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java79
-rw-r--r--tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java93
-rw-r--r--tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java107
-rw-r--r--tests/ActivityManagerPerfTests/utils/Android.mk31
-rw-r--r--tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java29
-rw-r--r--tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl21
-rw-r--r--tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java59
21 files changed, 1110 insertions, 40 deletions
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
index bb9dc4ae562e..da17818bbda0 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
@@ -25,7 +25,6 @@ import android.util.Log;
import java.io.File;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
@@ -78,10 +77,7 @@ public final class BenchmarkState {
// Statistics. These values will be filled when the benchmark has finished.
// The computation needs double precision, but long int is fine for final reporting.
- private long mMedian = 0;
- private double mMean = 0.0;
- private double mStandardDeviation = 0.0;
- private long mMin = 0;
+ private Stats mStats;
// Individual duration in nano seconds.
private ArrayList<Long> mResults = new ArrayList<>();
@@ -90,36 +86,6 @@ public final class BenchmarkState {
return TimeUnit.MILLISECONDS.toNanos(ms);
}
- /**
- * Calculates statistics.
- */
- private void calculateSatistics() {
- final int size = mResults.size();
- if (size <= 1) {
- throw new IllegalStateException("At least two results are necessary.");
- }
-
- Collections.sort(mResults);
- mMedian = size % 2 == 0 ? (mResults.get(size / 2) + mResults.get(size / 2 + 1)) / 2 :
- mResults.get(size / 2);
-
- mMin = mResults.get(0);
- for (int i = 0; i < size; ++i) {
- long result = mResults.get(i);
- mMean += result;
- if (result < mMin) {
- mMin = result;
- }
- }
- mMean /= (double) size;
-
- for (int i = 0; i < size; ++i) {
- final double tmp = mResults.get(i) - mMean;
- mStandardDeviation += tmp * tmp;
- }
- mStandardDeviation = Math.sqrt(mStandardDeviation / (double) (size - 1));
- }
-
// Stops the benchmark timer.
// This method can be called only when the timer is running.
public void pauseTiming() {
@@ -173,7 +139,7 @@ public final class BenchmarkState {
if (ENABLE_PROFILING) {
Debug.stopMethodTracing();
}
- calculateSatistics();
+ mStats = new Stats(mResults);
mState = FINISHED;
return false;
}
@@ -224,28 +190,28 @@ public final class BenchmarkState {
if (mState != FINISHED) {
throw new IllegalStateException("The benchmark hasn't finished");
}
- return (long) mMean;
+ return (long) mStats.getMean();
}
private long median() {
if (mState != FINISHED) {
throw new IllegalStateException("The benchmark hasn't finished");
}
- return mMedian;
+ return mStats.getMedian();
}
private long min() {
if (mState != FINISHED) {
throw new IllegalStateException("The benchmark hasn't finished");
}
- return mMin;
+ return mStats.getMin();
}
private long standardDeviation() {
if (mState != FINISHED) {
throw new IllegalStateException("The benchmark hasn't finished");
}
- return (long) mStandardDeviation;
+ return (long) mStats.getStandardDeviation();
}
private String summaryLine() {
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
new file mode 100644
index 000000000000..2c84db18ce54
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
@@ -0,0 +1,157 @@
+/*
+ * 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 android.perftests.utils;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Provides a benchmark framework.
+ *
+ * This differs from BenchmarkState in that rather than the class measuring the the elapsed time,
+ * the test passes in the elapsed time.
+ *
+ * Example usage:
+ *
+ * public void sampleMethod() {
+ * ManualBenchmarkState state = new ManualBenchmarkState();
+ *
+ * int[] src = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ * long elapsedTime = 0;
+ * while (state.keepRunning(elapsedTime)) {
+ * long startTime = System.nanoTime();
+ * int[] dest = new int[src.length];
+ * System.arraycopy(src, 0, dest, 0, src.length);
+ * elapsedTime = System.nanoTime() - startTime;
+ * }
+ * System.out.println(state.summaryLine());
+ * }
+ *
+ * Or use the PerfManualStatusReporter TestRule.
+ *
+ * Make sure that the overhead of checking the clock does not noticeably affect the results.
+ */
+public final class ManualBenchmarkState {
+ private static final String TAG = ManualBenchmarkState.class.getSimpleName();
+
+ // TODO: Tune these values.
+ // warm-up for duration
+ private static final long WARMUP_DURATION_NS = TimeUnit.SECONDS.toNanos(5);
+ // minimum iterations to warm-up for
+ private static final int WARMUP_MIN_ITERATIONS = 8;
+
+ // target testing for duration
+ private static final long TARGET_TEST_DURATION_NS = TimeUnit.SECONDS.toNanos(16);
+ private static final int MAX_TEST_ITERATIONS = 1000000;
+ private static final int MIN_TEST_ITERATIONS = 10;
+
+ private static final int NOT_STARTED = 0; // The benchmark has not started yet.
+ private static final int WARMUP = 1; // The benchmark is warming up.
+ private static final int RUNNING = 2; // The benchmark is running.
+ private static final int FINISHED = 3; // The benchmark has stopped.
+
+ private int mState = NOT_STARTED; // Current benchmark state.
+
+ private long mWarmupStartTime = 0;
+ private int mWarmupIterations = 0;
+
+ private int mMaxIterations = 0;
+
+ // Individual duration in nano seconds.
+ private ArrayList<Long> mResults = new ArrayList<>();
+
+ // Statistics. These values will be filled when the benchmark has finished.
+ // The computation needs double precision, but long int is fine for final reporting.
+ private Stats mStats;
+
+ private void beginBenchmark(long warmupDuration, int iterations) {
+ mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
+ mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
+ Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
+ mState = RUNNING;
+ }
+
+ /**
+ * Judges whether the benchmark needs more samples.
+ *
+ * For the usage, see class comment.
+ */
+ public boolean keepRunning(long duration) {
+ if (duration < 0) {
+ throw new RuntimeException("duration is negative: " + duration);
+ }
+ switch (mState) {
+ case NOT_STARTED:
+ mState = WARMUP;
+ mWarmupStartTime = System.nanoTime();
+ return true;
+ case WARMUP: {
+ final long timeSinceStartingWarmup = System.nanoTime() - mWarmupStartTime;
+ ++mWarmupIterations;
+ if (mWarmupIterations >= WARMUP_MIN_ITERATIONS
+ && timeSinceStartingWarmup >= WARMUP_DURATION_NS) {
+ beginBenchmark(timeSinceStartingWarmup, mWarmupIterations);
+ }
+ return true;
+ }
+ case RUNNING: {
+ mResults.add(duration);
+ final boolean keepRunning = mResults.size() < mMaxIterations;
+ if (!keepRunning) {
+ mStats = new Stats(mResults);
+ mState = FINISHED;
+ }
+ return keepRunning;
+ }
+ case FINISHED:
+ throw new IllegalStateException("The benchmark has finished.");
+ default:
+ throw new IllegalStateException("The benchmark is in an unknown state.");
+ }
+ }
+
+ private String summaryLine() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Summary: ");
+ sb.append("median=").append(mStats.getMedian()).append("ns, ");
+ sb.append("mean=").append(mStats.getMean()).append("ns, ");
+ sb.append("min=").append(mStats.getMin()).append("ns, ");
+ sb.append("max=").append(mStats.getMax()).append("ns, ");
+ sb.append("sigma=").append(mStats.getStandardDeviation()).append(", ");
+ sb.append("iteration=").append(mResults.size()).append(", ");
+ sb.append("values=").append(mResults.toString());
+ return sb.toString();
+ }
+
+ public void sendFullStatusReport(Instrumentation instrumentation, String key) {
+ if (mState != FINISHED) {
+ throw new IllegalStateException("The benchmark hasn't finished");
+ }
+ Log.i(TAG, key + summaryLine());
+ final Bundle status = new Bundle();
+ status.putLong(key + "_median", mStats.getMedian());
+ status.putLong(key + "_mean", (long) mStats.getMean());
+ status.putLong(key + "_stddev", (long) mStats.getStandardDeviation());
+ instrumentation.sendStatus(Activity.RESULT_OK, status);
+ }
+}
+
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java b/apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java
new file mode 100644
index 000000000000..0de6f1d944ff
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java
@@ -0,0 +1,73 @@
+/*
+ * 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 android.perftests.utils;
+
+import android.support.test.InstrumentationRegistry;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Use this rule to make sure we report the status after the test success.
+ *
+ * <code>
+ *
+ * @Rule public PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter();
+ * @Test public void functionName() {
+ * ManualBenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ *
+ * int[] src = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ * long elapsedTime = 0;
+ * while (state.keepRunning(elapsedTime)) {
+ * long startTime = System.nanoTime();
+ * int[] dest = new int[src.length];
+ * System.arraycopy(src, 0, dest, 0, src.length);
+ * elapsedTime = System.nanoTime() - startTime;
+ * }
+ * }
+ * </code>
+ *
+ * When test succeeded, the status report will use the key as
+ * "functionName_*"
+ */
+
+public class PerfManualStatusReporter implements TestRule {
+ private final ManualBenchmarkState mState;
+
+ public PerfManualStatusReporter() {
+ mState = new ManualBenchmarkState();
+ }
+
+ public ManualBenchmarkState getBenchmarkState() {
+ return mState;
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ base.evaluate();
+
+ mState.sendFullStatusReport(InstrumentationRegistry.getInstrumentation(),
+ description.getMethodName());
+ }
+ };
+ }
+}
+
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java b/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java
new file mode 100644
index 000000000000..acc44a8febfc
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java
@@ -0,0 +1,76 @@
+/*
+ * 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 android.perftests.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Stats {
+ private long mMedian, mMin, mMax;
+ private double mMean, mStandardDeviation;
+
+ /* Calculate stats in constructor. */
+ public Stats(List<Long> values) {
+ // make a copy since we're modifying it
+ values = new ArrayList<>(values);
+ final int size = values.size();
+ if (size < 2) {
+ throw new IllegalArgumentException("At least two results are necessary.");
+ }
+
+ Collections.sort(values);
+
+ mMedian = size % 2 == 0 ? (values.get(size / 2) + values.get(size / 2 - 1)) / 2 :
+ values.get(size / 2);
+
+ mMin = values.get(0);
+ mMax = values.get(values.size() - 1);
+
+ for (int i = 0; i < size; ++i) {
+ long result = values.get(i);
+ mMean += result;
+ }
+ mMean /= (double) size;
+
+ for (int i = 0; i < size; ++i) {
+ final double tmp = values.get(i) - mMean;
+ mStandardDeviation += tmp * tmp;
+ }
+ mStandardDeviation = Math.sqrt(mStandardDeviation / (double) (size - 1));
+ }
+
+ public double getMean() {
+ return mMean;
+ }
+
+ public long getMedian() {
+ return mMedian;
+ }
+
+ public long getMax() {
+ return mMax;
+ }
+
+ public long getMin() {
+ return mMin;
+ }
+
+ public double getStandardDeviation() {
+ return mStandardDeviation;
+ }
+}
diff --git a/tests/ActivityManagerPerfTests/README.txt b/tests/ActivityManagerPerfTests/README.txt
new file mode 100644
index 000000000000..77e0e90623fa
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/README.txt
@@ -0,0 +1,34 @@
+ActivityManagerPerfTests
+
+Performance tests for various ActivityManager components, e.g. Services, Broadcasts
+
+Command to run tests (not working yet, atest seems buggy)
+* atest .../frameworks/base/tests/ActivityManagerPerfTests
+* m ActivityManagerPerfTests ActivityManagerPerfTestsTestApp && \
+ adb install $OUT/data/app/ActivityManagerPerfTests/ActivityManagerPerfTests.apk && \
+ adb install $OUT/data/app/ActivityManagerPerfTestsTestApp/ActivityManagerPerfTestsTestApp.apk && \
+ adb shell am instrument -w \
+ com.android.frameworks.perftests.amtests/android.support.test.runner.AndroidJUnitRunner
+
+Overview
+* The numbers we are trying to measure are end-to-end numbers
+ * For example, the time it takes from sending an Intent to start a Service
+ to the time the Service runs its callbacks
+* System.nanoTime() is monotonic and consistent between processes, so we use that for measuring time
+* To make sure the test app is running, we start an Activity
+* If the test app is involved, it will measure the time and send it back to the instrumentation test
+ * The time is sent back through a Binder interface in the Intent
+ * Each sent time is tagged with an id since there can be multiple events that send back a time
+ * For example, one is sent when the Activity is started, and another could be sent when a
+ Broadcast is received
+
+Structure
+* tests
+ * Instrumentation test which runs the various performance tests and reports the results
+
+* test-app
+ * Target package which contains the Services, BroadcastReceivers, etc. to test against
+ * Sends the time it measures back to the test package
+
+* utils
+ * Utilities that both the instrumentation test and test app can use
diff --git a/tests/ActivityManagerPerfTests/test-app/Android.mk b/tests/ActivityManagerPerfTests/test-app/Android.mk
new file mode 100644
index 000000000000..b0a5db7a3134
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/test-app/Android.mk
@@ -0,0 +1,28 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ ActivityManagerPerfTestsUtils
+
+LOCAL_PACKAGE_NAME := ActivityManagerPerfTestsTestApp
+
+include $(BUILD_PACKAGE)
diff --git a/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
new file mode 100644
index 000000000000..71451101ac59
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/test-app/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.perftests.amteststestapp">
+ <application android:name=".TestApplication">
+ <activity android:name=".TestActivity" android:exported="true"/>
+ <receiver
+ android:name=".TestBroadcastReceiver"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="com.android.frameworks.perftests.ACTION_BROADCAST_MANIFEST_RECEIVE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </receiver>
+ </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
new file mode 100644
index 000000000000..7ea9ba3d05ee
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * 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.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.perftests.am.util.Constants;
+import com.android.frameworks.perftests.am.util.Utils;
+
+public class TestActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Utils.sendTime(getIntent(), Constants.TYPE_ACTIVITY_CREATED);
+ }
+}
diff --git a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestApplication.java b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestApplication.java
new file mode 100644
index 000000000000..e26ffcde7c07
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestApplication.java
@@ -0,0 +1,51 @@
+/*
+ * 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.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+
+import com.android.frameworks.perftests.am.util.Constants;
+import com.android.frameworks.perftests.am.util.Utils;
+
+public class TestApplication extends Application {
+ private static final String TAG = TestApplication.class.getSimpleName();
+
+ @Override
+ public void onCreate() {
+ createRegisteredReceiver();
+
+ super.onCreate();
+ }
+
+ // Create registered BroadcastReceiver
+ private void createRegisteredReceiver() {
+ BroadcastReceiver registered = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "RegisteredReceiver.onReceive");
+ Utils.sendTime(intent, Constants.TYPE_BROADCAST_RECEIVE);
+ }
+ };
+ IntentFilter intentFilter = new IntentFilter(Constants.ACTION_BROADCAST_REGISTERED_RECEIVE);
+ registerReceiver(registered, intentFilter);
+ }
+}
diff --git a/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestBroadcastReceiver.java b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestBroadcastReceiver.java
new file mode 100644
index 000000000000..336bf9d1fab6
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/test-app/src/com/android/frameworks/perftests/amteststestapp/TestBroadcastReceiver.java
@@ -0,0 +1,32 @@
+/*
+ * 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.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.frameworks.perftests.am.util.Constants;
+import com.android.frameworks.perftests.am.util.Utils;
+
+public class TestBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Utils.sendTime(intent, Constants.TYPE_BROADCAST_RECEIVE);
+ }
+}
diff --git a/tests/ActivityManagerPerfTests/tests/Android.mk b/tests/ActivityManagerPerfTests/tests/Android.mk
new file mode 100644
index 000000000000..daf603d6a63f
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/Android.mk
@@ -0,0 +1,33 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ apct-perftests-utils \
+ ActivityManagerPerfTestsUtils
+
+LOCAL_PACKAGE_NAME := ActivityManagerPerfTests
+
+# For android.permission.FORCE_STOP_PACKAGES permission
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml b/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
new file mode 100644
index 000000000000..4e194c66354e
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.perftests.amtests">
+ <uses-permission android:name="android.permission.DUMP" />
+ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.perftests.amtests"/>
+</manifest>
diff --git a/tests/ActivityManagerPerfTests/tests/AndroidTest.xml b/tests/ActivityManagerPerfTests/tests/AndroidTest.xml
new file mode 100644
index 000000000000..ffb5404d7d94
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs ActivityManager Performance Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="ActivityManagerPerfTests.apk"/>
+ <option name="test-file-name" value="ActivityManagerPerfTestsTestApp.apk"/>
+ <option name="cleanup-apks" value="true"/>
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="ActivityManagerPerfTests"/>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.frameworks.perftests.amtests"/>
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration> \ No newline at end of file
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
new file mode 100644
index 000000000000..661abe91337f
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.Context;
+import android.content.Intent;
+import android.perftests.utils.ManualBenchmarkState;
+import android.perftests.utils.PerfManualStatusReporter;
+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.Before;
+import org.junit.Rule;
+
+import java.util.function.LongSupplier;
+
+public class BasePerfTest {
+ private static final String TAG = BasePerfTest.class.getSimpleName();
+
+ private TimeReceiver mTimeReceiver;
+
+ @Rule
+ public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
+
+ protected Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mTimeReceiver = new TimeReceiver();
+ }
+
+ @After
+ public void tearDown() {
+ TargetPackageUtils.killTargetPackage(mContext);
+ }
+
+ protected Intent createIntent(String action) {
+ final Intent intent = new Intent(action);
+ intent.addFlags(
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ intent.putExtras(mTimeReceiver.createReceiveTimeExtraBinder());
+ return intent;
+ }
+
+ private void setUpIteration() {
+ mTimeReceiver.clear();
+ TargetPackageUtils.killTargetPackage(mContext);
+ }
+
+ protected void startTargetPackage() {
+ TargetPackageUtils.startTargetPackage(mContext, mTimeReceiver);
+ }
+
+ protected long getReceivedTimeNs(String type) {
+ return mTimeReceiver.getReceivedTimeNs(type);
+ }
+
+ protected void runPerfFunction(LongSupplier func) {
+ final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
+ long elapsedTimeNs = 0;
+ while (benchmarkState.keepRunning(elapsedTimeNs)) {
+ setUpIteration();
+ elapsedTimeNs = func.getAsLong();
+ }
+ }
+}
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
new file mode 100644
index 000000000000..795f49866f84
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.Intent;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.perftests.am.util.Constants;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class BroadcastPerfTest extends BasePerfTest {
+ @Test
+ public void manifestBroadcastRunning() {
+ runPerfFunction(() -> {
+ startTargetPackage();
+
+ final Intent intent = createIntent(Constants.ACTION_BROADCAST_MANIFEST_RECEIVE);
+
+ final long startTime = System.nanoTime();
+
+ mContext.sendBroadcast(intent);
+
+ final long endTime = getReceivedTimeNs(Constants.TYPE_BROADCAST_RECEIVE);
+
+ return endTime - startTime;
+ });
+ }
+
+ @Test
+ public void manifestBroadcastNotRunning() {
+ runPerfFunction(() -> {
+ final Intent intent = createIntent(Constants.ACTION_BROADCAST_MANIFEST_RECEIVE);
+
+ final long startTime = System.nanoTime();
+
+ mContext.sendBroadcast(intent);
+
+ final long endTime = getReceivedTimeNs(Constants.TYPE_BROADCAST_RECEIVE);
+
+ return endTime - startTime;
+ });
+ }
+
+ @Test
+ public void registeredBroadcast() {
+ runPerfFunction(() -> {
+ startTargetPackage();
+
+ final Intent intent = createIntent(Constants.ACTION_BROADCAST_REGISTERED_RECEIVE);
+
+ final long startTime = System.nanoTime();
+
+ mContext.sendBroadcast(intent);
+
+ final long endTime = getReceivedTimeNs(Constants.TYPE_BROADCAST_RECEIVE);
+
+ return endTime - startTime;
+ });
+ }
+}
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
new file mode 100644
index 000000000000..c86714156c2b
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TargetPackageUtils.java
@@ -0,0 +1,93 @@
+/*
+ * 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.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+
+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";
+
+ private static final long WAIT_TIME_MS = 100L;
+
+ // Cache for test app's uid, so we only have to query it once.
+ private static int sTestAppUid = -1;
+
+ /**
+ * Kills the test package synchronously.
+ */
+ public static void killTargetPackage(Context context) {
+ ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+ activityManager.forceStopPackage(PACKAGE_NAME);
+ while (targetPackageIsRunning(context)) {
+ sleep();
+ }
+
+ Utils.drainBroadcastQueue();
+ }
+
+ /**
+ * 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
+ 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);
+
+ while (!targetPackageIsRunning(context)) {
+ sleep();
+ }
+ // make sure Application has run
+ timeReceiver.getReceivedTimeNs(Constants.TYPE_ACTIVITY_CREATED);
+ Utils.drainBroadcastQueue();
+ }
+
+ private static boolean targetPackageIsRunning(Context context) {
+ final int uid = getTestAppUid(context);
+ final String result = Utils.runShellCommand(
+ String.format("cmd activity get-uid-state %d", uid));
+ 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();
+ try {
+ sTestAppUid = pm.getPackageUid(PACKAGE_NAME, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return sTestAppUid;
+ }
+
+}
+
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
new file mode 100644
index 000000000000..9cf6ee7c91d5
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/util/TimeReceiver.java
@@ -0,0 +1,107 @@
+/*
+ * 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.RemoteException;
+import android.util.Log;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * TimeReceiver will listen for any messages containing a timestamp by starting a BroadcastReceiver
+ * which listens for Intents with the SendTime.ACTION_SEND_TIME action.
+ */
+public class TimeReceiver {
+ private static final String TAG = TimeReceiver.class.getSimpleName();
+ private static final long DEFAULT_RECEIVE_TIME_TIMEOUT_MILLIS = 10000L;
+
+ private BlockingQueue<ReceivedMessage> mQueue = new LinkedBlockingQueue<>();
+
+ private static class ReceivedMessage {
+ private final String mReceivedMessageType;
+ private final long mReceivedTimeNs;
+
+ public ReceivedMessage(String receivedMessageType, long receivedTimeNs) {
+ mReceivedMessageType = receivedMessageType;
+ mReceivedTimeNs = receivedTimeNs;
+ }
+ }
+
+ 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));
+ }
+ });
+ return extras;
+ }
+
+ public long getReceivedTimeNs(String type) {
+ return getReceivedTimeNs(type, DEFAULT_RECEIVE_TIME_TIMEOUT_MILLIS);
+ }
+
+ /**
+ * Returns a received timestamp with the given type tag. Will throw away any messages with a
+ * different type tag. If it times out, a RuntimeException is thrown.
+ */
+ public long getReceivedTimeNs(String type, long timeoutMs) {
+ ReceivedMessage message;
+ long endTimeNs = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMs);
+ do {
+ long curTimeNs = System.nanoTime();
+ if (curTimeNs > endTimeNs) {
+ throw new RuntimeException("Timed out when listening for a time: " + type);
+ }
+ try {
+ Log.i(TAG, "waiting for message " + type);
+ message = mQueue.poll(endTimeNs - curTimeNs, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ if (message == null) {
+ throw new RuntimeException("Timed out when listening for a time: " + type);
+ }
+ Log.i(TAG, "got message " + message.mReceivedMessageType);
+ if (!type.equals(message.mReceivedMessageType)) {
+ Log.i(TAG, String.format("Expected type \"%s\", got \"%s\" (%d), skipping", type,
+ message.mReceivedMessageType, message.mReceivedTimeNs));
+ }
+ } while (!type.equals(message.mReceivedMessageType));
+ return message.mReceivedTimeNs;
+ }
+
+ /**
+ * Clears the message queue.
+ */
+ public void clear() {
+ mQueue.clear();
+ }
+}
diff --git a/tests/ActivityManagerPerfTests/utils/Android.mk b/tests/ActivityManagerPerfTests/utils/Android.mk
new file mode 100644
index 000000000000..7276e37afc7a
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/utils/Android.mk
@@ -0,0 +1,31 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ junit \
+ ub-uiautomator
+
+LOCAL_MODULE := ActivityManagerPerfTestsUtils
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
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
new file mode 100644
index 000000000000..6528028ee1a1
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Constants.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+public class Constants {
+ public static final String TYPE_ACTIVITY_CREATED = "activity_create";
+ public static final String TYPE_BROADCAST_RECEIVE = "broadcast_receive";
+
+ public static final String ACTION_BROADCAST_MANIFEST_RECEIVE =
+ "com.android.frameworks.perftests.ACTION_BROADCAST_MANIFEST_RECEIVE";
+ public static final String ACTION_BROADCAST_REGISTERED_RECEIVE =
+ "com.android.frameworks.perftests.ACTION_BROADCAST_REGISTERED_RECEIVE";
+
+ public static final String EXTRA_RECEIVER_CALLBACK = "receiver_callback_binder";
+}
diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl
new file mode 100644
index 000000000000..b43d49a1b8e4
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl
@@ -0,0 +1,21 @@
+/*
+ * 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;
+
+interface ITimeReceiverCallback {
+ void sendTime(String type, long timeNs);
+} \ No newline at end of file
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
new file mode 100644
index 000000000000..493d8cdd0803
--- /dev/null
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
@@ -0,0 +1,59 @@
+/*
+ * 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.content.Intent;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Log;
+
+import java.io.IOException;
+
+public class Utils {
+ private static final String TAG = "AmPerfTestsUtils";
+
+ public static void drainBroadcastQueue() {
+ runShellCommand("am wait-for-broadcast-idle");
+ }
+
+ /**
+ * Runs the command and returns the stdout.
+ */
+ public static String runShellCommand(String cmd) {
+ try {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Sends the current time in a message with the given type so TimeReceiver can receive it.
+ */
+ public static void sendTime(Intent intent, String type) {
+ final long time = System.nanoTime();
+ final ITimeReceiverCallback sendTimeBinder = ITimeReceiverCallback.Stub.asInterface(
+ intent.getExtras().getBinder(Constants.EXTRA_RECEIVER_CALLBACK));
+ try {
+ sendTimeBinder.sendTime(type, time);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+}