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); 8832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang 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; 9332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 9432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(INITIAL_LAUNCH_IDLE_TIMEOUT); 9532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu closeApp(app, false); 9632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 9732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 9832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // do the real app launch now 9932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (int i = 0; i < mLaunchIterations; i++) { 10032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (String app : mNameToResultKey.keySet()) { 10132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu long totalLaunchTime = mNameToLaunchTime.get(app); 10232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu long launchTime = 0; 10332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (totalLaunchTime < 0) { 10432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // skip if the app has previous failures 10532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 10632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 10732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu launchTime = startApp(app, true); 10832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (launchTime <= 0) { 10932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // if it fails once, skip the rest of the launches 11032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(app, -1L); 11132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu continue; 11232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 11332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu totalLaunchTime += launchTime; 11432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(app, totalLaunchTime); 11532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(POST_LAUNCH_IDLE_TIMEOUT); 11632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu closeApp(app, true); 11732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 11832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 11932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 12032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (String app : mNameToResultKey.keySet()) { 12132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu long totalLaunchTime = mNameToLaunchTime.get(app); 12232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (totalLaunchTime != -1) { 12332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putDouble(mNameToResultKey.get(app), 12432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu ((double) totalLaunchTime) / mLaunchIterations); 125f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 126f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 12732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu instrumentation.sendStatus(0, mResult); 128f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 129f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 130f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void parseArgs(Bundle args) { 131c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToResultKey = new LinkedHashMap<String, String>(); 13232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime = new HashMap<String, Long>(); 13332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS); 13432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (launchIterations != null) { 13532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mLaunchIterations = Integer.parseInt(launchIterations); 13632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 137f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appList = args.getString(KEY_APPS); 138f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (appList == null) 139f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 140f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 141f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appNames[] = appList.split("\\|"); 142f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (String pair : appNames) { 143f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String[] parts = pair.split("\\^"); 144f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (parts.length != 2) { 145f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.e(TAG, "The apps key is incorectly formatted"); 146f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine fail(); 147f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 148f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 149f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mNameToResultKey.put(parts[0], parts[1]); 15032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToLaunchTime.put(parts[0], 0L); 151f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 1526266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS); 1536266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (requiredAccounts != null) { 1546266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts = new HashSet<String>(); 1556266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String accountType : requiredAccounts.split(",")) { 1566266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.add(accountType); 1576266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 1586266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 159f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 160f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 161f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void createMappings() { 162c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToIntent = new LinkedHashMap<String, Intent>(); 163c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToProcess = new LinkedHashMap<String, String>(); 164f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 165f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine PackageManager pm = getInstrumentation().getContext() 166f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getPackageManager(); 167f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 168f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 169f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0); 170f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (ris == null || ris.isEmpty()) { 171f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Could not find any apps"); 172f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } else { 173f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ResolveInfo ri : ris) { 174f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = new Intent(intentToResolve); 175f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 176f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 177f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setClassName(ri.activityInfo.packageName, 178f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ri.activityInfo.name); 17932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String appName = ri.loadLabel(pm).toString(); 18032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (appName != null) { 18132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToIntent.put(appName, startIntent); 18232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToProcess.put(appName, ri.activityInfo.processName); 18332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 184f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 185f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 186f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 187f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 18832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private long startApp(String appName, boolean forceStopBeforeLaunch) 189f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine throws NameNotFoundException, RemoteException { 190f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Starting " + appName); 191f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 192f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = mNameToIntent.get(appName); 193c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu if (startIntent == null) { 194c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu Log.w(TAG, "App does not exist: " + appName); 19532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), "App does not exist"); 19632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return -1; 197c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu } 19832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch); 199f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread t = new Thread(runnable); 200f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.start(); 201f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 202f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.join(JOIN_TIMEOUT); 203f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 204f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 205f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 206c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu WaitResult result = runnable.getResult(); 20732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // report error if any of the following is true: 20832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * launch thread is alive 20932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * result is not null, but: 21032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * result is not START_SUCESS 21132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu // * or in case of no force stop, result is not TASK_TO_FRONT either 21232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (t.isAlive() || (result != null 21332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && ((result.result != ActivityManager.START_SUCCESS) 21432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && (!forceStopBeforeLaunch 21532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu && result.result != ActivityManager.START_TASK_TO_FRONT)))) { 216f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, "Assuming app " + appName + " crashed."); 21732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu reportError(appName, mNameToProcess.get(appName)); 21832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return -1; 219f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 22032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu return result.thisTime; 221f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 222f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 2236266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private void checkAccountSignIn() { 2246266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // ensure that the device has the required account types before starting test 2256266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // e.g. device must have a valid Google account sign in to measure a meaningful launch time 2266266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // for Gmail 2276266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts == null || mRequiredAccounts.isEmpty()) { 2286266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu return; 2296266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2306266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu final AccountManager am = 2316266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu (AccountManager) getInstrumentation().getTargetContext().getSystemService( 2326266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Context.ACCOUNT_SERVICE); 2336266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Account[] accounts = am.getAccounts(); 2346266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // use set here in case device has multiple accounts of the same type 2356266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Set<String> foundAccounts = new HashSet<String>(); 2366266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (Account account : accounts) { 2376266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.contains(account.type)) { 2386266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu foundAccounts.add(account.type); 2396266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2406266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2416266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // check if account type matches, if not, fail test with message on what account types 2426266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // are missing 2436266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.size() != foundAccounts.size()) { 2446266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.removeAll(foundAccounts); 2456266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu StringBuilder sb = new StringBuilder("Device missing these accounts:"); 2466266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String account : mRequiredAccounts) { 2476266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(' '); 2486266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(account); 2496266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2506266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu fail(sb.toString()); 2516266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2526266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 2536266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu 25432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void closeApp(String appName, boolean forceStopApp) { 255f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent homeIntent = new Intent(Intent.ACTION_MAIN); 256f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.addCategory(Intent.CATEGORY_HOME); 257f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 258f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 259f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine getInstrumentation().getContext().startActivity(homeIntent); 26032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(POST_LAUNCH_IDLE_TIMEOUT); 26132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (forceStopApp) { 26232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Intent startIntent = mNameToIntent.get(appName); 26332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (startIntent != null) { 26432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String packageName = startIntent.getComponent().getPackageName(); 26532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu try { 26632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 26732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } catch (RemoteException e) { 26832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Log.w(TAG, "Error closing app", e); 26932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 27013f77349778fbe95d665542be6f05006879854e2Guang Zhu } 27113f77349778fbe95d665542be6f05006879854e2Guang Zhu } 272f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 273f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 274f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void sleep(int time) { 275f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 276f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread.sleep(time); 277f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 278f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 279f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 280f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 281f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 28232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void reportError(String appName, String processName) { 283f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ActivityManager am = (ActivityManager) getInstrumentation() 284f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getContext().getSystemService(Context.ACTIVITY_SERVICE); 285f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState(); 286f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (crashes != null) { 287f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ProcessErrorStateInfo crash : crashes) { 288f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (!crash.processName.equals(processName)) 289f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine continue; 290f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 291f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName + " crashed: " + crash.shortMsg); 29232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), crash.shortMsg); 293f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 294f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 295f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 296f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 29732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), 298f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine "Crashed for unknown reason"); 299f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName 300f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine + " not found in process list, most likely it is crashed"); 301f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 302f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 303f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private class AppLaunchRunnable implements Runnable { 304f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Intent mLaunchIntent; 305f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private IActivityManager.WaitResult mResult; 30632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private boolean mForceStopBeforeLaunch; 30732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu 30832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch) { 309f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mLaunchIntent = intent; 31032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mForceStopBeforeLaunch = forceStopBeforeLaunch; 311f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 312f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 313f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine public IActivityManager.WaitResult getResult() { 314f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return mResult; 315f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 316f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 317f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine public void run() { 318f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 319c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu String packageName = mLaunchIntent.getComponent().getPackageName(); 32032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (mForceStopBeforeLaunch) { 32132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 32232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 323f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String mimeType = mLaunchIntent.getType(); 324f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (mimeType == null && mLaunchIntent.getData() != null 325f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine && "content".equals(mLaunchIntent.getData().getScheme())) { 326f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(), 327f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine UserHandle.USER_CURRENT); 328f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 329f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 330f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mResult = mAm.startActivityAndWait(null, null, mLaunchIntent, mimeType, 331f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine null, null, 0, mLaunchIntent.getFlags(), null, null, null, 332f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine UserHandle.USER_CURRENT); 333f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (RemoteException e) { 334f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, "Error launching app", e); 335f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 336f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 337f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 338f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine} 339