OSDN Git Service

Update display contents when metrics change
authorAndrii Kulian <akulian@google.com>
Tue, 21 Mar 2017 17:17:03 +0000 (10:17 -0700)
committerAndrii Kulian <akulian@google.com>
Tue, 21 Mar 2017 22:23:47 +0000 (15:23 -0700)
There are two separate overrides for display metrics in DisplayManager
and WindowManager:
- In DM - LogicalDisplay#mOverrideDisplayInfo, in most cases not null.
- In WM - DisplayContent#mBaseDisplayWidth/Height/Density, different
from #mInitialDisplayWidth/Height/Density values when some metrics are
forced.

When display was resized its windows weren't updated because of
two problems: old LogicaDisplay#mOverrideDisplayInfo was preventing
WM from detecting the change and override (base) display metrics were
never updated by resize.

When display size changes:
- Before this CL:
DM receives DISPLAY_CHANGED event, it updates internal values.
In most cases there is an override obtained from WM and WM doesn't
get new values from LogicalDisplay#getDisplayInfoLocked().

- With this CL:
DM receives DISPLAY_CHANGED event, it updates internal values and
resets the override received from WM. WM will receive updated values
and will decide whether to apply them or not: if there is no override
in WM - it will apply values from WM, otherwise it will keep the
override. In both cases WM will eventually update its own override
and will update the override in DM.

Bug: 35258051
Bug: 34164473
Test: android.server.cts.ActivityManagerDisplayTests
Test: #testDisplayResize
Test: #testForceDisplayMetrics
Change-Id: I80795434a6a35adb0577fbce334d76fabd2fa03d

core/java/android/view/Display.java
services/core/java/com/android/server/display/LogicalDisplay.java
services/core/java/com/android/server/wm/DisplayContent.java
services/core/java/com/android/server/wm/WindowManagerService.java

index 5494377..6dedbde 100644 (file)
@@ -50,7 +50,7 @@ import java.util.Arrays;
  * <li>The real display area specifies the part of the display that contains content
  * including the system decorations.  Even so, the real display area may be smaller than the
  * physical size of the display if the window manager is emulating a smaller display
- * using (adb shell am display-size).  Use the following methods to query the
+ * using (adb shell wm size).  Use the following methods to query the
  * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
  * </ul>
  * </p><p>
@@ -947,7 +947,7 @@ public final class Display {
      * The size is adjusted based on the current rotation of the display.
      * </p><p>
      * The real size may be smaller than the physical size of the screen when the
-     * window manager is emulating a smaller display (using adb shell am display-size).
+     * window manager is emulating a smaller display (using adb shell wm size).
      * </p>
      *
      * @param outSize Set to the real size of the display.
index a947b41..f9bc12b 100644 (file)
@@ -62,7 +62,18 @@ final class LogicalDisplay {
 
     private final int mDisplayId;
     private final int mLayerStack;
-    private DisplayInfo mOverrideDisplayInfo; // set by the window manager
+    /**
+     * Override information set by the window manager. Will be reported instead of {@link #mInfo}
+     * if not null.
+     * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
+     * @see #getDisplayInfoLocked()
+     */
+    private DisplayInfo mOverrideDisplayInfo;
+    /**
+     * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
+     * needs to be updated.
+     * @see #getDisplayInfoLocked()
+     */
     private DisplayInfo mInfo;
 
     // The display device that this logical display is based on and which
@@ -261,6 +272,9 @@ final class LogicalDisplay {
 
             mPrimaryDisplayDeviceInfo = deviceInfo;
             mInfo = null;
+            // Make sure that WM will be notified of new changes. It will then decide whether to
+            // apply them or not and will set the value again.
+            mOverrideDisplayInfo = null;
         }
     }
 
index e5b00f3..01a992f 100644 (file)
@@ -179,11 +179,23 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     // Mapping from a token IBinder to a WindowToken object on this display.
     private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
 
+    // Initial display metrics.
     int mInitialDisplayWidth = 0;
     int mInitialDisplayHeight = 0;
     int mInitialDisplayDensity = 0;
+
+    /**
+     * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
+     * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
+     * @see WindowManagerService#setForcedDisplaySize(int, int, int)
+     */
     int mBaseDisplayWidth = 0;
     int mBaseDisplayHeight = 0;
+    /**
+     * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
+     * but can be set from Settings or via shell command "adb shell wm density".
+     * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
+     */
     int mBaseDisplayDensity = 0;
     boolean mDisplayScalingDisabled;
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -1511,6 +1523,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     void updateDisplayInfo() {
         mDisplay.getDisplayInfo(mDisplayInfo);
         mDisplay.getMetrics(mDisplayMetrics);
+
+        // Check if display metrics changed and update base values if needed.
+        updateBaseDisplayMetricsIfNeeded();
+
         for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
             mTaskStackContainers.get(i).updateDisplayInfo(null);
         }
@@ -1526,10 +1542,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
             }
         }
 
-        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
-        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
-        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
-        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+        updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
+                mDisplayInfo.logicalDensityDpi);
+        mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+        mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+        mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
     }
 
     void getLogicalDisplayRect(Rect out) {
@@ -1559,6 +1576,50 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         }
     }
 
+    /**
+     * If display metrics changed, overrides are not set and it's not just a rotation - update base
+     * values.
+     */
+    private void updateBaseDisplayMetricsIfNeeded() {
+        final int orientation = mDisplayInfo.rotation;
+        final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+        final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
+        final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
+        int density = mDisplayInfo.logicalDensityDpi;
+
+        boolean displayMetricsChanged = false;
+
+        // Check if display size is not forced and changed in new display info.
+        boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
+                || mBaseDisplayHeight != mInitialDisplayHeight;
+        if (!isDisplaySizeForced) {
+            displayMetricsChanged = mBaseDisplayWidth != newWidth
+                    || mBaseDisplayHeight != newHeight;
+        }
+
+        // Check if display density is not forced and changed in new display info.
+        final int forcedDensity = mBaseDisplayDensity != mInitialDisplayDensity
+                ? mBaseDisplayDensity : 0;
+        if (forcedDensity != 0) {
+            density = forcedDensity;
+        } else {
+            displayMetricsChanged |= mBaseDisplayDensity != mDisplayInfo.logicalDensityDpi;
+        }
+
+        if (displayMetricsChanged) {
+            updateBaseDisplayMetrics(newWidth, newHeight, density);
+            mService.reconfigureDisplayLocked(this);
+        }
+    }
+
+    /** Update base (override) display metrics. */
+    void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
+        mBaseDisplayWidth = baseWidth;
+        mBaseDisplayHeight = baseHeight;
+        mBaseDisplayDensity = baseDensity;
+        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+    }
+
     void getContentRect(Rect out) {
         out.set(mContentRect);
     }
index 7539cd4..082491d 100644 (file)
@@ -5324,8 +5324,8 @@ public class WindowManagerService extends IWindowManager.Stub
                     if (displayContent.mBaseDisplayWidth != width
                             || displayContent.mBaseDisplayHeight != height) {
                         Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
-                        displayContent.mBaseDisplayWidth = width;
-                        displayContent.mBaseDisplayHeight = height;
+                        displayContent.updateBaseDisplayMetrics(width, height,
+                                displayContent.mBaseDisplayDensity);
                     }
                 } catch (NumberFormatException ex) {
                 }
@@ -5350,8 +5350,7 @@ public class WindowManagerService extends IWindowManager.Stub
     // displayContent must not be null
     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
-        displayContent.mBaseDisplayWidth = width;
-        displayContent.mBaseDisplayHeight = height;
+        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
         reconfigureDisplayLocked(displayContent);
     }