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.ActivityManager; 20 import android.app.IActivityManager; 21 import android.app.Instrumentation; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.pm.PackageManager; 25 import android.content.pm.ResolveInfo; 26 import android.os.Bundle; 27 import android.os.ParcelFileDescriptor; 28 import android.os.RemoteException; 29 import android.support.test.InstrumentationRegistry; 30 import android.support.test.launcherhelper.ILauncherStrategy; 31 import android.support.test.launcherhelper.LauncherStrategyFactory; 32 import android.support.test.rule.logging.AtraceLogger; 33 import android.support.test.uiautomator.By; 34 import android.support.test.uiautomator.UiDevice; 35 import android.support.test.uiautomator.UiObject2; 36 import android.support.test.uiautomator.Until; 37 import android.util.Log; 38 39 import java.io.BufferedReader; 40 import java.io.File; 41 import java.io.FileInputStream; 42 import java.io.InputStream; 43 import java.io.InputStreamReader; 44 import java.io.IOException; 45 import java.util.HashSet; 46 import java.util.HashMap; 47 import java.util.List; 48 import java.util.LinkedHashMap; 49 import java.util.Map; 50 import java.util.Set; 51 52 import org.junit.After; 53 import org.junit.Before; 54 import org.junit.Test; 55 56 public class AppTransitionTests { 57 58 private static final String TAG = AppTransitionTests.class.getSimpleName(); 59 private static final int JOIN_TIMEOUT = 10000; 60 private static final int DEFAULT_DROP_CACHE_DELAY = 2000; 61 private static final String DEFAULT_POST_LAUNCH_TIMEOUT = "5000"; 62 private static final String DEFAULT_LAUNCH_COUNT = "10"; 63 private static final String SUCCESS_MESSAGE = "Status: ok"; 64 private static final String HOT_LAUNCH_MESSAGE = "Warning: Activity not started, its current" 65 + " task has been brought to the front"; 66 private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh"; 67 private static final String APP_LAUNCH_CMD = "am start -W -n"; 68 private static final String FORCE_STOP = "am force-stop "; 69 private static final String PRE_LAUNCH_APPS = "pre_launch_apps"; 70 private static final String LAUNCH_APPS = "launch_apps"; 71 private static final String KEY_LAUNCH_ITERATIONS = "launch_iteration"; 72 private static final String KEY_POST_LAUNCH_TIMEOUT = "postlaunch_timeout"; 73 private static final String COLD_LAUNCH = "cold_launch"; 74 private static final String HOT_LAUNCH = "hot_launch"; 75 private static final String NOT_SURE = "not_sure"; 76 private static final String ACTIVITY = "Activity"; 77 private static final String NOT_SUCCESSFUL_MESSAGE = "App launch not successful"; 78 private static final String KEY_TRACE_DIRECTORY = "trace_directory"; 79 private static final String KEY_TRACE_CATEGORY = "trace_categories"; 80 private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize"; 81 private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval"; 82 private static final String DEFAULT_TRACE_CATEGORIES = "sched,freq,gfx,view,dalvik,webview," 83 + "input,wm,disk,am,wm"; 84 private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000"; 85 private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10"; 86 private static final String DELIMITER = ","; 87 private static final String SYSTEMUI_PACKAGE = "com.android.systemui"; 88 private Context mContext; 89 private UiDevice mDevice; 90 private PackageManager mPackageManager; 91 private IActivityManager mActivityManager; 92 private ILauncherStrategy mLauncherStrategy = null; 93 private Map<String, Intent> mAppLaunchIntentsMapping = null; 94 private String mTraceDirectoryStr = null; 95 private Bundle mResult = new Bundle(); 96 private Bundle mArgs; 97 private String mPreAppsList; 98 private int mLaunchIterations; 99 private int mPostLaunchTimeout; 100 private String[] mAppListArray; 101 private String[] mPreAppsListArray; 102 private File mRootTrace = null; 103 private File mRootTraceSubDir = null; 104 private int mTraceBufferSize = 0; 105 private int mTraceDumpInterval = 0; 106 private Set<String> mTraceCategoriesSet = null; 107 private AtraceLogger mAtraceLogger = null; 108 private String mComponentName = null; 109 private Map<String,String> mPreAppsComponentName = new HashMap<String, String>(); 110 111 @Before 112 public void setUp() throws Exception { 113 mPackageManager = getInstrumentation().getContext().getPackageManager(); 114 mContext = getInstrumentation().getContext(); 115 mArgs = InstrumentationRegistry.getArguments(); 116 mActivityManager = ActivityManager.getService(); 117 mDevice = UiDevice.getInstance(getInstrumentation()); 118 mLauncherStrategy = LauncherStrategyFactory.getInstance(mDevice).getLauncherStrategy(); 119 createLaunchIntentMappings(); 120 String mAppsList = mArgs.getString(LAUNCH_APPS); 121 mPreAppsList = mArgs.getString(PRE_LAUNCH_APPS); 122 mLaunchIterations = Integer.parseInt(mArgs.getString(KEY_LAUNCH_ITERATIONS, 123 DEFAULT_LAUNCH_COUNT)); 124 mPostLaunchTimeout = Integer.parseInt(mArgs.getString(KEY_POST_LAUNCH_TIMEOUT, 125 DEFAULT_POST_LAUNCH_TIMEOUT)); 126 if (null == mAppsList && mAppsList.isEmpty()) { 127 throw new IllegalArgumentException("Need atleast one app to do the" 128 + " app transition from launcher"); 129 } 130 mAppsList = mAppsList.replaceAll("%"," "); 131 mAppListArray = mAppsList.split(DELIMITER); 132 133 // Parse the trace parameters 134 mTraceDirectoryStr = mArgs.getString(KEY_TRACE_DIRECTORY); 135 if (isTracesEnabled()) { 136 String traceCategoriesStr = mArgs 137 .getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES); 138 mTraceBufferSize = Integer.parseInt(mArgs.getString(KEY_TRACE_BUFFERSIZE, 139 DEFAULT_TRACE_BUFFER_SIZE)); 140 mTraceDumpInterval = Integer.parseInt(mArgs.getString(KEY_TRACE_DUMPINTERVAL, 141 DEFAULT_TRACE_DUMP_INTERVAL)); 142 mTraceCategoriesSet = new HashSet<String>(); 143 if (!traceCategoriesStr.isEmpty()) { 144 String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER); 145 for (int i = 0; i < traceCategoriesSplit.length; i++) { 146 mTraceCategoriesSet.add(traceCategoriesSplit[i]); 147 } 148 } 149 } 150 mDevice.setOrientationNatural(); 151 sleep(mPostLaunchTimeout); 152 cleanTestApps(); 153 } 154 155 @After 156 public void tearDown() throws Exception{ 157 cleanTestApps(); 158 getInstrumentation().sendStatus(0, mResult); 159 } 160 161 /** 162 * Cold launch given list of apps for given launch count from the launcher screen. 163 * @throws IOException if there are issues in writing atrace file 164 * @throws InterruptedException if there are interrupt during the sleep 165 * @throws RemoteException if press home is not successful 166 */ 167 @Test 168 public void testColdLaunchFromLauncher() throws IOException, InterruptedException, 169 RemoteException { 170 if (isTracesEnabled()) { 171 createTraceDirectory("testColdLaunchFromLauncher"); 172 } 173 // Perform cold app launch from launcher screen 174 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 175 String appName = mAppListArray[appCount]; 176 // Additional launch to account for cold launch 177 if (setupAppLaunch(appName) == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 178 continue; 179 } 180 closeApps(new String[] { 181 appName 182 }); 183 getInstrumentation().getUiAutomation() 184 .executeShellCommand(DROP_CACHE_SCRIPT); 185 sleep(DEFAULT_DROP_CACHE_DELAY); 186 for (int launchCount = 0; launchCount <= mLaunchIterations; launchCount++) { 187 if (null != mAtraceLogger) { 188 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 189 mTraceDumpInterval, mRootTraceSubDir, 190 String.format("%s-%d", appName, launchCount)); 191 } 192 mLauncherStrategy.launch(appName, mComponentName.split("\\/")[0]); 193 if (null != mAtraceLogger) { 194 mAtraceLogger.atraceStop(); 195 } 196 sleep(mPostLaunchTimeout); 197 mDevice.pressHome(); 198 mDevice.waitForIdle(); 199 closeApps(new String[] { 200 appName 201 }); 202 sleep(mPostLaunchTimeout); 203 getInstrumentation().getUiAutomation() 204 .executeShellCommand(DROP_CACHE_SCRIPT); 205 sleep(DEFAULT_DROP_CACHE_DELAY); 206 } 207 mComponentName = null; 208 // Update the result with the component name 209 updateResult(appName); 210 } 211 } 212 213 /** 214 * Hot launch given list of apps for given launch count from the launcher screen. Same method can be 215 * used to test app to home transition delay information as well. 216 * @throws IOException if there are issues in writing atrace file 217 * @throws InterruptedException if there are interrupt during the sleep 218 * @throws RemoteException if press home is not successful 219 */ 220 @Test 221 public void testHotLaunchFromLauncher() throws IOException, InterruptedException, 222 RemoteException { 223 if (isTracesEnabled()) { 224 createTraceDirectory("testHotLaunchFromLauncher"); 225 } 226 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 227 String appName = mAppListArray[appCount]; 228 // Additional launch to account for cold launch 229 if (setupAppLaunch(appName) == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 230 continue; 231 } 232 // Hot app launch for given (launch iterations + 1) times. 233 for (int launchCount = 0; launchCount <= (mLaunchIterations); launchCount++) { 234 if (null != mAtraceLogger) { 235 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 236 mTraceDumpInterval, mRootTraceSubDir, 237 String.format("%s-%d", appName, (launchCount))); 238 } 239 mLauncherStrategy.launch(appName, mComponentName.split("\\/")[0]); 240 if (null != mAtraceLogger) { 241 mAtraceLogger.atraceStop(); 242 } 243 sleep(mPostLaunchTimeout); 244 mDevice.pressHome(); 245 sleep(mPostLaunchTimeout); 246 } 247 mComponentName = null; 248 // Update the result with the component name 249 updateResult(appName); 250 } 251 } 252 253 /** 254 * Launch an app and press recents for given list of apps for given launch counts. 255 * @throws IOException if there are issues in writing atrace file 256 * @throws InterruptedException if there are interrupt during the sleep 257 * @throws RemoteException if press recent apps is not successful 258 */ 259 @Test 260 public void testAppToRecents() throws IOException, InterruptedException, RemoteException { 261 if (isTracesEnabled()) { 262 createTraceDirectory("testAppToRecents"); 263 } 264 if (null == mPreAppsList && mPreAppsList.isEmpty()) { 265 throw new IllegalArgumentException("Need atleast few apps in the " 266 + "recents before starting the test"); 267 } 268 mPreAppsList = mPreAppsList.replaceAll("%"," "); 269 mPreAppsListArray = mPreAppsList.split(DELIMITER); 270 mPreAppsComponentName.clear(); 271 populateRecentsList(); 272 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 273 String appName = mAppListArray[appCount]; 274 long appLaunchTime = -1L; 275 for (int launchCount = 0; launchCount <= mLaunchIterations; launchCount++) { 276 mLauncherStrategy.launch(appName, mPreAppsComponentName.get(appName).split( 277 "\\/")[0]); 278 sleep(mPostLaunchTimeout); 279 if (null != mAtraceLogger && launchCount > 0) { 280 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 281 mTraceDumpInterval, mRootTraceSubDir, 282 String.format("%s-%d", appName, launchCount - 1)); 283 } 284 pressUiRecentApps(); 285 sleep(mPostLaunchTimeout); 286 if (null != mAtraceLogger && launchCount > 0) { 287 mAtraceLogger.atraceStop(); 288 } 289 mDevice.pressHome(); 290 sleep(mPostLaunchTimeout); 291 } 292 updateResult(appName); 293 } 294 } 295 296 /** 297 * Hot launch an app from recents for given list of apps for given launch counts. 298 * @throws IOException if there are issues in writing atrace file 299 * @throws InterruptedException if there are interrupt during the sleep 300 * @throws RemoteException if press recent apps is not successful 301 */ 302 @Test 303 public void testHotLaunchFromRecents() throws IOException, InterruptedException, 304 RemoteException { 305 if (isTracesEnabled()) { 306 createTraceDirectory("testHotLaunchFromRecents"); 307 } 308 if (null == mPreAppsList && mPreAppsList.isEmpty()) { 309 throw new IllegalArgumentException("Need atleast few apps in the" 310 + " recents before starting the test"); 311 } 312 mPreAppsList = mPreAppsList.replaceAll("%", " "); 313 mPreAppsListArray = mPreAppsList.split(DELIMITER); 314 mPreAppsComponentName.clear(); 315 populateRecentsList(); 316 for (int appCount = 0; appCount < mAppListArray.length; appCount++) { 317 String appName = mAppListArray[appCount]; 318 // To bring the app to launch as first item from recents task. 319 mLauncherStrategy.launch(appName, mPreAppsComponentName.get(appName).split( 320 "\\/")[0]); 321 sleep(mPostLaunchTimeout); 322 for (int launchCount = 0; launchCount <= mLaunchIterations; launchCount++) { 323 if (null != mAtraceLogger) { 324 mAtraceLogger.atraceStart(mTraceCategoriesSet, mTraceBufferSize, 325 mTraceDumpInterval, mRootTraceSubDir, 326 String.format("%s-%d", appName, (launchCount))); 327 } 328 openMostRecentTask(); 329 sleep(mPostLaunchTimeout); 330 if (null != mAtraceLogger) { 331 mAtraceLogger.atraceStop(); 332 } 333 mDevice.pressHome(); 334 sleep(mPostLaunchTimeout); 335 } 336 updateResult(appName); 337 } 338 } 339 340 /** 341 * Launch given app to account for the cold launch and track 342 * component name associated with the app. 343 * @throws RemoteException if press home is not successful 344 * @param appName 345 * @return 346 */ 347 public long setupAppLaunch(String appName) throws RemoteException { 348 long appLaunchTime = startApp(appName, NOT_SURE); 349 if (appLaunchTime == ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP) { 350 return appLaunchTime; 351 } 352 sleep(mPostLaunchTimeout); 353 mDevice.pressHome(); 354 sleep(mPostLaunchTimeout); 355 return appLaunchTime; 356 } 357 358 /** 359 * Press on the recents icon 360 * @throws RemoteException if press recents is not successful 361 */ 362 private void pressUiRecentApps() throws RemoteException { 363 mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "recent_apps")).click(); 364 } 365 366 /** 367 * To open the home screen. 368 * @throws RemoteException if press home is not successful 369 */ 370 private void pressUiHome() throws RemoteException { 371 mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "home")).click(); 372 } 373 374 /** 375 * Open recents task and click on the most recent task. 376 * @throws RemoteException if press recents is not successful 377 */ 378 public void openMostRecentTask() throws RemoteException { 379 pressUiRecentApps(); 380 UiObject2 recentsView = mDevice.wait(Until.findObject( 381 By.res(SYSTEMUI_PACKAGE, "recents_view")), 5000); 382 List<UiObject2> recentsTasks = recentsView.getChildren().get(0) 383 .getChildren(); 384 UiObject2 mostRecentTask = recentsTasks.get(recentsTasks.size() - 1); 385 mostRecentTask.click(); 386 } 387 388 /** 389 * Create sub directory under the trace root directory to store the trace files captured during 390 * the app transition. 391 * @param subDirectoryName 392 */ 393 private void createTraceDirectory(String subDirectoryName) throws IOException { 394 mRootTrace = new File(mTraceDirectoryStr); 395 if (!mRootTrace.exists() && !mRootTrace.mkdirs()) { 396 throw new IOException("Unable to create the trace directory"); 397 } 398 mRootTraceSubDir = new File(mRootTrace, subDirectoryName); 399 if (!mRootTraceSubDir.exists() && !mRootTraceSubDir.mkdirs()) { 400 throw new IOException("Unable to create the trace sub directory"); 401 } 402 mAtraceLogger = AtraceLogger.getAtraceLoggerInstance(getInstrumentation()); 403 } 404 405 /** 406 * Force stop the given list of apps, clear the cache and return to home screen. 407 * @throws RemoteException if press home is not successful 408 */ 409 private void cleanTestApps() throws RemoteException { 410 if (null != mPreAppsListArray && mPreAppsListArray.length > 0) { 411 closeApps(mPreAppsListArray); 412 } 413 closeApps(mAppListArray); 414 getInstrumentation().getUiAutomation() 415 .executeShellCommand(DROP_CACHE_SCRIPT); 416 sleep(DEFAULT_DROP_CACHE_DELAY); 417 mDevice.pressHome(); 418 sleep(mPostLaunchTimeout); 419 } 420 421 /** 422 * Populate the recents list with given list of apps. 423 * @throws RemoteException if press home is not successful 424 */ 425 private void populateRecentsList() throws RemoteException { 426 for (int preAppCount = 0; preAppCount < mPreAppsListArray.length; preAppCount++) { 427 startApp(mPreAppsListArray[preAppCount], NOT_SURE); 428 mPreAppsComponentName.put(mPreAppsListArray[preAppCount], mComponentName); 429 sleep(mPostLaunchTimeout); 430 mDevice.pressHome(); 431 sleep(mPostLaunchTimeout); 432 } 433 mComponentName = null; 434 } 435 436 437 /** 438 * To obtain the app name and corresponding intent to launch the app. 439 */ 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 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 */ 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 499 public AppLaunchRunnable(Intent intent, String launchMode) { 500 mLaunchIntent = intent; 501 mLaunchMode = launchMode; 502 } 503 504 public Long getResult() { 505 return mResult; 506 } 507 508 public String getCmpName() { 509 return mCmpName; 510 } 511 512 @Override 513 public void run() { 514 String packageName = mLaunchIntent.getComponent().getPackageName(); 515 String componentName = mLaunchIntent.getComponent().flattenToString(); 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 */ 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 == 3)) { 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 */ 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 */ 595 private boolean isTracesEnabled(){ 596 return (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty()); 597 } 598 599 /** 600 * Update the result status 601 * @param appName 602 */ 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().flattenToString()); 611 } 612 } 613 614 615 /** 616 * To sleep for given millisecs. 617 * @param time 618 */ 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 */ 631 private Instrumentation getInstrumentation() { 632 return InstrumentationRegistry.getInstrumentation(); 633 } 634 } 635