1 /* 2 * Copyright (C) 2020 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.car.pm; 18 19 import static androidx.car.app.activity.CarAppActivity.ACTION_SHOW_DIALOG; 20 import static androidx.car.app.activity.CarAppActivity.ACTION_START_SECOND_INSTANCE; 21 import static androidx.car.app.activity.CarAppActivity.SECOND_INSTANCE_TITLE; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assume.assumeTrue; 27 28 import android.app.Activity; 29 import android.app.ActivityOptions; 30 import android.app.AlertDialog; 31 import android.app.UiAutomation; 32 import android.car.Car; 33 import android.car.content.pm.CarPackageManager; 34 import android.car.drivingstate.CarDrivingStateEvent; 35 import android.car.drivingstate.CarDrivingStateManager; 36 import android.content.ComponentName; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.os.Bundle; 40 import android.support.test.uiautomator.By; 41 import android.support.test.uiautomator.Configurator; 42 import android.support.test.uiautomator.UiDevice; 43 import android.support.test.uiautomator.UiObject2; 44 import android.support.test.uiautomator.Until; 45 import android.view.Display; 46 47 import androidx.car.app.activity.CarAppActivity; 48 import androidx.test.ext.junit.runners.AndroidJUnit4; 49 import androidx.test.filters.MediumTest; 50 import androidx.test.platform.app.InstrumentationRegistry; 51 52 import org.junit.After; 53 import org.junit.Before; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 57 import java.util.concurrent.CopyOnWriteArrayList; 58 import java.util.concurrent.CountDownLatch; 59 import java.util.concurrent.TimeUnit; 60 61 @RunWith(AndroidJUnit4.class) 62 @MediumTest 63 public class CarPackageManagerServiceTest { 64 private static final String ACTIVITY_BLOCKING_ACTIVITY_TEXTVIEW_ID = 65 "com.android.systemui:id/blocking_text"; 66 private static final String ACTIVITY_BLOCKING_ACTIVITY_EXIT_BUTTON_ID = 67 "com.android.systemui:id/exit_button"; 68 69 // cf_x86_auto is very slow, so uses very long timeout. 70 private static final int UI_TIMEOUT_MS = 20_000; 71 private static final int NOT_FOUND_UI_TIMEOUT_MS = 10_000; 72 private static final long ACTIVITY_TIMEOUT_MS = 5000; 73 private static final int HOME_DISPLAYED_TIMEOUT_MS = 5_000; 74 75 private CarDrivingStateManager mCarDrivingStateManager; 76 private CarPackageManager mCarPackageManager; 77 78 private UiDevice mDevice; 79 80 private static final CopyOnWriteArrayList<TempActivity> sTestingActivities = 81 new CopyOnWriteArrayList<>(); 82 83 @Before setUp()84 public void setUp() throws Exception { 85 Car car = Car.createCar(getContext()); 86 mCarDrivingStateManager = (CarDrivingStateManager) 87 car.getCarManager(Car.CAR_DRIVING_STATE_SERVICE); 88 mCarPackageManager = (CarPackageManager) 89 car.getCarManager(Car.PACKAGE_SERVICE); 90 assertNotNull(mCarDrivingStateManager); 91 92 Configurator.getInstance() 93 .setUiAutomationFlags(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); 94 mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 95 ensureHomeIsDisplayed(); 96 setDrivingStateMoving(); 97 } 98 99 @After tearDown()100 public void tearDown() throws Exception { 101 setDrivingStateParked(); 102 103 for (TempActivity testingActivity : sTestingActivities) { 104 testingActivity.finishCompletely(); 105 sTestingActivities.remove(testingActivity); 106 } 107 } 108 109 @Test testBlockingActivity_doActivity_isNotBlocked()110 public void testBlockingActivity_doActivity_isNotBlocked() throws Exception { 111 startDoActivity(/* extra= */ null); 112 113 assertThat(mDevice.wait(Until.findObject(By.text( 114 DoActivity.class.getSimpleName())), 115 UI_TIMEOUT_MS)).isNotNull(); 116 assertBlockingActivityNotFound(); 117 } 118 119 @Test testBlockingActivity_doActivity_showingDialog_isNotBlocked()120 public void testBlockingActivity_doActivity_showingDialog_isNotBlocked() throws Exception { 121 startDoActivity(DoActivity.INTENT_EXTRA_SHOW_DIALOG); 122 123 assertThat(mDevice.wait(Until.findObject(By.text( 124 DoActivity.DIALOG_TITLE)), 125 UI_TIMEOUT_MS)).isNotNull(); 126 assertBlockingActivityNotFound(); 127 } 128 129 @Test testBlockingActivity_doTemplateActivity_isNotBlocked()130 public void testBlockingActivity_doTemplateActivity_isNotBlocked() throws Exception { 131 startActivity(toComponentName(getTestContext(), CarAppActivity.class)); 132 133 assertThat(mDevice.wait(Until.findObject(By.text( 134 CarAppActivity.class.getSimpleName())), 135 UI_TIMEOUT_MS)).isNotNull(); 136 assertBlockingActivityNotFound(); 137 } 138 139 @Test testBlockingActivity_multipleDoTemplateActivity_notBlocked()140 public void testBlockingActivity_multipleDoTemplateActivity_notBlocked() throws Exception { 141 startActivity(toComponentName(getTestContext(), CarAppActivity.class)); 142 assertThat(mDevice.wait(Until.findObject(By.text( 143 CarAppActivity.class.getSimpleName())), 144 UI_TIMEOUT_MS)).isNotNull(); 145 getContext().sendBroadcast(new Intent().setAction(ACTION_START_SECOND_INSTANCE) 146 .setPackage(getTestContext().getPackageName())); 147 assertThat(mDevice.wait(Until.findObject(By.text( 148 SECOND_INSTANCE_TITLE)), 149 UI_TIMEOUT_MS)).isNotNull(); 150 assertBlockingActivityNotFound(); 151 } 152 153 @Test testBlockingActivity_doTemplateActivity_showingDialog_isBlocked()154 public void testBlockingActivity_doTemplateActivity_showingDialog_isBlocked() throws Exception { 155 startActivity(toComponentName(getTestContext(), CarAppActivity.class)); 156 assertThat(mDevice.wait(Until.findObject(By.text( 157 CarAppActivity.class.getSimpleName())), 158 UI_TIMEOUT_MS)).isNotNull(); 159 assertBlockingActivityNotFound(); 160 assertThat(mCarPackageManager.isActivityDistractionOptimized( 161 getTestContext().getPackageName(), 162 CarAppActivity.class.getName() 163 )).isTrue(); 164 165 getContext().sendBroadcast(new Intent().setAction(ACTION_SHOW_DIALOG) 166 .setPackage(getTestContext().getPackageName())); 167 168 assertThat(mDevice.wait(Until.findObject(By.res(ACTIVITY_BLOCKING_ACTIVITY_TEXTVIEW_ID)), 169 UI_TIMEOUT_MS)).isNotNull(); 170 assertThat(mCarPackageManager.isActivityDistractionOptimized( 171 getTestContext().getPackageName(), 172 CarAppActivity.class.getName() 173 )).isFalse(); 174 } 175 176 @Test testBlockingActivity_nonDoActivity_isBlocked()177 public void testBlockingActivity_nonDoActivity_isBlocked() throws Exception { 178 testBlockingActivityShownForNdoActivity(); 179 } 180 181 @Test testBlockingActivity_nonDoActivity_carIdling_isBlocked()182 public void testBlockingActivity_nonDoActivity_carIdling_isBlocked() throws Exception { 183 setDrivingStateIdling(); 184 testBlockingActivityShownForNdoActivity(); 185 } 186 testBlockingActivityShownForNdoActivity()187 private void testBlockingActivityShownForNdoActivity() { 188 startNonDoActivity(NonDoActivity.EXTRA_DO_NOTHING); 189 190 // The label should be 'Close app' since NonDoActivity is the root task. 191 assertBlockingActivityFoundAndExit("Close app"); 192 193 // To exit ABA will close nonDoActivity. 194 assertBlockingActivityNotFound(); 195 assertThat(mDevice.wait(Until.findObject(By.text(NonDoActivity.class.getSimpleName())), 196 UI_TIMEOUT_MS)).isNull(); 197 } 198 199 @Test testBlockingActivity_DoLaunchesNonDoOnCreate_isBlocked()200 public void testBlockingActivity_DoLaunchesNonDoOnCreate_isBlocked() throws Exception { 201 startDoActivity(DoActivity.INTENT_EXTRA_LAUNCH_NONDO); 202 203 // The label should be 'Back' since NonDo's root task is DO. 204 assertBlockingActivityFoundAndExit("Back"); 205 206 // To exit ABA will show the root task, DoActivity. 207 assertBlockingActivityNotFound(); 208 assertThat(mDevice.wait(Until.findObject(By.text(DoActivity.class.getSimpleName())), 209 UI_TIMEOUT_MS)).isNotNull(); 210 } 211 212 @Test testBlockingActivity_DoLaunchesNonDo_nonDoIsKilled_noBlockingActivity()213 public void testBlockingActivity_DoLaunchesNonDo_nonDoIsKilled_noBlockingActivity() 214 throws Exception { 215 startDoActivity(DoActivity.INTENT_EXTRA_LAUNCH_NONDO_NEW_TASK); 216 assertBlockingActivityFound(); 217 218 for (TempActivity activity : sTestingActivities) { 219 if (activity instanceof NonDoActivity) { 220 activity.finishCompletely(); 221 sTestingActivities.remove(activity); 222 } 223 } 224 225 assertBlockingActivityNotFound(); 226 // After NonDo & ABA finishes, DoActivity will come to the top. 227 assertActivityLaunched(DoActivity.class.getSimpleName()); 228 } 229 230 @Test testBlockingActivity_DoLaunchesNonDo_DoIsKilled_isBlocked()231 public void testBlockingActivity_DoLaunchesNonDo_DoIsKilled_isBlocked() 232 throws Exception { 233 startDoActivity(DoActivity.INTENT_EXTRA_LAUNCH_NONDO_NEW_TASK); 234 assertBlockingActivityFound(); 235 236 for (TempActivity activity : sTestingActivities) { 237 if (activity instanceof DoActivity) { 238 activity.finishCompletely(); 239 sTestingActivities.remove(activity); 240 } 241 } 242 243 assertBlockingActivityFound(); 244 } 245 246 @Test testBlockingActivity_nonDoActivity_translucentDoOnTopOfBlockingActivityRemoved_nonDoRemainsBlocked()247 public void testBlockingActivity_nonDoActivity_translucentDoOnTopOfBlockingActivityRemoved_nonDoRemainsBlocked() { 248 startNonDoActivity(NonDoActivity.EXTRA_DO_NOTHING); 249 waitForBlockingActivityFound(); 250 251 startDoActivity(DoTranslucentActivity.EXTRA_ONRESUME_FINISH_IMMEDIATELY, 252 DoTranslucentActivity.class); 253 254 /* 255 Expected task stack: 256 NonDoActivity (not visible) -> ActivityBlockingActivity (visible) 257 */ 258 assertBlockingActivityFound(); 259 } 260 261 @Test testBlockingActivity_nonDoFinishesOnCreate_noBlockingActivity()262 public void testBlockingActivity_nonDoFinishesOnCreate_noBlockingActivity() 263 throws Exception { 264 startNonDoActivity(NonDoActivity.EXTRA_ONCREATE_FINISH_IMMEDIATELY); 265 266 assertBlockingActivityNotFound(); 267 } 268 269 @Test testBlockingActivity_nonDoLaunchesDoOnCreate_noBlockingActivity()270 public void testBlockingActivity_nonDoLaunchesDoOnCreate_noBlockingActivity() 271 throws Exception { 272 startNonDoActivity(NonDoActivity.EXTRA_ONCREATE_LAUNCH_DO_IMMEDIATELY); 273 274 assertBlockingActivityNotFound(); 275 } 276 277 @Test testBlockingActivity_nonDoFinishesOnResume_noBlockingActivity()278 public void testBlockingActivity_nonDoFinishesOnResume_noBlockingActivity() 279 throws Exception { 280 startNonDoActivity(NonDoActivity.EXTRA_ONRESUME_FINISH_IMMEDIATELY); 281 282 assertBlockingActivityNotFound(); 283 } 284 285 @Test testBlockingActivity_nonDoLaunchesDoOnResume_noBlockingActivity()286 public void testBlockingActivity_nonDoLaunchesDoOnResume_noBlockingActivity() 287 throws Exception { 288 startNonDoActivity(NonDoActivity.EXTRA_ONRESUME_LAUNCH_DO_IMMEDIATELY); 289 290 assertBlockingActivityNotFound(); 291 } 292 293 @Test testIsActivityBackedBySafeActivity_notMoving_nonDoActivity_returnsTrue()294 public void testIsActivityBackedBySafeActivity_notMoving_nonDoActivity_returnsTrue() 295 throws Exception { 296 setDrivingStateParked(); 297 298 startNonDoActivity(NonDoActivity.EXTRA_DO_NOTHING); 299 assertActivityLaunched(NonDoActivity.class.getSimpleName()); 300 301 ComponentName nonDoActivity = toComponentName(getTestContext(), NonDoActivity.class); 302 assertThat(mCarPackageManager.isActivityBackedBySafeActivity(nonDoActivity)).isTrue(); 303 } 304 305 @Test testIsActivityBackedBySafeActivity_moving_rootNonDoActivity_returnsFalse()306 public void testIsActivityBackedBySafeActivity_moving_rootNonDoActivity_returnsFalse() 307 throws Exception { 308 startNonDoActivity(NonDoActivity.EXTRA_DO_NOTHING); 309 assertBlockingActivityFound(); 310 311 ComponentName nonDoActivity = toComponentName(getTestContext(), NonDoActivity.class); 312 assertThat(mCarPackageManager.isActivityBackedBySafeActivity(nonDoActivity)).isFalse(); 313 } 314 315 @Test testIsActivityBackedBySafeActivity_moving_nonDoActivityBackedByDo_returnsTrue()316 public void testIsActivityBackedBySafeActivity_moving_nonDoActivityBackedByDo_returnsTrue() 317 throws Exception { 318 startDoActivity(DoActivity.INTENT_EXTRA_LAUNCH_NONDO); 319 // DoActivity will launch NonDoActivity consecutively. 320 assertBlockingActivityFound(); 321 322 ComponentName nonDoActivity = toComponentName(getTestContext(), NonDoActivity.class); 323 assertThat(mCarPackageManager.isActivityBackedBySafeActivity(nonDoActivity)).isTrue(); 324 } 325 326 @Test testIsActivityBackedBySafeActivity_moving_doActivity_returnsFalse()327 public void testIsActivityBackedBySafeActivity_moving_doActivity_returnsFalse() 328 throws Exception { 329 startDoActivity(/* extra= */ null); 330 assertActivityLaunched(DoActivity.class.getSimpleName()); 331 332 ComponentName doActivity = toComponentName(getTestContext(), DoActivity.class); 333 assertThat(mCarPackageManager.isActivityBackedBySafeActivity(doActivity)).isFalse(); 334 } 335 assertBlockingActivityNotFound()336 private void assertBlockingActivityNotFound() { 337 assertThat(mDevice.wait(Until.gone(By.res(ACTIVITY_BLOCKING_ACTIVITY_TEXTVIEW_ID)), 338 NOT_FOUND_UI_TIMEOUT_MS)).isNotNull(); 339 } 340 assertBlockingActivityFound()341 private void assertBlockingActivityFound() { 342 assertThat(waitForBlockingActivityFound()).isNotNull(); 343 } 344 waitForBlockingActivityFound()345 private UiObject2 waitForBlockingActivityFound() { 346 return mDevice.wait(Until.findObject(By.res(ACTIVITY_BLOCKING_ACTIVITY_TEXTVIEW_ID)), 347 UI_TIMEOUT_MS); 348 } 349 assertBlockingActivityFoundAndExit(String exitLabel)350 private void assertBlockingActivityFoundAndExit(String exitLabel) { 351 assertBlockingActivityFound(); 352 UiObject2 button = mDevice.findObject(By.res(ACTIVITY_BLOCKING_ACTIVITY_EXIT_BUTTON_ID)); 353 // TODO(b/200948830): Make the test not to compare the text directly. 354 assertThat(button.getText()).isEqualTo(exitLabel); 355 356 button.click(); 357 } 358 assertActivityLaunched(String title)359 private void assertActivityLaunched(String title) { 360 assertThat(mDevice.wait(Until.findObject(By.text(title)), UI_TIMEOUT_MS)).isNotNull(); 361 } 362 startActivity(ComponentName name)363 private void startActivity(ComponentName name) { 364 Intent intent = new Intent(); 365 intent.setComponent(name); 366 startActivity(intent); 367 } 368 startActivity(Intent intent)369 private void startActivity(Intent intent) { 370 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 371 ActivityOptions options = ActivityOptions.makeBasic(); 372 options.setLaunchDisplayId(Display.DEFAULT_DISPLAY); 373 getContext().startActivity(intent, options.toBundle()); 374 } 375 startNonDoActivity(int firstActionFlag)376 private void startNonDoActivity(int firstActionFlag) { 377 ComponentName activity = toComponentName(getTestContext(), NonDoActivity.class); 378 Intent intent = new Intent(); 379 intent.setComponent(activity); 380 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 381 intent.putExtra(NonDoActivity.EXTRA_FIRST_ACTION, firstActionFlag); 382 383 ActivityOptions options = ActivityOptions.makeBasic(); 384 options.setLaunchDisplayId(Display.DEFAULT_DISPLAY); 385 386 getContext().startActivity(intent, options.toBundle()); 387 } 388 startDoActivity(String extra)389 private void startDoActivity(String extra) { 390 startDoActivity(extra, DoActivity.class); 391 } 392 startDoActivity(String extra, Class<?> cls)393 private void startDoActivity(String extra, Class<?> cls) { 394 Intent intent = new Intent() 395 .setComponent(toComponentName(getTestContext(), cls)) 396 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 397 if (extra != null) { 398 intent.putExtra(extra, true); 399 } 400 startActivity(intent); 401 } 402 ensureHomeIsDisplayed()403 private void ensureHomeIsDisplayed() { 404 mDevice.pressHome(); 405 final String launcherPackage = mDevice.getLauncherPackageName(); 406 assertNotNull(launcherPackage); 407 408 assumeTrue("Home is not displayed even after " + HOME_DISPLAYED_TIMEOUT_MS + "ms.", 409 mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), 410 HOME_DISPLAYED_TIMEOUT_MS)); 411 } 412 setDrivingStateMoving()413 private void setDrivingStateMoving() { 414 mCarDrivingStateManager.injectDrivingState(CarDrivingStateEvent.DRIVING_STATE_MOVING); 415 } 416 setDrivingStateIdling()417 private void setDrivingStateIdling() { 418 mCarDrivingStateManager.injectDrivingState(CarDrivingStateEvent.DRIVING_STATE_IDLING); 419 } 420 setDrivingStateParked()421 private void setDrivingStateParked() { 422 mCarDrivingStateManager.injectDrivingState(CarDrivingStateEvent.DRIVING_STATE_PARKED); 423 } 424 toComponentName(Context ctx, Class<?> cls)425 private static ComponentName toComponentName(Context ctx, Class<?> cls) { 426 return ComponentName.createRelative(ctx, cls.getName()); 427 } 428 429 public static class DoTranslucentActivity extends TempActivity { 430 public static final String EXTRA_ONRESUME_FINISH_IMMEDIATELY = "ONRESUME_FINISH"; 431 432 @Override onResume()433 protected void onResume() { 434 super.onResume(); 435 if (getIntent().getBooleanExtra(EXTRA_ONRESUME_FINISH_IMMEDIATELY, false)) { 436 finish(); 437 } 438 } 439 } 440 441 public static class NonDoActivity extends TempActivity { 442 443 static final String EXTRA_FIRST_ACTION = "first_action"; 444 445 static final int EXTRA_DO_NOTHING = 0; 446 static final int EXTRA_ONCREATE_FINISH_IMMEDIATELY = 1; 447 static final int EXTRA_ONCREATE_LAUNCH_DO_IMMEDIATELY = 2; 448 static final int EXTRA_ONRESUME_FINISH_IMMEDIATELY = 3; 449 static final int EXTRA_ONRESUME_LAUNCH_DO_IMMEDIATELY = 4; 450 451 @Override onCreate(Bundle savedInstanceState)452 protected void onCreate(Bundle savedInstanceState) { 453 super.onCreate(savedInstanceState); 454 Bundle extras = getIntent().getExtras(); 455 if (extras != null) { 456 switch (extras.getInt(EXTRA_FIRST_ACTION, EXTRA_DO_NOTHING)) { 457 case EXTRA_ONCREATE_LAUNCH_DO_IMMEDIATELY: 458 startActivity(new Intent(this, DoActivity.class)); 459 finish(); 460 break; 461 case EXTRA_ONCREATE_FINISH_IMMEDIATELY: 462 finish(); 463 break; 464 default: 465 // do nothing 466 } 467 } 468 } 469 470 @Override onResume()471 protected void onResume() { 472 super.onResume(); 473 Bundle extras = getIntent().getExtras(); 474 if (extras != null) { 475 switch (extras.getInt(EXTRA_FIRST_ACTION, EXTRA_DO_NOTHING)) { 476 case EXTRA_ONRESUME_LAUNCH_DO_IMMEDIATELY: 477 startActivity(new Intent(this, DoActivity.class)); 478 finish(); 479 break; 480 case EXTRA_ONRESUME_FINISH_IMMEDIATELY: 481 finish(); 482 break; 483 default: 484 // do nothing 485 } 486 } 487 } 488 } 489 490 public static class DoActivity extends TempActivity { 491 public static final String INTENT_EXTRA_SHOW_DIALOG = "SHOW_DIALOG"; 492 public static final String DIALOG_TITLE = "Title"; 493 494 public static final String INTENT_EXTRA_LAUNCH_NONDO = "LAUNCH_NONDO"; 495 public static final String INTENT_EXTRA_LAUNCH_NONDO_NEW_TASK = "LAUNCH_NONDO_NEW_TASK"; 496 497 @Override onCreate(Bundle savedInstanceState)498 protected void onCreate(Bundle savedInstanceState) { 499 super.onCreate(savedInstanceState); 500 if (getIntent().getBooleanExtra(INTENT_EXTRA_LAUNCH_NONDO, false)) { 501 startActivity(new Intent(this, NonDoActivity.class)); 502 } 503 if (getIntent().getBooleanExtra(INTENT_EXTRA_LAUNCH_NONDO_NEW_TASK, false)) { 504 startActivity(new Intent(this, NonDoActivity.class) 505 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); 506 } 507 if (getIntent().getBooleanExtra(INTENT_EXTRA_SHOW_DIALOG, false)) { 508 AlertDialog dialog = new AlertDialog.Builder(DoActivity.this) 509 .setTitle(DIALOG_TITLE) 510 .setMessage("Message") 511 .create(); 512 dialog.show(); 513 } 514 } 515 } 516 517 /** Activity that closes itself after some timeout to clean up the screen. */ 518 public static class TempActivity extends Activity { 519 private final CountDownLatch mDestroyed = new CountDownLatch(1); 520 521 @Override onCreate(Bundle savedInstanceState)522 protected void onCreate(Bundle savedInstanceState) { 523 super.onCreate(savedInstanceState); 524 setTitle(this.getClass().getSimpleName()); 525 sTestingActivities.add(this); 526 } 527 528 @Override onDestroy()529 protected void onDestroy() { 530 sTestingActivities.remove(this); 531 super.onDestroy(); 532 mDestroyed.countDown(); 533 } 534 finishCompletely()535 void finishCompletely() throws InterruptedException { 536 finish(); 537 waitForDestroy(); 538 } 539 waitForDestroy()540 boolean waitForDestroy() throws InterruptedException { 541 return mDestroyed.await(ACTIVITY_TIMEOUT_MS, TimeUnit.MILLISECONDS); 542 } 543 } 544 getContext()545 private Context getContext() { 546 return InstrumentationRegistry.getInstrumentation().getTargetContext(); 547 } 548 getTestContext()549 private Context getTestContext() { 550 return InstrumentationRegistry.getInstrumentation().getContext(); 551 } 552 } 553