summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2018-08-02 21:16:56 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-08-02 21:16:56 +0000
commitc8280ca86a2194eef348e3d837fe78b26b350f81 (patch)
treef9e31ddd0d683acb8e7c12535ab34f35929bbb19
parente4c7d37e03146ada9becbc30468a9e4f9ad9c9eb (diff)
parente084604e63c0f3ac129b2e2d7d220e3ededa2949 (diff)
Merge "Bootstrap freeform external displays."
-rw-r--r--services/core/java/com/android/server/am/ActivityTaskManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplaySettings.java103
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java11
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java180
6 files changed, 288 insertions, 30 deletions
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index f2b097b28efd..54c2ee51c7a2 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -27,6 +27,7 @@ import static android.Manifest.permission.REMOVE_TASKS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.STOP_APP_SWITCHES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
+import static android.content.pm.PackageManager.FEATURE_PC;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
import static android.provider.Settings.System.FONT_SCALE;
@@ -541,6 +542,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
final boolean forceResizable = Settings.Global.getInt(
resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
+ final boolean isPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
// Transfer any global setting for forcing RTL layout, into a System Property
SystemProperties.set(DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
@@ -573,6 +575,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
mWindowManager.setForceResizableTasks(mForceResizableActivities);
mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
+ mWindowManager.setSupportsFreeformWindowManagement(mSupportsFreeformWindowManagement);
+ mWindowManager.setIsPc(isPc);
// This happens before any activities are started, so we can change global configuration
// in-place.
updateConfigurationLocked(configuration, null, true);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d7d5cf84ede0..4ab06a28712d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1389,9 +1389,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
- // TODO: Probably best to set this based on some setting in the display content object,
- // so the display can be configured for things like fullscreen.
- config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ config.windowConfiguration.setWindowingMode(getWindowingMode());
final float density = mDisplayMetrics.density;
config.screenWidthDp =
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index 97b64dc2b6b1..bbb690f6a34a 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -19,12 +19,19 @@ package com.android.server.wm;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.app.WindowConfiguration;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Environment;
+import android.provider.Settings;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
+import android.view.Display;
+import android.view.DisplayInfo;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
@@ -43,37 +50,48 @@ import org.xmlpull.v1.XmlSerializer;
/**
* Current persistent settings about a display
*/
-public class DisplaySettings {
+class DisplaySettings {
private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplaySettings" : TAG_WM;
+ private final WindowManagerService mService;
private final AtomicFile mFile;
private final HashMap<String, Entry> mEntries = new HashMap<String, Entry>();
- public static class Entry {
- public final String name;
- public int overscanLeft;
- public int overscanTop;
- public int overscanRight;
- public int overscanBottom;
+ private static class Entry {
+ private final String name;
+ private int overscanLeft;
+ private int overscanTop;
+ private int overscanRight;
+ private int overscanBottom;
+ private int windowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
- public Entry(String _name) {
+ private Entry(String _name) {
name = _name;
}
}
- public DisplaySettings() {
- File dataDir = Environment.getDataDirectory();
- File systemDir = new File(dataDir, "system");
- mFile = new AtomicFile(new File(systemDir, "display_settings.xml"), "wm-displays");
+ DisplaySettings(WindowManagerService service) {
+ this(service, new File(Environment.getDataDirectory(), "system"));
}
- public void getOverscanLocked(String name, String uniqueId, Rect outRect) {
+ @VisibleForTesting
+ DisplaySettings(WindowManagerService service, File folder) {
+ mService = service;
+ mFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays");
+ }
+
+ private Entry getEntry(String name, String uniqueId) {
// Try to get the entry with the unique if possible.
// Else, fall back on the display name.
Entry entry;
if (uniqueId == null || (entry = mEntries.get(uniqueId)) == null) {
entry = mEntries.get(name);
}
+ return entry;
+ }
+
+ private void getOverscanLocked(String name, String uniqueId, Rect outRect) {
+ final Entry entry = getEntry(name, uniqueId);
if (entry != null) {
outRect.left = entry.overscanLeft;
outRect.top = entry.overscanTop;
@@ -84,7 +102,7 @@ public class DisplaySettings {
}
}
- public void setOverscanLocked(String uniqueId, String name, int left, int top, int right,
+ void setOverscanLocked(String uniqueId, String name, int left, int top, int right,
int bottom) {
if (left == 0 && top == 0 && right == 0 && bottom == 0) {
// Right now all we are storing is overscan; if there is no overscan,
@@ -105,7 +123,47 @@ public class DisplaySettings {
entry.overscanBottom = bottom;
}
- public void readSettingsLocked() {
+ private int getWindowingModeLocked(String name, String uniqueId, int displayId) {
+ final Entry entry = getEntry(name, uniqueId);
+ int windowingMode = entry != null ? entry.windowingMode
+ : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ // This display used to be in freeform, but we don't support freeform anymore, so fall
+ // back to fullscreen.
+ if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
+ && !mService.mSupportsFreeformWindowManagement) {
+ return WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+ }
+ // No record is present so use default windowing mode policy.
+ if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ windowingMode = (mService.mIsPc && mService.mSupportsFreeformWindowManagement)
+ ? WindowConfiguration.WINDOWING_MODE_FREEFORM
+ : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+ } else {
+ windowingMode = mService.mSupportsFreeformWindowManagement
+ ? WindowConfiguration.WINDOWING_MODE_FREEFORM
+ : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+ }
+ }
+ return windowingMode;
+ }
+
+ void applySettingsToDisplayLocked(DisplayContent dc) {
+ final DisplayInfo displayInfo = dc.getDisplayInfo();
+
+ // Setting windowing mode first, because it may override overscan values later.
+ dc.setWindowingMode(getWindowingModeLocked(displayInfo.name, displayInfo.uniqueId,
+ dc.getDisplayId()));
+
+ final Rect rect = new Rect();
+ getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
+ displayInfo.overscanLeft = rect.left;
+ displayInfo.overscanTop = rect.top;
+ displayInfo.overscanRight = rect.right;
+ displayInfo.overscanBottom = rect.bottom;
+ }
+
+ void readSettingsLocked() {
FileInputStream stream;
try {
stream = mFile.openRead();
@@ -169,11 +227,15 @@ public class DisplaySettings {
}
private int getIntAttribute(XmlPullParser parser, String name) {
+ return getIntAttribute(parser, name, 0 /* defaultValue */);
+ }
+
+ private int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
try {
String str = parser.getAttributeValue(null, name);
- return str != null ? Integer.parseInt(str) : 0;
+ return str != null ? Integer.parseInt(str) : defaultValue;
} catch (NumberFormatException e) {
- return 0;
+ return defaultValue;
}
}
@@ -186,12 +248,14 @@ public class DisplaySettings {
entry.overscanTop = getIntAttribute(parser, "overscanTop");
entry.overscanRight = getIntAttribute(parser, "overscanRight");
entry.overscanBottom = getIntAttribute(parser, "overscanBottom");
+ entry.windowingMode = getIntAttribute(parser, "windowingMode",
+ WindowConfiguration.WINDOWING_MODE_UNDEFINED);
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
}
- public void writeSettingsLocked() {
+ void writeSettingsLocked() {
FileOutputStream stream;
try {
stream = mFile.startWrite();
@@ -221,6 +285,9 @@ public class DisplaySettings {
if (entry.overscanBottom != 0) {
out.attribute(null, "overscanBottom", Integer.toString(entry.overscanBottom));
}
+ if (entry.windowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+ out.attribute(null, "windowingMode", Integer.toString(entry.windowingMode));
+ }
out.endTag(null, "display");
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index ca4fa648e543..a6bda37d6e3d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -224,16 +224,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
- final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Rect rect = new Rect();
- mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
- displayInfo.overscanLeft = rect.left;
- displayInfo.overscanTop = rect.top;
- displayInfo.overscanRight = rect.right;
- displayInfo.overscanBottom = rect.bottom;
+ mService.mDisplaySettings.applySettingsToDisplayLocked(dc);
+
if (mService.mDisplayManagerInternal != null) {
mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
- displayId, displayInfo);
+ displayId, dc.getDisplayInfo());
dc.configureDisplayPolicy();
// Tap Listeners are supported for:
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ea68e17732af..ab735af9a075 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -565,6 +565,8 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mForceResizableTasks = false;
boolean mSupportsPictureInPicture = false;
+ boolean mSupportsFreeformWindowManagement = false;
+ boolean mIsPc = false;
boolean mDisableTransitionAnimation = false;
@@ -953,7 +955,7 @@ public class WindowManagerService extends IWindowManager.Stub
com.android.internal.R.bool.config_disableTransitionAnimation);
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
- mDisplaySettings = new DisplaySettings();
+ mDisplaySettings = new DisplaySettings(this);
mDisplaySettings.readSettingsLocked();
mPolicy = policy;
@@ -6910,6 +6912,18 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ public void setSupportsFreeformWindowManagement(boolean supportsFreeformWindowManagement) {
+ synchronized (mWindowMap) {
+ mSupportsFreeformWindowManagement = supportsFreeformWindowManagement;
+ }
+ }
+
+ public void setIsPc(boolean isPc) {
+ synchronized (mWindowMap) {
+ mIsPc = isPc;
+ }
+ }
+
static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
new file mode 100644
index 000000000000..0ea56ed146fc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2018 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 com.android.server.wm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.app.WindowConfiguration;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class DisplaySettingsTests extends WindowTestsBase {
+
+ private File mTestFolder;
+ private DisplaySettings mTarget;
+
+ private DisplayContent mPrimaryDisplay;
+ private DisplayContent mSecondaryDisplay;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mTestFolder = InstrumentationRegistry.getContext().getCacheDir();
+ deleteRecursively(mTestFolder);
+
+ sWm.setSupportsFreeformWindowManagement(false);
+ sWm.setIsPc(false);
+
+ mTarget = new DisplaySettings(sWm, mTestFolder);
+ mTarget.readSettingsLocked();
+
+ mPrimaryDisplay = sWm.getDefaultDisplayContentLocked();
+ mSecondaryDisplay = createNewDisplay();
+ assertNotEquals(Display.DEFAULT_DISPLAY, mSecondaryDisplay.getDisplayId());
+ }
+
+ @Test
+ public void testPrimaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+ mPrimaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testPrimaryDisplayDefaultToFullscreenWithFreeformSupportNonPc() {
+ sWm.setSupportsFreeformWindowManagement(true);
+
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+ mPrimaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testPrimaryDisplayDefaultToFreeformWithFreeformIsPc() {
+ sWm.setSupportsFreeformWindowManagement(true);
+ sWm.setIsPc(true);
+
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+ mPrimaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testSecondaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+ mSecondaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportNonPc() {
+ sWm.setSupportsFreeformWindowManagement(true);
+
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+ mSecondaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportIsPc() {
+ sWm.setSupportsFreeformWindowManagement(true);
+ sWm.setIsPc(true);
+
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+ mSecondaryDisplay.getWindowingMode());
+ }
+
+ @Test
+ public void testDefaultToZeroOverscan() {
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ assertOverscan(mPrimaryDisplay, 0 /* left */, 0 /* top */, 0 /* right */, 0 /* bottom */);
+ }
+
+ @Test
+ public void testPersistOverscanInSameInstance() {
+ final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
+ mTarget.setOverscanLocked(info.uniqueId, info.name, 1 /* left */, 2 /* top */,
+ 3 /* right */, 4 /* bottom */);
+
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+ }
+
+ @Test
+ public void testPersistOverscanAcrossInstances() {
+ final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
+ mTarget.setOverscanLocked(info.uniqueId, info.name, 1 /* left */, 2 /* top */,
+ 3 /* right */, 4 /* bottom */);
+ mTarget.writeSettingsLocked();
+
+ DisplaySettings target = new DisplaySettings(sWm, mTestFolder);
+ target.readSettingsLocked();
+
+ target.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+ }
+
+ private static void assertOverscan(DisplayContent display, int left, int top, int right,
+ int bottom) {
+ final DisplayInfo info = display.getDisplayInfo();
+
+ assertEquals(left, info.overscanLeft);
+ assertEquals(top, info.overscanTop);
+ assertEquals(right, info.overscanRight);
+ assertEquals(bottom, info.overscanBottom);
+ }
+
+ private static boolean deleteRecursively(File file) {
+ if (file.isFile()) {
+ return file.delete();
+ }
+
+ boolean fullyDeleted = true;
+ final File[] files = file.listFiles();
+ for (File child : files) {
+ fullyDeleted &= deleteRecursively(child);
+ }
+ fullyDeleted &= file.delete();
+ return fullyDeleted;
+ }
+}