Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2015 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 android.server.cts;
     18 
     19 import java.awt.Rectangle;
     20 
     21 public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {
     22 
     23     private static final String TEST_ACTIVITY_NAME = "TestActivity";
     24     private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
     25     private static final String DOCKED_ACTIVITY_NAME = "DockedActivity";
     26     private static final String LAUNCH_TO_SIDE_ACTIVITY_NAME = "LaunchToSideActivity";
     27     private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
     28     private static final String SINGLE_INSTANCE_ACTIVITY_NAME = "SingleInstanceActivity";
     29     private static final String SINGLE_TASK_ACTIVITY_NAME = "SingleTaskActivity";
     30 
     31     private static final int TASK_SIZE = 600;
     32     private static final int STACK_SIZE = 300;
     33 
     34     public void testStackList() throws Exception {
     35         executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
     36         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
     37         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
     38         mAmWmState.assertContainsStack(
     39                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
     40         mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
     41     }
     42 
     43     public void testDockActivity() throws Exception {
     44         launchActivityInDockStack(TEST_ACTIVITY_NAME);
     45         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
     46         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
     47         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
     48     }
     49 
     50     public void testNonResizeableNotDocked() throws Exception {
     51         launchActivityInDockStack(NON_RESIZEABLE_ACTIVITY_NAME);
     52         mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});
     53 
     54         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
     55         mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
     56         mAmWmState.assertFrontStack(
     57                 "Fullscreen stack must be front stack.", FULLSCREEN_WORKSPACE_STACK_ID);
     58     }
     59 
     60     public void testLaunchToSide() throws Exception {
     61         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
     62         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
     63         mAmWmState.computeState(mDevice, new String[] {LAUNCH_TO_SIDE_ACTIVITY_NAME});
     64 
     65         mAmWmState.assertContainsStack(
     66                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
     67         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
     68     }
     69 
     70     public void testLaunchToSideAndBringToFront() throws Exception {
     71         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
     72         final String[] waitForFirstVisible = new String[] {TEST_ACTIVITY_NAME};
     73         final String[] waitForSecondVisible = new String[] {NO_RELAUNCH_ACTIVITY_NAME};
     74 
     75         // Launch activity to side.
     76         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
     77         mAmWmState.computeState(mDevice, waitForFirstVisible);
     78         int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
     79                 .getTasks().size();
     80         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
     81                 TEST_ACTIVITY_NAME);
     82 
     83         // Launch another activity to side to cover first one.
     84         launchActivityInStack(NO_RELAUNCH_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
     85         mAmWmState.computeState(mDevice, waitForSecondVisible);
     86         int taskNumberCovered = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
     87                 .getTasks().size();
     88         mAmWmState.assertEquals("Fullscreen stack must have one task added.",
     89                 taskNumberInitial + 1, taskNumberCovered);
     90         mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
     91                 NO_RELAUNCH_ACTIVITY_NAME);
     92 
     93         // Launch activity that was first launched to side. It should be brought to front.
     94         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
     95         mAmWmState.computeState(mDevice, waitForFirstVisible);
     96         int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
     97                 .getTasks().size();
     98         mAmWmState.assertEquals("Task number in fullscreen stack must remain the same.",
     99                 taskNumberCovered, taskNumberFinal);
    100         mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
    101                 TEST_ACTIVITY_NAME);
    102     }
    103 
    104     public void testLaunchToSideMultiple() throws Exception {
    105         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    106         final String[] waitForActivitiesVisible = new String[] {TEST_ACTIVITY_NAME};
    107 
    108         // Launch activity to side.
    109         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    110         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    111         int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
    112                 .getTasks().size();
    113         mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
    114                 mAmWmState.getAmState()
    115                         .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
    116 
    117         // Try to launch to side same activity again.
    118         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    119         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    120         int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
    121                 .getTasks().size();
    122         mAmWmState.assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
    123         mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
    124                 TEST_ACTIVITY_NAME);
    125         mAmWmState.assertNotNull("Launched to side activity must remain in fullscreen stack.",
    126                 mAmWmState.getAmState()
    127                         .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
    128     }
    129 
    130     public void testLaunchToSideSingleInstance() throws Exception {
    131         launchTargetToSide(SINGLE_INSTANCE_ACTIVITY_NAME, false);
    132     }
    133 
    134     public void testLaunchToSideSingleTask() throws Exception {
    135         launchTargetToSide(SINGLE_TASK_ACTIVITY_NAME, false);
    136     }
    137 
    138     public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
    139         launchTargetToSide(TEST_ACTIVITY_NAME, true);
    140     }
    141 
    142     private void launchTargetToSide(String targetActivityName,
    143                                     boolean taskCountMustIncrement) throws Exception {
    144         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    145         final String[] waitForActivitiesVisible = new String[] {targetActivityName};
    146 
    147         // Launch activity to side with data.
    148         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME, true, false, targetActivityName);
    149         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    150         int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
    151                 .getTasks().size();
    152         mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
    153                 mAmWmState.getAmState()
    154                         .getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));
    155 
    156         // Try to launch to side same activity again with different data.
    157         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME, true, false, targetActivityName);
    158         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    159         int taskNumberSecondLaunch = mAmWmState.getAmState()
    160                 .getStackById(FULLSCREEN_WORKSPACE_STACK_ID).getTasks().size();
    161         if (taskCountMustIncrement) {
    162             mAmWmState.assertEquals("Task number must be incremented.", taskNumberInitial + 1,
    163                     taskNumberSecondLaunch);
    164         } else {
    165             mAmWmState.assertEquals("Task number must not change.", taskNumberInitial,
    166                     taskNumberSecondLaunch);
    167         }
    168         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
    169                 targetActivityName);
    170         mAmWmState.assertNotNull("Launched to side activity must be launched in fullscreen stack.",
    171                 mAmWmState.getAmState()
    172                         .getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));
    173 
    174         // Try to launch to side same activity again with no data.
    175         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME, false, false, targetActivityName);
    176         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    177         int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
    178                 .getTasks().size();
    179         if (taskCountMustIncrement) {
    180             mAmWmState.assertEquals("Task number must be incremented.", taskNumberSecondLaunch + 1,
    181                     taskNumberFinal);
    182         } else {
    183             mAmWmState.assertEquals("Task number must not change.", taskNumberSecondLaunch,
    184                     taskNumberFinal);
    185         }
    186         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
    187                 targetActivityName);
    188         mAmWmState.assertNotNull("Launched to side activity must be launched in fullscreen stack.",
    189                 mAmWmState.getAmState()
    190                         .getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));
    191     }
    192 
    193     public void testLaunchToSideMultipleWithFlag() throws Exception {
    194         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    195         final String[] waitForActivitiesVisible = new String[] {TEST_ACTIVITY_NAME};
    196 
    197         // Launch activity to side.
    198         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    199         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    200         int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
    201                 .getTasks().size();
    202         mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
    203                 mAmWmState.getAmState()
    204                         .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
    205 
    206         // Try to launch to side same activity again, but with Intent#FLAG_ACTIVITY_MULTIPLE_TASK.
    207         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME, false, true);
    208         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    209         int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
    210                 .getTasks().size();
    211         mAmWmState.assertEquals("Task number must be incremented.", taskNumberInitial + 1,
    212                 taskNumberFinal);
    213         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
    214                 TEST_ACTIVITY_NAME);
    215         mAmWmState.assertNotNull("Launched to side activity must remain in fullscreen stack.",
    216                 mAmWmState.getAmState()
    217                         .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
    218     }
    219 
    220     public void testRotationWhenDocked() throws Exception {
    221         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    222         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    223         final String[] waitForActivitiesVisible = new String[] {LAUNCH_TO_SIDE_ACTIVITY_NAME};
    224         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    225         mAmWmState.assertContainsStack(
    226                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
    227         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
    228 
    229         // Rotate device single steps (90) 0-1-2-3.
    230         // Each time we compute the state we implicitly assert valid bounds.
    231         setDeviceRotation(0);
    232         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    233         setDeviceRotation(1);
    234         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    235         setDeviceRotation(2);
    236         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    237         setDeviceRotation(3);
    238         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    239         // Double steps (180) We ended the single step at 3. So, we jump directly to 1 for double
    240         // step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
    241         setDeviceRotation(1);
    242         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    243         setDeviceRotation(3);
    244         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    245         setDeviceRotation(0);
    246         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    247         setDeviceRotation(2);
    248         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    249         setDeviceRotation(0);
    250         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    251     }
    252 
    253     public void testRotationWhenDockedWhileLocked() throws Exception {
    254         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    255         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
    256         final String[] waitForActivitiesVisible = new String[] {LAUNCH_TO_SIDE_ACTIVITY_NAME};
    257         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    258         mAmWmState.assertSanity();
    259         mAmWmState.assertContainsStack(
    260                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
    261         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
    262 
    263         lockDevice();
    264         setDeviceRotation(0);
    265         unlockDevice();
    266         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    267 
    268         lockDevice();
    269         setDeviceRotation(1);
    270         unlockDevice();
    271         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    272 
    273         lockDevice();
    274         setDeviceRotation(2);
    275         unlockDevice();
    276         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    277 
    278         lockDevice();
    279         setDeviceRotation(3);
    280         unlockDevice();
    281         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    282     }
    283 
    284     public void testResizeDockedStack() throws Exception {
    285         launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
    286         launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
    287         resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
    288         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME, DOCKED_ACTIVITY_NAME},
    289                 false /* compareTaskAndStackBounds */);
    290         mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
    291         mAmWmState.assertContainsStack("Must contain fullscreen stack",
    292                 FULLSCREEN_WORKSPACE_STACK_ID);
    293         assertEquals(new Rectangle(0, 0, STACK_SIZE, STACK_SIZE),
    294                 mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds());
    295         mAmWmState.assertDockedTaskBounds(TASK_SIZE, DOCKED_ACTIVITY_NAME);
    296         mAmWmState.assertVisibility(DOCKED_ACTIVITY_NAME, true);
    297         mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true);
    298     }
    299 
    300     public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
    301         executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
    302         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
    303         final Rectangle fullScreenBounds =
    304                 mAmWmState.getWmState().getStack(FULLSCREEN_WORKSPACE_STACK_ID).getBounds();
    305 
    306         moveActivityToDockStack(TEST_ACTIVITY_NAME);
    307         launchActivityInStack(NO_RELAUNCH_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
    308 
    309         mAmWmState.computeState(mDevice,
    310                 new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
    311         final Rectangle initialDockBounds =
    312                 mAmWmState.getWmState().getStack(DOCKED_STACK_ID).getBounds();
    313 
    314         clearLogcat();
    315 
    316         Rectangle newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, true);
    317         resizeDockedStack(newBounds.width, newBounds.height, newBounds.width, newBounds.height);
    318 
    319         // We resize twice to make sure we cross an orientation change threshold for both
    320         // activities.
    321         newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, false);
    322         resizeDockedStack(newBounds.width, newBounds.height, newBounds.width, newBounds.height);
    323 
    324         mAmWmState.computeState(mDevice,
    325                 new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
    326 
    327         assertActivityLifecycle(TEST_ACTIVITY_NAME, true);
    328         assertActivityLifecycle(NO_RELAUNCH_ACTIVITY_NAME, false);
    329     }
    330 
    331     private Rectangle computeNewDockBounds(
    332             Rectangle fullscreenBounds, Rectangle dockBounds, boolean reduceSize) {
    333         final boolean inLandscape = fullscreenBounds.width > dockBounds.width;
    334         // We are either increasing size or reducing it.
    335         final float sizeChangeFactor = reduceSize ? 0.5f : 1.5f;
    336         final Rectangle newBounds = new Rectangle(dockBounds);
    337         if (inLandscape) {
    338             // In landscape we change the width.
    339             newBounds.width *= sizeChangeFactor;
    340         } else {
    341             // In portrait we change the height
    342             newBounds.height *= sizeChangeFactor;
    343         }
    344 
    345         return newBounds;
    346     }
    347 
    348     private void launchActivityToSide(String activityName) throws Exception {
    349         launchActivityToSide(activityName, false, false);
    350     }
    351 
    352     private void launchActivityToSide(String activityName, boolean randomData,
    353                                       boolean multipleTaskFlag) throws Exception {
    354         launchActivityToSide(activityName, randomData, multipleTaskFlag, null);
    355     }
    356 
    357     private void launchActivityToSide(String activityName, boolean randomData,
    358                                       boolean multipleTaskFlag, String targetActivityName)
    359             throws Exception {
    360         StringBuilder commandBuilder = new StringBuilder(getAmStartCmd(activityName));
    361         commandBuilder.append(" -f 0x20000000 --ez launch_to_the_side true");
    362         if (randomData) {
    363             commandBuilder.append(" --ez random_data true");
    364         }
    365         if (multipleTaskFlag) {
    366             commandBuilder.append(" --ez multiple_task true");
    367         }
    368         if (targetActivityName != null) {
    369             commandBuilder.append(" --es target_activity ").append(targetActivityName);
    370         }
    371         executeShellCommand(commandBuilder.toString());
    372     }
    373 }
    374