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