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
This commit is contained in:
Riddle Hsu
2022-07-08 23:52:54 +08:00
parent 188a4273d2
commit 6565924b5e
2 changed files with 18 additions and 10 deletions

View File

@@ -5485,17 +5485,19 @@ class WindowState extends WindowContainer<WindowState> 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;

View File

@@ -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})