Home | History | Annotate | Download | only in am
      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