Merge "Explicitly invoke keyguard for visibility test" into oc-dev
am: c1f7fd18f9
Change-Id: Ib0eae3c29ab1cbc912f93044b5bc4c072a17f054
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayLockedKeyguardTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayLockedKeyguardTests.java
new file mode 100644
index 0000000..d520f2c
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayLockedKeyguardTests.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 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.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import static android.server.cts.ActivityManagerState.STATE_RESUMED;
+import static android.server.cts.ActivityManagerState.STATE_STOPPED;
+import static android.server.cts.StateLogger.logE;
+
+/**
+ * Display tests that require a locked keyguard.
+ *
+ * Build: mmma -j32 cts/hostsidetests/services
+ * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerDisplayLockedKeyguardTests
+ */
+public class ActivityManagerDisplayLockedKeyguardTests extends ActivityManagerDisplayTestBase {
+
+ private static final String TEST_ACTIVITY_NAME = "TestActivity";
+ private static final String VIRTUAL_DISPLAY_ACTIVITY = "VirtualDisplayActivity";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ setLockCredential();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ removeLockCredential();
+ gotoKeyguard();
+ } catch (DeviceNotAvailableException e) {
+ logE(e.getMessage());
+ }
+ super.tearDown();
+ }
+
+ /**
+ * Test that virtual display content is hidden when device is locked.
+ */
+ public void testVirtualDisplayHidesContentWhenLocked() throws Exception {
+ if (!supportsMultiDisplay() || !isHandheld()) { return; }
+
+ // Create new usual virtual display.
+ final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
+ mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
+
+ // Launch activity on new secondary display.
+ launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
+ mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
+
+ // Lock the device.
+ gotoKeyguard();
+ mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
+ mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_STOPPED);
+ mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, false /* visible */);
+
+ // Unlock and check if visibility is back.
+ unlockDeviceWithCredential();
+ mAmWmState.waitForKeyguardGone(mDevice);
+ mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_RESUMED);
+ mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
+ }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTestBase.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTestBase.java
new file mode 100644
index 0000000..cf44ad7
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTestBase.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2017 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.cts;
+
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import static android.server.cts.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
+import static android.server.cts.StateLogger.log;
+import static android.server.cts.StateLogger.logE;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Base class for ActivityManager display tests.
+ *
+ * @see ActivityManagerDisplayTests
+ * @see ActivityManagerDisplayLockedKeyguardTests
+ */
+public class ActivityManagerDisplayTestBase extends ActivityManagerTestBase {
+
+ static final int CUSTOM_DENSITY_DPI = 222;
+
+ private static final String DUMPSYS_ACTIVITY_PROCESSES = "dumpsys activity processes";
+ private static final String VIRTUAL_DISPLAY_ACTIVITY = "VirtualDisplayActivity";
+ private static final int INVALID_DENSITY_DPI = -1;
+
+ private boolean mVirtualDisplayCreated;
+
+ /** Temp storage used for parsing. */
+ final LinkedList<String> mDumpLines = new LinkedList<>();
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ destroyVirtualDisplays();
+ } catch (DeviceNotAvailableException e) {
+ logE(e.getMessage());
+ }
+ super.tearDown();
+ }
+
+ /** Contains the configurations applied to attached displays. */
+ static final class DisplayState {
+ int mDisplayId;
+ String mOverrideConfig;
+
+ private DisplayState(int displayId, String overrideConfig) {
+ mDisplayId = displayId;
+ mOverrideConfig = overrideConfig;
+ }
+
+ private int getWidth() {
+ final String[] configParts = mOverrideConfig.split(" ");
+ for (String part : configParts) {
+ if (part.endsWith("dp") && part.startsWith("w")) {
+ final String widthString = part.substring(1, part.length() - 3);
+ return Integer.parseInt(widthString);
+ }
+ }
+
+ return -1;
+ }
+
+ private int getHeight() {
+ final String[] configParts = mOverrideConfig.split(" ");
+ for (String part : configParts) {
+ if (part.endsWith("dp") && part.startsWith("h")) {
+ final String heightString = part.substring(1, part.length() - 3);
+ return Integer.parseInt(heightString);
+ }
+ }
+
+ return -1;
+ }
+
+ int getDpi() {
+ final String[] configParts = mOverrideConfig.split(" ");
+ for (String part : configParts) {
+ if (part.endsWith("dpi")) {
+ final String densityDpiString = part.substring(0, part.length() - 3);
+ return Integer.parseInt(densityDpiString);
+ }
+ }
+
+ return -1;
+ }
+ }
+
+ /** Contains the configurations applied to attached displays. */
+ static final class ReportedDisplays {
+ private static final Pattern sGlobalConfigurationPattern =
+ Pattern.compile("mGlobalConfiguration: (\\{.*\\})");
+ private static final Pattern sDisplayOverrideConfigurationsPattern =
+ Pattern.compile("Display override configurations:");
+ private static final Pattern sDisplayConfigPattern =
+ Pattern.compile("(\\d+): (\\{.*\\})");
+
+ String mGlobalConfig;
+ private Map<Integer, DisplayState> mDisplayStates = new HashMap<>();
+
+ static ReportedDisplays create(LinkedList<String> dump) {
+ final ReportedDisplays result = new ReportedDisplays();
+
+ while (!dump.isEmpty()) {
+ final String line = dump.pop().trim();
+
+ Matcher matcher = sDisplayOverrideConfigurationsPattern.matcher(line);
+ if (matcher.matches()) {
+ log(line);
+ while (ReportedDisplays.shouldContinueExtracting(dump, sDisplayConfigPattern)) {
+ final String displayOverrideConfigLine = dump.pop().trim();
+ log(displayOverrideConfigLine);
+ matcher = sDisplayConfigPattern.matcher(displayOverrideConfigLine);
+ matcher.matches();
+ final Integer displayId = Integer.valueOf(matcher.group(1));
+ result.mDisplayStates.put(displayId,
+ new DisplayState(displayId, matcher.group(2)));
+ }
+ continue;
+ }
+
+ matcher = sGlobalConfigurationPattern.matcher(line);
+ if (matcher.matches()) {
+ log(line);
+ result.mGlobalConfig = matcher.group(1);
+ }
+ }
+
+ return result;
+ }
+
+ /** Check if next line in dump matches the pattern and we should continue extracting. */
+ static boolean shouldContinueExtracting(LinkedList<String> dump, Pattern matchingPattern) {
+ if (dump.isEmpty()) {
+ return false;
+ }
+
+ final String line = dump.peek().trim();
+ return matchingPattern.matcher(line).matches();
+ }
+
+ DisplayState getDisplayState(int displayId) {
+ return mDisplayStates.get(displayId);
+ }
+
+ /** Return the display state with width, height, dpi */
+ DisplayState getDisplayState(int width, int height, int dpi) {
+ for (Map.Entry<Integer, DisplayState> entry : mDisplayStates.entrySet()) {
+ final DisplayState ds = entry.getValue();
+ if (ds.mDisplayId != DEFAULT_DISPLAY_ID && ds.getDpi() == dpi
+ && ds.getWidth() == width && ds.getHeight() == height) {
+ return ds;
+ }
+ }
+ return null;
+ }
+
+ /** Check if reported state is valid. */
+ boolean isValidState(int expectedDisplayCount) {
+ if (mDisplayStates.size() != expectedDisplayCount) {
+ return false;
+ }
+
+ for (Map.Entry<Integer, DisplayState> entry : mDisplayStates.entrySet()) {
+ final DisplayState ds = entry.getValue();
+ if (ds.mDisplayId != DEFAULT_DISPLAY_ID && ds.getDpi() == -1) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ ReportedDisplays getDisplaysStates() throws DeviceNotAvailableException {
+ final CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ mDevice.executeShellCommand(DUMPSYS_ACTIVITY_PROCESSES, outputReceiver);
+ String dump = outputReceiver.getOutput();
+ mDumpLines.clear();
+
+ Collections.addAll(mDumpLines, dump.split("\\n"));
+
+ return ReportedDisplays.create(mDumpLines);
+ }
+
+ /** Find the display that was not originally reported in oldDisplays and added in newDisplays */
+ private List<ActivityManagerDisplayTests.DisplayState> findNewDisplayStates(
+ ReportedDisplays oldDisplays, ReportedDisplays newDisplays) {
+ final ArrayList<DisplayState> displays = new ArrayList();
+
+ for (Integer displayId : newDisplays.mDisplayStates.keySet()) {
+ if (!oldDisplays.mDisplayStates.containsKey(displayId)) {
+ displays.add(newDisplays.getDisplayState(displayId));
+ }
+ }
+
+ return displays;
+ }
+
+ /**
+ * Create new virtual display.
+ * @param densityDpi provide custom density for the display.
+ * @param launchInSplitScreen start {@link VirtualDisplayActivity} to side from
+ * {@link LaunchingActivity} on primary display.
+ * @param publicDisplay make display public.
+ * @param resizeDisplay should resize display when surface size changes.
+ * @param launchActivity should launch test activity immediately after display creation.
+ * @return {@link ActivityManagerDisplayTests.DisplayState} of newly created display.
+ * @throws Exception
+ */
+ private List<ActivityManagerDisplayTests.DisplayState> createVirtualDisplays(int densityDpi,
+ boolean launchInSplitScreen, boolean publicDisplay, boolean resizeDisplay,
+ String launchActivity, int displayCount) throws Exception {
+ // Start an activity that is able to create virtual displays.
+ if (launchInSplitScreen) {
+ getLaunchActivityBuilder().setToSide(true)
+ .setTargetActivityName(VIRTUAL_DISPLAY_ACTIVITY).execute();
+ } else {
+ launchActivity(VIRTUAL_DISPLAY_ACTIVITY);
+ }
+ mAmWmState.computeState(mDevice, new String[] {VIRTUAL_DISPLAY_ACTIVITY},
+ false /* compareTaskAndStackBounds */);
+ final ActivityManagerDisplayTests.ReportedDisplays originalDS = getDisplaysStates();
+ final int originalDisplayCount = originalDS.mDisplayStates.size();
+
+ // Create virtual display with custom density dpi.
+ executeShellCommand(getCreateVirtualDisplayCommand(densityDpi, publicDisplay, resizeDisplay,
+ launchActivity, displayCount));
+ mVirtualDisplayCreated = true;
+
+ // Wait for the virtual display to be created and get configurations.
+ final ActivityManagerDisplayTests.ReportedDisplays ds =
+ getDisplayStateAfterChange(originalDisplayCount + displayCount);
+ assertEquals("New virtual display must be created",
+ originalDisplayCount + displayCount, ds.mDisplayStates.size());
+
+ // Find the newly added display.
+ final List<ActivityManagerDisplayTests.DisplayState> newDisplays
+ = findNewDisplayStates(originalDS, ds);
+ assertTrue("New virtual display must be created", displayCount == newDisplays.size());
+
+ return newDisplays;
+ }
+
+ /**
+ * Destroy existing virtual display.
+ */
+ void destroyVirtualDisplays() throws Exception {
+ if (mVirtualDisplayCreated) {
+ executeShellCommand(getDestroyVirtualDisplayCommand());
+ mVirtualDisplayCreated = false;
+ }
+ }
+
+ static class VirtualDisplayBuilder {
+ private final ActivityManagerDisplayTestBase mTests;
+
+ private int mDensityDpi = CUSTOM_DENSITY_DPI;
+ private boolean mLaunchInSplitScreen = false;
+ private boolean mPublicDisplay = false;
+ private boolean mResizeDisplay = true;
+ private String mLaunchActivity = null;
+
+ public VirtualDisplayBuilder(ActivityManagerDisplayTestBase tests) {
+ mTests = tests;
+ }
+
+ public VirtualDisplayBuilder setDensityDpi(int densityDpi) {
+ mDensityDpi = densityDpi;
+ return this;
+ }
+
+ public VirtualDisplayBuilder setLaunchInSplitScreen(boolean launchInSplitScreen) {
+ mLaunchInSplitScreen = launchInSplitScreen;
+ return this;
+ }
+
+ public VirtualDisplayBuilder setPublicDisplay(boolean publicDisplay) {
+ mPublicDisplay = publicDisplay;
+ return this;
+ }
+
+ public VirtualDisplayBuilder setResizeDisplay(boolean resizeDisplay) {
+ mResizeDisplay = resizeDisplay;
+ return this;
+ }
+
+ public VirtualDisplayBuilder setLaunchActivity(String launchActivity) {
+ mLaunchActivity = launchActivity;
+ return this;
+ }
+
+ public DisplayState build() throws Exception {
+ final List<DisplayState> displays = build(1);
+ return displays != null && !displays.isEmpty() ? displays.get(0) : null;
+ }
+
+ public List<DisplayState> build(int count) throws Exception {
+ return mTests.createVirtualDisplays(mDensityDpi, mLaunchInSplitScreen, mPublicDisplay,
+ mResizeDisplay, mLaunchActivity, count);
+ }
+ }
+
+ private static String getCreateVirtualDisplayCommand(int densityDpi, boolean publicDisplay,
+ boolean resizeDisplay, String launchActivity, int displayCount) {
+ final StringBuilder commandBuilder
+ = new StringBuilder(getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY));
+ commandBuilder.append(" -f 0x20000000");
+ commandBuilder.append(" --es command create_display");
+ if (densityDpi != INVALID_DENSITY_DPI) {
+ commandBuilder.append(" --ei density_dpi ").append(densityDpi);
+ }
+ commandBuilder.append(" --ei count ").append(displayCount);
+ commandBuilder.append(" --ez public_display ").append(publicDisplay);
+ commandBuilder.append(" --ez resize_display ").append(resizeDisplay);
+ if (launchActivity != null) {
+ commandBuilder.append(" --es launch_target_activity ").append(launchActivity);
+ }
+ return commandBuilder.toString();
+ }
+
+ private static String getDestroyVirtualDisplayCommand() {
+ return getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY) + " -f 0x20000000" +
+ " --es command destroy_display";
+ }
+
+ /** Wait for provided number of displays and report their configurations. */
+ ReportedDisplays getDisplayStateAfterChange(int expectedDisplayCount)
+ throws DeviceNotAvailableException {
+ ReportedDisplays ds = getDisplaysStates();
+
+ int retriesLeft = 5;
+ while (!ds.isValidState(expectedDisplayCount) && retriesLeft-- > 0) {
+ log("***Waiting for the correct number of displays...");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ log(e.toString());
+ }
+ ds = getDisplaysStates();
+ }
+
+ return ds;
+ }
+
+ /** Checks if the device supports multi-display. */
+ boolean supportsMultiDisplay() throws Exception {
+ return hasDeviceFeature("android.software.activities_on_secondary_displays");
+ }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
index 9ea71d8..4e07eb4 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
@@ -20,19 +20,14 @@
import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
-import java.awt.Rectangle;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static android.server.cts.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
import static android.server.cts.ActivityManagerState.STATE_RESUMED;
-import static android.server.cts.ActivityManagerState.STATE_STOPPED;
import static android.server.cts.StateLogger.log;
import static android.server.cts.StateLogger.logE;
@@ -40,8 +35,7 @@
* Build: mmma -j32 cts/hostsidetests/services
* Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerDisplayTests
*/
-public class ActivityManagerDisplayTests extends ActivityManagerTestBase {
- private static final String DUMPSYS_ACTIVITY_PROCESSES = "dumpsys activity processes";
+public class ActivityManagerDisplayTests extends ActivityManagerDisplayTestBase {
private static final String WM_SIZE = "wm size";
private static final String WM_DENSITY = "wm density";
@@ -54,17 +48,10 @@
private static final String VR_TEST_ACTIVITY_NAME = "VrTestActivity";
private static final String SECOND_PACKAGE_NAME = "android.server.cts.second";
private static final String THIRD_PACKAGE_NAME = "android.server.cts.third";
- private static final int INVALID_DENSITY_DPI = -1;
- private static final int CUSTOM_DENSITY_DPI = 222;
private static final int VR_VIRTUAL_DISPLAY_WIDTH = 70;
private static final int VR_VIRTUAL_DISPLAY_HEIGHT = 90;
private static final int VR_VIRTUAL_DISPLAY_DPI = 320;
- /** Temp storage used for parsing. */
- private final LinkedList<String> mDumpLines = new LinkedList<>();
-
- private boolean mVirtualDisplayCreated;
-
/** Physical display metrics and overrides in the beginning of the test. */
private ReportedDisplayMetrics mInitialDisplayMetrics;
@@ -77,7 +64,6 @@
@Override
protected void tearDown() throws Exception {
try {
- destroyVirtualDisplays();
enablePersistentVrMode(false);
restoreDisplayMetricsOverrides();
} catch (DeviceNotAvailableException e) {
@@ -131,9 +117,6 @@
// Find the density of created display.
final int newDensityDpi = newDisplay.getDpi();
assertEquals(CUSTOM_DENSITY_DPI, newDensityDpi);
-
- // Destroy the created display.
- executeShellCommand(getDestroyVirtualDisplayCommand());
}
/**
@@ -1001,31 +984,6 @@
}
/**
- * Test that virtual display content is hidden when device is locked.
- */
- public void testVirtualDisplayHidesContentWhenLocked() throws Exception {
- if (!supportsMultiDisplay() || !isHandheld()) { return; }
-
- // Create new usual virtual display.
- final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
- mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-
- // Launch activity on new secondary display.
- launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
- mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-
- // Lock the device.
- sleepDevice();
- mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_STOPPED);
- mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, false /* visible */);
-
- // Unlock and check if visibility is back.
- wakeUpAndUnlockDevice();
- mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_RESUMED);
- mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
- }
-
- /**
* Test that all activities that were on the private display are destroyed on display removal.
*/
@Presubmit
@@ -1526,317 +1484,8 @@
}
}
- /** Find the display that was not originally reported in oldDisplays and added in newDisplays */
- private List<DisplayState> findNewDisplayStates(ReportedDisplays oldDisplays,
- ReportedDisplays newDisplays) {
- final ArrayList<DisplayState> displays = new ArrayList();
-
- for (Integer displayId : newDisplays.mDisplayStates.keySet()) {
- if (!oldDisplays.mDisplayStates.containsKey(displayId)) {
- displays.add(newDisplays.getDisplayState(displayId));
- }
- }
-
- return displays;
- }
-
- /**
- * Create new virtual display.
- * @param densityDpi provide custom density for the display.
- * @param launchInSplitScreen start {@link VirtualDisplayActivity} to side from
- * {@link LaunchingActivity} on primary display.
- * @param publicDisplay make display public.
- * @param resizeDisplay should resize display when surface size changes.
- * @param launchActivity should launch test activity immediately after display creation.
- * @return {@link DisplayState} of newly created display.
- * @throws Exception
- */
- private List<DisplayState> createVirtualDisplays(int densityDpi, boolean launchInSplitScreen,
- boolean publicDisplay, boolean resizeDisplay, String launchActivity, int displayCount)
- throws Exception {
- // Start an activity that is able to create virtual displays.
- if (launchInSplitScreen) {
- getLaunchActivityBuilder().setToSide(true)
- .setTargetActivityName(VIRTUAL_DISPLAY_ACTIVITY).execute();
- } else {
- launchActivity(VIRTUAL_DISPLAY_ACTIVITY);
- }
- mAmWmState.computeState(mDevice, new String[] {VIRTUAL_DISPLAY_ACTIVITY},
- false /* compareTaskAndStackBounds */);
- final ReportedDisplays originalDS = getDisplaysStates();
- final int originalDisplayCount = originalDS.mDisplayStates.size();
-
- // Create virtual display with custom density dpi.
- executeShellCommand(getCreateVirtualDisplayCommand(densityDpi, publicDisplay, resizeDisplay,
- launchActivity, displayCount));
- mVirtualDisplayCreated = true;
-
- // Wait for the virtual display to be created and get configurations.
- final ReportedDisplays ds =
- getDisplayStateAfterChange(originalDisplayCount + displayCount);
- assertEquals("New virtual display must be created",
- originalDisplayCount + displayCount, ds.mDisplayStates.size());
-
- // Find the newly added display.
- final List<DisplayState> newDisplays = findNewDisplayStates(originalDS, ds);
- assertTrue("New virtual display must be created", displayCount == newDisplays.size());
-
- return newDisplays;
- }
-
- /**
- * Destroy existing virtual display.
- */
- private void destroyVirtualDisplays() throws Exception {
- if (mVirtualDisplayCreated) {
- executeShellCommand(getDestroyVirtualDisplayCommand());
- mVirtualDisplayCreated = false;
- }
- }
-
- /** Wait for provided number of displays and report their configurations. */
- private ReportedDisplays getDisplayStateAfterChange(int expectedDisplayCount)
- throws DeviceNotAvailableException {
- ReportedDisplays ds = getDisplaysStates();
-
- int retriesLeft = 5;
- while (!ds.isValidState(expectedDisplayCount) && retriesLeft-- > 0) {
- log("***Waiting for the correct number of displays...");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- log(e.toString());
- }
- ds = getDisplaysStates();
- }
-
- return ds;
- }
-
- private ReportedDisplays getDisplaysStates() throws DeviceNotAvailableException {
- final CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
- mDevice.executeShellCommand(DUMPSYS_ACTIVITY_PROCESSES, outputReceiver);
- String dump = outputReceiver.getOutput();
- mDumpLines.clear();
-
- Collections.addAll(mDumpLines, dump.split("\\n"));
-
- return ReportedDisplays.create(mDumpLines);
- }
-
- /** Contains the configurations applied to attached displays. */
- private static final class DisplayState {
- private int mDisplayId;
- private String mOverrideConfig;
-
- private DisplayState(int displayId, String overrideConfig) {
- mDisplayId = displayId;
- mOverrideConfig = overrideConfig;
- }
-
- private int getWidth() {
- final String[] configParts = mOverrideConfig.split(" ");
- for (String part : configParts) {
- if (part.endsWith("dp") && part.startsWith("w")) {
- final String widthString = part.substring(1, part.length() - 3);
- return Integer.parseInt(widthString);
- }
- }
-
- return -1;
- }
-
- private int getHeight() {
- final String[] configParts = mOverrideConfig.split(" ");
- for (String part : configParts) {
- if (part.endsWith("dp") && part.startsWith("h")) {
- final String heightString = part.substring(1, part.length() - 3);
- return Integer.parseInt(heightString);
- }
- }
-
- return -1;
- }
-
- private int getDpi() {
- final String[] configParts = mOverrideConfig.split(" ");
- for (String part : configParts) {
- if (part.endsWith("dpi")) {
- final String densityDpiString = part.substring(0, part.length() - 3);
- return Integer.parseInt(densityDpiString);
- }
- }
-
- return -1;
- }
- }
-
-
-
- /** Contains the configurations applied to attached displays. */
- private static final class ReportedDisplays {
- private static final Pattern sGlobalConfigurationPattern =
- Pattern.compile("mGlobalConfiguration: (\\{.*\\})");
- private static final Pattern sDisplayOverrideConfigurationsPattern =
- Pattern.compile("Display override configurations:");
- private static final Pattern sDisplayConfigPattern =
- Pattern.compile("(\\d+): (\\{.*\\})");
-
- private String mGlobalConfig;
- private Map<Integer, DisplayState> mDisplayStates = new HashMap<>();
-
- static ReportedDisplays create(LinkedList<String> dump) {
- final ReportedDisplays result = new ReportedDisplays();
-
- while (!dump.isEmpty()) {
- final String line = dump.pop().trim();
-
- Matcher matcher = sDisplayOverrideConfigurationsPattern.matcher(line);
- if (matcher.matches()) {
- log(line);
- while (ReportedDisplays.shouldContinueExtracting(dump, sDisplayConfigPattern)) {
- final String displayOverrideConfigLine = dump.pop().trim();
- log(displayOverrideConfigLine);
- matcher = sDisplayConfigPattern.matcher(displayOverrideConfigLine);
- matcher.matches();
- final Integer displayId = Integer.valueOf(matcher.group(1));
- result.mDisplayStates.put(displayId,
- new DisplayState(displayId, matcher.group(2)));
- }
- continue;
- }
-
- matcher = sGlobalConfigurationPattern.matcher(line);
- if (matcher.matches()) {
- log(line);
- result.mGlobalConfig = matcher.group(1);
- }
- }
-
- return result;
- }
-
- /** Check if next line in dump matches the pattern and we should continue extracting. */
- static boolean shouldContinueExtracting(LinkedList<String> dump, Pattern matchingPattern) {
- if (dump.isEmpty()) {
- return false;
- }
-
- final String line = dump.peek().trim();
- return matchingPattern.matcher(line).matches();
- }
-
- DisplayState getDisplayState(int displayId) {
- return mDisplayStates.get(displayId);
- }
-
- /** Return the display state with width, height, dpi */
- DisplayState getDisplayState(int width, int height, int dpi) {
- for (Map.Entry<Integer, DisplayState> entry : mDisplayStates.entrySet()) {
- final DisplayState ds = entry.getValue();
- if (ds.mDisplayId != DEFAULT_DISPLAY_ID && ds.getDpi() == dpi
- && ds.getWidth() == width && ds.getHeight() == height) {
- return ds;
- }
- }
- return null;
- }
-
- /** Check if reported state is valid. */
- boolean isValidState(int expectedDisplayCount) {
- if (mDisplayStates.size() != expectedDisplayCount) {
- return false;
- }
-
- for (Map.Entry<Integer, DisplayState> entry : mDisplayStates.entrySet()) {
- final DisplayState ds = entry.getValue();
- if (ds.mDisplayId != DEFAULT_DISPLAY_ID && ds.getDpi() == -1) {
- return false;
- }
- }
- return true;
- }
- }
-
- private static class VirtualDisplayBuilder {
- private final ActivityManagerDisplayTests mTests;
-
- private int mDensityDpi = CUSTOM_DENSITY_DPI;
- private boolean mLaunchInSplitScreen = false;
- private boolean mPublicDisplay = false;
- private boolean mResizeDisplay = true;
- private String mLaunchActivity = null;
-
- public VirtualDisplayBuilder(ActivityManagerDisplayTests tests) {
- mTests = tests;
- }
-
- public VirtualDisplayBuilder setDensityDpi(int densityDpi) {
- mDensityDpi = densityDpi;
- return this;
- }
-
- public VirtualDisplayBuilder setLaunchInSplitScreen(boolean launchInSplitScreen) {
- mLaunchInSplitScreen = launchInSplitScreen;
- return this;
- }
-
- public VirtualDisplayBuilder setPublicDisplay(boolean publicDisplay) {
- mPublicDisplay = publicDisplay;
- return this;
- }
-
- public VirtualDisplayBuilder setResizeDisplay(boolean resizeDisplay) {
- mResizeDisplay = resizeDisplay;
- return this;
- }
-
- public VirtualDisplayBuilder setLaunchActivity(String launchActivity) {
- mLaunchActivity = launchActivity;
- return this;
- }
-
- public DisplayState build() throws Exception {
- final List<DisplayState> displays = build(1);
- return displays != null && !displays.isEmpty() ? displays.get(0) : null;
- }
-
- public List<DisplayState> build(int count) throws Exception {
- return mTests.createVirtualDisplays(mDensityDpi, mLaunchInSplitScreen, mPublicDisplay,
- mResizeDisplay, mLaunchActivity, count);
- }
- }
-
- private static String getCreateVirtualDisplayCommand(int densityDpi, boolean publicDisplay,
- boolean resizeDisplay, String launchActivity, int displayCount) {
- final StringBuilder commandBuilder
- = new StringBuilder(getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY));
- commandBuilder.append(" -f 0x20000000");
- commandBuilder.append(" --es command create_display");
- if (densityDpi != INVALID_DENSITY_DPI) {
- commandBuilder.append(" --ei density_dpi ").append(densityDpi);
- }
- commandBuilder.append(" --ei count ").append(displayCount);
- commandBuilder.append(" --ez public_display ").append(publicDisplay);
- commandBuilder.append(" --ez resize_display ").append(resizeDisplay);
- if (launchActivity != null) {
- commandBuilder.append(" --es launch_target_activity ").append(launchActivity);
- }
- return commandBuilder.toString();
- }
-
- private static String getDestroyVirtualDisplayCommand() {
- return getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY) + " -f 0x20000000" +
- " --es command destroy_display";
- }
-
private static String getResizeVirtualDisplayCommand() {
return getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY) + " -f 0x20000000" +
" --es command resize_display";
}
-
- /** Checks if the device supports multi-display. */
- private boolean supportsMultiDisplay() throws Exception {
- return hasDeviceFeature("android.software.activities_on_secondary_displays");
- }
}