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 18164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.OutputStreamWriter; 19164cca0b341051b659b7276381756012e23427eeGopinath 206266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport android.accounts.Account; 216266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport android.accounts.AccountManager; 22164cca0b341051b659b7276381756012e23427eeGopinathimport android.app.ActivityManagerNative; 23f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManager; 24f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManager.ProcessErrorStateInfo; 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; 33164cca0b341051b659b7276381756012e23427eeGopinathimport android.app.UiAutomation; 34164cca0b341051b659b7276381756012e23427eeGopinathimport android.app.IActivityManager; 35164cca0b341051b659b7276381756012e23427eeGopinathimport android.app.IActivityManager.WaitResult; 36164cca0b341051b659b7276381756012e23427eeGopinathimport android.support.test.rule.logging.AtraceLogger; 37f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestCase; 38f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestRunner; 39f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.util.Log; 40164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.File; 41164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.IOException; 4232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhuimport java.util.HashMap; 436266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport java.util.HashSet; 44c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhuimport java.util.LinkedHashMap; 45f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.List; 46164cca0b341051b659b7276381756012e23427eeGopinathimport java.util.ArrayList; 47f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.Map; 486266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhuimport java.util.Set; 49164cca0b341051b659b7276381756012e23427eeGopinathimport android.os.ParcelFileDescriptor; 50164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.FileInputStream; 51164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.FileOutputStream; 52164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.InputStream; 53164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.BufferedReader; 54164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.BufferedWriter; 55164cca0b341051b659b7276381756012e23427eeGopinathimport java.io.InputStreamReader; 56f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 57f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine/** 58f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * This test is intended to measure the time it takes for the apps to start. 59f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Names of the applications are passed in command line, and the 60f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * test starts each application, and reports the start up time in milliseconds. 61f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * The instrumentation expects the following key to be passed on the command line: 62f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * apps - A list of applications to start and their corresponding result keys 63f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * in the following format: 64f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * -e apps <app name>^<result key>|<app name>^<result key> 65f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine */ 66f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavinepublic class AppLaunch extends InstrumentationTestCase { 67f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 68f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private static final int JOIN_TIMEOUT = 10000; 6932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final String TAG = AppLaunch.class.getSimpleName(); 706266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // optional parameter: comma separated list of required account types before proceeding 716266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // with the app launch 726266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts"; 73164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_APPS = "apps"; 74164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_TRIAL_LAUNCH = "trial_launch"; 75164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations"; 76164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_LAUNCH_ORDER = "launch_order"; 77164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_DROP_CACHE = "drop_cache"; 78164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_SIMPLEPPERF_CMD = "simpleperf_cmd"; 79164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_TRACE_ITERATIONS = "trace_iterations"; 80164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_LAUNCH_DIRECTORY = "launch_directory"; 81164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_TRACE_DIRECTORY = "trace_directory"; 82164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_TRACE_CATEGORY = "trace_categories"; 83164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize"; 84164cca0b341051b659b7276381756012e23427eeGopinath private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval"; 85349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz private static final String WEARABLE_ACTION_GOOGLE = 86349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz "com.google.android.wearable.action.GOOGLE"; 875aa567a8697ffbb1629816cceda36e3aec041c43Gopinath private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 60000; //60s to allow app to idle 8832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches 89164cca0b341051b659b7276381756012e23427eeGopinath private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; //5s between launching apps 90164cca0b341051b659b7276381756012e23427eeGopinath private static final String LAUNCH_SUB_DIRECTORY = "launch_logs"; 91164cca0b341051b659b7276381756012e23427eeGopinath private static final String LAUNCH_FILE = "applaunch.txt"; 92164cca0b341051b659b7276381756012e23427eeGopinath private static final String TRACE_SUB_DIRECTORY = "atrace_logs"; 93164cca0b341051b659b7276381756012e23427eeGopinath private static final String DEFAULT_TRACE_CATEGORIES = "sched,freq,gfx,view,dalvik,webview," 94164cca0b341051b659b7276381756012e23427eeGopinath + "input,wm,disk,am,wm"; 95164cca0b341051b659b7276381756012e23427eeGopinath private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000"; 96164cca0b341051b659b7276381756012e23427eeGopinath private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10"; 97164cca0b341051b659b7276381756012e23427eeGopinath private static final String TRIAL_LAUNCH = "TRAIL_LAUNCH"; 98164cca0b341051b659b7276381756012e23427eeGopinath private static final String DELIMITER = ","; 99164cca0b341051b659b7276381756012e23427eeGopinath private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh"; 100164cca0b341051b659b7276381756012e23427eeGopinath private static final String APP_LAUNCH_CMD = "am start -W -n"; 101164cca0b341051b659b7276381756012e23427eeGopinath private static final String SUCCESS_MESSAGE = "Status: ok"; 102164cca0b341051b659b7276381756012e23427eeGopinath private static final String THIS_TIME = "ThisTime:"; 103164cca0b341051b659b7276381756012e23427eeGopinath private static final String LAUNCH_ITERATION = "LAUNCH_ITERATION - %d"; 104164cca0b341051b659b7276381756012e23427eeGopinath private static final String TRACE_ITERATION = "TRACE_ITERATION - %d"; 105164cca0b341051b659b7276381756012e23427eeGopinath private static final String LAUNCH_ITERATION_PREFIX = "LAUNCH_ITERATION"; 106164cca0b341051b659b7276381756012e23427eeGopinath private static final String TRACE_ITERATION_PREFIX = "TRACE_ITERATION"; 107164cca0b341051b659b7276381756012e23427eeGopinath private static final String LAUNCH_ORDER_CYCLIC = "cyclic"; 108164cca0b341051b659b7276381756012e23427eeGopinath private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential"; 109164cca0b341051b659b7276381756012e23427eeGopinath 110f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 111f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, Intent> mNameToIntent; 112f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, String> mNameToProcess; 113164cca0b341051b659b7276381756012e23427eeGopinath private List<LaunchOrder> mLaunchOrderList = new ArrayList<LaunchOrder>(); 114f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Map<String, String> mNameToResultKey; 115164cca0b341051b659b7276381756012e23427eeGopinath private Map<String, List<Long>> mNameToLaunchTime; 116f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private IActivityManager mAm; 117164cca0b341051b659b7276381756012e23427eeGopinath private String mSimplePerfCmd = null; 118164cca0b341051b659b7276381756012e23427eeGopinath private String mLaunchOrder = null; 119164cca0b341051b659b7276381756012e23427eeGopinath private boolean mDropCache = false; 12032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private int mLaunchIterations = 10; 121164cca0b341051b659b7276381756012e23427eeGopinath private int mTraceLaunchCount = 0; 122164cca0b341051b659b7276381756012e23427eeGopinath private String mTraceDirectoryStr = null; 12332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private Bundle mResult = new Bundle(); 1246266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private Set<String> mRequiredAccounts; 125164cca0b341051b659b7276381756012e23427eeGopinath private boolean mTrailLaunch = true; 126164cca0b341051b659b7276381756012e23427eeGopinath private File mFile = null; 127164cca0b341051b659b7276381756012e23427eeGopinath private FileOutputStream mOutputStream = null; 128164cca0b341051b659b7276381756012e23427eeGopinath private BufferedWriter mBufferedWriter = null; 129164cca0b341051b659b7276381756012e23427eeGopinath 130f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 131e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu @Override 132e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu protected void setUp() throws Exception { 133e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu super.setUp(); 134e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0); 135e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu } 136e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu 137e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu @Override 138e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu protected void tearDown() throws Exception { 139e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE); 140e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu super.tearDown(); 141e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu } 142e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu 143164cca0b341051b659b7276381756012e23427eeGopinath public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException, 144164cca0b341051b659b7276381756012e23427eeGopinath IOException, InterruptedException { 145f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine InstrumentationTestRunner instrumentation = 146f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine (InstrumentationTestRunner)getInstrumentation(); 1473a34d17412a5a304e39be1966a16627677d2136fSvetoslav Bundle args = instrumentation.getArguments(); 148f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mAm = ActivityManagerNative.getDefault(); 149164cca0b341051b659b7276381756012e23427eeGopinath String launchDirectory = args.getString(KEY_LAUNCH_DIRECTORY); 150164cca0b341051b659b7276381756012e23427eeGopinath mTraceDirectoryStr = args.getString(KEY_TRACE_DIRECTORY); 151164cca0b341051b659b7276381756012e23427eeGopinath mDropCache = Boolean.parseBoolean(args.getString(KEY_DROP_CACHE)); 152164cca0b341051b659b7276381756012e23427eeGopinath mSimplePerfCmd = args.getString(KEY_SIMPLEPPERF_CMD); 153164cca0b341051b659b7276381756012e23427eeGopinath mLaunchOrder = args.getString(KEY_LAUNCH_ORDER, LAUNCH_ORDER_CYCLIC); 154f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine createMappings(); 155f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine parseArgs(args); 1566266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu checkAccountSignIn(); 157f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 158164cca0b341051b659b7276381756012e23427eeGopinath // Root directory for applaunch file to log the app launch output 159164cca0b341051b659b7276381756012e23427eeGopinath // Will be useful in case of simpleperf command is used 160164cca0b341051b659b7276381756012e23427eeGopinath File launchRootDir = null; 161164cca0b341051b659b7276381756012e23427eeGopinath if (null != launchDirectory && !launchDirectory.isEmpty()) { 162164cca0b341051b659b7276381756012e23427eeGopinath launchRootDir = new File(launchDirectory); 163164cca0b341051b659b7276381756012e23427eeGopinath if (!launchRootDir.exists() && !launchRootDir.mkdirs()) { 164164cca0b341051b659b7276381756012e23427eeGopinath throw new IOException("Unable to create the destination directory"); 16532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 16632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 167164cca0b341051b659b7276381756012e23427eeGopinath 168164cca0b341051b659b7276381756012e23427eeGopinath try { 169164cca0b341051b659b7276381756012e23427eeGopinath File launchSubDir = new File(launchRootDir, LAUNCH_SUB_DIRECTORY); 170164cca0b341051b659b7276381756012e23427eeGopinath if (!launchSubDir.exists() && !launchSubDir.mkdirs()) { 171164cca0b341051b659b7276381756012e23427eeGopinath throw new IOException("Unable to create the lauch file sub directory"); 172164cca0b341051b659b7276381756012e23427eeGopinath } 173164cca0b341051b659b7276381756012e23427eeGopinath mFile = new File(launchSubDir, LAUNCH_FILE); 174164cca0b341051b659b7276381756012e23427eeGopinath mOutputStream = new FileOutputStream(mFile); 175164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter = new BufferedWriter(new OutputStreamWriter( 176164cca0b341051b659b7276381756012e23427eeGopinath mOutputStream)); 177164cca0b341051b659b7276381756012e23427eeGopinath 178164cca0b341051b659b7276381756012e23427eeGopinath // Root directory for trace file during the launches 179164cca0b341051b659b7276381756012e23427eeGopinath File rootTrace = null; 180164cca0b341051b659b7276381756012e23427eeGopinath File rootTraceSubDir = null; 181164cca0b341051b659b7276381756012e23427eeGopinath int traceBufferSize = 0; 182164cca0b341051b659b7276381756012e23427eeGopinath int traceDumpInterval = 0; 183164cca0b341051b659b7276381756012e23427eeGopinath Set<String> traceCategoriesSet = null; 184164cca0b341051b659b7276381756012e23427eeGopinath if (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty()) { 185164cca0b341051b659b7276381756012e23427eeGopinath rootTrace = new File(mTraceDirectoryStr); 186164cca0b341051b659b7276381756012e23427eeGopinath if (!rootTrace.exists() && !rootTrace.mkdirs()) { 187164cca0b341051b659b7276381756012e23427eeGopinath throw new IOException("Unable to create the trace directory"); 18832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 189164cca0b341051b659b7276381756012e23427eeGopinath rootTraceSubDir = new File(rootTrace, TRACE_SUB_DIRECTORY); 190164cca0b341051b659b7276381756012e23427eeGopinath if (!rootTraceSubDir.exists() && !rootTraceSubDir.mkdirs()) { 191164cca0b341051b659b7276381756012e23427eeGopinath throw new IOException("Unable to create the trace sub directory"); 19232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 193164cca0b341051b659b7276381756012e23427eeGopinath assertNotNull("Trace iteration parameter is mandatory", 194164cca0b341051b659b7276381756012e23427eeGopinath args.getString(KEY_TRACE_ITERATIONS)); 195164cca0b341051b659b7276381756012e23427eeGopinath mTraceLaunchCount = Integer.parseInt(args.getString(KEY_TRACE_ITERATIONS)); 196164cca0b341051b659b7276381756012e23427eeGopinath String traceCategoriesStr = args 197164cca0b341051b659b7276381756012e23427eeGopinath .getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES); 198164cca0b341051b659b7276381756012e23427eeGopinath traceBufferSize = Integer.parseInt(args.getString(KEY_TRACE_BUFFERSIZE, 199164cca0b341051b659b7276381756012e23427eeGopinath DEFAULT_TRACE_BUFFER_SIZE)); 200164cca0b341051b659b7276381756012e23427eeGopinath traceDumpInterval = Integer.parseInt(args.getString(KEY_TRACE_DUMPINTERVAL, 201164cca0b341051b659b7276381756012e23427eeGopinath DEFAULT_TRACE_DUMP_INTERVAL)); 202164cca0b341051b659b7276381756012e23427eeGopinath traceCategoriesSet = new HashSet<String>(); 203164cca0b341051b659b7276381756012e23427eeGopinath if (!traceCategoriesStr.isEmpty()) { 204164cca0b341051b659b7276381756012e23427eeGopinath String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER); 205164cca0b341051b659b7276381756012e23427eeGopinath for (int i = 0; i < traceCategoriesSplit.length; i++) { 206164cca0b341051b659b7276381756012e23427eeGopinath traceCategoriesSet.add(traceCategoriesSplit[i]); 207164cca0b341051b659b7276381756012e23427eeGopinath } 2082861a89bed9066e206917c41357a5e589e8482cbGuang Zhu } 209164cca0b341051b659b7276381756012e23427eeGopinath } 210164cca0b341051b659b7276381756012e23427eeGopinath 211164cca0b341051b659b7276381756012e23427eeGopinath // Get the app launch order based on launch order, trial launch, 212164cca0b341051b659b7276381756012e23427eeGopinath // launch iterations and trace iterations 213164cca0b341051b659b7276381756012e23427eeGopinath setLaunchOrder(); 214164cca0b341051b659b7276381756012e23427eeGopinath 215164cca0b341051b659b7276381756012e23427eeGopinath for (LaunchOrder launch : mLaunchOrderList) { 216164cca0b341051b659b7276381756012e23427eeGopinath 217164cca0b341051b659b7276381756012e23427eeGopinath // App launch times for trial launch will not be used for final 218164cca0b341051b659b7276381756012e23427eeGopinath // launch time calculations. 219164cca0b341051b659b7276381756012e23427eeGopinath if (launch.getLaunchReason().equals(TRIAL_LAUNCH)) { 220164cca0b341051b659b7276381756012e23427eeGopinath // In the "applaunch.txt" file, trail launches is referenced using 221164cca0b341051b659b7276381756012e23427eeGopinath // "TRIAL_LAUNCH" 222164cca0b341051b659b7276381756012e23427eeGopinath long launchTime = startApp(launch.getApp(), true, launch.getLaunchReason()); 223164cca0b341051b659b7276381756012e23427eeGopinath if (launchTime < 0) { 224164cca0b341051b659b7276381756012e23427eeGopinath List<Long> appLaunchList = new ArrayList<Long>(); 225164cca0b341051b659b7276381756012e23427eeGopinath appLaunchList.add(-1L); 226164cca0b341051b659b7276381756012e23427eeGopinath mNameToLaunchTime.put(launch.getApp(), appLaunchList); 227164cca0b341051b659b7276381756012e23427eeGopinath // simply pass the app if launch isn't successful 228164cca0b341051b659b7276381756012e23427eeGopinath // error should have already been logged by startApp 229164cca0b341051b659b7276381756012e23427eeGopinath continue; 230164cca0b341051b659b7276381756012e23427eeGopinath } 231164cca0b341051b659b7276381756012e23427eeGopinath sleep(INITIAL_LAUNCH_IDLE_TIMEOUT); 232164cca0b341051b659b7276381756012e23427eeGopinath closeApp(launch.getApp(), true); 233164cca0b341051b659b7276381756012e23427eeGopinath dropCache(); 234164cca0b341051b659b7276381756012e23427eeGopinath sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 235164cca0b341051b659b7276381756012e23427eeGopinath } 236164cca0b341051b659b7276381756012e23427eeGopinath 237164cca0b341051b659b7276381756012e23427eeGopinath // App launch times used for final calculation 238164cca0b341051b659b7276381756012e23427eeGopinath if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) { 239164cca0b341051b659b7276381756012e23427eeGopinath long launchTime = -1; 240164cca0b341051b659b7276381756012e23427eeGopinath if (null != mNameToLaunchTime.get(launch.getApp())) { 241164cca0b341051b659b7276381756012e23427eeGopinath long firstLaunchTime = mNameToLaunchTime.get(launch.getApp()).get(0); 242164cca0b341051b659b7276381756012e23427eeGopinath if (firstLaunchTime < 0) { 243164cca0b341051b659b7276381756012e23427eeGopinath // skip if the app has failures while launched first 244164cca0b341051b659b7276381756012e23427eeGopinath continue; 245164cca0b341051b659b7276381756012e23427eeGopinath } 246164cca0b341051b659b7276381756012e23427eeGopinath } 247164cca0b341051b659b7276381756012e23427eeGopinath // In the "applaunch.txt" file app launches are referenced using 248164cca0b341051b659b7276381756012e23427eeGopinath // "LAUNCH_ITERATION - ITERATION NUM" 249164cca0b341051b659b7276381756012e23427eeGopinath launchTime = startApp(launch.getApp(), true, launch.getLaunchReason()); 250164cca0b341051b659b7276381756012e23427eeGopinath if (launchTime < 0) { 251164cca0b341051b659b7276381756012e23427eeGopinath // if it fails once, skip the rest of the launches 252164cca0b341051b659b7276381756012e23427eeGopinath List<Long> appLaunchList = new ArrayList<Long>(); 253164cca0b341051b659b7276381756012e23427eeGopinath appLaunchList.add(-1L); 254164cca0b341051b659b7276381756012e23427eeGopinath mNameToLaunchTime.put(launch.getApp(), appLaunchList); 255164cca0b341051b659b7276381756012e23427eeGopinath continue; 256164cca0b341051b659b7276381756012e23427eeGopinath } else { 257164cca0b341051b659b7276381756012e23427eeGopinath if (null != mNameToLaunchTime.get(launch.getApp())) { 258164cca0b341051b659b7276381756012e23427eeGopinath mNameToLaunchTime.get(launch.getApp()).add(launchTime); 259164cca0b341051b659b7276381756012e23427eeGopinath } else { 260164cca0b341051b659b7276381756012e23427eeGopinath List<Long> appLaunchList = new ArrayList<Long>(); 261164cca0b341051b659b7276381756012e23427eeGopinath appLaunchList.add(launchTime); 262164cca0b341051b659b7276381756012e23427eeGopinath mNameToLaunchTime.put(launch.getApp(), appLaunchList); 263164cca0b341051b659b7276381756012e23427eeGopinath } 264164cca0b341051b659b7276381756012e23427eeGopinath } 265164cca0b341051b659b7276381756012e23427eeGopinath sleep(POST_LAUNCH_IDLE_TIMEOUT); 266164cca0b341051b659b7276381756012e23427eeGopinath closeApp(launch.getApp(), true); 267164cca0b341051b659b7276381756012e23427eeGopinath dropCache(); 268164cca0b341051b659b7276381756012e23427eeGopinath sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 269164cca0b341051b659b7276381756012e23427eeGopinath } 270164cca0b341051b659b7276381756012e23427eeGopinath 271164cca0b341051b659b7276381756012e23427eeGopinath // App launch times for trace launch will not be used for final 272164cca0b341051b659b7276381756012e23427eeGopinath // launch time calculations. 273164cca0b341051b659b7276381756012e23427eeGopinath if (launch.getLaunchReason().contains(TRACE_ITERATION_PREFIX)) { 274164cca0b341051b659b7276381756012e23427eeGopinath AtraceLogger atraceLogger = AtraceLogger 275164cca0b341051b659b7276381756012e23427eeGopinath .getAtraceLoggerInstance(getInstrumentation()); 276164cca0b341051b659b7276381756012e23427eeGopinath // Start the trace 277164cca0b341051b659b7276381756012e23427eeGopinath try { 278164cca0b341051b659b7276381756012e23427eeGopinath atraceLogger.atraceStart(traceCategoriesSet, traceBufferSize, 279164cca0b341051b659b7276381756012e23427eeGopinath traceDumpInterval, rootTraceSubDir, 280164cca0b341051b659b7276381756012e23427eeGopinath String.format("%s-%s", launch.getApp(), launch.getLaunchReason())); 281164cca0b341051b659b7276381756012e23427eeGopinath startApp(launch.getApp(), true, launch.getLaunchReason()); 282164cca0b341051b659b7276381756012e23427eeGopinath sleep(POST_LAUNCH_IDLE_TIMEOUT); 283164cca0b341051b659b7276381756012e23427eeGopinath } finally { 284164cca0b341051b659b7276381756012e23427eeGopinath // Stop the trace 285164cca0b341051b659b7276381756012e23427eeGopinath atraceLogger.atraceStop(); 286164cca0b341051b659b7276381756012e23427eeGopinath closeApp(launch.getApp(), true); 287164cca0b341051b659b7276381756012e23427eeGopinath dropCache(); 288164cca0b341051b659b7276381756012e23427eeGopinath sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT); 289164cca0b341051b659b7276381756012e23427eeGopinath } 290164cca0b341051b659b7276381756012e23427eeGopinath } 291164cca0b341051b659b7276381756012e23427eeGopinath } 292164cca0b341051b659b7276381756012e23427eeGopinath } finally { 293164cca0b341051b659b7276381756012e23427eeGopinath if (null != mBufferedWriter) { 294164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter.close(); 29532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 29632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 297164cca0b341051b659b7276381756012e23427eeGopinath 29832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu for (String app : mNameToResultKey.keySet()) { 299164cca0b341051b659b7276381756012e23427eeGopinath StringBuilder launchTimes = new StringBuilder(); 300164cca0b341051b659b7276381756012e23427eeGopinath for (Long launch : mNameToLaunchTime.get(app)) { 301164cca0b341051b659b7276381756012e23427eeGopinath launchTimes.append(launch); 302164cca0b341051b659b7276381756012e23427eeGopinath launchTimes.append(","); 303f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 304164cca0b341051b659b7276381756012e23427eeGopinath mResult.putString(mNameToResultKey.get(app), launchTimes.toString()); 305f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 30632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu instrumentation.sendStatus(0, mResult); 307f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 308f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 309164cca0b341051b659b7276381756012e23427eeGopinath /** 310164cca0b341051b659b7276381756012e23427eeGopinath * If launch order is "cyclic" then apps will be launched one after the 311164cca0b341051b659b7276381756012e23427eeGopinath * other for each iteration count. 312164cca0b341051b659b7276381756012e23427eeGopinath * If launch order is "sequential" then each app will be launched for given number 313164cca0b341051b659b7276381756012e23427eeGopinath * iterations at once before launching the other apps. 314164cca0b341051b659b7276381756012e23427eeGopinath */ 315164cca0b341051b659b7276381756012e23427eeGopinath private void setLaunchOrder() { 316164cca0b341051b659b7276381756012e23427eeGopinath if (LAUNCH_ORDER_CYCLIC.equalsIgnoreCase(mLaunchOrder)) { 317164cca0b341051b659b7276381756012e23427eeGopinath if (mTrailLaunch) { 318164cca0b341051b659b7276381756012e23427eeGopinath for (String app : mNameToResultKey.keySet()) { 319164cca0b341051b659b7276381756012e23427eeGopinath mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH)); 320164cca0b341051b659b7276381756012e23427eeGopinath } 321164cca0b341051b659b7276381756012e23427eeGopinath } 322164cca0b341051b659b7276381756012e23427eeGopinath for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) { 323164cca0b341051b659b7276381756012e23427eeGopinath for (String app : mNameToResultKey.keySet()) { 324164cca0b341051b659b7276381756012e23427eeGopinath mLaunchOrderList.add(new LaunchOrder(app, 325164cca0b341051b659b7276381756012e23427eeGopinath String.format(LAUNCH_ITERATION, launchCount))); 326164cca0b341051b659b7276381756012e23427eeGopinath } 327164cca0b341051b659b7276381756012e23427eeGopinath } 328164cca0b341051b659b7276381756012e23427eeGopinath if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) { 329164cca0b341051b659b7276381756012e23427eeGopinath for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) { 330164cca0b341051b659b7276381756012e23427eeGopinath for (String app : mNameToResultKey.keySet()) { 331164cca0b341051b659b7276381756012e23427eeGopinath mLaunchOrderList.add(new LaunchOrder(app, 332164cca0b341051b659b7276381756012e23427eeGopinath String.format(TRACE_ITERATION, traceCount))); 333164cca0b341051b659b7276381756012e23427eeGopinath } 334164cca0b341051b659b7276381756012e23427eeGopinath } 335164cca0b341051b659b7276381756012e23427eeGopinath } 336164cca0b341051b659b7276381756012e23427eeGopinath } else if (LAUNCH_ORDER_SEQUENTIAL.equalsIgnoreCase(mLaunchOrder)) { 337164cca0b341051b659b7276381756012e23427eeGopinath for (String app : mNameToResultKey.keySet()) { 338164cca0b341051b659b7276381756012e23427eeGopinath if (mTrailLaunch) { 339164cca0b341051b659b7276381756012e23427eeGopinath mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH)); 340164cca0b341051b659b7276381756012e23427eeGopinath } 341164cca0b341051b659b7276381756012e23427eeGopinath for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) { 342164cca0b341051b659b7276381756012e23427eeGopinath mLaunchOrderList.add(new LaunchOrder(app, 343164cca0b341051b659b7276381756012e23427eeGopinath String.format(LAUNCH_ITERATION, launchCount))); 344164cca0b341051b659b7276381756012e23427eeGopinath } 345164cca0b341051b659b7276381756012e23427eeGopinath if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) { 346164cca0b341051b659b7276381756012e23427eeGopinath for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) { 347164cca0b341051b659b7276381756012e23427eeGopinath mLaunchOrderList.add(new LaunchOrder(app, 348164cca0b341051b659b7276381756012e23427eeGopinath String.format(TRACE_ITERATION, traceCount))); 349164cca0b341051b659b7276381756012e23427eeGopinath } 350164cca0b341051b659b7276381756012e23427eeGopinath } 351164cca0b341051b659b7276381756012e23427eeGopinath } 352164cca0b341051b659b7276381756012e23427eeGopinath } else { 353164cca0b341051b659b7276381756012e23427eeGopinath assertTrue("Launch order is not valid parameter", false); 354164cca0b341051b659b7276381756012e23427eeGopinath } 355164cca0b341051b659b7276381756012e23427eeGopinath } 356164cca0b341051b659b7276381756012e23427eeGopinath 357164cca0b341051b659b7276381756012e23427eeGopinath private void dropCache() { 358164cca0b341051b659b7276381756012e23427eeGopinath if (true == mDropCache) { 359164cca0b341051b659b7276381756012e23427eeGopinath assertNotNull("Issue in dropping the cache", 360164cca0b341051b659b7276381756012e23427eeGopinath getInstrumentation().getUiAutomation() 361164cca0b341051b659b7276381756012e23427eeGopinath .executeShellCommand(DROP_CACHE_SCRIPT)); 362164cca0b341051b659b7276381756012e23427eeGopinath } 363164cca0b341051b659b7276381756012e23427eeGopinath } 364164cca0b341051b659b7276381756012e23427eeGopinath 365f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void parseArgs(Bundle args) { 366c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToResultKey = new LinkedHashMap<String, String>(); 367164cca0b341051b659b7276381756012e23427eeGopinath mNameToLaunchTime = new HashMap<String, List<Long>>(); 36832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS); 36932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (launchIterations != null) { 37032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mLaunchIterations = Integer.parseInt(launchIterations); 37132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 372f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appList = args.getString(KEY_APPS); 373f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (appList == null) 374f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 375f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 376f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String appNames[] = appList.split("\\|"); 377f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (String pair : appNames) { 378f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine String[] parts = pair.split("\\^"); 379f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (parts.length != 2) { 3806fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim Log.e(TAG, "The apps key is incorrectly formatted"); 381f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine fail(); 382f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 383f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 384f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mNameToResultKey.put(parts[0], parts[1]); 385164cca0b341051b659b7276381756012e23427eeGopinath mNameToLaunchTime.put(parts[0], null); 386f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 3876266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS); 3886266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (requiredAccounts != null) { 3896266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts = new HashSet<String>(); 3906266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String accountType : requiredAccounts.split(",")) { 3916266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.add(accountType); 3926266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 3936266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 394164cca0b341051b659b7276381756012e23427eeGopinath mTrailLaunch = "true".equals(args.getString(KEY_TRIAL_LAUNCH)); 395f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 396f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 3976fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim private boolean hasLeanback(Context context) { 3986fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); 3996fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim } 4006fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim 401f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void createMappings() { 402c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToIntent = new LinkedHashMap<String, Intent>(); 403c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu mNameToProcess = new LinkedHashMap<String, String>(); 404f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 405f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine PackageManager pm = getInstrumentation().getContext() 406f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getPackageManager(); 407f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 4086fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim intentToResolve.addCategory(hasLeanback(getInstrumentation().getContext()) ? 4096fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim Intent.CATEGORY_LEANBACK_LAUNCHER : 4106fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim Intent.CATEGORY_LAUNCHER); 411f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0); 412349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz resolveLoop(ris, intentToResolve, pm); 4136fc955071afc4125a6a52bf7ab01129416ae0dbfHyungtae Tim Kim // For Wear 414349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz intentToResolve = new Intent(WEARABLE_ACTION_GOOGLE); 415349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz ris = pm.queryIntentActivities(intentToResolve, 0); 416349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz resolveLoop(ris, intentToResolve, pm); 417349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz } 418349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz 419349537b73710655d48e8e3a8472b058d8c1381c8Joshua Schwarz private void resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm) { 420f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (ris == null || ris.isEmpty()) { 421f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Could not find any apps"); 422f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } else { 423f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ResolveInfo ri : ris) { 424f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = new Intent(intentToResolve); 425f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 426f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 427f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine startIntent.setClassName(ri.activityInfo.packageName, 428f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ri.activityInfo.name); 42932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String appName = ri.loadLabel(pm).toString(); 43032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (appName != null) { 43132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToIntent.put(appName, startIntent); 43232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mNameToProcess.put(appName, ri.activityInfo.processName); 43332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 434f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 435f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 436f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 437f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 438164cca0b341051b659b7276381756012e23427eeGopinath private long startApp(String appName, boolean forceStopBeforeLaunch, String launchReason) 439f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine throws NameNotFoundException, RemoteException { 440f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.i(TAG, "Starting " + appName); 441f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 442f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent startIntent = mNameToIntent.get(appName); 443c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu if (startIntent == null) { 444c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu Log.w(TAG, "App does not exist: " + appName); 44532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), "App does not exist"); 446164cca0b341051b659b7276381756012e23427eeGopinath return -1L; 447c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu } 448164cca0b341051b659b7276381756012e23427eeGopinath AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch , 449164cca0b341051b659b7276381756012e23427eeGopinath launchReason); 450f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread t = new Thread(runnable); 451f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.start(); 452f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 453f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine t.join(JOIN_TIMEOUT); 454f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 455f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 456f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 457164cca0b341051b659b7276381756012e23427eeGopinath return runnable.getResult(); 458f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 459f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 4606266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu private void checkAccountSignIn() { 4616266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // ensure that the device has the required account types before starting test 4626266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // e.g. device must have a valid Google account sign in to measure a meaningful launch time 4636266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // for Gmail 4646266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts == null || mRequiredAccounts.isEmpty()) { 4656266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu return; 4666266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 4676266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu final AccountManager am = 4686266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu (AccountManager) getInstrumentation().getTargetContext().getSystemService( 4696266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Context.ACCOUNT_SERVICE); 4706266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Account[] accounts = am.getAccounts(); 4716266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // use set here in case device has multiple accounts of the same type 4726266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu Set<String> foundAccounts = new HashSet<String>(); 4736266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (Account account : accounts) { 4746266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.contains(account.type)) { 4756266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu foundAccounts.add(account.type); 4766266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 4776266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 4786266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // check if account type matches, if not, fail test with message on what account types 4796266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu // are missing 4806266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu if (mRequiredAccounts.size() != foundAccounts.size()) { 4816266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu mRequiredAccounts.removeAll(foundAccounts); 4826266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu StringBuilder sb = new StringBuilder("Device missing these accounts:"); 4836266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu for (String account : mRequiredAccounts) { 4846266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(' '); 4856266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu sb.append(account); 4866266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 4876266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu fail(sb.toString()); 4886266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 4896266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu } 4906266a436f35622f3b48de8d7b245bb5f8a4c567dGuang Zhu 49132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void closeApp(String appName, boolean forceStopApp) { 492f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Intent homeIntent = new Intent(Intent.ACTION_MAIN); 493f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.addCategory(Intent.CATEGORY_HOME); 494f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 495f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 496f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine getInstrumentation().getContext().startActivity(homeIntent); 49732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu sleep(POST_LAUNCH_IDLE_TIMEOUT); 49832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (forceStopApp) { 49932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Intent startIntent = mNameToIntent.get(appName); 50032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (startIntent != null) { 50132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu String packageName = startIntent.getComponent().getPackageName(); 50232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu try { 50332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 50432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } catch (RemoteException e) { 50532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu Log.w(TAG, "Error closing app", e); 50632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 50713f77349778fbe95d665542be6f05006879854e2Guang Zhu } 50813f77349778fbe95d665542be6f05006879854e2Guang Zhu } 509f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 510f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 511f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private void sleep(int time) { 512f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 513f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Thread.sleep(time); 514f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (InterruptedException e) { 515f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine // ignore 516f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 517f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 518f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 51932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private void reportError(String appName, String processName) { 520f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine ActivityManager am = (ActivityManager) getInstrumentation() 521f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine .getContext().getSystemService(Context.ACTIVITY_SERVICE); 522f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState(); 523f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (crashes != null) { 524f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine for (ProcessErrorStateInfo crash : crashes) { 525f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine if (!crash.processName.equals(processName)) 526f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine continue; 527f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 528f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName + " crashed: " + crash.shortMsg); 52932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), crash.shortMsg); 530f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return; 531f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 532f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 533f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 53432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mResult.putString(mNameToResultKey.get(appName), 535f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine "Crashed for unknown reason"); 536f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, appName 537f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine + " not found in process list, most likely it is crashed"); 538f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 539f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 540164cca0b341051b659b7276381756012e23427eeGopinath private class LaunchOrder { 541164cca0b341051b659b7276381756012e23427eeGopinath private String mApp; 542164cca0b341051b659b7276381756012e23427eeGopinath private String mLaunchReason; 543164cca0b341051b659b7276381756012e23427eeGopinath 544164cca0b341051b659b7276381756012e23427eeGopinath LaunchOrder(String app,String launchReason){ 545164cca0b341051b659b7276381756012e23427eeGopinath mApp = app; 546164cca0b341051b659b7276381756012e23427eeGopinath mLaunchReason = launchReason; 547164cca0b341051b659b7276381756012e23427eeGopinath } 548164cca0b341051b659b7276381756012e23427eeGopinath 549164cca0b341051b659b7276381756012e23427eeGopinath public String getApp() { 550164cca0b341051b659b7276381756012e23427eeGopinath return mApp; 551164cca0b341051b659b7276381756012e23427eeGopinath } 552164cca0b341051b659b7276381756012e23427eeGopinath 553164cca0b341051b659b7276381756012e23427eeGopinath public void setApp(String app) { 554164cca0b341051b659b7276381756012e23427eeGopinath mApp = app; 555164cca0b341051b659b7276381756012e23427eeGopinath } 556164cca0b341051b659b7276381756012e23427eeGopinath 557164cca0b341051b659b7276381756012e23427eeGopinath public String getLaunchReason() { 558164cca0b341051b659b7276381756012e23427eeGopinath return mLaunchReason; 559164cca0b341051b659b7276381756012e23427eeGopinath } 560164cca0b341051b659b7276381756012e23427eeGopinath 561164cca0b341051b659b7276381756012e23427eeGopinath public void setLaunchReason(String launchReason) { 562164cca0b341051b659b7276381756012e23427eeGopinath mLaunchReason = launchReason; 563164cca0b341051b659b7276381756012e23427eeGopinath } 564164cca0b341051b659b7276381756012e23427eeGopinath } 565164cca0b341051b659b7276381756012e23427eeGopinath 566f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private class AppLaunchRunnable implements Runnable { 567f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine private Intent mLaunchIntent; 568164cca0b341051b659b7276381756012e23427eeGopinath private Long mResult; 56932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu private boolean mForceStopBeforeLaunch; 570164cca0b341051b659b7276381756012e23427eeGopinath private String mLaunchReason; 57132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu 572164cca0b341051b659b7276381756012e23427eeGopinath public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch, 573164cca0b341051b659b7276381756012e23427eeGopinath String launchReason) { 574f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine mLaunchIntent = intent; 57532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mForceStopBeforeLaunch = forceStopBeforeLaunch; 576164cca0b341051b659b7276381756012e23427eeGopinath mLaunchReason = launchReason; 577eaf08cf7d0aaceb187dd879f7cd53c9d26d4bd75Yuanlang Song mResult = -1L; 578f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 579f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 580164cca0b341051b659b7276381756012e23427eeGopinath public Long getResult() { 581f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine return mResult; 582f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 583f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine 584f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine public void run() { 585f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine try { 586c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu String packageName = mLaunchIntent.getComponent().getPackageName(); 587164cca0b341051b659b7276381756012e23427eeGopinath String componentName = mLaunchIntent.getComponent().flattenToShortString(); 58832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu if (mForceStopBeforeLaunch) { 58932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT); 59032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu } 591164cca0b341051b659b7276381756012e23427eeGopinath String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName); 592164cca0b341051b659b7276381756012e23427eeGopinath if (null != mSimplePerfCmd) { 593164cca0b341051b659b7276381756012e23427eeGopinath launchCmd = String.format("%s %s", mSimplePerfCmd, launchCmd); 594f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 595164cca0b341051b659b7276381756012e23427eeGopinath Log.v(TAG, "Final launch cmd:" + launchCmd); 596164cca0b341051b659b7276381756012e23427eeGopinath ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation() 597164cca0b341051b659b7276381756012e23427eeGopinath .executeShellCommand(launchCmd); 598164cca0b341051b659b7276381756012e23427eeGopinath mResult = Long.parseLong(parseLaunchTimeAndWrite(parcelDesc, String.format 599164cca0b341051b659b7276381756012e23427eeGopinath ("App Launch :%s %s", 600164cca0b341051b659b7276381756012e23427eeGopinath componentName, mLaunchReason)), 10); 601f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } catch (RemoteException e) { 602f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine Log.w(TAG, "Error launching app", e); 603f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 604f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 605164cca0b341051b659b7276381756012e23427eeGopinath 606164cca0b341051b659b7276381756012e23427eeGopinath /** 607164cca0b341051b659b7276381756012e23427eeGopinath * Method to parse the launch time info and write the result to file 608164cca0b341051b659b7276381756012e23427eeGopinath * 609164cca0b341051b659b7276381756012e23427eeGopinath * @param parcelDesc 610164cca0b341051b659b7276381756012e23427eeGopinath * @return 611164cca0b341051b659b7276381756012e23427eeGopinath */ 612164cca0b341051b659b7276381756012e23427eeGopinath private String parseLaunchTimeAndWrite(ParcelFileDescriptor parcelDesc, String headerInfo) { 613164cca0b341051b659b7276381756012e23427eeGopinath String launchTime = "-1"; 614164cca0b341051b659b7276381756012e23427eeGopinath boolean launchSuccess = false; 615164cca0b341051b659b7276381756012e23427eeGopinath try { 616164cca0b341051b659b7276381756012e23427eeGopinath InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor()); 617164cca0b341051b659b7276381756012e23427eeGopinath StringBuilder appLaunchOuput = new StringBuilder(); 618164cca0b341051b659b7276381756012e23427eeGopinath /* SAMPLE OUTPUT : 619164cca0b341051b659b7276381756012e23427eeGopinath Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator } 620164cca0b341051b659b7276381756012e23427eeGopinath Status: ok 621164cca0b341051b659b7276381756012e23427eeGopinath Activity: com.google.android.calculator/com.android.calculator2.Calculator 622164cca0b341051b659b7276381756012e23427eeGopinath ThisTime: 357 623164cca0b341051b659b7276381756012e23427eeGopinath TotalTime: 357 624164cca0b341051b659b7276381756012e23427eeGopinath WaitTime: 377 625164cca0b341051b659b7276381756012e23427eeGopinath Complete*/ 626164cca0b341051b659b7276381756012e23427eeGopinath BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( 627164cca0b341051b659b7276381756012e23427eeGopinath inputStream)); 628164cca0b341051b659b7276381756012e23427eeGopinath String line = null; 629164cca0b341051b659b7276381756012e23427eeGopinath int lineCount = 1; 630164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter.newLine(); 631164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter.write(headerInfo); 632164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter.newLine(); 633164cca0b341051b659b7276381756012e23427eeGopinath while ((line = bufferedReader.readLine()) != null) { 634164cca0b341051b659b7276381756012e23427eeGopinath if (lineCount == 2 && line.contains(SUCCESS_MESSAGE)) { 635164cca0b341051b659b7276381756012e23427eeGopinath launchSuccess = true; 636164cca0b341051b659b7276381756012e23427eeGopinath } 637164cca0b341051b659b7276381756012e23427eeGopinath if (launchSuccess && lineCount == 4) { 638164cca0b341051b659b7276381756012e23427eeGopinath String launchSplit[] = line.split(":"); 639164cca0b341051b659b7276381756012e23427eeGopinath launchTime = launchSplit[1].trim(); 640164cca0b341051b659b7276381756012e23427eeGopinath } 641164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter.write(line); 642164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter.newLine(); 643164cca0b341051b659b7276381756012e23427eeGopinath lineCount++; 644164cca0b341051b659b7276381756012e23427eeGopinath } 645164cca0b341051b659b7276381756012e23427eeGopinath mBufferedWriter.flush(); 646164cca0b341051b659b7276381756012e23427eeGopinath inputStream.close(); 647164cca0b341051b659b7276381756012e23427eeGopinath } catch (IOException e) { 648164cca0b341051b659b7276381756012e23427eeGopinath Log.w(TAG, "Error writing the launch file", e); 649164cca0b341051b659b7276381756012e23427eeGopinath } 650164cca0b341051b659b7276381756012e23427eeGopinath return launchTime; 651164cca0b341051b659b7276381756012e23427eeGopinath } 652164cca0b341051b659b7276381756012e23427eeGopinath 653f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine } 654f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine} 655