1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.server.am;
18 
19 import static android.server.am.ComponentNameUtils.getActivityName;
20 import static android.server.am.Components.ALT_LAUNCHING_ACTIVITY;
21 import static android.server.am.Components.LAUNCHING_ACTIVITY;
22 import static android.server.am.Components.RESIZEABLE_ACTIVITY;
23 import static android.server.am.Components.VR_TEST_ACTIVITY;
24 import static android.view.Display.DEFAULT_DISPLAY;
25 
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assume.assumeFalse;
29 import static org.junit.Assume.assumeTrue;
30 
31 import android.server.am.ActivityManagerState.ActivityDisplay;
32 
33 import org.junit.Before;
34 import org.junit.Test;
35 
36 import java.util.List;
37 
38 /**
39  * Build/Install/Run:
40  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerVrDisplayTests
41  */
42 public class ActivityManagerVrDisplayTests extends ActivityManagerDisplayTestBase {
43     private static final int VR_VIRTUAL_DISPLAY_WIDTH = 700;
44     private static final int VR_VIRTUAL_DISPLAY_HEIGHT = 900;
45     private static final int VR_VIRTUAL_DISPLAY_DPI = 320;
46 
47 
48     @Before
49     @Override
setUp()50     public void setUp() throws Exception {
51         super.setUp();
52 
53         assumeTrue(supportsVrMode());
54     }
55 
56     /**
57      * VrModeSession is used to enable or disable persistent vr mode and the vr virtual display. For
58      * standalone vr devices, VrModeSession has no effect, because the device is already in
59      * persistent vr mode whenever it's on, and turning off persistent vr mode on a standalone vr
60      * device puts the device in a bad state.
61      */
62     private static class VrModeSession implements AutoCloseable {
63         private boolean applyVrModeChanges = !ActivityManagerTestBase.isUiModeLockedToVrHeadset();
64 
enablePersistentVrMode()65         void enablePersistentVrMode() throws Exception {
66             if (!applyVrModeChanges) { return; }
67             executeShellCommand("setprop vr_virtualdisplay true");
68             executeShellCommand("vr set-persistent-vr-mode-enabled true");
69         }
70 
71         @Override
close()72         public void close() throws Exception {
73             if (!applyVrModeChanges) { return; }
74             executeShellCommand("vr set-persistent-vr-mode-enabled false");
75             executeShellCommand("setprop vr_virtualdisplay false");
76         }
77     }
78 
79     /**
80      * Tests that any new activity launch in Vr mode is in Vr display.
81      */
82     @Test
testVrActivityLaunch()83     public void testVrActivityLaunch() throws Exception {
84         assumeTrue(supportsMultiDisplay());
85 
86         try (final VrModeSession vrModeSession = new VrModeSession()) {
87             // Put the device in persistent vr mode.
88             vrModeSession.enablePersistentVrMode();
89 
90             // Launch the VR activity.
91             launchActivity(VR_TEST_ACTIVITY);
92             mAmWmState.computeState(VR_TEST_ACTIVITY);
93             mAmWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
94 
95             // Launch the non-VR 2D activity and check where it ends up.
96             launchActivity(LAUNCHING_ACTIVITY);
97             mAmWmState.computeState(LAUNCHING_ACTIVITY);
98 
99             // Ensure that the subsequent activity is visible
100             mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
101 
102             // Check that activity is launched in focused stack on primary display.
103             mAmWmState.assertFocusedActivity("Launched activity must be focused",
104                     LAUNCHING_ACTIVITY);
105             final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
106             final ActivityManagerState.ActivityStack focusedStack
107                     = mAmWmState.getAmState().getStackById(focusedStackId);
108             assertEquals("Launched activity must be resumed in focused stack",
109                     getActivityName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
110 
111             // Check if the launch activity is in Vr virtual display id.
112             final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
113             final ActivityDisplay vrDisplay = getDisplayState(reportedDisplays,
114                     VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
115             assertNotNull("Vr mode should have a virtual display", vrDisplay);
116 
117             // Check if the focused activity is on this virtual stack.
118             assertEquals("Launch in Vr mode should be in virtual stack", vrDisplay.mId,
119                     focusedStack.mDisplayId);
120         }
121     }
122 
123     /**
124      * Tests that any activity already present is re-launched in Vr display in vr mode.
125      */
126     @Test
testVrActivityReLaunch()127     public void testVrActivityReLaunch() throws Exception {
128         assumeTrue(supportsMultiDisplay());
129 
130         // Launch a 2D activity.
131         launchActivity(LAUNCHING_ACTIVITY);
132 
133         try (final VrModeSession vrModeSession = new VrModeSession()) {
134             // Put the device in persistent vr mode.
135             vrModeSession.enablePersistentVrMode();
136 
137             // Launch the VR activity.
138             launchActivity(VR_TEST_ACTIVITY);
139             mAmWmState.computeState(VR_TEST_ACTIVITY);
140             mAmWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
141 
142             // Re-launch the non-VR 2D activity and check where it ends up.
143             launchActivity(LAUNCHING_ACTIVITY);
144             mAmWmState.computeState(LAUNCHING_ACTIVITY);
145 
146             // Ensure that the subsequent activity is visible
147             mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
148 
149             // Check that activity is launched in focused stack on primary display.
150             mAmWmState.assertFocusedActivity("Launched activity must be focused",
151                     LAUNCHING_ACTIVITY);
152             final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
153             final ActivityManagerState.ActivityStack focusedStack
154                     = mAmWmState.getAmState().getStackById(focusedStackId);
155             assertEquals("Launched activity must be resumed in focused stack",
156                     getActivityName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
157 
158             // Check if the launch activity is in Vr virtual display id.
159             final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
160             final ActivityDisplay vrDisplay = getDisplayState(reportedDisplays,
161                     VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
162             assertNotNull("Vr mode should have a virtual display", vrDisplay);
163 
164             // Check if the focused activity is on this virtual stack.
165             assertEquals("Launch in Vr mode should be in virtual stack", vrDisplay.mId,
166                     focusedStack.mDisplayId);
167         }
168     }
169 
170     /**
171      * Tests that any new activity launch post Vr mode is in the main display.
172      */
173     @Test
testActivityLaunchPostVr()174     public void testActivityLaunchPostVr() throws Exception {
175         assumeTrue(supportsMultiDisplay());
176         // This test doesn't apply to a standalone vr device, since vr is always enabled, and
177         // there is no "post vr" behavior to verify.
178         assumeFalse(isUiModeLockedToVrHeadset());
179 
180         try (final VrModeSession vrModeSession = new VrModeSession()) {
181             // Put the device in persistent vr mode.
182             vrModeSession.enablePersistentVrMode();
183 
184             // Launch the VR activity.
185             launchActivity(VR_TEST_ACTIVITY);
186             mAmWmState.computeState(VR_TEST_ACTIVITY);
187             mAmWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
188 
189             // Launch the non-VR 2D activity and check where it ends up.
190             launchActivity(ALT_LAUNCHING_ACTIVITY);
191             mAmWmState.computeState(ALT_LAUNCHING_ACTIVITY);
192 
193             // Ensure that the subsequent activity is visible
194             mAmWmState.assertVisibility(ALT_LAUNCHING_ACTIVITY, true /* visible */);
195 
196             // Check that activity is launched in focused stack on primary display.
197             mAmWmState.assertFocusedActivity("Launched activity must be focused",
198                     ALT_LAUNCHING_ACTIVITY);
199             final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
200             final ActivityManagerState.ActivityStack focusedStack
201                     = mAmWmState.getAmState().getStackById(focusedStackId);
202             assertEquals("Launched activity must be resumed in focused stack",
203                     getActivityName(ALT_LAUNCHING_ACTIVITY),
204                     focusedStack.mResumedActivity);
205 
206             // Check if the launch activity is in Vr virtual display id.
207             final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
208             final ActivityDisplay vrDisplay = getDisplayState(reportedDisplays,
209                     VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT,
210                     VR_VIRTUAL_DISPLAY_DPI);
211             assertNotNull("Vr mode should have a virtual display", vrDisplay);
212 
213             // Check if the focused activity is on this virtual stack.
214             assertEquals("Launch in Vr mode should be in virtual stack", vrDisplay.mId,
215                     focusedStack.mDisplayId);
216 
217         }
218 
219         // There isn't a direct launch of activity which can take an user out of persistent VR mode.
220         // This sleep is to account for that delay and let device settle once it comes out of VR
221         // mode.
222         try {
223             Thread.sleep(2000);
224         } catch (Exception e) {
225             e.printStackTrace();
226         }
227 
228         // Launch the non-VR 2D activity and check where it ends up.
229         launchActivity(RESIZEABLE_ACTIVITY);
230         mAmWmState.computeState(RESIZEABLE_ACTIVITY);
231 
232         // Ensure that the subsequent activity is visible
233         mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
234 
235         // Check that activity is launched in focused stack on primary display.
236         mAmWmState.assertFocusedActivity("Launched activity must be focused", RESIZEABLE_ACTIVITY);
237         final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY);
238         final ActivityManagerState.ActivityStack frontStack
239                 = mAmWmState.getAmState().getStackById(frontStackId);
240         assertEquals("Launched activity must be resumed in front stack",
241                 getActivityName(RESIZEABLE_ACTIVITY), frontStack.mResumedActivity);
242         assertEquals("Front stack must be on primary display",
243                 DEFAULT_DISPLAY, frontStack.mDisplayId);
244     }
245 }
246