Loading services/core/java/com/android/server/wm/Letterbox.java +42 −17 Original line number Diff line number Diff line Loading @@ -58,10 +58,12 @@ public class Letterbox { private final LetterboxSurface mLeft = new LetterboxSurface("left"); private final LetterboxSurface mBottom = new LetterboxSurface("bottom"); private final LetterboxSurface mRight = new LetterboxSurface("right"); // Prevents wallpaper from peeking through near rounded corners. It's not included in // mSurfaces array since it isn't needed in methods like notIntersectsOrFullyContains // or attachInput. private final LetterboxSurface mBehind = new LetterboxSurface("behind"); // One surface that fills the whole window is used over multiple surfaces to: // - Prevents wallpaper from peeking through near rounded corners. // - For "blurred wallpaper" background, to avoid having visible border between surfaces. // One surface approach isn't always preferred over multiple surfaces due to rendering cost // for overlaping an app window and letterbox surfaces. private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow"); private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom }; /** Loading Loading @@ -104,7 +106,7 @@ public class Letterbox { mLeft.layout(outer.left, outer.top, inner.left, outer.bottom, surfaceOrigin); mBottom.layout(outer.left, inner.bottom, outer.right, outer.bottom, surfaceOrigin); mRight.layout(inner.right, outer.top, outer.right, outer.bottom, surfaceOrigin); mBehind.layout(inner.left, inner.top, inner.right, inner.bottom, surfaceOrigin); mFullWindowSurface.layout(outer.left, outer.top, outer.right, outer.bottom, surfaceOrigin); } Loading Loading @@ -168,39 +170,48 @@ public class Letterbox { for (LetterboxSurface surface : mSurfaces) { surface.remove(); } mBehind.remove(); mFullWindowSurface.remove(); } /** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */ public boolean needsApplySurfaceChanges() { if (useFullWindowSurface()) { return mFullWindowSurface.needsApplySurfaceChanges(); } for (LetterboxSurface surface : mSurfaces) { if (surface.needsApplySurfaceChanges()) { return true; } } if (mAreCornersRounded.get() && mBehind.needsApplySurfaceChanges()) { return true; } return false; } public void applySurfaceChanges(SurfaceControl.Transaction t) { if (useFullWindowSurface()) { mFullWindowSurface.applySurfaceChanges(t); for (LetterboxSurface surface : mSurfaces) { surface.applySurfaceChanges(t); surface.remove(); } if (mAreCornersRounded.get()) { mBehind.applySurfaceChanges(t); } else { mBehind.remove(); for (LetterboxSurface surface : mSurfaces) { surface.applySurfaceChanges(t); } mFullWindowSurface.remove(); } } /** Enables touches to slide into other neighboring surfaces. */ void attachInput(WindowState win) { if (useFullWindowSurface()) { mFullWindowSurface.attachInput(win); } else { for (LetterboxSurface surface : mSurfaces) { surface.attachInput(win); } } } void onMovedToDisplay(int displayId) { for (LetterboxSurface surface : mSurfaces) { Loading @@ -208,6 +219,16 @@ public class Letterbox { surface.mInputInterceptor.mWindowHandle.displayId = displayId; } } if (mFullWindowSurface.mInputInterceptor != null) { mFullWindowSurface.mInputInterceptor.mWindowHandle.displayId = displayId; } } /** * Returns {@code true} when using {@link #mFullWindowSurface} instead of {@link mSurfaces}. */ private boolean useFullWindowSurface() { return mAreCornersRounded.get() || mHasWallpaperBackgroundSupplier.get(); } private static class InputInterceptor { Loading Loading @@ -308,6 +329,10 @@ public class Letterbox { mInputInterceptor = new InputInterceptor("Letterbox_" + mType + "_", win); } boolean isRemoved() { return mSurface != null || mInputInterceptor != null; } public void remove() { if (mSurface != null) { mTransactionFactory.get().remove(mSurface).apply(); Loading services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java +21 −12 Original line number Diff line number Diff line Loading @@ -200,28 +200,37 @@ public class LetterboxTest { assertTrue(mLetterbox.needsApplySurfaceChanges()); mLetterbox.applySurfaceChanges(mTransaction); verify(mTransaction).setAlpha(mSurfaces.top, mDarkScrimAlpha); verify(mTransaction).setAlpha(mSurfaces.fullWindowSurface, mDarkScrimAlpha); } @Test public void testApplySurfaceChanges_cornersNotRounded_surfaceBehindNotCreated() { public void testApplySurfaceChanges_cornersNotRounded_surfaceFullWindowSurfaceNotCreated() { mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); mLetterbox.applySurfaceChanges(mTransaction); assertNull(mSurfaces.behind); assertNull(mSurfaces.fullWindowSurface); } @Test public void testApplySurfaceChanges_cornersRounded_surfaceBehindCreated() { public void testApplySurfaceChanges_cornersRounded_surfaceFullWindowSurfaceCreated() { mAreCornersRounded = true; mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); mLetterbox.applySurfaceChanges(mTransaction); assertNotNull(mSurfaces.behind); assertNotNull(mSurfaces.fullWindowSurface); } @Test public void testNotIntersectsOrFullyContains_cornersRounded_doesNotCheckSurfaceBehind() { public void testApplySurfaceChanges_wallpaperBackground_surfaceFullWindowSurfaceCreated() { mHasWallpaperBackground = true; mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); mLetterbox.applySurfaceChanges(mTransaction); assertNotNull(mSurfaces.fullWindowSurface); } @Test public void testNotIntersectsOrFullyContains_cornersRounded() { mAreCornersRounded = true; mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(0, 0)); mLetterbox.applySurfaceChanges(mTransaction); Loading Loading @@ -249,8 +258,8 @@ public class LetterboxTest { public SurfaceControl right; private SurfaceControl.Builder mBottomBuilder; public SurfaceControl bottom; private SurfaceControl.Builder mBehindBuilder; public SurfaceControl behind; private SurfaceControl.Builder mFullWindowSurfaceBuilder; public SurfaceControl fullWindowSurface; @Override public SurfaceControl.Builder get() { Loading @@ -265,8 +274,8 @@ public class LetterboxTest { mRightBuilder = (SurfaceControl.Builder) i.getMock(); } else if (((String) i.getArgument(0)).contains("bottom")) { mBottomBuilder = (SurfaceControl.Builder) i.getMock(); } else if (((String) i.getArgument(0)).contains("behind")) { mBehindBuilder = (SurfaceControl.Builder) i.getMock(); } else if (((String) i.getArgument(0)).contains("fullWindow")) { mFullWindowSurfaceBuilder = (SurfaceControl.Builder) i.getMock(); } return i.getMock(); }); Loading @@ -281,8 +290,8 @@ public class LetterboxTest { right = control; } else if (i.getMock() == mBottomBuilder) { bottom = control; } else if (i.getMock() == mBehindBuilder) { behind = control; } else if (i.getMock() == mFullWindowSurfaceBuilder) { fullWindowSurface = control; } return control; }).when(builder).build(); Loading Loading
services/core/java/com/android/server/wm/Letterbox.java +42 −17 Original line number Diff line number Diff line Loading @@ -58,10 +58,12 @@ public class Letterbox { private final LetterboxSurface mLeft = new LetterboxSurface("left"); private final LetterboxSurface mBottom = new LetterboxSurface("bottom"); private final LetterboxSurface mRight = new LetterboxSurface("right"); // Prevents wallpaper from peeking through near rounded corners. It's not included in // mSurfaces array since it isn't needed in methods like notIntersectsOrFullyContains // or attachInput. private final LetterboxSurface mBehind = new LetterboxSurface("behind"); // One surface that fills the whole window is used over multiple surfaces to: // - Prevents wallpaper from peeking through near rounded corners. // - For "blurred wallpaper" background, to avoid having visible border between surfaces. // One surface approach isn't always preferred over multiple surfaces due to rendering cost // for overlaping an app window and letterbox surfaces. private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow"); private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom }; /** Loading Loading @@ -104,7 +106,7 @@ public class Letterbox { mLeft.layout(outer.left, outer.top, inner.left, outer.bottom, surfaceOrigin); mBottom.layout(outer.left, inner.bottom, outer.right, outer.bottom, surfaceOrigin); mRight.layout(inner.right, outer.top, outer.right, outer.bottom, surfaceOrigin); mBehind.layout(inner.left, inner.top, inner.right, inner.bottom, surfaceOrigin); mFullWindowSurface.layout(outer.left, outer.top, outer.right, outer.bottom, surfaceOrigin); } Loading Loading @@ -168,39 +170,48 @@ public class Letterbox { for (LetterboxSurface surface : mSurfaces) { surface.remove(); } mBehind.remove(); mFullWindowSurface.remove(); } /** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */ public boolean needsApplySurfaceChanges() { if (useFullWindowSurface()) { return mFullWindowSurface.needsApplySurfaceChanges(); } for (LetterboxSurface surface : mSurfaces) { if (surface.needsApplySurfaceChanges()) { return true; } } if (mAreCornersRounded.get() && mBehind.needsApplySurfaceChanges()) { return true; } return false; } public void applySurfaceChanges(SurfaceControl.Transaction t) { if (useFullWindowSurface()) { mFullWindowSurface.applySurfaceChanges(t); for (LetterboxSurface surface : mSurfaces) { surface.applySurfaceChanges(t); surface.remove(); } if (mAreCornersRounded.get()) { mBehind.applySurfaceChanges(t); } else { mBehind.remove(); for (LetterboxSurface surface : mSurfaces) { surface.applySurfaceChanges(t); } mFullWindowSurface.remove(); } } /** Enables touches to slide into other neighboring surfaces. */ void attachInput(WindowState win) { if (useFullWindowSurface()) { mFullWindowSurface.attachInput(win); } else { for (LetterboxSurface surface : mSurfaces) { surface.attachInput(win); } } } void onMovedToDisplay(int displayId) { for (LetterboxSurface surface : mSurfaces) { Loading @@ -208,6 +219,16 @@ public class Letterbox { surface.mInputInterceptor.mWindowHandle.displayId = displayId; } } if (mFullWindowSurface.mInputInterceptor != null) { mFullWindowSurface.mInputInterceptor.mWindowHandle.displayId = displayId; } } /** * Returns {@code true} when using {@link #mFullWindowSurface} instead of {@link mSurfaces}. */ private boolean useFullWindowSurface() { return mAreCornersRounded.get() || mHasWallpaperBackgroundSupplier.get(); } private static class InputInterceptor { Loading Loading @@ -308,6 +329,10 @@ public class Letterbox { mInputInterceptor = new InputInterceptor("Letterbox_" + mType + "_", win); } boolean isRemoved() { return mSurface != null || mInputInterceptor != null; } public void remove() { if (mSurface != null) { mTransactionFactory.get().remove(mSurface).apply(); Loading
services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java +21 −12 Original line number Diff line number Diff line Loading @@ -200,28 +200,37 @@ public class LetterboxTest { assertTrue(mLetterbox.needsApplySurfaceChanges()); mLetterbox.applySurfaceChanges(mTransaction); verify(mTransaction).setAlpha(mSurfaces.top, mDarkScrimAlpha); verify(mTransaction).setAlpha(mSurfaces.fullWindowSurface, mDarkScrimAlpha); } @Test public void testApplySurfaceChanges_cornersNotRounded_surfaceBehindNotCreated() { public void testApplySurfaceChanges_cornersNotRounded_surfaceFullWindowSurfaceNotCreated() { mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); mLetterbox.applySurfaceChanges(mTransaction); assertNull(mSurfaces.behind); assertNull(mSurfaces.fullWindowSurface); } @Test public void testApplySurfaceChanges_cornersRounded_surfaceBehindCreated() { public void testApplySurfaceChanges_cornersRounded_surfaceFullWindowSurfaceCreated() { mAreCornersRounded = true; mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); mLetterbox.applySurfaceChanges(mTransaction); assertNotNull(mSurfaces.behind); assertNotNull(mSurfaces.fullWindowSurface); } @Test public void testNotIntersectsOrFullyContains_cornersRounded_doesNotCheckSurfaceBehind() { public void testApplySurfaceChanges_wallpaperBackground_surfaceFullWindowSurfaceCreated() { mHasWallpaperBackground = true; mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); mLetterbox.applySurfaceChanges(mTransaction); assertNotNull(mSurfaces.fullWindowSurface); } @Test public void testNotIntersectsOrFullyContains_cornersRounded() { mAreCornersRounded = true; mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(0, 0)); mLetterbox.applySurfaceChanges(mTransaction); Loading Loading @@ -249,8 +258,8 @@ public class LetterboxTest { public SurfaceControl right; private SurfaceControl.Builder mBottomBuilder; public SurfaceControl bottom; private SurfaceControl.Builder mBehindBuilder; public SurfaceControl behind; private SurfaceControl.Builder mFullWindowSurfaceBuilder; public SurfaceControl fullWindowSurface; @Override public SurfaceControl.Builder get() { Loading @@ -265,8 +274,8 @@ public class LetterboxTest { mRightBuilder = (SurfaceControl.Builder) i.getMock(); } else if (((String) i.getArgument(0)).contains("bottom")) { mBottomBuilder = (SurfaceControl.Builder) i.getMock(); } else if (((String) i.getArgument(0)).contains("behind")) { mBehindBuilder = (SurfaceControl.Builder) i.getMock(); } else if (((String) i.getArgument(0)).contains("fullWindow")) { mFullWindowSurfaceBuilder = (SurfaceControl.Builder) i.getMock(); } return i.getMock(); }); Loading @@ -281,8 +290,8 @@ public class LetterboxTest { right = control; } else if (i.getMock() == mBottomBuilder) { bottom = control; } else if (i.getMock() == mBehindBuilder) { behind = control; } else if (i.getMock() == mFullWindowSurfaceBuilder) { fullWindowSurface = control; } return control; }).when(builder).build(); Loading