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.ShellCommandHelper.executeShellCommand; 20 import static android.server.wm.ShellCommandHelper.executeShellCommandAndGetStdout; 21 import static android.server.wm.app.Components.TEST_ACTIVITY; 22 import static android.server.wm.displaysize.Components.SMALLEST_WIDTH_ACTIVITY; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertTrue; 26 27 import android.graphics.Point; 28 import android.hardware.display.DisplayManager; 29 import android.hardware.display.VirtualDisplay; 30 import android.os.Build; 31 import android.os.Handler; 32 import android.os.Looper; 33 import android.platform.test.annotations.Presubmit; 34 import android.view.Display; 35 36 import org.junit.After; 37 import org.junit.Test; 38 39 /** 40 * Ensure that compatibility dialog is shown when launching an application with 41 * an unsupported smallest width. 42 * 43 * <p>Build/Install/Run: 44 * atest CtsWindowManagerDeviceTestCases:DisplaySizeTest 45 */ 46 @Presubmit 47 @android.server.wm.annotation.Group3 48 public class DisplaySizeTest extends ActivityManagerTestBase { 49 50 /** @see com.android.server.wm.UnsupportedDisplaySizeDialog */ 51 private static final String UNSUPPORTED_DISPLAY_SIZE_DIALOG_NAME = 52 "UnsupportedDisplaySizeDialog"; 53 54 @After tearDown()55 public void tearDown() { 56 // Ensure app process is stopped. 57 stopTestPackage(SMALLEST_WIDTH_ACTIVITY.getPackageName()); 58 stopTestPackage(TEST_ACTIVITY.getPackageName()); 59 } 60 61 @Test testCompatibilityDialog()62 public void testCompatibilityDialog() { 63 // Launch some other app (not to perform density change on launcher). 64 launchActivity(TEST_ACTIVITY); 65 mWmState.assertActivityDisplayed(TEST_ACTIVITY); 66 67 createManagedScreenDensitySession().setUnsupportedDensity(); 68 69 // Launch target app. 70 launchActivity(SMALLEST_WIDTH_ACTIVITY); 71 mWmState.assertActivityDisplayed(SMALLEST_WIDTH_ACTIVITY); 72 mWmState.assertWindowDisplayed(UNSUPPORTED_DISPLAY_SIZE_DIALOG_NAME); 73 } 74 75 @Test testCompatibilityDialogWhenFocused()76 public void testCompatibilityDialogWhenFocused() { 77 launchActivity(SMALLEST_WIDTH_ACTIVITY); 78 mWmState.assertActivityDisplayed(SMALLEST_WIDTH_ACTIVITY); 79 80 createManagedScreenDensitySession().setUnsupportedDensity(); 81 82 mWmState.assertWindowDisplayed(UNSUPPORTED_DISPLAY_SIZE_DIALOG_NAME); 83 } 84 85 @Test testCompatibilityDialogAfterReturn()86 public void testCompatibilityDialogAfterReturn() { 87 // Launch target app. 88 launchActivity(SMALLEST_WIDTH_ACTIVITY); 89 mWmState.assertActivityDisplayed(SMALLEST_WIDTH_ACTIVITY); 90 // Launch another activity. 91 final CommandSession.ActivitySession activity = createManagedActivityClientSession() 92 .startActivity(getLaunchActivityBuilder().setUseInstrumentation() 93 .setTargetActivity(TEST_ACTIVITY)); 94 mWmState.assertActivityDisplayed(TEST_ACTIVITY); 95 separateTestJournal(); 96 97 createManagedScreenDensitySession().setUnsupportedDensity(); 98 99 assertActivityLifecycle(TEST_ACTIVITY, true /* relaunched */); 100 activity.finish(); 101 102 mWmState.assertActivityDisplayed(SMALLEST_WIDTH_ACTIVITY); 103 mWmState.assertWindowDisplayed(UNSUPPORTED_DISPLAY_SIZE_DIALOG_NAME); 104 } 105 106 @Test testSizeRangesAfterSettingDisplaySize()107 public void testSizeRangesAfterSettingDisplaySize() throws InterruptedException { 108 VirtualDisplay virtualDisplay = null; 109 try { 110 final int initialLength = 500; 111 final int newLength = 1000; 112 final DisplayManager displayManager = mDm; 113 virtualDisplay = displayManager.createVirtualDisplay("CtsDisplay", initialLength, 114 initialLength, 160 /* densityDpi */, null /* surface */, 0 /* flags */); 115 final Display targetDisplay = virtualDisplay.getDisplay(); 116 final int targetDisplayId = targetDisplay.getDisplayId(); 117 final boolean[] displayChanged = { false }; 118 displayManager.registerDisplayListener(new DisplayManager.DisplayListener() { 119 @Override 120 public void onDisplayAdded(int displayId) {} 121 122 @Override 123 public void onDisplayRemoved(int displayId) {} 124 125 @Override 126 public void onDisplayChanged(int displayId) { 127 if (displayId == targetDisplayId) { 128 synchronized (displayManager) { 129 displayChanged[0] = true; 130 displayManager.notify(); 131 } 132 displayManager.unregisterDisplayListener(this); 133 } 134 } 135 }, new Handler(Looper.getMainLooper())); 136 137 executeShellCommand(String.format("wm size %sx%s -d %s", 138 newLength, newLength, targetDisplayId)); 139 140 synchronized (displayManager) { 141 if (!displayChanged[0]) { 142 displayManager.wait(3000 /* milliseconds */); 143 } 144 assertTrue("DisplayManager must receive onDisplayChanged event", displayChanged[0]); 145 } 146 147 final Point expectedSize = new Point(newLength, newLength); 148 final Point smallestSize = new Point(); 149 final Point largestSize = new Point(); 150 targetDisplay.getCurrentSizeRange(smallestSize, largestSize); 151 assertEquals("Smallest size must be changed.", expectedSize, smallestSize); 152 assertEquals("Largest size must be changed.", expectedSize, largestSize); 153 } finally { 154 if (virtualDisplay != null) { 155 virtualDisplay.release(); 156 } 157 } 158 } 159 createManagedScreenDensitySession()160 protected ScreenDensitySession createManagedScreenDensitySession() { 161 return mObjectTracker.manage(new ScreenDensitySession()); 162 } 163 164 private static class ScreenDensitySession implements AutoCloseable { 165 private static final String DENSITY_PROP_DEVICE = "ro.sf.lcd_density"; 166 private static final String DENSITY_PROP_EMULATOR = "qemu.sf.lcd_density"; 167 setUnsupportedDensity()168 void setUnsupportedDensity() { 169 // Set device to 0.85 zoom. It doesn't matter that we're zooming out 170 // since the feature verifies that we're in a non-default density. 171 final int stableDensity = getStableDensity(); 172 final int targetDensity = (int) (stableDensity * 0.85); 173 setDensity(targetDensity); 174 } 175 176 @Override close()177 public void close() throws Exception { 178 resetDensity(); 179 } 180 getStableDensity()181 private int getStableDensity() { 182 final String densityProp; 183 if (Build.IS_EMULATOR) { 184 densityProp = DENSITY_PROP_EMULATOR; 185 } else { 186 densityProp = DENSITY_PROP_DEVICE; 187 } 188 189 return Integer.parseInt( 190 executeShellCommandAndGetStdout("getprop " + densityProp).trim()); 191 } 192 setDensity(int targetDensity)193 private void setDensity(int targetDensity) { 194 executeShellCommand("wm density " + targetDensity); 195 196 // Verify that the density is changed. 197 final String output = executeShellCommandAndGetStdout("wm density"); 198 final boolean success = output.contains("Override density: " + targetDensity); 199 200 assertTrue("Failed to set density to " + targetDensity, success); 201 } 202 resetDensity()203 private void resetDensity() { 204 executeShellCommand("wm density reset"); 205 } 206 } 207 } 208