1 /* 2 * Copyright (C) 2017 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.server.am; 18 19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 23 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 24 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 26 27 import static com.android.server.am.ActivityStack.ActivityState.PAUSING; 28 import static com.android.server.am.ActivityStack.ActivityState.RESUMED; 29 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING; 30 31 import static org.junit.Assert.assertEquals; 32 import static org.junit.Assert.assertFalse; 33 import static org.junit.Assert.assertNotNull; 34 import static org.junit.Assert.assertNull; 35 import static org.junit.Assert.assertTrue; 36 import static org.mockito.ArgumentMatchers.any; 37 import static org.mockito.ArgumentMatchers.eq; 38 import static org.mockito.Mockito.anyInt; 39 import static org.mockito.Mockito.doReturn; 40 import static org.mockito.Mockito.mock; 41 import static org.mockito.Mockito.times; 42 import static org.mockito.Mockito.verify; 43 44 import android.content.pm.ActivityInfo; 45 import android.os.UserHandle; 46 import android.platform.test.annotations.Presubmit; 47 import android.support.test.filters.SmallTest; 48 import android.support.test.runner.AndroidJUnit4; 49 50 import org.junit.runner.RunWith; 51 import org.junit.Before; 52 import org.junit.Test; 53 54 /** 55 * Tests for the {@link ActivityStack} class. 56 * 57 * Build/Install/Run: 58 * atest FrameworksServicesTests:com.android.server.am.ActivityStackTests 59 */ 60 @SmallTest 61 @Presubmit 62 @RunWith(AndroidJUnit4.class) 63 public class ActivityStackTests extends ActivityTestsBase { 64 private ActivityManagerService mService; 65 private ActivityStackSupervisor mSupervisor; 66 private ActivityDisplay mDefaultDisplay; 67 private ActivityStack mStack; 68 private TaskRecord mTask; 69 70 @Before 71 @Override 72 public void setUp() throws Exception { 73 super.setUp(); 74 75 mService = createActivityManagerService(); 76 mSupervisor = mService.mStackSupervisor; 77 mDefaultDisplay = mService.mStackSupervisor.getDefaultDisplay(); 78 mStack = mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 79 true /* onTop */); 80 mTask = new TaskBuilder(mSupervisor).setStack(mStack).build(); 81 } 82 83 @Test 84 public void testEmptyTaskCleanupOnRemove() throws Exception { 85 assertNotNull(mTask.getWindowContainerController()); 86 mStack.removeTask(mTask, "testEmptyTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING); 87 assertNull(mTask.getWindowContainerController()); 88 } 89 90 @Test 91 public void testOccupiedTaskCleanupOnRemove() throws Exception { 92 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build(); 93 assertNotNull(mTask.getWindowContainerController()); 94 mStack.removeTask(mTask, "testOccupiedTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING); 95 assertNotNull(mTask.getWindowContainerController()); 96 } 97 98 @Test 99 public void testResumedActivity() throws Exception { 100 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build(); 101 assertEquals(mStack.getResumedActivity(), null); 102 r.setState(RESUMED, "testResumedActivity"); 103 assertEquals(mStack.getResumedActivity(), r); 104 r.setState(PAUSING, "testResumedActivity"); 105 assertEquals(mStack.getResumedActivity(), null); 106 } 107 108 @Test 109 public void testResumedActivityFromTaskReparenting() { 110 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build(); 111 // Ensure moving task between two stacks updates resumed activity 112 r.setState(RESUMED, "testResumedActivityFromTaskReparenting"); 113 assertEquals(mStack.getResumedActivity(), r); 114 115 final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack( 116 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); 117 118 mTask.reparent(destStack, true /* toTop */, TaskRecord.REPARENT_KEEP_STACK_AT_FRONT, 119 false /* animate */, true /* deferResume*/, 120 "testResumedActivityFromTaskReparenting"); 121 122 assertEquals(mStack.getResumedActivity(), null); 123 assertEquals(destStack.getResumedActivity(), r); 124 } 125 126 @Test 127 public void testResumedActivityFromActivityReparenting() { 128 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build(); 129 // Ensure moving task between two stacks updates resumed activity 130 r.setState(RESUMED, "testResumedActivityFromActivityReparenting"); 131 assertEquals(mStack.getResumedActivity(), r); 132 133 final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack( 134 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); 135 final TaskRecord destTask = new TaskBuilder(mSupervisor).setStack(destStack).build(); 136 137 mTask.removeActivity(r); 138 destTask.addActivityToTop(r); 139 140 assertEquals(mStack.getResumedActivity(), null); 141 assertEquals(destStack.getResumedActivity(), r); 142 } 143 144 @Test 145 public void testPrimarySplitScreenToFullscreenWhenMovedToBack() throws Exception { 146 // Create primary splitscreen stack. This will create secondary stacks and places the 147 // existing fullscreen stack on the bottom. 148 final ActivityStack primarySplitScreen = mDefaultDisplay.createStack( 149 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */); 150 151 // Assert windowing mode. 152 assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); 153 154 // Move primary to back. 155 primarySplitScreen.moveToBack("testPrimarySplitScreenToFullscreenWhenMovedToBack", 156 null /* task */); 157 158 // Assert that stack is at the bottom. 159 assertEquals(mDefaultDisplay.getIndexOf(primarySplitScreen), 0); 160 161 // Ensure no longer in splitscreen. 162 assertEquals(primarySplitScreen.getWindowingMode(), WINDOWING_MODE_FULLSCREEN); 163 } 164 165 @Test 166 public void testStopActivityWhenActivityDestroyed() throws Exception { 167 final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build(); 168 r.info.flags |= ActivityInfo.FLAG_NO_HISTORY; 169 mSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", mStack); 170 mStack.stopActivityLocked(r); 171 // Mostly testing to make sure there is a crash in the call part, so if we get here we are 172 // good-to-go! 173 } 174 175 @Test 176 public void testFindTaskWithOverlay() throws Exception { 177 final ActivityRecord r = new ActivityBuilder(mService) 178 .setCreateTask(true) 179 .setStack(mStack) 180 .setUid(0) 181 .build(); 182 final TaskRecord task = r.getTask(); 183 // Overlay must be for a different user to prevent recognizing a matching top activity 184 final ActivityRecord taskOverlay = new ActivityBuilder(mService).setTask(task) 185 .setUid(UserHandle.PER_USER_RANGE * 2).build(); 186 taskOverlay.mTaskOverlay = true; 187 188 final ActivityStackSupervisor.FindTaskResult result = 189 new ActivityStackSupervisor.FindTaskResult(); 190 mStack.findTaskLocked(r, result); 191 192 assertEquals(task.getTopActivity(false /* includeOverlays */), r); 193 assertEquals(task.getTopActivity(true /* includeOverlays */), taskOverlay); 194 assertNotNull(result.r); 195 } 196 197 @Test 198 public void testShouldBeVisible_Fullscreen() throws Exception { 199 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 200 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 201 final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 202 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */); 203 204 assertTrue(homeStack.shouldBeVisible(null /* starting */)); 205 assertTrue(pinnedStack.shouldBeVisible(null /* starting */)); 206 207 final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 208 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); 209 // Home stack shouldn't be visible behind an opaque fullscreen stack, but pinned stack 210 // should be visible since it is always on-top. 211 fullscreenStack.setIsTranslucent(false); 212 assertFalse(homeStack.shouldBeVisible(null /* starting */)); 213 assertTrue(pinnedStack.shouldBeVisible(null /* starting */)); 214 assertTrue(fullscreenStack.shouldBeVisible(null /* starting */)); 215 216 // Home stack should be visible behind a translucent fullscreen stack. 217 fullscreenStack.setIsTranslucent(true); 218 assertTrue(homeStack.shouldBeVisible(null /* starting */)); 219 assertTrue(pinnedStack.shouldBeVisible(null /* starting */)); 220 } 221 222 @Test 223 public void testShouldBeVisible_SplitScreen() throws Exception { 224 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 225 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 226 // Home stack should always be fullscreen for this test. 227 homeStack.setSupportsSplitScreen(false); 228 final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(mDefaultDisplay, 229 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */); 230 final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(mDefaultDisplay, 231 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */); 232 233 // Home stack shouldn't be visible if both halves of split-screen are opaque. 234 splitScreenPrimary.setIsTranslucent(false); 235 splitScreenSecondary.setIsTranslucent(false); 236 assertFalse(homeStack.shouldBeVisible(null /* starting */)); 237 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */)); 238 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */)); 239 240 // Home stack should be visible if one of the halves of split-screen is translucent. 241 splitScreenPrimary.setIsTranslucent(true); 242 assertTrue(homeStack.shouldBeVisible(null /* starting */)); 243 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */)); 244 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */)); 245 246 final TestActivityStack splitScreenSecondary2 = createStackForShouldBeVisibleTest(mDefaultDisplay, 247 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */); 248 // First split-screen secondary shouldn't be visible behind another opaque split-split 249 // secondary. 250 splitScreenSecondary2.setIsTranslucent(false); 251 assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */)); 252 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */)); 253 254 // First split-screen secondary should be visible behind another translucent split-screen 255 // secondary. 256 splitScreenSecondary2.setIsTranslucent(true); 257 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */)); 258 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */)); 259 260 final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 261 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */); 262 263 // Split-screen stacks shouldn't be visible behind an opaque fullscreen stack. 264 assistantStack.setIsTranslucent(false); 265 assertTrue(assistantStack.shouldBeVisible(null /* starting */)); 266 assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */)); 267 assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */)); 268 assertFalse(splitScreenSecondary2.shouldBeVisible(null /* starting */)); 269 270 // Split-screen stacks should be visible behind a translucent fullscreen stack. 271 assistantStack.setIsTranslucent(true); 272 assertTrue(assistantStack.shouldBeVisible(null /* starting */)); 273 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */)); 274 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */)); 275 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */)); 276 277 // Assistant stack shouldn't be visible behind translucent split-screen stack 278 assistantStack.setIsTranslucent(false); 279 splitScreenPrimary.setIsTranslucent(true); 280 splitScreenSecondary2.setIsTranslucent(true); 281 splitScreenSecondary2.moveToFront("testShouldBeVisible_SplitScreen"); 282 splitScreenPrimary.moveToFront("testShouldBeVisible_SplitScreen"); 283 assertFalse(assistantStack.shouldBeVisible(null /* starting */)); 284 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */)); 285 assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */)); 286 } 287 288 @Test 289 public void testShouldBeVisible_Finishing() throws Exception { 290 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 291 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 292 final TestActivityStack translucentStack = createStackForShouldBeVisibleTest( 293 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 294 true /* onTop */); 295 translucentStack.setIsTranslucent(true); 296 297 assertTrue(homeStack.shouldBeVisible(null /* starting */)); 298 assertTrue(translucentStack.shouldBeVisible(null /* starting */)); 299 300 final ActivityRecord topRunningHomeActivity = homeStack.topRunningActivityLocked(); 301 topRunningHomeActivity.finishing = true; 302 final ActivityRecord topRunningTranslucentActivity = 303 translucentStack.topRunningActivityLocked(); 304 topRunningTranslucentActivity.finishing = true; 305 306 // Home shouldn't be visible since its activity is marked as finishing and it isn't the top 307 // of the stack list. 308 assertFalse(homeStack.shouldBeVisible(null /* starting */)); 309 // Home should be visible if we are starting an activity within it. 310 assertTrue(homeStack.shouldBeVisible(topRunningHomeActivity /* starting */)); 311 // The translucent stack should be visible since it is the top of the stack list even though 312 // it has its activity marked as finishing. 313 assertTrue(translucentStack.shouldBeVisible(null /* starting */)); 314 } 315 316 @Test 317 public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() { 318 mDefaultDisplay.removeChild(mStack); 319 320 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 321 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 322 final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 323 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); 324 325 homeStack.setIsTranslucent(false); 326 fullscreenStack.setIsTranslucent(false); 327 328 // Ensure that we don't move the home stack if it is already behind the top fullscreen stack 329 int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack); 330 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack); 331 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack); 332 assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex); 333 } 334 335 @Test 336 public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindTranslucent() { 337 mDefaultDisplay.removeChild(mStack); 338 339 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 340 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 341 final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 342 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); 343 344 homeStack.setIsTranslucent(false); 345 fullscreenStack.setIsTranslucent(true); 346 347 // Ensure that we don't move the home stack if it is already behind the top fullscreen stack 348 int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack); 349 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack); 350 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack); 351 assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex); 352 } 353 354 @Test 355 public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeOnTop() { 356 mDefaultDisplay.removeChild(mStack); 357 358 final TestActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 359 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); 360 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 361 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 362 363 homeStack.setIsTranslucent(false); 364 fullscreenStack.setIsTranslucent(false); 365 366 // Ensure we don't move the home stack if it is already on top 367 int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack); 368 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == null); 369 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack); 370 assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex); 371 } 372 373 @Test 374 public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreen() { 375 mDefaultDisplay.removeChild(mStack); 376 377 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 378 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 379 final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest( 380 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 381 true /* onTop */); 382 final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest( 383 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 384 true /* onTop */); 385 final TestActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 386 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */); 387 388 homeStack.setIsTranslucent(false); 389 fullscreenStack1.setIsTranslucent(false); 390 fullscreenStack2.setIsTranslucent(false); 391 392 // Ensure that we move the home stack behind the bottom most fullscreen stack, ignoring the 393 // pinned stack 394 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1); 395 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack); 396 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack2); 397 } 398 399 @Test 400 public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreenAndTranslucent() { 401 mDefaultDisplay.removeChild(mStack); 402 403 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 404 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 405 final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest( 406 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 407 true /* onTop */); 408 final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest( 409 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 410 true /* onTop */); 411 412 homeStack.setIsTranslucent(false); 413 fullscreenStack1.setIsTranslucent(false); 414 fullscreenStack2.setIsTranslucent(true); 415 416 // Ensure that we move the home stack behind the bottom most non-translucent fullscreen 417 // stack 418 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1); 419 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack); 420 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1); 421 } 422 423 @Test 424 public void testMoveHomeStackBehindStack_BehindHomeStack() { 425 mDefaultDisplay.removeChild(mStack); 426 427 final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest( 428 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 429 true /* onTop */); 430 final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest( 431 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 432 true /* onTop */); 433 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 434 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 435 436 homeStack.setIsTranslucent(false); 437 fullscreenStack1.setIsTranslucent(false); 438 fullscreenStack2.setIsTranslucent(false); 439 440 // Ensure we don't move the home stack behind itself 441 int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack); 442 mDefaultDisplay.moveStackBehindStack(homeStack, homeStack); 443 assertTrue(mDefaultDisplay.getIndexOf(homeStack) == homeStackIndex); 444 } 445 446 @Test 447 public void testMoveHomeStackBehindStack() { 448 mDefaultDisplay.removeChild(mStack); 449 450 final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest( 451 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 452 true /* onTop */); 453 final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest( 454 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 455 true /* onTop */); 456 final TestActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest( 457 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 458 true /* onTop */); 459 final TestActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest( 460 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 461 true /* onTop */); 462 final TestActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 463 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); 464 465 mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack1); 466 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack1); 467 mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack2); 468 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack2); 469 mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack4); 470 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack4); 471 mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack2); 472 assertTrue(mDefaultDisplay.getStackAbove(homeStack) == fullscreenStack2); 473 } 474 475 @Test 476 public void testSplitScreenMoveToFront() throws Exception { 477 final TestActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest( 478 mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, 479 true /* onTop */); 480 final TestActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest( 481 mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, 482 true /* onTop */); 483 final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay, 484 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */); 485 486 splitScreenPrimary.setIsTranslucent(false); 487 splitScreenSecondary.setIsTranslucent(false); 488 assistantStack.setIsTranslucent(false); 489 490 assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */)); 491 assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */)); 492 assertTrue(assistantStack.shouldBeVisible(null /* starting */)); 493 494 splitScreenSecondary.moveToFront("testSplitScreenMoveToFront"); 495 496 assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */)); 497 assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */)); 498 assertFalse(assistantStack.shouldBeVisible(null /* starting */)); 499 } 500 501 private <T extends ActivityStack> T createStackForShouldBeVisibleTest( 502 ActivityDisplay display, int windowingMode, int activityType, boolean onTop) { 503 final T stack = display.createStack(windowingMode, activityType, onTop); 504 final ActivityRecord r = new ActivityBuilder(mService).setUid(0).setStack(stack) 505 .setCreateTask(true).build(); 506 return stack; 507 } 508 509 @Test 510 public void testFinishDisabledPackageActivities() throws Exception { 511 final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); 512 final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build(); 513 514 // Making the second activity a task overlay without an app means it will be removed from 515 // the task's activities as well once first activity is removed. 516 secondActivity.mTaskOverlay = true; 517 secondActivity.app = null; 518 519 assertEquals(mTask.mActivities.size(), 2); 520 521 mStack.finishDisabledPackageActivitiesLocked(firstActivity.packageName, null, 522 true /* doit */, true /* evenPersistent */, UserHandle.USER_ALL); 523 524 assertTrue(mTask.mActivities.isEmpty()); 525 assertTrue(mStack.getAllTasks().isEmpty()); 526 } 527 528 @Test 529 public void testHandleAppDied() throws Exception { 530 final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); 531 final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build(); 532 533 // Making the first activity a task overlay means it will be removed from the task's 534 // activities as well once second activity is removed as handleAppDied processes the 535 // activity list in reverse. 536 firstActivity.mTaskOverlay = true; 537 firstActivity.app = null; 538 539 // second activity will be immediately removed as it has no state. 540 secondActivity.haveState = false; 541 542 assertEquals(mTask.mActivities.size(), 2); 543 544 mStack.handleAppDiedLocked(secondActivity.app); 545 546 assertTrue(mTask.mActivities.isEmpty()); 547 assertTrue(mStack.getAllTasks().isEmpty()); 548 } 549 550 @Test 551 public void testShouldSleepActivities() throws Exception { 552 // When focused activity and keyguard is going away, we should not sleep regardless 553 // of the display state 554 verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/, 555 true /* displaySleeping */, false /* expected*/); 556 557 // When not the focused stack, defer to display sleeping state. 558 verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/, 559 true /* displaySleeping */, true /* expected*/); 560 561 // If keyguard is going away, defer to the display sleeping state. 562 verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/, 563 true /* displaySleeping */, true /* expected*/); 564 verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/, 565 false /* displaySleeping */, false /* expected*/); 566 } 567 568 @Test 569 public void testStackOrderChangedOnRemoveStack() throws Exception { 570 StackOrderChangedListener listener = new StackOrderChangedListener(); 571 mDefaultDisplay.registerStackOrderChangedListener(listener); 572 try { 573 mDefaultDisplay.removeChild(mStack); 574 } finally { 575 mDefaultDisplay.unregisterStackOrderChangedListener(listener); 576 } 577 assertTrue(listener.changed); 578 } 579 580 @Test 581 public void testStackOrderChangedOnAddPositionStack() throws Exception { 582 mDefaultDisplay.removeChild(mStack); 583 584 StackOrderChangedListener listener = new StackOrderChangedListener(); 585 mDefaultDisplay.registerStackOrderChangedListener(listener); 586 try { 587 mDefaultDisplay.addChild(mStack, 0); 588 } finally { 589 mDefaultDisplay.unregisterStackOrderChangedListener(listener); 590 } 591 assertTrue(listener.changed); 592 } 593 594 @Test 595 public void testStackOrderChangedOnPositionStack() throws Exception { 596 StackOrderChangedListener listener = new StackOrderChangedListener(); 597 try { 598 final TestActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest( 599 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, 600 true /* onTop */); 601 mDefaultDisplay.registerStackOrderChangedListener(listener); 602 mDefaultDisplay.positionChildAtBottom(fullscreenStack1); 603 } finally { 604 mDefaultDisplay.unregisterStackOrderChangedListener(listener); 605 } 606 assertTrue(listener.changed); 607 } 608 609 private void verifyShouldSleepActivities(boolean focusedStack, 610 boolean keyguardGoingAway, boolean displaySleeping, boolean expected) { 611 mSupervisor.mFocusedStack = focusedStack ? mStack : null; 612 613 final ActivityDisplay display = mock(ActivityDisplay.class); 614 final KeyguardController keyguardController = mSupervisor.getKeyguardController(); 615 616 doReturn(display).when(mSupervisor).getActivityDisplay(anyInt()); 617 doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway(); 618 doReturn(displaySleeping).when(display).isSleeping(); 619 620 assertEquals(expected, mStack.shouldSleepActivities()); 621 } 622 623 private class StackOrderChangedListener implements ActivityDisplay.OnStackOrderChangedListener { 624 boolean changed = false; 625 626 @Override 627 public void onStackOrderChanged() { 628 changed = true; 629 } 630 } 631 } 632