AppLaunch.java revision 6fc955071afc4125a6a52bf7ab01129416ae0dbf
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; 25e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhuimport android.app.UiAutomation; 26f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.Context; 27f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.Intent; 28f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.PackageManager; 29f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.PackageManager.NameNotFoundException; 30f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.ResolveInfo; 31f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.Bundle; 32f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.RemoteException; 33f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.UserHandle; 34f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestCase; 35f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestRunner; 36f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.util.Log; 37f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 3832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhuimport java.util.HashMap; 396266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport java.util.HashSet; 40c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhuimport java.util.LinkedHashMap; 41f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.List; 42f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.Map; 436266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport java.util.Set; 44f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 45f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine/** 46f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * This test is intended to measure the time it takes for the apps to start. 47f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Names of the applications are passed in command line, and the 48f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * test starts each application, and reports the start up time in milliseconds. 49f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * The instrumentation expects the following key to be passed on the command line: 50f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * apps - A list of applications to start and their corresponding result keys 51f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * in the following format: 52f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * -e apps <app name>^<result key>|<app name>^<result key> 53f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine */ 54f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavinepublic class AppLaunch extends InstrumentationTestCase { 55f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 56f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private static final int JOIN_TIMEOUT = 10000; 5732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final String TAG = AppLaunch.class.getSimpleName(); 58f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private static final String KEY_APPS = "apps"; 5932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations"; 606266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // optional parameter: comma separated list of required account types before proceeding 616266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // with the app launch 626266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts"; 63349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz private static final String WEARABLE_ACTION_GOOGLE = 64349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz "com.google.android.wearable.action.GOOGLE"; 6532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 7500; //7.5s to allow app to idle 6632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches 6732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps 68f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 69f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, Intent> mNameToIntent; 70f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, String> mNameToProcess; 71f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, String> mNameToResultKey; 7232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private Map<String, Long> mNameToLaunchTime; 73f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private IActivityManager mAm; 7432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private int mLaunchIterations = 10; 7532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private Bundle mResult = new Bundle(); 766266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private Set<String> mRequiredAccounts; 77f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 78e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu @Override 79e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu protected void setUp() throws Exception { 80e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu super.setUp(); 81e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0); 82e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu } 83e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu 84e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu @Override 85e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu protected void tearDown() throws Exception { 86e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE); 87e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu super.tearDown(); 88e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu } 89e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu 9032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException { 91f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine InstrumentationTestRunner instrumentation = 92f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine (InstrumentationTestRunner)getInstrumentation(); 933a34d17412a5a304e39be1966a16627677d2136fSvetoslav Bundle args = instrumentation.getArguments(); 94f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mAm = ActivityManagerNative.getDefault(); 95f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 96f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine createMappings(); 97f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine parseArgs(args); 986266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu checkAccountSignIn(); 99f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 10032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // do initial app launch, without force stopping 101f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (String app : mNameToResultKey.keySet()) { 10232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu long launchTime = startApp(app, false); 1032861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (launchTime <= 0) { 10432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(app, -1L); 10532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // simply pass the app if launch isn't successful 10632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // error should have already been logged by startApp 10732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 1082861a89bed9066e206917c41357a5e589e8482cbGuang Zhu } else { 1092861a89bed9066e206917c41357a5e589e8482cbGuang Zhu mNameToLaunchTime.put(app, launchTime); 11032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 11132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(INITIAL_LAUNCH_IDLE_TIMEOUT); 11232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu closeApp(app, false); 11332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 11432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 11532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // do the real app launch now 11632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (int i = 0; i < mLaunchIterations; i++) { 11732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (String app : mNameToResultKey.keySet()) { 1182861a89bed9066e206917c41357a5e589e8482cbGuang Zhu long prevLaunchTime = mNameToLaunchTime.get(app); 11932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu long launchTime = 0; 1202861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (prevLaunchTime < 0) { 12132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // skip if the app has previous failures 12232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 12332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 12432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu launchTime = startApp(app, true); 12532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (launchTime <= 0) { 12632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // if it fails once, skip the rest of the launches 12732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(app, -1L); 12832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 12932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 1302861a89bed9066e206917c41357a5e589e8482cbGuang Zhu // keep the min launch time 1312861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (launchTime < prevLaunchTime) { 1322861a89bed9066e206917c41357a5e589e8482cbGuang Zhu mNameToLaunchTime.put(app, launchTime); 1332861a89bed9066e206917c41357a5e589e8482cbGuang Zhu } 13432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(POST_LAUNCH_IDLE_TIMEOUT); 13532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu closeApp(app, true); 13632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 13732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 13832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 13932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (String app : mNameToResultKey.keySet()) { 1402861a89bed9066e206917c41357a5e589e8482cbGuang Zhu long launchTime = mNameToLaunchTime.get(app); 1412861a89bed9066e206917c41357a5e589e8482cbGuang Zhu if (launchTime != -1) { 1422861a89bed9066e206917c41357a5e589e8482cbGuang Zhu mResult.putLong(mNameToResultKey.get(app), launchTime); 143f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 144f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 14532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu instrumentation.sendStatus(0, mResult); 146f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 147f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 148f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void parseArgs(Bundle args) { 149c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToResultKey = new LinkedHashMap<String, String>(); 15032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime = new HashMap<String, Long>(); 15132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS); 15232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (launchIterations != null) { 15332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mLaunchIterations = Integer.parseInt(launchIterations); 15432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 155f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appList = args.getString(KEY_APPS); 156f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (appList == null) 157f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 158f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 159f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appNames[] = appList.split("\\|"); 160f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (String pair : appNames) { 161f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String[] parts = pair.split("\\^"); 162f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (parts.length != 2) { 1636fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim Log.e(TAG, "The apps key is incorrectly formatted"); 164f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine fail(); 165f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 166f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 167f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mNameToResultKey.put(parts[0], parts[1]); 16832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(parts[0], 0L); 169f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 1706266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS); 1716266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (requiredAccounts != null) { 1726266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts = new HashSet<String>(); 1736266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String accountType : requiredAccounts.split(",")) { 1746266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.add(accountType); 1756266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 1766266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 177f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 178f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 1796fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim private boolean hasLeanback(Context context) { 1806fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); 1816fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim } 1826fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim 183f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void createMappings() { 184c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToIntent = new LinkedHashMap<String, Intent>(); 185c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToProcess = new LinkedHashMap<String, String>(); 186f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 187f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine PackageManager pm = getInstrumentation().getContext() 188f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getPackageManager(); 189f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 1906fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim intentToResolve.addCategory(hasLeanback(getInstrumentation().getContext()) ? 1916fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim Intent.CATEGORY_LEANBACK_LAUNCHER : 1926fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim Intent.CATEGORY_LAUNCHER); 193f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0); 194349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz resolveLoop(ris, intentToResolve, pm); 1956fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim // For Wear 196349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz intentToResolve = new Intent(WEARABLE_ACTION_GOOGLE); 197349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz ris = pm.queryIntentActivities(intentToResolve, 0); 198349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz resolveLoop(ris, intentToResolve, pm); 199349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz } 200349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz 201349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz private void resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm) { 202f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (ris == null || ris.isEmpty()) { 203f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Could not find any apps"); 204f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } else { 205f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ResolveInfo ri : ris) { 206f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = new Intent(intentToResolve); 207f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 208f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 209f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setClassName(ri.activityInfo.packageName, 210f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ri.activityInfo.name); 21132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String appName = ri.loadLabel(pm).toString(); 21232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (appName != null) { 21332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToIntent.put(appName, startIntent); 21432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToProcess.put(appName, ri.activityInfo.processName); 21532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 216f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 217f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 218f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 219f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 22032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private long startApp(String appName, boolean forceStopBeforeLaunch) 221f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine throws NameNotFoundException, RemoteException { 222f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Starting " + appName); 223f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 224f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = mNameToIntent.get(appName); 225c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu if (startIntent == null) { 226c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu Log.w(TAG, "App does not exist: " + appName); 22732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), "App does not exist"); 22832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return -1; 229c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu } 23032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch); 231f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread t = new Thread(runnable); 232f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.start(); 233f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 234f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.join(JOIN_TIMEOUT); 235f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 236f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 237f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 238c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu WaitResult result = runnable.getResult(); 23932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // report error if any of the following is true: 24032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * launch thread is alive 24132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * result is not null, but: 2426fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim // * result is not START_SUCCESS 24332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * or in case of no force stop, result is not TASK_TO_FRONT either 24432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (t.isAlive() || (result != null 24532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && ((result.result != ActivityManager.START_SUCCESS) 24632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && (!forceStopBeforeLaunch 24732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && result.result != ActivityManager.START_TASK_TO_FRONT)))) { 248f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, "Assuming app " + appName + " crashed."); 24932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu reportError(appName, mNameToProcess.get(appName)); 25032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return -1; 251f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 25232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return result.thisTime; 253f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 254f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 2556266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private void checkAccountSignIn() { 2566266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // ensure that the device has the required account types before starting test 2576266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // e.g. device must have a valid Google account sign in to measure a meaningful launch time 2586266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // for Gmail 2596266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts == null || mRequiredAccounts.isEmpty()) { 2606266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu return; 2616266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2626266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu final AccountManager am = 2636266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu (AccountManager) getInstrumentation().getTargetContext().getSystemService( 2646266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Context.ACCOUNT_SERVICE); 2656266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Account[] accounts = am.getAccounts(); 2666266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // use set here in case device has multiple accounts of the same type 2676266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Set<String> foundAccounts = new HashSet<String>(); 2686266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (Account account : accounts) { 2696266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.contains(account.type)) { 2706266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu foundAccounts.add(account.type); 2716266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2726266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2736266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // check if account type matches, if not, fail test with message on what account types 2746266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // are missing 2756266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.size() != foundAccounts.size()) { 2766266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.removeAll(foundAccounts); 2776266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu StringBuilder sb = new StringBuilder("Device missing these accounts:"); 2786266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String account : mRequiredAccounts) { 2796266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(' '); 2806266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(account); 2816266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2826266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu fail(sb.toString()); 2836266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2846266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2856266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu 28632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void closeApp(String appName, boolean forceStopApp) { 287f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent homeIntent = new Intent(Intent.ACTION_MAIN); 288f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.addCategory(Intent.CATEGORY_HOME); 289f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 290f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 291f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine getInstrumentation().getContext().startActivity(homeIntent); 29232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(POST_LAUNCH_IDLE_TIMEOUT); 29332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (forceStopApp) { 29432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Intent startIntent = mNameToIntent.get(appName); 29532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (startIntent != null) { 29632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String packageName = startIntent.getComponent().getPackageName(); 29732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu try { 29832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 29932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } catch (RemoteException e) { 30032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Log.w(TAG, "Error closing app", e); 30132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 30213f77349778fbe95d665542be6f05006879854e2Guang Zhu } 30313f77349778fbe95d665542be6f05006879854e2Guang Zhu } 304f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 305f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 306f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void sleep(int time) { 307f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 308f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread.sleep(time); 309f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 310f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 311f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 312f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 313f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 31432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void reportError(String appName, String processName) { 315f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ActivityManager am = (ActivityManager) getInstrumentation() 316f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getContext().getSystemService(Context.ACTIVITY_SERVICE); 317f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState(); 318f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (crashes != null) { 319f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ProcessErrorStateInfo crash : crashes) { 320f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (!crash.processName.equals(processName)) 321f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine continue; 322f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 323f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName + " crashed: " + crash.shortMsg); 32432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), crash.shortMsg); 325f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 326f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 327f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 328f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 32932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), 330f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine "Crashed for unknown reason"); 331f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName 332f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine + " not found in process list, most likely it is crashed"); 333f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 334f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 335f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private class AppLaunchRunnable implements Runnable { 336f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Intent mLaunchIntent; 337f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private IActivityManager.WaitResult mResult; 33832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private boolean mForceStopBeforeLaunch; 33932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu 34032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch) { 341f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mLaunchIntent = intent; 34232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mForceStopBeforeLaunch = forceStopBeforeLaunch; 343f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 344f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 345f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine public IActivityManager.WaitResult getResult() { 346f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return mResult; 347f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 348f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 349f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine public void run() { 350f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 351c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu String packageName = mLaunchIntent.getComponent().getPackageName(); 35232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (mForceStopBeforeLaunch) { 35332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 35432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 355f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String mimeType = mLaunchIntent.getType(); 356f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (mimeType == null && mLaunchIntent.getData() != null 357f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine && "content".equals(mLaunchIntent.getData().getScheme())) { 358f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(), 359f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine UserHandle.USER_CURRENT); 360f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 361f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 362f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mResult = mAm.startActivityAndWait(null, null, mLaunchIntent, mimeType, 3631b012d302b56b4adf950035136d1d191a1936d5aJeff Hao null, null, 0, mLaunchIntent.getFlags(), null, null, 364f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine UserHandle.USER_CURRENT); 365f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (RemoteException e) { 366f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, "Error launching app", e); 367f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 368f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 369f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 370f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine} 371