summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMaxim Siniavine <siniavine@google.com>2012-10-02 15:56:03 -0700
committerMaxim Siniavine <siniavine@google.com>2012-11-20 18:01:55 -0800
commitf58e5b6cdcecee6184784b3a6ac33f60341de170 (patch)
tree1559e7a690c4dabcff9a456affa6ee0a23a3400b /tests
parent89ac38bf70bb21e34c8c29b96e6316343ee46e87 (diff)
downloadframeworks_base-f58e5b6cdcecee6184784b3a6ac33f60341de170.zip
frameworks_base-f58e5b6cdcecee6184784b3a6ac33f60341de170.tar.gz
frameworks_base-f58e5b6cdcecee6184784b3a6ac33f60341de170.tar.bz2
Added app launch test.
The test will start each app and report the time it takes for the app to start in milliseconds. Change-Id: I974ac36f70f0d982aa01e46824fe138eb641d680
Diffstat (limited to 'tests')
-rw-r--r--tests/AppLaunch/Android.mk17
-rw-r--r--tests/AppLaunch/AndroidManifest.xml13
-rw-r--r--tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java216
3 files changed, 246 insertions, 0 deletions
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
new file mode 100644
index 0000000..c0560fd
--- /dev/null
+++ b/tests/AppLaunch/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := AppLaunch
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file
diff --git a/tests/AppLaunch/AndroidManifest.xml b/tests/AppLaunch/AndroidManifest.xml
new file mode 100644
index 0000000..ac6760b
--- /dev/null
+++ b/tests/AppLaunch/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.applaunch"
+ android:sharedUserId="android.uid.system" >
+ <instrumentation android:label="Measure app start up time"
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.tests.applaunch" />
+
+ <application android:label="App Launch Test">
+ <uses-library android:name="android.test.runner" />
+ </application>
+</manifest> \ No newline at end of file
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
new file mode 100644
index 0000000..e9374e0
--- /dev/null
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2012 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.tests.applaunch;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.test.InstrumentationTestCase;
+import android.test.InstrumentationTestRunner;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test is intended to measure the time it takes for the apps to start.
+ * Names of the applications are passed in command line, and the
+ * test starts each application, and reports the start up time in milliseconds.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class AppLaunch extends InstrumentationTestCase {
+
+ private static final int JOIN_TIMEOUT = 10000;
+ private static final String TAG = "AppLaunch";
+ private static final String KEY_APPS = "apps";
+
+ private Map<String, Intent> mNameToIntent;
+ private Map<String, String> mNameToProcess;
+ private Map<String, String> mNameToResultKey;
+
+ private IActivityManager mAm;
+
+ public void testMeasureStartUpTime() throws RemoteException {
+ InstrumentationTestRunner instrumentation =
+ (InstrumentationTestRunner)getInstrumentation();
+ Bundle args = instrumentation.getBundle();
+ mAm = ActivityManagerNative.getDefault();
+
+ createMappings();
+ parseArgs(args);
+
+ Bundle results = new Bundle();
+ for (String app : mNameToResultKey.keySet()) {
+ try {
+ startApp(app, results);
+ closeApp();
+ } catch (NameNotFoundException e) {
+ Log.i(TAG, "Application " + app + " not found");
+ }
+
+ }
+ instrumentation.sendStatus(0, results);
+ }
+
+ private void parseArgs(Bundle args) {
+ mNameToResultKey = new HashMap<String, String>();
+ String appList = args.getString(KEY_APPS);
+
+ if (appList == null)
+ return;
+
+ String appNames[] = appList.split("\\|");
+ for (String pair : appNames) {
+ String[] parts = pair.split("\\^");
+ if (parts.length != 2) {
+ Log.e(TAG, "The apps key is incorectly formatted");
+ fail();
+ }
+
+ mNameToResultKey.put(parts[0], parts[1]);
+ }
+ }
+
+ private void createMappings() {
+ mNameToIntent = new HashMap<String, Intent>();
+ mNameToProcess = new HashMap<String, String>();
+
+ PackageManager pm = getInstrumentation().getContext()
+ .getPackageManager();
+ Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+ intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+ List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+ if (ris == null || ris.isEmpty()) {
+ Log.i(TAG, "Could not find any apps");
+ } else {
+ for (ResolveInfo ri : ris) {
+ Intent startIntent = new Intent(intentToResolve);
+ startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ startIntent.setClassName(ri.activityInfo.packageName,
+ ri.activityInfo.name);
+ mNameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
+ mNameToProcess.put(ri.loadLabel(pm).toString(),
+ ri.activityInfo.processName);
+ }
+ }
+ }
+
+ private void startApp(String appName, Bundle results)
+ throws NameNotFoundException, RemoteException {
+ Log.i(TAG, "Starting " + appName);
+
+ Intent startIntent = mNameToIntent.get(appName);
+ AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
+ Thread t = new Thread(runnable);
+ long startTime = System.currentTimeMillis();
+ t.start();
+ try {
+ t.join(JOIN_TIMEOUT);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ if(t.isAlive() || (runnable.getResult() != null &&
+ runnable.getResult().result != ActivityManager.START_SUCCESS)) {
+ Log.w(TAG, "Assuming app " + appName + " crashed.");
+ reportError(appName, mNameToProcess.get(appName), results);
+ return;
+ }
+ long startUpTime = System.currentTimeMillis() - startTime;
+ results.putString(mNameToResultKey.get(appName), String.valueOf(startUpTime));
+ sleep(5000);
+ }
+
+ private void closeApp() {
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ getInstrumentation().getContext().startActivity(homeIntent);
+ sleep(3000);
+ }
+
+ private void sleep(int time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+
+ private void reportError(String appName, String processName, Bundle results) {
+ ActivityManager am = (ActivityManager) getInstrumentation()
+ .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+ if (crashes != null) {
+ for (ProcessErrorStateInfo crash : crashes) {
+ if (!crash.processName.equals(processName))
+ continue;
+
+ Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+ results.putString(mNameToResultKey.get(appName), crash.shortMsg);
+ return;
+ }
+ }
+
+ results.putString(mNameToResultKey.get(appName),
+ "Crashed for unknown reason");
+ Log.w(TAG, appName
+ + " not found in process list, most likely it is crashed");
+ }
+
+ private class AppLaunchRunnable implements Runnable {
+ private Intent mLaunchIntent;
+ private IActivityManager.WaitResult mResult;
+ public AppLaunchRunnable(Intent intent) {
+ mLaunchIntent = intent;
+ }
+
+ public IActivityManager.WaitResult getResult() {
+ return mResult;
+ }
+
+ public void run() {
+ try {
+ String mimeType = mLaunchIntent.getType();
+ if (mimeType == null && mLaunchIntent.getData() != null
+ && "content".equals(mLaunchIntent.getData().getScheme())) {
+ mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
+ UserHandle.USER_CURRENT);
+ }
+
+ mResult = mAm.startActivityAndWait(null, mLaunchIntent, mimeType,
+ null, null, 0, mLaunchIntent.getFlags(), null, null, null,
+ UserHandle.USER_CURRENT);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error launching app", e);
+ }
+ }
+ }
+}