diff options
3 files changed, 54 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d9f36bd84899..b28297ed4af8 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -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; @@ -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; @@ -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; } /** @@ -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; @@ -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), diff --git a/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java index a2f37a56598d..6d8e07a919cc 100644 --- a/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java +++ b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java @@ -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); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 178fabcc6a47..92b670ed9699 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -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; @@ -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( |