Add new system API for stable display size
Fixes: 34388294
Test: manual
Change-Id: Ie380230bbd82370f507161b4cdb6f0d100b09f11
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 8269042..d0a1d9e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -31,6 +31,8 @@
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Point;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
@@ -211,6 +213,12 @@
// The virtual display adapter, or null if not registered.
private VirtualDisplayAdapter mVirtualDisplayAdapter;
+ // The stable device screen height and width. These are not tied to a specific display, even
+ // the default display, because they need to be stable over the course of the device's entire
+ // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like
+ // device).
+ private Point mStableDisplaySize = new Point();
+
// Viewports of the default display and the display that should receive touch
// input from an external source. Used by the input system.
private final DisplayViewport mDefaultViewport = new DisplayViewport();
@@ -284,7 +292,10 @@
// adapter is up so that we have it's configuration. We could load it lazily, but since
// we're going to have to read it in eventually we may as well do it here rather than after
// we've waited for the display to register itself with us.
- mPersistentDataStore.loadIfNeeded();
+ synchronized(mSyncRoot) {
+ mPersistentDataStore.loadIfNeeded();
+ loadStableDisplayValuesLocked();
+ }
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
@@ -346,6 +357,34 @@
return mHandler;
}
+ private void loadStableDisplayValuesLocked() {
+ final Point size = mPersistentDataStore.getStableDisplaySize();
+ if (size.x > 0 && size.y > 0) {
+ // Just set these values directly so we don't write the display persistent data again
+ // unnecessarily
+ mStableDisplaySize.set(size.x, size.y);
+ } else {
+ final Resources res = mContext.getResources();
+ final int width = res.getInteger(
+ com.android.internal.R.integer.config_stableDeviceDisplayWidth);
+ final int height = res.getInteger(
+ com.android.internal.R.integer.config_stableDeviceDisplayHeight);
+ if (width > 0 && height > 0) {
+ setStableDisplaySizeLocked(width, height);
+ }
+ }
+ }
+
+ private Point getStableDisplaySizeInternal() {
+ Point r = new Point();
+ synchronized (mSyncRoot) {
+ if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) {
+ r.set(mStableDisplaySize.x, mStableDisplaySize.y);
+ }
+ }
+ return r;
+ }
+
private void registerDisplayTransactionListenerInternal(
DisplayTransactionListener listener) {
// List is self-synchronized copy-on-write.
@@ -770,18 +809,6 @@
if (work != null) {
work.run();
}
- if (display != null && display.getPrimaryDisplayDeviceLocked() == device) {
- int colorMode = mPersistentDataStore.getColorMode(device);
- if (colorMode == Display.COLOR_MODE_INVALID) {
- if ((device.getDisplayDeviceInfoLocked().flags
- & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
- colorMode = mDefaultDisplayDefaultColorMode;
- } else {
- colorMode = Display.COLOR_MODE_DEFAULT;
- }
- }
- display.setRequestedColorModeLocked(colorMode);
- }
scheduleTraversalLocked(false);
}
@@ -886,6 +913,11 @@
return null;
}
+ configureColorModeLocked(display, device);
+ if (isDefault) {
+ recordStableDisplayStatsIfNeededLocked(display);
+ }
+
mLogicalDisplays.put(displayId, display);
// Wake up waitForDefaultDisplay.
@@ -907,6 +939,40 @@
return displayId;
}
+ private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) {
+ if (display.getPrimaryDisplayDeviceLocked() == device) {
+ int colorMode = mPersistentDataStore.getColorMode(device);
+ if (colorMode == Display.COLOR_MODE_INVALID) {
+ if ((device.getDisplayDeviceInfoLocked().flags
+ & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
+ colorMode = mDefaultDisplayDefaultColorMode;
+ } else {
+ colorMode = Display.COLOR_MODE_DEFAULT;
+ }
+ }
+ display.setRequestedColorModeLocked(colorMode);
+ }
+ }
+
+ // If we've never recorded stable device stats for this device before and they aren't
+ // explicitly configured, go ahead and record the stable device stats now based on the status
+ // of the default display at first boot.
+ private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) {
+ if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) {
+ DisplayInfo info = d.getDisplayInfoLocked();
+ setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight());
+ }
+ }
+
+ private void setStableDisplaySizeLocked(int width, int height) {
+ mStableDisplaySize = new Point(width, height);
+ try {
+ mPersistentDataStore.setStableDisplaySize(mStableDisplaySize);
+ } finally {
+ mPersistentDataStore.saveIfNeeded();
+ }
+ }
+
// Updates all existing logical displays given the current set of display devices.
// Removes invalid logical displays.
// Sends notifications if needed.
@@ -1166,6 +1232,8 @@
pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
+ pw.println(" mStableDisplaySize=" + mStableDisplaySize);
+
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.increaseIndent();
@@ -1378,6 +1446,19 @@
}
}
+ /**
+ * Returns the stable device display size, in pixels.
+ */
+ @Override // Binder call
+ public Point getStableDisplaySize() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getStableDisplaySizeInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override // Binder call
public void registerCallback(IDisplayManagerCallback callback) {
if (callback == null) {
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 47701b9..34c8e22 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -23,6 +23,7 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.graphics.Point;
import android.hardware.display.WifiDisplay;
import android.util.AtomicFile;
import android.util.Slog;
@@ -60,6 +61,10 @@
* <color-mode>0</color-mode>
* </display>
* </display-states>
+ * <stable-device-values>
+ * <stable-display-height>1920<stable-display-height>
+ * <stable-display-width>1080<stable-display-width>
+ * </stable-device-values>
* </display-manager-state>
* </code>
*
@@ -75,6 +80,9 @@
private final HashMap<String, DisplayState> mDisplayStates =
new HashMap<String, DisplayState>();
+ // Display values which should be stable across the device's lifetime.
+ private final StableDeviceValues mStableDeviceValues = new StableDeviceValues();
+
// The atomic file used to safely read or write the file.
private final AtomicFile mAtomicFile;
@@ -162,6 +170,7 @@
}
public boolean forgetWifiDisplay(String deviceAddress) {
+ loadIfNeeded();
int index = findRememberedWifiDisplay(deviceAddress);
if (index >= 0) {
mRememberedWifiDisplays.remove(index);
@@ -204,6 +213,18 @@
return false;
}
+ public Point getStableDisplaySize() {
+ loadIfNeeded();
+ return mStableDeviceValues.getDisplaySize();
+ }
+
+ public void setStableDisplaySize(Point size) {
+ loadIfNeeded();
+ if (mStableDeviceValues.setDisplaySize(size)) {
+ setDirty();
+ }
+ }
+
private DisplayState getDisplayState(String uniqueId, boolean createIfAbsent) {
loadIfNeeded();
DisplayState state = mDisplayStates.get(uniqueId);
@@ -290,6 +311,9 @@
if (parser.getName().equals("display-states")) {
loadDisplaysFromXml(parser);
}
+ if (parser.getName().equals("stable-device-values")) {
+ mStableDeviceValues.loadFromXml(parser);
+ }
}
}
@@ -363,6 +387,9 @@
serializer.endTag(null, "display");
}
serializer.endTag(null, "display-states");
+ serializer.startTag(null, "stable-device-values");
+ mStableDeviceValues.saveToXml(serializer);
+ serializer.endTag(null, "stable-device-values");
serializer.endTag(null, "display-manager-state");
serializer.endDocument();
}
@@ -382,6 +409,8 @@
pw.println(" " + i++ + ": " + entry.getKey());
entry.getValue().dump(pw, " ");
}
+ pw.println(" StableDeviceValues:");
+ mStableDeviceValues.dump(pw, " ");
}
private static final class DisplayState {
@@ -417,8 +446,66 @@
serializer.endTag(null, "color-mode");
}
- private void dump(final PrintWriter pw, final String prefix) {
+ public void dump(final PrintWriter pw, final String prefix) {
pw.println(prefix + "ColorMode=" + mColorMode);
}
}
+
+ private static final class StableDeviceValues {
+ private int mWidth;
+ private int mHeight;
+
+ private Point getDisplaySize() {
+ return new Point(mWidth, mHeight);
+ }
+
+ public boolean setDisplaySize(Point r) {
+ if (mWidth != r.x || mHeight != r.y) {
+ mWidth = r.x;
+ mHeight = r.y;
+ return true;
+ }
+ return false;
+ }
+
+ public void loadFromXml(XmlPullParser parser) throws IOException, XmlPullParserException {
+ final int outerDepth = parser.getDepth();
+ while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+ switch (parser.getName()) {
+ case "stable-display-width":
+ mWidth = loadIntValue(parser);
+ break;
+ case "stable-display-height":
+ mHeight = loadIntValue(parser);
+ break;
+ }
+ }
+ }
+
+ private static int loadIntValue(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ try {
+ String value = parser.nextText();
+ return Integer.parseInt(value);
+ } catch (NumberFormatException nfe) {
+ return 0;
+ }
+ }
+
+ public void saveToXml(XmlSerializer serializer) throws IOException {
+ if (mWidth > 0 && mHeight > 0) {
+ serializer.startTag(null, "stable-display-width");
+ serializer.text(Integer.toString(mWidth));
+ serializer.endTag(null, "stable-display-width");
+ serializer.startTag(null, "stable-display-height");
+ serializer.text(Integer.toString(mHeight));
+ serializer.endTag(null, "stable-display-height");
+ }
+ }
+
+ public void dump(final PrintWriter pw, final String prefix) {
+ pw.println(prefix + "StableDisplayWidth=" + mWidth);
+ pw.println(prefix + "StableDisplayHeight=" + mHeight);
+ }
+ }
}