From 6565924b5e484acf9aae0814e20f4284896979ba Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 8 Jul 2022 23:52:54 +0800 Subject: [PATCH] Undo parent's scale for child window with different override scale An app of a different package can add a child window to another app's window. If the app of parent window has override scale, it will draw its content in a scaled environment. But if the child doesn't have override scale, it still draw in with natural size of the device. Then the child surface should still show without scale, so the scale from parent surface should be reversed. Bug: 182362657 Test: atest WindowStateTests#testCompatOverrideScale Change-Id: I83b32090ceb2e92d644e83b9b14ea68ef2ca96f2 --- .../java/com/android/server/wm/WindowState.java | 14 ++++++++------ .../com/android/server/wm/WindowStateTests.java | 14 ++++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 30d18ab043697..ee6aa7e0cbfd8 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})