Loading services/core/java/com/android/server/wm/WindowState.java +23 −3 Original line number Diff line number Diff line Loading @@ -258,6 +258,7 @@ import com.android.internal.util.ToBooleanFunction; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.LocalAnimationAdapter.AnimationSpec; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.utils.CoordinateTransforms; import java.io.PrintWriter; import java.lang.ref.WeakReference; Loading Loading @@ -638,6 +639,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private PowerManager.WakeLock mDrawLock; private final Rect mTmpRect = new Rect(); private final Rect mTmpRect2 = new Rect(); private final Point mTmpPoint = new Point(); private final Transaction mTmpTransaction; Loading Loading @@ -1160,13 +1162,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** * @return {@code true} if the application runs in size compatibility mode or has an app level * scaling override set. * scaling override set. This method always returns {@code false} on child window because it * should follow parent's scale. * @see CompatModePackages#getCompatScale * @see android.content.res.CompatibilityInfo#supportsScreen * @see ActivityRecord#hasSizeCompatBounds() */ boolean hasCompatScale() { return mOverrideScale != 1f || hasCompatScale(mAttrs, mActivityRecord); return (mOverrideScale != 1f || hasCompatScale(mAttrs, mActivityRecord)) && !mIsChildWindow; } /** Loading Loading @@ -1338,7 +1341,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } layoutDisplayFrame = new Rect(windowFrames.mDisplayFrame); layoutDisplayFrame = mTmpRect2; layoutDisplayFrame.set(windowFrames.mDisplayFrame); windowFrames.mDisplayFrame.set(windowFrames.mContainingFrame); layoutXDiff = mInsetFrame.left - windowFrames.mContainingFrame.left; layoutYDiff = mInsetFrame.top - windowFrames.mContainingFrame.top; Loading Loading @@ -4442,6 +4446,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP h = Math.min(h, ph); } if (mIsChildWindow) { final WindowState parent = getTopParentWindow(); if (parent.hasCompatScale()) { // Scale the containing and display frames because they are in screen coordinates. // The position of frames are already relative to parent so only size is scaled. mTmpRect.set(containingFrame); containingFrame = mTmpRect; CoordinateTransforms.scaleRectSize(containingFrame, parent.mInvGlobalScale); if (fitToDisplay) { mTmpRect2.set(displayFrame); displayFrame = mTmpRect2; CoordinateTransforms.scaleRectSize(displayFrame, parent.mInvGlobalScale); } } } // Set mFrame Gravity.apply(mAttrs.gravity, w, h, containingFrame, (int) (x + mAttrs.horizontalMargin * pw), Loading services/core/java/com/android/server/wm/utils/CoordinateTransforms.java +6 −0 Original line number Diff line number Diff line Loading @@ -152,4 +152,10 @@ public class CoordinateTransforms { transform.mapRect(tmp); inOutRect.set((int) tmp.left, (int) tmp.top, (int) tmp.right, (int) tmp.bottom); } /** Scales the rect without changing its position. */ public static void scaleRectSize(Rect inOutRect, float scale) { inOutRect.right = inOutRect.left + (int) (inOutRect.width() * scale + .5f); inOutRect.bottom = inOutRect.top + (int) (inOutRect.height() * scale + .5f); } } services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +25 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; Loading Loading @@ -577,21 +578,43 @@ public class WindowStateTests extends WindowTestsBase { spyOn(cmp); doReturn(overrideScale).when(cmp).getCompatScale(anyString(), anyInt()); final WindowState w = createWindow(null, TYPE_APPLICATION_OVERLAY, "win"); makeWindowVisible(w); final WindowState child = createWindow(w, TYPE_APPLICATION_PANEL, "child"); assertTrue(w.hasCompatScale()); assertFalse(child.hasCompatScale()); makeWindowVisible(w, child); w.setRequestedSize(100, 200); child.setRequestedSize(50, 100); child.mAttrs.width = child.mAttrs.height = 0; w.mAttrs.x = w.mAttrs.y = 100; w.mAttrs.width = w.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT; w.mAttrs.gravity = Gravity.TOP | Gravity.LEFT; child.mAttrs.gravity = Gravity.CENTER; DisplayContentTests.performLayout(mDisplayContent); // Frame on screen = 100x200. Compat frame on client = 50x100. // Frame on screen = 200x400 (200, 200 - 400, 600). Compat frame on client = 100x200. final Rect unscaledCompatFrame = new Rect(w.getWindowFrames().mCompatFrame); unscaledCompatFrame.scale(overrideScale); final Rect parentFrame = w.getFrame(); assertEquals(w.getWindowFrames().mFrame, unscaledCompatFrame); final Rect childFrame = child.getFrame(); assertEquals(childFrame, child.getWindowFrames().mCompatFrame); // Child frame = 50x100 (225, 250 - 275, 350) according to Gravity.CENTER. final int childX = parentFrame.left + child.mRequestedWidth / 2; final int childY = parentFrame.top + child.mRequestedHeight / 2; final Rect expectedChildFrame = new Rect(childX, childY, childX + child.mRequestedWidth, childY + child.mRequestedHeight); assertEquals(expectedChildFrame, childFrame); // Surface should apply the scale. w.prepareSurfaces(); verify(w.getPendingTransaction()).setMatrix(w.getSurfaceControl(), overrideScale, 0, 0, overrideScale); // Child surface inherits parent's scale, so it doesn't need to scale. verify(child.getPendingTransaction(), never()).setMatrix(any(), anyInt(), anyInt(), anyInt(), anyInt()); // According to "dp * density / 160 = px", density is scaled and the size in dp is the same. final CompatibilityInfo compatInfo = cmp.compatibilityInfoForPackageLocked( Loading Loading
services/core/java/com/android/server/wm/WindowState.java +23 −3 Original line number Diff line number Diff line Loading @@ -258,6 +258,7 @@ import com.android.internal.util.ToBooleanFunction; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.LocalAnimationAdapter.AnimationSpec; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.utils.CoordinateTransforms; import java.io.PrintWriter; import java.lang.ref.WeakReference; Loading Loading @@ -638,6 +639,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private PowerManager.WakeLock mDrawLock; private final Rect mTmpRect = new Rect(); private final Rect mTmpRect2 = new Rect(); private final Point mTmpPoint = new Point(); private final Transaction mTmpTransaction; Loading Loading @@ -1160,13 +1162,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** * @return {@code true} if the application runs in size compatibility mode or has an app level * scaling override set. * scaling override set. This method always returns {@code false} on child window because it * should follow parent's scale. * @see CompatModePackages#getCompatScale * @see android.content.res.CompatibilityInfo#supportsScreen * @see ActivityRecord#hasSizeCompatBounds() */ boolean hasCompatScale() { return mOverrideScale != 1f || hasCompatScale(mAttrs, mActivityRecord); return (mOverrideScale != 1f || hasCompatScale(mAttrs, mActivityRecord)) && !mIsChildWindow; } /** Loading Loading @@ -1338,7 +1341,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } layoutDisplayFrame = new Rect(windowFrames.mDisplayFrame); layoutDisplayFrame = mTmpRect2; layoutDisplayFrame.set(windowFrames.mDisplayFrame); windowFrames.mDisplayFrame.set(windowFrames.mContainingFrame); layoutXDiff = mInsetFrame.left - windowFrames.mContainingFrame.left; layoutYDiff = mInsetFrame.top - windowFrames.mContainingFrame.top; Loading Loading @@ -4442,6 +4446,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP h = Math.min(h, ph); } if (mIsChildWindow) { final WindowState parent = getTopParentWindow(); if (parent.hasCompatScale()) { // Scale the containing and display frames because they are in screen coordinates. // The position of frames are already relative to parent so only size is scaled. mTmpRect.set(containingFrame); containingFrame = mTmpRect; CoordinateTransforms.scaleRectSize(containingFrame, parent.mInvGlobalScale); if (fitToDisplay) { mTmpRect2.set(displayFrame); displayFrame = mTmpRect2; CoordinateTransforms.scaleRectSize(displayFrame, parent.mInvGlobalScale); } } } // Set mFrame Gravity.apply(mAttrs.gravity, w, h, containingFrame, (int) (x + mAttrs.horizontalMargin * pw), Loading
services/core/java/com/android/server/wm/utils/CoordinateTransforms.java +6 −0 Original line number Diff line number Diff line Loading @@ -152,4 +152,10 @@ public class CoordinateTransforms { transform.mapRect(tmp); inOutRect.set((int) tmp.left, (int) tmp.top, (int) tmp.right, (int) tmp.bottom); } /** Scales the rect without changing its position. */ public static void scaleRectSize(Rect inOutRect, float scale) { inOutRect.right = inOutRect.left + (int) (inOutRect.width() * scale + .5f); inOutRect.bottom = inOutRect.top + (int) (inOutRect.height() * scale + .5f); } }
services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +25 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; Loading Loading @@ -577,21 +578,43 @@ public class WindowStateTests extends WindowTestsBase { spyOn(cmp); doReturn(overrideScale).when(cmp).getCompatScale(anyString(), anyInt()); final WindowState w = createWindow(null, TYPE_APPLICATION_OVERLAY, "win"); makeWindowVisible(w); final WindowState child = createWindow(w, TYPE_APPLICATION_PANEL, "child"); assertTrue(w.hasCompatScale()); assertFalse(child.hasCompatScale()); makeWindowVisible(w, child); w.setRequestedSize(100, 200); child.setRequestedSize(50, 100); child.mAttrs.width = child.mAttrs.height = 0; w.mAttrs.x = w.mAttrs.y = 100; w.mAttrs.width = w.mAttrs.height = WindowManager.LayoutParams.WRAP_CONTENT; w.mAttrs.gravity = Gravity.TOP | Gravity.LEFT; child.mAttrs.gravity = Gravity.CENTER; DisplayContentTests.performLayout(mDisplayContent); // Frame on screen = 100x200. Compat frame on client = 50x100. // Frame on screen = 200x400 (200, 200 - 400, 600). Compat frame on client = 100x200. final Rect unscaledCompatFrame = new Rect(w.getWindowFrames().mCompatFrame); unscaledCompatFrame.scale(overrideScale); final Rect parentFrame = w.getFrame(); assertEquals(w.getWindowFrames().mFrame, unscaledCompatFrame); final Rect childFrame = child.getFrame(); assertEquals(childFrame, child.getWindowFrames().mCompatFrame); // Child frame = 50x100 (225, 250 - 275, 350) according to Gravity.CENTER. final int childX = parentFrame.left + child.mRequestedWidth / 2; final int childY = parentFrame.top + child.mRequestedHeight / 2; final Rect expectedChildFrame = new Rect(childX, childY, childX + child.mRequestedWidth, childY + child.mRequestedHeight); assertEquals(expectedChildFrame, childFrame); // Surface should apply the scale. w.prepareSurfaces(); verify(w.getPendingTransaction()).setMatrix(w.getSurfaceControl(), overrideScale, 0, 0, overrideScale); // Child surface inherits parent's scale, so it doesn't need to scale. verify(child.getPendingTransaction(), never()).setMatrix(any(), anyInt(), anyInt(), anyInt(), anyInt()); // According to "dp * density / 160 = px", density is scaled and the size in dp is the same. final CompatibilityInfo compatInfo = cmp.compatibilityInfoForPackageLocked( Loading