summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app-perf-tests/Android.mk18
-rw-r--r--app-perf-tests/AndroidManifest.xml18
-rw-r--r--app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java102
-rw-r--r--app-perf-tests/src/com/android/documentsui/LauncherActivity.java64
-rw-r--r--src/com/android/documentsui/BaseActivity.java44
-rw-r--r--src/com/android/documentsui/Shared.java5
6 files changed, 250 insertions, 1 deletions
diff --git a/app-perf-tests/Android.mk b/app-perf-tests/Android.mk
new file mode 100644
index 000000000..3f12906b7
--- /dev/null
+++ b/app-perf-tests/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
+
+LOCAL_PACKAGE_NAME := DocumentsUIAppPerfTests
+LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/app-perf-tests/AndroidManifest.xml b/app-perf-tests/AndroidManifest.xml
new file mode 100644
index 000000000..1c3ed80ad
--- /dev/null
+++ b/app-perf-tests/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.documentsui.appperftests">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <activity
+ android:name="com.android.documentsui.LauncherActivity" />
+ </application>
+
+ <!-- This package instrumentates itself, so the DocumentsUI process can be killed without
+ killing the testing package. -->
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.documentsui.appperftests"
+ android:label="App performance tests for DocumentsUI" />
+
+</manifest>
diff --git a/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
new file mode 100644
index 000000000..d6e8a96f3
--- /dev/null
+++ b/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 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.documentsui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.support.test.uiautomator.UiDevice;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+@LargeTest
+public class FilesAppPerfTest extends InstrumentationTestCase {
+
+ // Keys used to report metrics to APCT.
+ private static final String KEY_FILES_COLD_START_PERFORMANCE_MEDIAN =
+ "files-cold-start-performance-median";
+ private static final String KEY_FILES_WARM_START_PERFORMANCE_MEDIAN =
+ "files-warm-start-performance-median";
+
+ private static final String TARGET_PACKAGE = "com.android.documentsui";
+
+ private static final int NUM_MEASUREMENTS = 10;
+
+ private LauncherActivity mActivity;
+ private UiDevice mDevice;
+
+ @Override
+ public void setUp() {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ }
+
+ public void testFilesColdStartPerformance() throws Exception {
+ runFilesStartPerformanceTest(true);
+ }
+
+ public void testFilesWarmStartPerformance() throws Exception {
+ runFilesStartPerformanceTest(false);
+ }
+
+ public void runFilesStartPerformanceTest(boolean cold) throws Exception {
+ long[] measurements = new long[NUM_MEASUREMENTS];
+ for (int i = 0; i < NUM_MEASUREMENTS; i++) {
+ if (cold) {
+ // Kill all providers, as well as DocumentsUI to measure a cold start.
+ killProviders();
+ mDevice.executeShellCommand("am force-stop " + TARGET_PACKAGE);
+ }
+ mDevice.waitForIdle();
+
+ LauncherActivity.testCaseLatch = new CountDownLatch(1);
+ mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
+ LauncherActivity.class, null);
+ LauncherActivity.testCaseLatch.await();
+ measurements[i] = LauncherActivity.measurement;
+ }
+
+ reportMetrics(cold ? KEY_FILES_COLD_START_PERFORMANCE_MEDIAN
+ : KEY_FILES_WARM_START_PERFORMANCE_MEDIAN, measurements);
+ }
+
+ private void reportMetrics(String key, long[] measurements) {
+ final Bundle status = new Bundle();
+ Arrays.sort(measurements);
+ final long median = measurements[NUM_MEASUREMENTS / 2 - 1];
+ status.putDouble(key, median);
+
+ getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+ }
+
+ private void killProviders() throws Exception {
+ final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+ final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+ final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0);
+ for (ResolveInfo info : providers) {
+ final String packageName = info.providerInfo.packageName;
+ mDevice.executeShellCommand("am force-stop " + packageName);
+ }
+ }
+}
diff --git a/app-perf-tests/src/com/android/documentsui/LauncherActivity.java b/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
new file mode 100644
index 000000000..21fc52e00
--- /dev/null
+++ b/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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.documentsui;
+
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+
+public class LauncherActivity extends Activity {
+ private static final String TARGET_PACKAGE = "com.android.documentsui";
+ private static final int BENCHMARK_REQUEST_CODE = 1986;
+
+ public static CountDownLatch testCaseLatch = null;
+ public static long measurement = -1;
+
+ private long mStartTime = -1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ new Handler().post(new Runnable() {
+ @Override public void run() {
+ final Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT");
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.putExtra(EXTRA_BENCHMARK, true);
+ intent.setType("*/*");
+
+ mStartTime = System.currentTimeMillis();
+ startActivityForResult(intent, BENCHMARK_REQUEST_CODE);
+ }
+ });
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == BENCHMARK_REQUEST_CODE) {
+ measurement = System.currentTimeMillis() - mStartTime;
+ testCaseLatch.countDown();
+ finish();
+ }
+ }
+}
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index 1a8ce18ce..b5f8d64de 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -17,6 +17,7 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
import static com.android.documentsui.State.MODE_GRID;
import android.app.Activity;
@@ -30,6 +31,9 @@ import android.content.pm.ProviderInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.MessageQueue;
+import android.os.MessageQueue.IdleHandler;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.support.annotation.CallSuper;
@@ -60,6 +64,8 @@ import java.util.concurrent.Executor;
public abstract class BaseActivity extends Activity
implements SearchManagerListener, NavigationView.Environment {
+ private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests";
+
State mState;
RootsCache mRoots;
SearchViewManager mSearchManager;
@@ -92,11 +98,20 @@ public abstract class BaseActivity extends Activity
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ final Intent intent = getIntent();
+
+ // If startup benchmark is requested by a whitelisted testing package, then close the
+ // activity once idle, and notify the testing activity.
+ if (intent.getBooleanExtra(EXTRA_BENCHMARK, false) &&
+ BENCHMARK_TESTING_PACKAGE.equals(getCallingPackage())) {
+ closeOnIdleForTesting();
+ }
+
setContentView(mLayoutId);
mDrawer = DrawerController.create(this);
mState = getState(icicle);
- Metrics.logActivityLaunch(this, mState, getIntent());
+ Metrics.logActivityLaunch(this, mState, intent);
mRoots = DocumentsApplication.getRootsCache(this);
@@ -668,6 +683,33 @@ public abstract class BaseActivity extends Activity
}
}
+ /**
+ * Closes the activity when it's idle. Used only for tests.
+ */
+ private void closeOnIdleForTesting() {
+ addEventListener(new EventListener() {
+ @Override
+ public void onDirectoryNavigated(Uri uri) {
+ }
+
+ @Override
+ public void onDirectoryLoaded(Uri uri) {
+ getMainLooper().getQueue().addIdleHandler(new IdleHandler() {
+ @Override
+ public boolean queueIdle() {
+ setResult(RESULT_OK);
+ finish();
+ return false;
+ }
+ });
+ new Handler().post(new Runnable() {
+ @Override public void run() {
+ }
+ });
+ }
+ });
+ }
+
private static final class HandleRootsChangedTask
extends PairedTask<BaseActivity, RootInfo, RootInfo> {
DocumentInfo mHome;
diff --git a/src/com/android/documentsui/Shared.java b/src/com/android/documentsui/Shared.java
index b53942106..1fbf0440e 100644
--- a/src/com/android/documentsui/Shared.java
+++ b/src/com/android/documentsui/Shared.java
@@ -86,6 +86,11 @@ public final class Shared {
*/
public static final String EXTRA_IGNORE_STATE = "ignoreState";
+ /**
+ * Extra for an Intent for enabling performance benchmark. Used only by tests.
+ */
+ public static final String EXTRA_BENCHMARK = "com.android.documentsui.benchmark";
+
private static final Collator sCollator;
static {