diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index af8c4c8e93701..1ba036e646950 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5485,17 +5485,19 @@ class WindowState extends WindowContainer implements WindowManagerP } private void updateScaleIfNeeded() { - if (mIsChildWindow) { - // Child window follows parent's scale. - return; - } if (!isVisibleRequested() && !(mIsWallpaper && mToken.isVisible())) { // Skip if it is requested to be invisible, but if it is wallpaper, it may be in // transition that still needs to update the scale for zoom effect. return; } - float newHScale = mHScale * mGlobalScale * mWallpaperScale; - float newVScale = mVScale * mGlobalScale * mWallpaperScale; + float globalScale = mGlobalScale; + final WindowState parent = getParentWindow(); + if (parent != null) { + // Undo parent's scale because the child surface has inherited scale from parent. + globalScale *= parent.mInvGlobalScale; + } + final float newHScale = mHScale * globalScale * mWallpaperScale; + final float newVScale = mVScale * globalScale * mWallpaperScale; if (mLastHScale != newHScale || mLastVScale != newVScale) { getSyncTransaction().setMatrix(mSurfaceControl, newHScale, 0, 0, newVScale); mLastHScale = newHScale; 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 446ec8b2680bc..334cfd5fbb8fd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -664,12 +664,11 @@ public class WindowStateTests extends WindowTestsBase { assertEquals(expectedChildPos, childPos); // Surface should apply the scale. + final SurfaceControl.Transaction t = w.getPendingTransaction(); w.prepareSurfaces(); - verify(w.getPendingTransaction()).setMatrix(w.getSurfaceControl(), - overrideScale, 0, 0, overrideScale); + verify(t).setMatrix(w.mSurfaceControl, 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()); + verify(t, 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( @@ -686,6 +685,13 @@ public class WindowStateTests extends WindowTestsBase { final Rect unscaledClientBounds = new Rect(clientConfig.windowConfiguration.getBounds()); unscaledClientBounds.scale(overrideScale); assertEquals(w.getWindowConfiguration().getBounds(), unscaledClientBounds); + + // Child window without scale (e.g. different app) should apply inverse scale of parent. + doReturn(1f).when(cmp).getCompatScale(anyString(), anyInt()); + final WindowState child2 = createWindow(w, TYPE_APPLICATION_SUB_PANEL, "child2"); + clearInvocations(t); + child2.prepareSurfaces(); + verify(t).setMatrix(child2.mSurfaceControl, w.mInvGlobalScale, 0, 0, w.mInvGlobalScale); } @UseTestDisplay(addWindows = {W_ABOVE_ACTIVITY, W_NOTIFICATION_SHADE})