1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.apptransition.tests; 18 19 import android.app.ActivityManagerNative; 20 import android.app.IActivityManager; 21 import android.app.Instrumentation; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.ActivityInfo; 26 import android.content.pm.PackageManager; 27 import android.content.pm.PackageManager.NameNotFoundException; 28 import android.content.pm.ResolveInfo; 29 import android.os.Bundle; 30 import android.os.Environment; 31 import android.os.ParcelFileDescriptor; 32 import android.os.RemoteException; 33 import android.support.test.InstrumentationRegistry; 34 import android.support.test.launcherhelper.ILauncherStrategy; 35 import android.support.test.launcherhelper.LauncherStrategyFactory; 36 import android.support.test.rule.logging.AtraceLogger; 37 import android.support.test.uiautomator.By; 38 import android.support.test.uiautomator.UiDevice; 39 import android.support.test.uiautomator.UiObjectNotFoundException; 40 import android.support.test.uiautomator.UiObject2; 41 import android.support.test.uiautomator.Until; 42 import android.util.Log; 43 44 import java.io.BufferedReader; 45 import java.io.File; 46 import java.io.FileInputStream; 47 import java.io.InputStream; 48 import java.io.InputStreamReader; 49 import java.io.IOException; 50 import java.util.ArrayList; 51 import java.util.HashSet; 52 import java.util.List; 53 import java.util.LinkedHashMap; 54 import java.util.Map; 55 import java.util.Set; 56 57 import org.junit.After; 58 import org.junit.Before; 59 import org.junit.Test; 60 61 public class AppTransitionTests { 62 63 private static final String TAG = AppTransitionTests.class.getSimpleName(); 64 private static final int JOIN_TIMEOUT = 10000; 65 private static final String DEFAULT_POST_LAUNCH_TIMEOUT = "5000"; 66 private static final String DEFAULT_LAUNCH_COUNT = "10"; 67 private static final String SUCCESS_MESSAGE = "Status: ok"; 68 private static final String HOT_LAUNCH_MESSAGE = "Warning: Activity not started, its current" 69 + " task has been brought to the front"; 70 private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh"; 71 private static final String APP_LAUNCH_CMD = "am start -W -n"; 72 private static final String FORCE_STOP = "am force-stop "; 73 private static final String PRE_LAUNCH_APPS = "pre_launch_apps"; 74 private static final String LAUNCH_APPS = "launch_apps"; 75 private static final String KEY_LAUNCH_ITERATIONS = "launch_iteration"; 76 private static final String KEY_POST_LAUNCH_TIMEOUT = "postlaunch_timeout"; 77 private static final String COLD_LAUNCH = "cold_launch"; 78 private static final String HOT_LAUNCH = "hot_launch"; 79 private static final String NOT_SURE = "not_sure"; 80 private static final String ACTIVITY = "Activity"; 81 private static final String NOT_SUCCESSFUL_MESSAGE = "App launch not successful"; 82 private static final String KEY_TRACE_DIRECTORY = "trace_directory"; 83 private static final String KEY_TRACE_CATEGORY = "trace_categories"; 84 private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize"; 85 private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval"; 86 private static final String DEFAULT_TRACE_CATEGORIES = "sched,freq,gfx,view,dalvik,webview," 87 + "input,wm,disk,am,wm"; 88 private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000"; 89 private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10"; 90 private static final String DELIMITER = ","; 91 private static final String SYSTEMUI_PACKAGE = "com.android.systemui"; 92 private Context mContext; 93 private UiDevice mDevice; 94 private PackageManager mPackageManager; 95 private IActivityManager mActivityManager; 96 private ILauncherStrategy mLauncherStrategy = null; 97 private Map<String, Intent> mAppLaunchIntentsMapping = null; 98 private String mTraceDirectoryStr = null; 99 private Bundle mResult = new Bundle(); 100 private Bundle mArgs; 101 private String mPreAppsList; 102 private int mLaunchIterations; 103 private int mPostLaunchTimeout; 104 private String[] mAppListArray; 105 private String[] mPreAppsListArray; 106 private File mRootTrace = null; 107 private File mRootTraceSubDir = null; 108 private int mTraceBufferSize = 0; 109 private int mTraceDumpInterval = 0; 110 private Set<String> mTraceCategoriesSet = null; 111 private AtraceLogger mAtraceLogger = null; 112 private String mComponentName = null; 113 114 @Before setUp()115 public void setUp() throws Exception { 116 mPackageManager = getInstrumentation().getContext().getPackageManager(); 117 mContext = getInstrumentation().getContext(); 118 mArgs = InstrumentationRegistry.getArguments(); 119 mActivityManager = ActivityManagerNative.getDefault(); 120 mDevice = UiDevice.getInstance(getInstrumentation()); 121 mLauncherStrategy = LauncherStrategyFactory.getInstance(mDevice).getLauncherStrategy(); 122 createLaunchIntentMappings(); 123 String mAppsList = mArgs.getString(LAUNCH_APPS); 124 mPreAppsList = mArgs.getString(PRE_LAUNCH_APPS); 125 mLaunchIterations = Integer.parseInt(mArgs.getString(KEY_LAUNCH_ITERATIONS, 126 DEFAULT_LAUNCH_COUNT)); 127 mPostLaunchTimeout = Integer.parseInt(mArgs.getString(KEY_POST_LAUNCH_TIMEOUT, 128 DEFAULT_POST_LAUNCH_TIMEOUT)); 129 if (null == mAppsList && mAppsList.isEmpty()) { 130 throw new IllegalArgumentException("Need atleast one app to do the" 131 + " app transition from launcher"); 132 } 133 mAppsList = mAppsList.replaceAll("%"," "); 134 mAppListArray = mAppsList.split(DELIMITER); 135 136 // Parse the trace parameters 137 mTraceDirectoryStr = mArgs.getString(KEY_TRACE_DIRECTORY); 138 if (isTracesEnabled()) { 139 String traceCategoriesStr = mArgs 140 .getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES); 141 mTraceBufferSize = Integer.parseInt(mArgs.getString(KEY_TRACE_BUFFERSIZE, 142 DEFAULT_TRACE_BUFFER_SIZE)); 143 mTraceDumpInterval = Integer.parseInt(mArgs.getString(KEY_TRACE_DUMPINTERVAL, 144 DEFAULT_TRACE_DUMP_INTERVAL)); 145 mTraceCategoriesSet = new HashSet<String>(); 146 if (!traceCategoriesStr.isEmpty()) { 147 String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER); 148 for (int i = 0; i < traceCategoriesSplit.length; i++) { 149 mTraceCategoriesSet.add(traceCategoriesSplit[i]); 150 } 151 } 152 } 153 mDevice.setOrientationNatural(); 154 cleanTestApps(); 155 } 156 157 @After tearDown()158 public void tearDown() throws Exception{ 159 cleanTestApps(); 160 getInstrumentation().sendStatus(0, mResult); 161 } 162 163 /** 164 * Cold launch given list of apps for given launch count from the launcher screen. 165 * @throws IOException if there are issues in writing atrace file 166 * @throws InterruptedException if there are interrupt during the sleep 167 * @throws RemoteException if press home is not successful 168 */ 169 @Test testColdLaunchFromLauncher()170 public void testColdLaunchFromLauncher() throws IOException, InterruptedException, 171 RemoteException { 172 if (isTracesEnabled()) { 173 createTraceDirectory("testColdLaunchFromLauncher"); 174 } 175 // Perform cold app launch from launcher screen 176 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 177 String appName = mAppListArray[appCount]; 178 for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) { 179 if (null != mAtraceLogger) { 180 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 181 mTraceDumpInterval, mRootTraceSubDir, 182 String.format("%s-%d", appName, launchCount)); 183 } 184 mLauncherStrategy.launch(appName, mAppLaunchIntentsMapping.get(appName). 185 getComponent().flattenToShortString().split("\\/")[0]); 186 if (null != mAtraceLogger) { 187 mAtraceLogger.atraceStop(); 188 } 189 sleep(mPostLaunchTimeout); 190 closeApps(new String[] { 191 appName 192 }); 193 pressUiHome(); 194 sleep(mPostLaunchTimeout); 195 getInstrumentation().getUiAutomation() 196 .executeShellCommand(DROP_CACHE_SCRIPT); 197 } 198 // Update the result with the component name 199 updateResult(appName); 200 } 201 } 202 203 /** 204 * Hot launch given list of apps for given launch count from the launcher screen. Same method can be 205 * used to test app to home transition delay information as well. 206 * @throws IOException if there are issues in writing atrace file 207 * @throws InterruptedException if there are interrupt during the sleep 208 * @throws RemoteException if press home is not successful 209 */ 210 @Test testHotLaunchFromLauncher()211 public void testHotLaunchFromLauncher() throws IOException, InterruptedException, 212 RemoteException { 213 if (isTracesEnabled()) { 214 createTraceDirectory("testHotLaunchFromLauncher"); 215 } 216 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 217 String appName = mAppListArray[appCount]; 218 // Additional launches to account for cold launch and one hot launch. 219 if (setupAppLaunch(appName) == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 220 continue; 221 } 222 // Hot app launch for given launch iterations. 223 for (int launchCount = 0; launchCount < (mLaunchIterations); launchCount++) { 224 if (null != mAtraceLogger) { 225 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 226 mTraceDumpInterval, mRootTraceSubDir, 227 String.format("%s-%d", appName, (launchCount))); 228 } 229 mLauncherStrategy.launch(appName, mComponentName.split("\\/")[0]); 230 if (null != mAtraceLogger) { 231 mAtraceLogger.atraceStop(); 232 } 233 sleep(mPostLaunchTimeout); 234 pressUiHome(); 235 sleep(mPostLaunchTimeout); 236 } 237 // Update the result with the component name 238 updateResult(appName); 239 } 240 } 241 242 /** 243 * Launch an app and press recents for given list of apps for given launch counts. 244 * @throws IOException if there are issues in writing atrace file 245 * @throws InterruptedException if there are interrupt during the sleep 246 * @throws RemoteException if press recent apps is not successful 247 */ 248 @Test testAppToRecents()249 public void testAppToRecents() throws IOException, InterruptedException, RemoteException { 250 if (isTracesEnabled()) { 251 createTraceDirectory("testAppToRecents"); 252 } 253 if (null == mPreAppsList && mPreAppsList.isEmpty()) { 254 throw new IllegalArgumentException("Need atleast few apps in the " 255 + "recents before starting the test"); 256 } 257 mPreAppsList = mPreAppsList.replaceAll("%"," "); 258 mPreAppsListArray = mPreAppsList.split(DELIMITER); 259 populateRecentsList(); 260 // Increment by one to account for the first cold launch and discard it 261 // while parsing 262 mLaunchIterations++; 263 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 264 String appName = mAppListArray[appCount]; 265 long appLaunchTime = -1L; 266 for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) { 267 // "NOT_SURE" for first launch because apps in the PreAppsList 268 // could be part of AppList 269 if (launchCount == 0) { 270 appLaunchTime = startApp(appName, NOT_SURE); 271 } else { 272 appLaunchTime = startApp(appName, HOT_LAUNCH); 273 } 274 if (appLaunchTime == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 275 break; 276 } 277 sleep(mPostLaunchTimeout); 278 if (null != mAtraceLogger && launchCount > 0) { 279 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 280 mTraceDumpInterval, mRootTraceSubDir, 281 String.format("%s-%d", appName, launchCount - 1)); 282 } 283 pressUiRecentApps(); 284 sleep(mPostLaunchTimeout); 285 if (null != mAtraceLogger && launchCount > 0) { 286 mAtraceLogger.atraceStop(); 287 } 288 pressUiHome(); 289 sleep(mPostLaunchTimeout); 290 } 291 updateResult(appName); 292 } 293 } 294 295 /** 296 * Hot launch an app from recents for given list of apps for given launch counts. 297 * @throws IOException if there are issues in writing atrace file 298 * @throws InterruptedException if there are interrupt during the sleep 299 * @throws RemoteException if press recent apps is not successful 300 */ 301 @Test testHotLaunchFromRecents()302 public void testHotLaunchFromRecents() throws IOException, InterruptedException, 303 RemoteException { 304 if (isTracesEnabled()) { 305 createTraceDirectory("testHotLaunchFromRecents"); 306 } 307 if (null == mPreAppsList && mPreAppsList.isEmpty()) { 308 throw new IllegalArgumentException("Need atleast few apps in the" 309 + " recents before starting the test"); 310 } 311 mPreAppsList = mPreAppsList.replaceAll("%", " "); 312 mPreAppsListArray = mPreAppsList.split(DELIMITER); 313 populateRecentsList(); 314 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 315 String appName = mAppListArray[appCount]; 316 // Additional launches to account for cold launch and one hot launch. 317 if (setupAppLaunch(appName) == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 318 continue; 319 } 320 for (int launchCount = 0; launchCount < (mLaunchIterations); launchCount++) { 321 if (null != mAtraceLogger) { 322 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 323 mTraceDumpInterval, mRootTraceSubDir, 324 String.format("%s-%d", appName, (launchCount))); 325 } 326 openMostRecentTask(); 327 sleep(mPostLaunchTimeout); 328 if (null != mAtraceLogger) { 329 mAtraceLogger.atraceStop(); 330 } 331 pressUiHome(); 332 sleep(mPostLaunchTimeout); 333 } 334 updateResult(appName); 335 } 336 } 337 338 /** 339 * Launch given app couple of times to account for the cold launch and one hot launch and 340 * to update component name associated with the hot launch of the given app. 341 * @throws RemoteException if press home is not successful 342 * @param appName 343 * @return 344 */ setupAppLaunch(String appName)345 public long setupAppLaunch(String appName) throws RemoteException { 346 long appLaunchTime = startApp(appName, NOT_SURE); 347 if (appLaunchTime == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 348 return appLaunchTime; 349 } 350 sleep(mPostLaunchTimeout); 351 pressUiHome(); 352 appLaunchTime = startApp(appName, HOT_LAUNCH); 353 if (appLaunchTime == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 354 return appLaunchTime; 355 } 356 sleep(mPostLaunchTimeout); 357 pressUiHome(); 358 return appLaunchTime; 359 } 360 361 /** 362 * Press on the recents icon 363 * @throws RemoteException if press recents is not successful 364 */ pressUiRecentApps()365 private void pressUiRecentApps() throws RemoteException { 366 mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "recent_apps")).click(); 367 } 368 369 /** 370 * To open the home screen. 371 * @throws RemoteException if press home is not successful 372 */ pressUiHome()373 private void pressUiHome() throws RemoteException { 374 mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "home")).click(); 375 } 376 377 /** 378 * Open recents task and click on the most recent task. 379 * @throws RemoteException if press recents is not successful 380 */ openMostRecentTask()381 public void openMostRecentTask() throws RemoteException { 382 pressUiRecentApps(); 383 UiObject2 recentsView = mDevice.wait(Until.findObject( 384 By.res(SYSTEMUI_PACKAGE, "recents_view")), 5000); 385 List<UiObject2> recentsTasks = recentsView.getChildren().get(0) 386 .getChildren(); 387 UiObject2 mostRecentTask = recentsTasks.get(recentsTasks.size() - 1); 388 mostRecentTask.click(); 389 } 390 391 /** 392 * Create sub directory under the trace root directory to store the trace files captured during 393 * the app transition. 394 * @param subDirectoryName 395 */ createTraceDirectory(String subDirectoryName)396 private void createTraceDirectory(String subDirectoryName) throws IOException { 397 mRootTrace = new File(mTraceDirectoryStr); 398 if (!mRootTrace.exists() && !mRootTrace.mkdirs()) { 399 throw new IOException("Unable to create the trace directory"); 400 } 401 mRootTraceSubDir = new File(mRootTrace, subDirectoryName); 402 if (!mRootTraceSubDir.exists() && !mRootTraceSubDir.mkdirs()) { 403 throw new IOException("Unable to create the trace sub directory"); 404 } 405 mAtraceLogger = AtraceLogger.getAtraceLoggerInstance(getInstrumentation()); 406 } 407 408 /** 409 * Force stop the given list of apps, clear the cache and return to home screen. 410 * @throws RemoteException if press home is not successful 411 */ cleanTestApps()412 private void cleanTestApps() throws RemoteException { 413 if (null != mPreAppsListArray && mPreAppsListArray.length > 0) { 414 closeApps(mPreAppsListArray); 415 } 416 closeApps(mAppListArray); 417 getInstrumentation().getUiAutomation() 418 .executeShellCommand(DROP_CACHE_SCRIPT); 419 pressUiHome(); 420 sleep(mPostLaunchTimeout); 421 } 422 423 /** 424 * Populate the recents list with given list of apps. 425 * @throws RemoteException if press home is not successful 426 */ populateRecentsList()427 private void populateRecentsList() throws RemoteException { 428 for (int preAppCount = 0; preAppCount < mPreAppsListArray.length; preAppCount++) { 429 startApp(mPreAppsListArray[preAppCount], COLD_LAUNCH); 430 sleep(mPostLaunchTimeout); 431 pressUiHome(); 432 sleep(mPostLaunchTimeout); 433 } 434 } 435 436 437 /** 438 * To obtain the app name and corresponding intent to launch the app. 439 */ createLaunchIntentMappings()440 private void createLaunchIntentMappings() { 441 mAppLaunchIntentsMapping = new LinkedHashMap<String, Intent>(); 442 PackageManager pm = getInstrumentation().getContext() 443 .getPackageManager(); 444 Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 445 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 446 List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0); 447 resolveLoop(ris, intentToResolve, pm); 448 } 449 resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm)450 private void resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm) { 451 if (ris == null || ris.isEmpty()) { 452 Log.i(TAG, "Could not find any apps"); 453 } else { 454 for (ResolveInfo ri : ris) { 455 Intent startIntent = new Intent(intentToResolve); 456 startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 457 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 458 startIntent.setClassName(ri.activityInfo.packageName, 459 ri.activityInfo.name); 460 String appName = ri.loadLabel(pm).toString(); 461 if (appName != null) { 462 mAppLaunchIntentsMapping.put(appName, startIntent); 463 } 464 } 465 } 466 } 467 468 /** 469 * Launch an app using the app name and return the app launch time. If app launch time is -1 470 * then app launch is not successful. 471 * @param appName Name of an app as listed in the launcher 472 * @param launchMode Cold or Hot launch 473 * @return 474 */ startApp(String appName, String launchMode)475 private long startApp(String appName, String launchMode) { 476 Log.i(TAG, "Starting " + appName); 477 Intent startIntent = mAppLaunchIntentsMapping.get(appName); 478 if (startIntent == null) { 479 return -1L; 480 } 481 AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, launchMode); 482 Thread t = new Thread(runnable); 483 t.start(); 484 try { 485 t.join(JOIN_TIMEOUT); 486 } catch (InterruptedException e) { 487 // ignore 488 } 489 mComponentName = runnable.getCmpName(); 490 return runnable.getResult(); 491 } 492 493 private class AppLaunchRunnable implements Runnable { 494 private Intent mLaunchIntent; 495 private String mLaunchMode; 496 private Long mResult = -1L; 497 private String mCmpName; 498 AppLaunchRunnable(Intent intent, String launchMode)499 public AppLaunchRunnable(Intent intent, String launchMode) { 500 mLaunchIntent = intent; 501 mLaunchMode = launchMode; 502 } 503 getResult()504 public Long getResult() { 505 return mResult; 506 } 507 getCmpName()508 public String getCmpName() { 509 return mCmpName; 510 } 511 512 @Override run()513 public void run() { 514 String packageName = mLaunchIntent.getComponent().getPackageName(); 515 String componentName = mLaunchIntent.getComponent().flattenToShortString(); 516 String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName); 517 ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation() 518 .executeShellCommand(launchCmd); 519 mResult = Long.parseLong(parseLaunchTime(parcelDesc)); 520 } 521 522 /** 523 * Returns launch time if app launch is successful otherwise "-1" 524 * @param parcelDesc 525 * @return 526 */ parseLaunchTime(ParcelFileDescriptor parcelDesc)527 private String parseLaunchTime(ParcelFileDescriptor parcelDesc) { 528 String launchTime = "-1"; 529 boolean launchSuccess = false; 530 mCmpName = null; 531 try { 532 InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor()); 533 StringBuilder appLaunchOuput = new StringBuilder(); 534 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( 535 inputStream)); 536 String line = null; 537 int lineCount = 1; 538 while ((line = bufferedReader.readLine()) != null) { 539 if (lineCount == 2) { 540 if ((mLaunchMode.contains(COLD_LAUNCH) || mLaunchMode.contains(NOT_SURE)) 541 && line.contains(SUCCESS_MESSAGE)) { 542 launchSuccess = true; 543 } else if ((mLaunchMode.contains(HOT_LAUNCH) || mLaunchMode 544 .contains(NOT_SURE)) && line.contains(HOT_LAUNCH_MESSAGE)) { 545 launchSuccess = true; 546 } 547 } 548 if ((launchSuccess && (mLaunchMode.contains(COLD_LAUNCH) 549 || mLaunchMode.contains(NOT_SURE)) && lineCount == 4) || 550 (launchSuccess && (mLaunchMode.contains(HOT_LAUNCH) || 551 mLaunchMode.contains(NOT_SURE)) && lineCount == 5)) { 552 String launchSplit[] = line.split(":"); 553 launchTime = launchSplit[1].trim(); 554 } 555 // Needed to update the component name if the very first launch activity 556 // is different from hot launch activity (i.e YouTube) 557 if ((launchSuccess && (mLaunchMode.contains(HOT_LAUNCH) || 558 mLaunchMode.contains(NOT_SURE)) && lineCount == 4)) { 559 String activitySplit[] = line.split(":"); 560 if (activitySplit[0].contains(ACTIVITY)) { 561 mCmpName = activitySplit[1].trim(); 562 } 563 } 564 lineCount++; 565 } 566 inputStream.close(); 567 } catch (IOException e) { 568 Log.w(TAG, "Error writing the launch file", e); 569 } 570 return launchTime; 571 } 572 } 573 574 /** 575 * To force stop the given list of apps based on the app name. 576 * @param appNames 577 */ closeApps(String[] appNames)578 private void closeApps(String[] appNames) { 579 for (int i = 0; i < appNames.length; i++) { 580 Intent startIntent = mAppLaunchIntentsMapping.get(appNames[i]); 581 if (startIntent != null) { 582 String packageName = startIntent.getComponent().getPackageName(); 583 584 getInstrumentation().getUiAutomation().executeShellCommand( 585 FORCE_STOP + packageName); 586 } 587 sleep(1000); 588 } 589 sleep(mPostLaunchTimeout); 590 } 591 592 /** 593 * @return 594 */ isTracesEnabled()595 private boolean isTracesEnabled(){ 596 return (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty()); 597 } 598 599 /** 600 * Update the result status 601 * @param appName 602 */ updateResult(String appName)603 private void updateResult(String appName) { 604 // Component name needed for parsing the events log 605 if (null != mComponentName) { 606 mResult.putString(appName, mComponentName); 607 } else { 608 // Component name needed for parsing the events log 609 mResult.putString(appName, mAppLaunchIntentsMapping.get(appName). 610 getComponent().flattenToShortString()); 611 } 612 } 613 614 615 /** 616 * To sleep for given millisecs. 617 * @param time 618 */ sleep(int time)619 private void sleep(int time) { 620 try { 621 Thread.sleep(time); 622 } catch (InterruptedException e) { 623 // ignore 624 } 625 } 626 627 /** 628 * Return the instrumentation from the registry. 629 * @return 630 */ getInstrumentation()631 private Instrumentation getInstrumentation() { 632 return InstrumentationRegistry.getInstrumentation(); 633 } 634 } 635