• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.wm;
18 
19 import static android.server.wm.ComponentNameUtils.getActivityName;
20 import static android.server.wm.ShellCommandHelper.executeShellCommand;
21 import static android.server.wm.app.Components.ALT_LAUNCHING_ACTIVITY;
22 import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
23 import static android.server.wm.app.Components.RESIZEABLE_ACTIVITY;
24 import static android.server.wm.app.Components.VR_TEST_ACTIVITY;
25 import static android.view.Display.DEFAULT_DISPLAY;
26 
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assume.assumeFalse;
30 import static org.junit.Assume.assumeTrue;
31 
32 import android.content.ComponentName;
33 import android.platform.test.annotations.Presubmit;
34 import android.provider.Settings;
35 import android.server.wm.WindowManagerState.DisplayContent;
36 import android.server.wm.settings.SettingsSession;
37 
38 import com.android.cts.verifier.vr.MockVrListenerService;
39 
40 import org.junit.Before;
41 import org.junit.Test;
42 
43 import java.util.List;
44 
45 /**
46  * Build/Install/Run:
47  *     atest CtsWindowManagerDeviceTestCases:VrDisplayTests
48  */
49 @Presubmit
50 @android.server.wm.annotation.Group3
51 public class VrDisplayTests extends MultiDisplayTestBase {
52     private static final int VR_VIRTUAL_DISPLAY_WIDTH = 700;
53     private static final int VR_VIRTUAL_DISPLAY_HEIGHT = 900;
54     private static final int VR_VIRTUAL_DISPLAY_DPI = 320;
55 
56 
57     @Before
58     @Override
setUp()59     public void setUp() throws Exception {
60         super.setUp();
61 
62         assumeTrue(supportsVrMode());
63     }
64 
65     /**
66      * VrModeSession is used to enable or disable persistent vr mode and the vr virtual display. For
67      * standalone vr devices, VrModeSession has no effect, because the device is already in
68      * persistent vr mode whenever it's on, and turning off persistent vr mode on a standalone vr
69      * device puts the device in a bad state.
70      */
71     private static class VrModeSession implements AutoCloseable {
72         private boolean applyVrModeChanges = !ActivityManagerTestBase.isUiModeLockedToVrHeadset();
73 
enablePersistentVrMode()74         void enablePersistentVrMode() {
75             if (!applyVrModeChanges) { return; }
76             executeShellCommand("setprop vr_virtualdisplay true");
77             executeShellCommand("vr set-persistent-vr-mode-enabled true");
78         }
79 
80         @Override
close()81         public void close() {
82             if (!applyVrModeChanges) { return; }
83             executeShellCommand("vr set-persistent-vr-mode-enabled false");
84             executeShellCommand("setprop vr_virtualdisplay false");
85         }
86     }
87 
88     /**
89      * Helper class to enable vr listener.
90      * VrManagerService uses SettingChangeListener to monitor ENABLED_VR_LISTENERS changed.
91      * We need to update Settings to let Vr service know if MockVrListenerService is enabled.
92      */
93     private static class EnableVrListenerSession extends SettingsSession<String> {
EnableVrListenerSession()94         public EnableVrListenerSession() {
95             super(Settings.Secure.getUriFor(Settings.Secure.ENABLED_VR_LISTENERS),
96                     Settings.Secure::getString,
97                     Settings.Secure::putString);
98         }
99 
enableVrListener(ComponentName targetVrComponent)100         public void enableVrListener(ComponentName targetVrComponent) {
101             ComponentName component = new ComponentName(targetVrComponent.getPackageName(),
102                     MockVrListenerService.class.getName());
103             set(component.flattenToString());
104         }
105     }
106 
107     /**
108      * Tests that any new activity launch in Vr mode is in Vr display.
109      */
110     @Test
testVrActivityLaunch()111     public void testVrActivityLaunch() {
112         assumeTrue(supportsMultiDisplay());
113 
114         final VrModeSession vrModeSession = mObjectTracker.manage(new VrModeSession());
115         final EnableVrListenerSession enableVrListenerSession =
116                 mObjectTracker.manage(new EnableVrListenerSession());
117 
118         // Put the device in persistent vr mode.
119         vrModeSession.enablePersistentVrMode();
120         enableVrListenerSession.enableVrListener(VR_TEST_ACTIVITY);
121 
122         // Launch the VR activity.
123         launchActivity(VR_TEST_ACTIVITY);
124         mWmState.computeState(VR_TEST_ACTIVITY);
125         mWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
126 
127         // Launch the non-VR 2D activity and check where it ends up.
128         launchActivity(LAUNCHING_ACTIVITY);
129         mWmState.computeState(LAUNCHING_ACTIVITY);
130 
131         // Ensure that the subsequent activity is visible
132         mWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
133 
134         // Check that activity is launched in focused task on primary display.
135         mWmState.assertFocusedActivity("Launched activity must be focused",
136                 LAUNCHING_ACTIVITY);
137         final int focusedTaskId = mWmState.getFocusedTaskId();
138         final WindowManagerState.Task focusedTask = mWmState.getRootTask(focusedTaskId);
139         assertEquals("Launched activity must be resumed in focused task",
140                 getActivityName(LAUNCHING_ACTIVITY), focusedTask.mResumedActivity);
141 
142         // Check if the launch activity is in Vr virtual display id.
143         final List<DisplayContent> reportedDisplays = getDisplaysStates();
144         final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
145                 VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
146         assertNotNull("Vr mode should have a virtual display", vrDisplay);
147 
148         // Check if the focused activity is on this virtual task.
149         assertEquals("Launch in Vr mode should be in virtual task", vrDisplay.mId,
150                 focusedTask.mDisplayId);
151     }
152 
153     /**
154      * Tests that any activity already present is re-launched in Vr display in vr mode.
155      */
156     @Test
testVrActivityReLaunch()157     public void testVrActivityReLaunch() {
158         assumeTrue(supportsMultiDisplay());
159 
160         // Launch a 2D activity.
161         launchActivity(LAUNCHING_ACTIVITY);
162 
163         final VrModeSession vrModeSession = mObjectTracker.manage(new VrModeSession());
164         final EnableVrListenerSession enableVrListenerSession =
165                 mObjectTracker.manage(new EnableVrListenerSession());
166 
167         // Put the device in persistent vr mode.
168         vrModeSession.enablePersistentVrMode();
169         enableVrListenerSession.enableVrListener(VR_TEST_ACTIVITY);
170 
171         // Launch the VR activity.
172         launchActivity(VR_TEST_ACTIVITY);
173         mWmState.computeState(VR_TEST_ACTIVITY);
174         mWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
175 
176         // Re-launch the non-VR 2D activity and check where it ends up.
177         launchActivity(LAUNCHING_ACTIVITY);
178         mWmState.computeState(LAUNCHING_ACTIVITY);
179 
180         // Ensure that the subsequent activity is visible
181         mWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
182 
183         // Check that activity is launched in focused task on primary display.
184         mWmState.assertFocusedActivity("Launched activity must be focused",
185                 LAUNCHING_ACTIVITY);
186         final int focusedTaskId = mWmState.getFocusedTaskId();
187         final WindowManagerState.Task focusedTask
188                 = mWmState.getRootTask(focusedTaskId);
189         assertEquals("Launched activity must be resumed in focused task",
190                 getActivityName(LAUNCHING_ACTIVITY), focusedTask.mResumedActivity);
191 
192         // Check if the launch activity is in Vr virtual display id.
193         final List<DisplayContent> reportedDisplays = getDisplaysStates();
194         final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
195                 VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
196         assertNotNull("Vr mode should have a virtual display", vrDisplay);
197 
198         // Check if the focused activity is on this virtual task.
199         assertEquals("Launch in Vr mode should be in virtual task", vrDisplay.mId,
200                 focusedTask.mDisplayId);
201     }
202 
203     /**
204      * Tests that any new activity launch post Vr mode is in the main display.
205      */
206     @Test
testActivityLaunchPostVr()207     public void testActivityLaunchPostVr() throws Exception {
208         assumeTrue(supportsMultiDisplay());
209         // This test doesn't apply to a standalone vr device, since vr is always enabled, and
210         // there is no "post vr" behavior to verify.
211         assumeFalse(isUiModeLockedToVrHeadset());
212 
213         try (final VrModeSession vrModeSession = new VrModeSession();
214              final EnableVrListenerSession enableVrListenerSession =
215                      new EnableVrListenerSession()) {
216             // Put the device in persistent vr mode.
217             vrModeSession.enablePersistentVrMode();
218             enableVrListenerSession.enableVrListener(VR_TEST_ACTIVITY);
219 
220             // Launch the VR activity.
221             launchActivity(VR_TEST_ACTIVITY);
222             mWmState.computeState(VR_TEST_ACTIVITY);
223             mWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
224 
225             // Launch the non-VR 2D activity and check where it ends up.
226             launchActivity(ALT_LAUNCHING_ACTIVITY);
227             mWmState.computeState(ALT_LAUNCHING_ACTIVITY);
228 
229             // Ensure that the subsequent activity is visible
230             mWmState.assertVisibility(ALT_LAUNCHING_ACTIVITY, true /* visible */);
231 
232             // Check that activity is launched in focused task on primary display.
233             mWmState.assertFocusedActivity("Launched activity must be focused",
234                     ALT_LAUNCHING_ACTIVITY);
235             final int focusedTaskId = mWmState.getFocusedTaskId();
236             final WindowManagerState.Task focusedTask = mWmState.getRootTask(focusedTaskId);
237             assertEquals("Launched activity must be resumed in focused task",
238                     getActivityName(ALT_LAUNCHING_ACTIVITY),
239                     focusedTask.mResumedActivity);
240 
241             // Check if the launch activity is in Vr virtual display id.
242             final List<DisplayContent> reportedDisplays = getDisplaysStates();
243             final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
244                     VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT,
245                     VR_VIRTUAL_DISPLAY_DPI);
246             assertNotNull("Vr mode should have a virtual display", vrDisplay);
247 
248             // Check if the focused activity is on this virtual task.
249             assertEquals("Launch in Vr mode should be in virtual task", vrDisplay.mId,
250                     focusedTask.mDisplayId);
251 
252         }
253 
254         // There isn't a direct launch of activity which can take an user out of persistent VR mode.
255         // This sleep is to account for that delay and let device settle once it comes out of VR
256         // mode.
257         try {
258             Thread.sleep(2000);
259         } catch (Exception e) {
260             e.printStackTrace();
261         }
262 
263         // Launch the non-VR 2D activity and check where it ends up.
264         launchActivity(RESIZEABLE_ACTIVITY);
265         mWmState.computeState(RESIZEABLE_ACTIVITY);
266 
267         // Ensure that the subsequent activity is visible
268         mWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
269 
270         // Check that activity is launched in focused task on primary display.
271         mWmState.assertFocusedActivity("Launched activity must be focused", RESIZEABLE_ACTIVITY);
272         final int frontRootTaskId = mWmState.getFrontRootTaskId(DEFAULT_DISPLAY);
273         final WindowManagerState.Task frontRootTask
274                 = mWmState.getRootTask(frontRootTaskId);
275         assertEquals("Launched activity must be resumed in front root task",
276                 getActivityName(RESIZEABLE_ACTIVITY), frontRootTask.mResumedActivity);
277         assertEquals("Front root task must be on primary display",
278                 DEFAULT_DISPLAY, frontRootTask.mDisplayId);
279     }
280 }
281