AppLaunch.java revision 2861a89bed9066e206917c41357a5e589e8482cb
1f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine/* 232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu * Copyright (C) 2013 The Android Open Source Project 3f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * 4f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Licensed under the Apache License, Version 2.0 (the "License"); 5f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * you may not use this file except in compliance with the License. 6f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * You may obtain a copy of the License at 7f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * 8f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * http://www.apache.org/licenses/LICENSE-2.0 9f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * 10f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Unless required by applicable law or agreed to in writing, software 11f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * distributed under the License is distributed on an "AS IS" BASIS, 12f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * See the License for the specific language governing permissions and 14f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * limitations under the License. 15f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine */ 16f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavinepackage com.android.tests.applaunch; 17f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 186266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport android.accounts.Account; 196266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport android.accounts.AccountManager; 20f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManager; 21f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManager.ProcessErrorStateInfo; 22f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManagerNative; 23f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.IActivityManager; 2413f77349778fbe95d665542be6f05006879854e2Guang Zhuimport android.app.IActivityManager.WaitResult; 25f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.Context; 26f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.Intent; 27f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.PackageManager; 28f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.PackageManager.NameNotFoundException; 29f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.ResolveInfo; 30f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.Bundle; 31f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.RemoteException; 32f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.UserHandle; 33f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestCase; 34f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestRunner; 35f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.util.Log; 36f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 3732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhuimport java.util.HashMap; 386266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport java.util.HashSet; 39c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhuimport java.util.LinkedHashMap; 40f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.List; 41f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.Map; 426266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport java.util.Set; 43f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 44f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine/** 45f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * This test is intended to measure the time it takes for the apps to start. 46f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Names of the applications are passed in command line, and the 47f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * test starts each application, and reports the start up time in milliseconds. 48f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * The instrumentation expects the following key to be passed on the command line: 49f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * apps - A list of applications to start and their corresponding result keys 50f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * in the following format: 51f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * -e apps <app name>^<result key>|<app name>^<result key> 52f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine */ 53f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavinepublic class AppLaunch extends InstrumentationTestCase { 54f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 55f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private static final int JOIN_TIMEOUT = 10000; 5632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final String TAG = AppLaunch.class.getSimpleName(); 57f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private static final String KEY_APPS = "apps"; 5832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations"; 596266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // optional parameter: comma separated list of required account types before proceeding 606266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // with the app launch 616266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts"; 6232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 7500; //7.5s to allow app to idle 6332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches 6432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps 65f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 66f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, Intent> mNameToIntent; 67f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, String> mNameToProcess; 68f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, String> mNameToResultKey; 6932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private Map<String, Long> mNameToLaunchTime; 70f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private IActivityManager mAm; 7132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private int mLaunchIterations = 10; 7232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private Bundle mResult = new Bundle(); 736266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private Set<String> mRequiredAccounts; 74f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 7532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException { 76f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine InstrumentationTestRunner instrumentation = 77f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine (InstrumentationTestRunner)getInstrumentation(); 783a34d17412a5a304e39be1966a16627677d2136fSvetoslav Bundle args = instrumentation.getArguments(); 79f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mAm = ActivityManagerNative.getDefault(); 80f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 81f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine createMappings(); 82f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine parseArgs(args); 836266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu checkAccountSignIn(); 84f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 8532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // do initial app launch, without force stopping 86f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (String app : mNameToResultKey.keySet()) { 8732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu long launchTime = startApp(app, false); 882861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (launchTime <= 0) { 8932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(app, -1L); 9032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // simply pass the app if launch isn't successful 9132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // error should have already been logged by startApp 9232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 932861a89bed9066e206917c41357a5e589e8482cbGuang Zhu } else { 942861a89bed9066e206917c41357a5e589e8482cbGuang Zhu mNameToLaunchTime.put(app, launchTime); 9532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 9632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(INITIAL_LAUNCH_IDLE_TIMEOUT); 9732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu closeApp(app, false); 9832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 9932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 10032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // do the real app launch now 10132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (int i = 0; i < mLaunchIterations; i++) { 10232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (String app : mNameToResultKey.keySet()) { 1032861a89bed9066e206917c41357a5e589e8482cbGuang Zhu long prevLaunchTime = mNameToLaunchTime.get(app); 10432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu long launchTime = 0; 1052861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (prevLaunchTime < 0) { 10632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // skip if the app has previous failures 10732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 10832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 10932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu launchTime = startApp(app, true); 11032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (launchTime <= 0) { 11132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // if it fails once, skip the rest of the launches 11232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(app, -1L); 11332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 11432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 1152861a89bed9066e206917c41357a5e589e8482cbGuang Zhu // keep the min launch time 1162861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (launchTime < prevLaunchTime) { 1172861a89bed9066e206917c41357a5e589e8482cbGuang Zhu mNameToLaunchTime.put(app, launchTime); 1182861a89bed9066e206917c41357a5e589e8482cbGuang Zhu } 11932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(POST_LAUNCH_IDLE_TIMEOUT); 12032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu closeApp(app, true); 12132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 12232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 12332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 12432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (String app : mNameToResultKey.keySet()) { 1252861a89bed9066e206917c41357a5e589e8482cbGuang Zhu long launchTime = mNameToLaunchTime.get(app); 1262861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (launchTime != -1) { 1272861a89bed9066e206917c41357a5e589e8482cbGuang Zhu mResult.putLong(mNameToResultKey.get(app), launchTime); 128f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 129f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 13032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu instrumentation.sendStatus(0, mResult); 131f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 132f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 133f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void parseArgs(Bundle args) { 134c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToResultKey = new LinkedHashMap<String, String>(); 13532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime = new HashMap<String, Long>(); 13632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS); 13732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (launchIterations != null) { 13832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mLaunchIterations = Integer.parseInt(launchIterations); 13932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 140f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appList = args.getString(KEY_APPS); 141f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (appList == null) 142f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 143f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 144f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appNames[] = appList.split("\\|"); 145f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (String pair : appNames) { 146f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String[] parts = pair.split("\\^"); 147f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (parts.length != 2) { 148f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.e(TAG, "The apps key is incorectly formatted"); 149f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine fail(); 150f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 151f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 152f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mNameToResultKey.put(parts[0], parts[1]); 15332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(parts[0], 0L); 154f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 1556266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS); 1566266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (requiredAccounts != null) { 1576266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts = new HashSet<String>(); 1586266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String accountType : requiredAccounts.split(",")) { 1596266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.add(accountType); 1606266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 1616266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 162f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 163f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 164f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void createMappings() { 165c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToIntent = new LinkedHashMap<String, Intent>(); 166c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToProcess = new LinkedHashMap<String, String>(); 167f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 168f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine PackageManager pm = getInstrumentation().getContext() 169f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getPackageManager(); 170f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 171f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 172f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0); 173f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (ris == null || ris.isEmpty()) { 174f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Could not find any apps"); 175f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } else { 176f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ResolveInfo ri : ris) { 177f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = new Intent(intentToResolve); 178f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 179f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 180f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setClassName(ri.activityInfo.packageName, 181f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ri.activityInfo.name); 18232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String appName = ri.loadLabel(pm).toString(); 18332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (appName != null) { 18432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToIntent.put(appName, startIntent); 18532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToProcess.put(appName, ri.activityInfo.processName); 18632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 187f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 188f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 189f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 190f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 19132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private long startApp(String appName, boolean forceStopBeforeLaunch) 192f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine throws NameNotFoundException, RemoteException { 193f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Starting " + appName); 194f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 195f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = mNameToIntent.get(appName); 196c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu if (startIntent == null) { 197c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu Log.w(TAG, "App does not exist: " + appName); 19832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), "App does not exist"); 19932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return -1; 200c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu } 20132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch); 202f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread t = new Thread(runnable); 203f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.start(); 204f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 205f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.join(JOIN_TIMEOUT); 206f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 207f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 208f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 209c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu WaitResult result = runnable.getResult(); 21032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // report error if any of the following is true: 21132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * launch thread is alive 21232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * result is not null, but: 21332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * result is not START_SUCESS 21432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * or in case of no force stop, result is not TASK_TO_FRONT either 21532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (t.isAlive() || (result != null 21632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && ((result.result != ActivityManager.START_SUCCESS) 21732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && (!forceStopBeforeLaunch 21832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && result.result != ActivityManager.START_TASK_TO_FRONT)))) { 219f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, "Assuming app " + appName + " crashed."); 22032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu reportError(appName, mNameToProcess.get(appName)); 22132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return -1; 222f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 22332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return result.thisTime; 224f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 225f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 2266266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private void checkAccountSignIn() { 2276266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // ensure that the device has the required account types before starting test 2286266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // e.g. device must have a valid Google account sign in to measure a meaningful launch time 2296266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // for Gmail 2306266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts == null || mRequiredAccounts.isEmpty()) { 2316266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu return; 2326266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2336266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu final AccountManager am = 2346266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu (AccountManager) getInstrumentation().getTargetContext().getSystemService( 2356266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Context.ACCOUNT_SERVICE); 2366266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Account[] accounts = am.getAccounts(); 2376266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // use set here in case device has multiple accounts of the same type 2386266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Set<String> foundAccounts = new HashSet<String>(); 2396266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (Account account : accounts) { 2406266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.contains(account.type)) { 2416266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu foundAccounts.add(account.type); 2426266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2436266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2446266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // check if account type matches, if not, fail test with message on what account types 2456266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // are missing 2466266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.size() != foundAccounts.size()) { 2476266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.removeAll(foundAccounts); 2486266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu StringBuilder sb = new StringBuilder("Device missing these accounts:"); 2496266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String account : mRequiredAccounts) { 2506266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(' '); 2516266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(account); 2526266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2536266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu fail(sb.toString()); 2546266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2556266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2566266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu 25732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void closeApp(String appName, boolean forceStopApp) { 258f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent homeIntent = new Intent(Intent.ACTION_MAIN); 259f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.addCategory(Intent.CATEGORY_HOME); 260f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 261f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 262f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine getInstrumentation().getContext().startActivity(homeIntent); 26332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(POST_LAUNCH_IDLE_TIMEOUT); 26432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (forceStopApp) { 26532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Intent startIntent = mNameToIntent.get(appName); 26632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (startIntent != null) { 26732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String packageName = startIntent.getComponent().getPackageName(); 26832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu try { 26932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 27032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } catch (RemoteException e) { 27132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Log.w(TAG, "Error closing app", e); 27232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 27313f77349778fbe95d665542be6f05006879854e2Guang Zhu } 27413f77349778fbe95d665542be6f05006879854e2Guang Zhu } 275f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 276f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 277f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void sleep(int time) { 278f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 279f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread.sleep(time); 280f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 281f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 282f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 283f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 284f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 28532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void reportError(String appName, String processName) { 286f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ActivityManager am = (ActivityManager) getInstrumentation() 287f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getContext().getSystemService(Context.ACTIVITY_SERVICE); 288f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState(); 289f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (crashes != null) { 290f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ProcessErrorStateInfo crash : crashes) { 291f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (!crash.processName.equals(processName)) 292f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine continue; 293f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 294f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName + " crashed: " + crash.shortMsg); 29532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), crash.shortMsg); 296f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 297f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 298f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 299f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 30032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), 301f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine "Crashed for unknown reason"); 302f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName 303f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine + " not found in process list, most likely it is crashed"); 304f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 305f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 306f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private class AppLaunchRunnable implements Runnable { 307f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Intent mLaunchIntent; 308f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private IActivityManager.WaitResult mResult; 30932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private boolean mForceStopBeforeLaunch; 31032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu 31132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch) { 312f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mLaunchIntent = intent; 31332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mForceStopBeforeLaunch = forceStopBeforeLaunch; 314f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 315f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 316f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine public IActivityManager.WaitResult getResult() { 317f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return mResult; 318f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 319f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 320f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine public void run() { 321f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 322c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu String packageName = mLaunchIntent.getComponent().getPackageName(); 32332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (mForceStopBeforeLaunch) { 32432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 32532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 326f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String mimeType = mLaunchIntent.getType(); 327f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (mimeType == null && mLaunchIntent.getData() != null 328f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine && "content".equals(mLaunchIntent.getData().getScheme())) { 329f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(), 330f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine UserHandle.USER_CURRENT); 331f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 332f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 333f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mResult = mAm.startActivityAndWait(null, null, mLaunchIntent, mimeType, 334f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine null, null, 0, mLaunchIntent.getFlags(), null, null, null, 335f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine UserHandle.USER_CURRENT); 336f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (RemoteException e) { 337f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, "Error launching app", e); 338f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 339f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 340f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 341f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine} 342