blob: d76e49b4aac67a4bb5b11c485666f871ff1fd47c [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.server.wm;
import static android.server.wm.ComponentNameUtils.getActivityName;
import static android.server.wm.app.Components.ALT_LAUNCHING_ACTIVITY;
import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
import static android.server.wm.app.Components.RESIZEABLE_ACTIVITY;
import static android.server.wm.app.Components.VR_TEST_ACTIVITY;
import static android.view.Display.DEFAULT_DISPLAY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.content.ComponentName;
import android.platform.test.annotations.FlakyTest;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.server.wm.WindowManagerState.DisplayContent;
import android.server.wm.settings.SettingsSession;
import com.android.cts.verifier.vr.MockVrListenerService;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
/**
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:VrDisplayTests
*/
@Presubmit
@FlakyTest
@android.server.wm.annotation.Group3
public class VrDisplayTests extends MultiDisplayTestBase {
private static final int VR_VIRTUAL_DISPLAY_WIDTH = 700;
private static final int VR_VIRTUAL_DISPLAY_HEIGHT = 900;
private static final int VR_VIRTUAL_DISPLAY_DPI = 320;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
assumeTrue(supportsVrMode());
}
/**
* VrModeSession is used to enable or disable persistent vr mode and the vr virtual display. For
* standalone vr devices, VrModeSession has no effect, because the device is already in
* persistent vr mode whenever it's on, and turning off persistent vr mode on a standalone vr
* device puts the device in a bad state.
*/
private static class VrModeSession implements AutoCloseable {
private boolean applyVrModeChanges = !ActivityManagerTestBase.isUiModeLockedToVrHeadset();
void enablePersistentVrMode() {
if (!applyVrModeChanges) { return; }
executeShellCommand("setprop vr_virtualdisplay true");
executeShellCommand("vr set-persistent-vr-mode-enabled true");
}
@Override
public void close() {
if (!applyVrModeChanges) { return; }
executeShellCommand("vr set-persistent-vr-mode-enabled false");
executeShellCommand("setprop vr_virtualdisplay false");
}
}
/**
* Helper class to enable vr listener.
* VrManagerService uses SettingChangeListener to monitor ENABLED_VR_LISTENERS changed.
* We need to update Settings to let Vr service know if MockVrListenerService is enabled.
*/
private static class EnableVrListenerSession extends SettingsSession<String> {
public EnableVrListenerSession() {
super(Settings.Secure.getUriFor(Settings.Secure.ENABLED_VR_LISTENERS),
Settings.Secure::getString,
Settings.Secure::putString);
}
public void enableVrListener(ComponentName targetVrComponent) {
ComponentName component = new ComponentName(targetVrComponent.getPackageName(),
MockVrListenerService.class.getName());
set(component.flattenToString());
}
}
/**
* Tests that any new activity launch in Vr mode is in Vr display.
*/
@Test
public void testVrActivityLaunch() {
assumeTrue(supportsMultiDisplay());
final VrModeSession vrModeSession = mObjectTracker.manage(new VrModeSession());
final EnableVrListenerSession enableVrListenerSession =
mObjectTracker.manage(new EnableVrListenerSession());
// Put the device in persistent vr mode.
vrModeSession.enablePersistentVrMode();
enableVrListenerSession.enableVrListener(VR_TEST_ACTIVITY);
// Launch the VR activity.
launchActivity(VR_TEST_ACTIVITY);
mWmState.computeState(VR_TEST_ACTIVITY);
mWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
// Launch the non-VR 2D activity and check where it ends up.
launchActivity(LAUNCHING_ACTIVITY);
mWmState.computeState(LAUNCHING_ACTIVITY);
// Ensure that the subsequent activity is visible
mWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
// Check that activity is launched in focused task on primary display.
mWmState.assertFocusedActivity("Launched activity must be focused",
LAUNCHING_ACTIVITY);
final int focusedTaskId = mWmState.getFocusedTaskId();
final WindowManagerState.Task focusedTask = mWmState.getRootTask(focusedTaskId);
assertEquals("Launched activity must be resumed in focused task",
getActivityName(LAUNCHING_ACTIVITY), focusedTask.mResumedActivity);
// Check if the launch activity is in Vr virtual display id.
final List<DisplayContent> reportedDisplays = getDisplaysStates();
final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
assertNotNull("Vr mode should have a virtual display", vrDisplay);
// Check if the focused activity is on this virtual task.
assertEquals("Launch in Vr mode should be in virtual task", vrDisplay.mId,
focusedTask.mDisplayId);
}
/**
* Tests that any activity already present is re-launched in Vr display in vr mode.
*/
@Test
public void testVrActivityReLaunch() {
assumeTrue(supportsMultiDisplay());
// Launch a 2D activity.
launchActivity(LAUNCHING_ACTIVITY);
final VrModeSession vrModeSession = mObjectTracker.manage(new VrModeSession());
final EnableVrListenerSession enableVrListenerSession =
mObjectTracker.manage(new EnableVrListenerSession());
// Put the device in persistent vr mode.
vrModeSession.enablePersistentVrMode();
enableVrListenerSession.enableVrListener(VR_TEST_ACTIVITY);
// Launch the VR activity.
launchActivity(VR_TEST_ACTIVITY);
mWmState.computeState(VR_TEST_ACTIVITY);
mWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
// Re-launch the non-VR 2D activity and check where it ends up.
launchActivity(LAUNCHING_ACTIVITY);
mWmState.computeState(LAUNCHING_ACTIVITY);
// Ensure that the subsequent activity is visible
mWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
// Check that activity is launched in focused task on primary display.
mWmState.assertFocusedActivity("Launched activity must be focused",
LAUNCHING_ACTIVITY);
final int focusedTaskId = mWmState.getFocusedTaskId();
final WindowManagerState.Task focusedTask
= mWmState.getRootTask(focusedTaskId);
assertEquals("Launched activity must be resumed in focused task",
getActivityName(LAUNCHING_ACTIVITY), focusedTask.mResumedActivity);
// Check if the launch activity is in Vr virtual display id.
final List<DisplayContent> reportedDisplays = getDisplaysStates();
final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
assertNotNull("Vr mode should have a virtual display", vrDisplay);
// Check if the focused activity is on this virtual task.
assertEquals("Launch in Vr mode should be in virtual task", vrDisplay.mId,
focusedTask.mDisplayId);
}
/**
* Tests that any new activity launch post Vr mode is in the main display.
*/
@Test
public void testActivityLaunchPostVr() throws Exception {
assumeTrue(supportsMultiDisplay());
// This test doesn't apply to a standalone vr device, since vr is always enabled, and
// there is no "post vr" behavior to verify.
assumeFalse(isUiModeLockedToVrHeadset());
try (final VrModeSession vrModeSession = new VrModeSession();
final EnableVrListenerSession enableVrListenerSession =
new EnableVrListenerSession()) {
// Put the device in persistent vr mode.
vrModeSession.enablePersistentVrMode();
enableVrListenerSession.enableVrListener(VR_TEST_ACTIVITY);
// Launch the VR activity.
launchActivity(VR_TEST_ACTIVITY);
mWmState.computeState(VR_TEST_ACTIVITY);
mWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
// Launch the non-VR 2D activity and check where it ends up.
launchActivity(ALT_LAUNCHING_ACTIVITY);
mWmState.computeState(ALT_LAUNCHING_ACTIVITY);
// Ensure that the subsequent activity is visible
mWmState.assertVisibility(ALT_LAUNCHING_ACTIVITY, true /* visible */);
// Check that activity is launched in focused task on primary display.
mWmState.assertFocusedActivity("Launched activity must be focused",
ALT_LAUNCHING_ACTIVITY);
final int focusedTaskId = mWmState.getFocusedTaskId();
final WindowManagerState.Task focusedTask = mWmState.getRootTask(focusedTaskId);
assertEquals("Launched activity must be resumed in focused task",
getActivityName(ALT_LAUNCHING_ACTIVITY),
focusedTask.mResumedActivity);
// Check if the launch activity is in Vr virtual display id.
final List<DisplayContent> reportedDisplays = getDisplaysStates();
final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT,
VR_VIRTUAL_DISPLAY_DPI);
assertNotNull("Vr mode should have a virtual display", vrDisplay);
// Check if the focused activity is on this virtual task.
assertEquals("Launch in Vr mode should be in virtual task", vrDisplay.mId,
focusedTask.mDisplayId);
}
// There isn't a direct launch of activity which can take an user out of persistent VR mode.
// This sleep is to account for that delay and let device settle once it comes out of VR
// mode.
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
// Launch the non-VR 2D activity and check where it ends up.
launchActivity(RESIZEABLE_ACTIVITY);
mWmState.computeState(RESIZEABLE_ACTIVITY);
// Ensure that the subsequent activity is visible
mWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
// Check that activity is launched in focused task on primary display.
mWmState.assertFocusedActivity("Launched activity must be focused", RESIZEABLE_ACTIVITY);
final int frontRootTaskId = mWmState.getFrontRootTaskId(DEFAULT_DISPLAY);
final WindowManagerState.Task frontRootTask
= mWmState.getRootTask(frontRootTaskId);
assertEquals("Launched activity must be resumed in front root task",
getActivityName(RESIZEABLE_ACTIVITY), frontRootTask.mResumedActivity);
assertEquals("Front root task must be on primary display",
DEFAULT_DISPLAY, frontRootTask.mDisplayId);
}
}