Loading services/core/java/com/android/server/wm/ActivityRecord.java +47 −3 Original line number Diff line number Diff line Loading @@ -660,6 +660,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean mUseTransferredAnimation; /** Whether we need to setup the animation to animate only within the letterbox. */ private boolean mNeedsLetterboxedAnimation; /** * @see #currentLaunchCanTurnScreenOn() */ Loading Loading @@ -1762,8 +1765,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLetterboxUiController.layoutLetterbox(winHint); } boolean hasWallpaperBackgroudForLetterbox() { return mLetterboxUiController.hasWallpaperBackgroudForLetterbox(); boolean hasWallpaperBackgroundForLetterbox() { return mLetterboxUiController.hasWallpaperBackgroundForLetterbox(); } void updateLetterboxSurface(WindowState winHint, Transaction t) { mLetterboxUiController.updateLetterboxSurface(winHint, t); } void updateLetterboxSurface(WindowState winHint) { Loading Loading @@ -5334,6 +5341,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A commitVisibility(visible, performLayout, false /* fromTransition */); } void setNeedsLetterboxedAnimation(boolean needsLetterboxedAnimation) { mNeedsLetterboxedAnimation = needsLetterboxedAnimation; } boolean isNeedsLetterboxedAnimation() { return mNeedsLetterboxedAnimation; } boolean isInLetterboxAnimation() { return mNeedsLetterboxedAnimation && isAnimating(); } /** * Post process after applying an app transition animation. * Loading Loading @@ -7261,6 +7280,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A .setParent(getAnimationLeashParent()) .setName(getSurfaceControl() + " - animation-bounds") .setCallsite("ActivityRecord.createAnimationBoundsLayer"); if (mNeedsLetterboxedAnimation) { // Needs to be an effect layer to support rounded corners builder.setEffectLayer(); } final SurfaceControl boundsLayer = builder.build(); t.show(boundsLayer); return boundsLayer; Loading Loading @@ -7298,6 +7321,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAnimatingActivityRegistry.notifyStarting(this); } if (mNeedsLetterboxedAnimation) { updateLetterboxSurface(findMainWindow(), t); mNeedsAnimationBoundsLayer = true; } // If the animation needs to be cropped then an animation bounds layer is created as a // child of the root pinned task or animation layer. The leash is then reparented to this // new layer. Loading @@ -7320,6 +7348,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A t.setLayer(leash, 0); t.setLayer(mAnimationBoundsLayer, getLastLayer()); if (mNeedsLetterboxedAnimation) { final int cornerRadius = mLetterboxUiController .getRoundedCornersRadius(findMainWindow()); final Rect letterboxInnerBounds = new Rect(); getLetterboxInnerBounds(letterboxInnerBounds); t.setCornerRadius(mAnimationBoundsLayer, cornerRadius) .setCrop(mAnimationBoundsLayer, letterboxInnerBounds); } // Reparent leash to animation bounds layer. t.reparent(leash, mAnimationBoundsLayer); } Loading Loading @@ -7433,6 +7472,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAnimationBoundsLayer = null; } mNeedsAnimationBoundsLayer = false; if (mNeedsLetterboxedAnimation) { mNeedsLetterboxedAnimation = false; updateLetterboxSurface(findMainWindow(), t); } if (mAnimatingActivityRegistry != null) { mAnimatingActivityRegistry.notifyFinished(this); } Loading @@ -7445,7 +7490,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished"); mTransit = TRANSIT_OLD_UNSET; mTransitFlags = 0; mNeedsAnimationBoundsLayer = false; setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "ActivityRecord"); Loading services/core/java/com/android/server/wm/AppTransitionController.java +28 −0 Original line number Diff line number Diff line Loading @@ -81,9 +81,11 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Rect; import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; import android.view.Display; import android.view.RemoteAnimationAdapter; Loading Loading @@ -1028,6 +1030,32 @@ public class AppTransitionController { return; } if (AppTransition.isActivityTransitOld(transit)) { final ArrayList<Pair<ActivityRecord, Rect>> closingLetterboxes = new ArrayList(); for (int i = 0; i < closingApps.size(); ++i) { ActivityRecord closingApp = closingApps.valueAt(i); if (closingApp.areBoundsLetterboxed()) { final Rect insets = closingApp.getLetterboxInsets(); closingLetterboxes.add(new Pair(closingApp, insets)); } } for (int i = 0; i < openingApps.size(); ++i) { ActivityRecord openingApp = openingApps.valueAt(i); if (openingApp.areBoundsLetterboxed()) { final Rect openingInsets = openingApp.getLetterboxInsets(); for (Pair<ActivityRecord, Rect> closingLetterbox : closingLetterboxes) { final Rect closingInsets = closingLetterbox.second; if (openingInsets.equals(closingInsets)) { ActivityRecord closingApp = closingLetterbox.first; openingApp.setNeedsLetterboxedAnimation(true); closingApp.setNeedsLetterboxedAnimation(true); } } } } } final ArraySet<WindowContainer> openingWcs = getAnimationTargets( openingApps, closingApps, true /* visible */); final ArraySet<WindowContainer> closingWcs = getAnimationTargets( Loading services/core/java/com/android/server/wm/Letterbox.java +12 −6 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ public class Letterbox { private final Supplier<Boolean> mHasWallpaperBackgroundSupplier; private final Supplier<Integer> mBlurRadiusSupplier; private final Supplier<Float> mDarkScrimAlphaSupplier; private final Supplier<SurfaceControl> mParentSurfaceSupplier; private final Rect mOuter = new Rect(); private final Rect mInner = new Rect(); Loading Loading @@ -87,7 +88,8 @@ public class Letterbox { Supplier<Integer> blurRadiusSupplier, Supplier<Float> darkScrimAlphaSupplier, IntConsumer doubleTapCallbackX, IntConsumer doubleTapCallbackY) { IntConsumer doubleTapCallbackY, Supplier<SurfaceControl> parentSurface) { mSurfaceControlFactory = surfaceControlFactory; mTransactionFactory = transactionFactory; mAreCornersRounded = areCornersRounded; Loading @@ -97,6 +99,7 @@ public class Letterbox { mDarkScrimAlphaSupplier = darkScrimAlphaSupplier; mDoubleTapCallbackX = doubleTapCallbackX; mDoubleTapCallbackY = doubleTapCallbackY; mParentSurfaceSupplier = parentSurface; } /** Loading @@ -121,7 +124,6 @@ public class Letterbox { mFullWindowSurface.layout(outer.left, outer.top, outer.right, outer.bottom, surfaceOrigin); } /** * Gets the insets between the outer and inner rects. */ Loading Loading @@ -333,6 +335,7 @@ public class Letterbox { private SurfaceControl mSurface; private Color mColor; private boolean mHasWallpaperBackground; private SurfaceControl mParentSurface; private final Rect mSurfaceFrameRelative = new Rect(); private final Rect mLayoutFrameGlobal = new Rect(); Loading Loading @@ -403,10 +406,12 @@ public class Letterbox { } mColor = mColorSupplier.get(); mParentSurface = mParentSurfaceSupplier.get(); t.setColor(mSurface, getRgbColorArray()); t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top); t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(), mSurfaceFrameRelative.height()); t.reparent(mSurface, mParentSurface); mHasWallpaperBackground = mHasWallpaperBackgroundSupplier.get(); updateAlphaAndBlur(t); Loading Loading @@ -452,12 +457,13 @@ public class Letterbox { public boolean needsApplySurfaceChanges() { return !mSurfaceFrameRelative.equals(mLayoutFrameRelative) // If mSurfaceFrameRelative is empty then mHasWallpaperBackground and mColor // may never be updated in applySurfaceChanges but this doesn't mean that // update is needed. // If mSurfaceFrameRelative is empty then mHasWallpaperBackground, mColor, // and mParentSurface may never be updated in applySurfaceChanges but this // doesn't mean that update is needed. || !mSurfaceFrameRelative.isEmpty() && (mHasWallpaperBackgroundSupplier.get() != mHasWallpaperBackground || !mColorSupplier.get().equals(mColor)); || !mColorSupplier.get().equals(mColor) || mParentSurfaceSupplier.get() != mParentSurface); } } } services/core/java/com/android/server/wm/LetterboxConfiguration.java +5 −5 Original line number Diff line number Diff line Loading @@ -265,7 +265,7 @@ final class LetterboxConfiguration { } /** * Overrides corners raidus for activities presented in the letterbox mode. If given value < 0, * Overrides corners radius for activities presented in the letterbox mode. If given value < 0, * both it and a value of {@link * com.android.internal.R.integer.config_letterboxActivityCornersRadius} will be ignored and * corners of the activity won't be rounded. Loading @@ -275,7 +275,7 @@ final class LetterboxConfiguration { } /** * Resets corners raidus for activities presented in the letterbox mode to {@link * Resets corners radius for activities presented in the letterbox mode to {@link * com.android.internal.R.integer.config_letterboxActivityCornersRadius}. */ void resetLetterboxActivityCornersRadius() { Loading @@ -291,7 +291,7 @@ final class LetterboxConfiguration { } /** * Gets corners raidus for activities presented in the letterbox mode. * Gets corners radius for activities presented in the letterbox mode. */ int getLetterboxActivityCornersRadius() { return mLetterboxActivityCornersRadius; Loading @@ -318,7 +318,7 @@ final class LetterboxConfiguration { /** * Sets color of letterbox background which is used when {@link * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as * fallback for other backfround types. * fallback for other background types. */ void setLetterboxBackgroundColor(Color color) { mLetterboxBackgroundColorOverride = color; Loading @@ -327,7 +327,7 @@ final class LetterboxConfiguration { /** * Sets color ID of letterbox background which is used when {@link * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as * fallback for other backfround types. * fallback for other background types. */ void setLetterboxBackgroundColorResourceId(int colorId) { mLetterboxBackgroundColorResourceIdOverride = colorId; Loading services/core/java/com/android/server/wm/LetterboxUiController.java +99 −35 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ final class LetterboxUiController { // Taskbar expanded height. Used to determine whether to crop an app window to display rounded // corners above the taskbar. private float mExpandedTaskBarHeight; private final float mExpandedTaskBarHeight; private boolean mShowWallpaperForLetterboxBackground; Loading Loading @@ -120,7 +120,7 @@ final class LetterboxUiController { } } boolean hasWallpaperBackgroudForLetterbox() { boolean hasWallpaperBackgroundForLetterbox() { return mShowWallpaperForLetterboxBackground; } Loading @@ -137,6 +137,11 @@ final class LetterboxUiController { void getLetterboxInnerBounds(Rect outBounds) { if (mLetterbox != null) { outBounds.set(mLetterbox.getInnerFrame()); final WindowState w = mActivityRecord.findMainWindow(); if (w == null) { return; } adjustBoundsForTaskbar(w, outBounds); } else { outBounds.setEmpty(); } Loading @@ -160,13 +165,17 @@ final class LetterboxUiController { } void updateLetterboxSurface(WindowState winHint) { updateLetterboxSurface(winHint, mActivityRecord.getSyncTransaction()); } void updateLetterboxSurface(WindowState winHint, Transaction t) { final WindowState w = mActivityRecord.findMainWindow(); if (w != winHint && winHint != null && w != null) { return; } layoutLetterbox(winHint); if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) { mLetterbox.applySurfaceChanges(mActivityRecord.getSyncTransaction()); mLetterbox.applySurfaceChanges(t); } } Loading @@ -191,14 +200,22 @@ final class LetterboxUiController { mActivityRecord.mWmService.mTransactionFactory, this::shouldLetterboxHaveRoundedCorners, this::getLetterboxBackgroundColor, this::hasWallpaperBackgroudForLetterbox, this::hasWallpaperBackgroundForLetterbox, this::getLetterboxWallpaperBlurRadius, this::getLetterboxWallpaperDarkScrimAlpha, this::handleHorizontalDoubleTap, this::handleVerticalDoubleTap); this::handleVerticalDoubleTap, this::getLetterboxParentSurface); mLetterbox.attachInput(w); } if (mActivityRecord.isInLetterboxAnimation()) { // In this case we attach the letterbox to the task instead of the activity. mActivityRecord.getTask().getPosition(mTmpPoint); } else { mActivityRecord.getPosition(mTmpPoint); } // Get the bounds of the "space-to-fill". The transformed bounds have the highest // priority because the activity is launched in a rotated environment. In multi-window // mode, the task-level represents this. In fullscreen-mode, the task container does Loading @@ -215,6 +232,13 @@ final class LetterboxUiController { } } SurfaceControl getLetterboxParentSurface() { if (mActivityRecord.isInLetterboxAnimation()) { return mActivityRecord.getTask().getSurfaceControl(); } return mActivityRecord.getSurfaceControl(); } private boolean shouldLetterboxHaveRoundedCorners() { // TODO(b/214030873): remove once background is drawn for transparent activities // Letterbox shouldn't have rounded corners if the activity is transparent Loading Loading @@ -436,7 +460,7 @@ final class LetterboxUiController { } break; case LETTERBOX_BACKGROUND_WALLPAPER: if (hasWallpaperBackgroudForLetterbox()) { if (hasWallpaperBackgroundForLetterbox()) { // Color is used for translucent scrim that dims wallpaper. return Color.valueOf(Color.BLACK); } Loading @@ -459,15 +483,14 @@ final class LetterboxUiController { private void updateRoundedCorners(WindowState mainWindow) { final SurfaceControl windowSurface = mainWindow.getClientViewRootSurface(); if (windowSurface != null && windowSurface.isValid()) { Transaction transaction = mActivityRecord.getSyncTransaction(); final InsetsState insetsState = mainWindow.getInsetsState(); final InsetsSource taskbarInsetsSource = insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); if (!isLetterboxedNotForDisplayCutout(mainWindow) || !mLetterboxConfiguration.isLetterboxActivityCornersRounded() || taskbarInsetsSource == null) { final Transaction transaction = mActivityRecord.getSyncTransaction(); if (!requiresRoundedCorners(mainWindow) || mActivityRecord.isInLetterboxAnimation()) { // We don't want corner radius on the window. // In the case the ActivityRecord requires a letterboxed animation we never want // rounded corners on the window because rounded corners are applied at the // animation-bounds surface level and rounded corners on the window would interfere // with that leading to unexpected rounded corner positioning during the animation. transaction .setWindowCrop(windowSurface, null) .setCornerRadius(windowSurface, 0); Loading @@ -476,48 +499,89 @@ final class LetterboxUiController { Rect cropBounds = null; // Rounded corners should be displayed above the taskbar. When taskbar is hidden, // an insets frame is equal to a navigation bar which shouldn't affect position of // rounded corners since apps are expected to handle navigation bar inset. // This condition checks whether the taskbar is visible. // Do not crop the taskbar inset if the window is in immersive mode - the user can // swipe to show/hide the taskbar as an overlay. if (taskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight && taskbarInsetsSource.isVisible()) { if (hasVisibleTaskbar(mainWindow)) { cropBounds = new Rect(mActivityRecord.getBounds()); // Activity bounds are in screen coordinates while (0,0) for activity's surface // control is at the top left corner of an app window so offsetting bounds // accordingly. cropBounds.offsetTo(0, 0); // Rounded cornerners should be displayed above the taskbar. cropBounds.bottom = Math.min(cropBounds.bottom, taskbarInsetsSource.getFrame().top); if (mActivityRecord.inSizeCompatMode() && mActivityRecord.getSizeCompatScale() < 1.0f) { cropBounds.scale(1.0f / mActivityRecord.getSizeCompatScale()); } // Rounded corners should be displayed above the taskbar. adjustBoundsForTaskbarUnchecked(mainWindow, cropBounds); } transaction .setWindowCrop(windowSurface, cropBounds) .setCornerRadius(windowSurface, getRoundedCorners(insetsState)); .setCornerRadius(windowSurface, getRoundedCornersRadius(mainWindow)); } } // Returns rounded corners radius based on override in private boolean requiresRoundedCorners(WindowState mainWindow) { final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow); return isLetterboxedNotForDisplayCutout(mainWindow) && mLetterboxConfiguration.isLetterboxActivityCornersRounded() && taskbarInsetsSource != null; } // Returns rounded corners radius the letterboxed activity should have based on override in // R.integer.config_letterboxActivityCornersRadius or min device bottom corner radii. // Device corners can be different on the right and left sides but we use the same radius // for all corners for consistency and pick a minimal bottom one for consistency with a // taskbar rounded corners. private int getRoundedCorners(InsetsState insetsState) { int getRoundedCornersRadius(WindowState mainWindow) { if (!requiresRoundedCorners(mainWindow)) { return 0; } if (mLetterboxConfiguration.getLetterboxActivityCornersRadius() >= 0) { return mLetterboxConfiguration.getLetterboxActivityCornersRadius(); } final InsetsState insetsState = mainWindow.getInsetsState(); return Math.min( getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_LEFT), getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_RIGHT)); } /** * Returns whether the taskbar is visible. Returns false if the window is in immersive mode, * since the user can swipe to show/hide the taskbar as an overlay. */ private boolean hasVisibleTaskbar(WindowState mainWindow) { final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow); return taskbarInsetsSource != null && taskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight && taskbarInsetsSource.isVisible(); } private InsetsSource getTaskbarInsetsSource(WindowState mainWindow) { final InsetsState insetsState = mainWindow.getInsetsState(); return insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); } private void adjustBoundsForTaskbar(WindowState mainWindow, Rect bounds) { // Rounded corners should be displayed above the taskbar. When taskbar is hidden, // an insets frame is equal to a navigation bar which shouldn't affect position of // rounded corners since apps are expected to handle navigation bar inset. // This condition checks whether the taskbar is visible. // Do not crop the taskbar inset if the window is in immersive mode - the user can // swipe to show/hide the taskbar as an overlay. if (hasVisibleTaskbar(mainWindow)) { adjustBoundsForTaskbarUnchecked(mainWindow, bounds); } } private void adjustBoundsForTaskbarUnchecked(WindowState mainWindow, Rect bounds) { // Rounded corners should be displayed above the taskbar. bounds.bottom = Math.min(bounds.bottom, getTaskbarInsetsSource(mainWindow).getFrame().top); if (mActivityRecord.inSizeCompatMode() && mActivityRecord.getSizeCompatScale() < 1.0f) { bounds.scale(1.0f / mActivityRecord.getSizeCompatScale()); } } private int getInsetsStateCornerRadius( InsetsState insetsState, @RoundedCorner.Position int position) { RoundedCorner corner = insetsState.getRoundedCorners().getRoundedCorner(position); Loading Loading @@ -592,7 +656,7 @@ final class LetterboxUiController { + letterboxBackgroundTypeToString( mLetterboxConfiguration.getLetterboxBackgroundType())); pw.println(prefix + " letterboxCornerRadius=" + getRoundedCorners(mainWin.getInsetsState())); + getRoundedCornersRadius(mainWin)); if (mLetterboxConfiguration.getLetterboxBackgroundType() == LETTERBOX_BACKGROUND_WALLPAPER) { pw.println(prefix + " isLetterboxWallpaperBlurSupported=" Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +47 −3 Original line number Diff line number Diff line Loading @@ -660,6 +660,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean mUseTransferredAnimation; /** Whether we need to setup the animation to animate only within the letterbox. */ private boolean mNeedsLetterboxedAnimation; /** * @see #currentLaunchCanTurnScreenOn() */ Loading Loading @@ -1762,8 +1765,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLetterboxUiController.layoutLetterbox(winHint); } boolean hasWallpaperBackgroudForLetterbox() { return mLetterboxUiController.hasWallpaperBackgroudForLetterbox(); boolean hasWallpaperBackgroundForLetterbox() { return mLetterboxUiController.hasWallpaperBackgroundForLetterbox(); } void updateLetterboxSurface(WindowState winHint, Transaction t) { mLetterboxUiController.updateLetterboxSurface(winHint, t); } void updateLetterboxSurface(WindowState winHint) { Loading Loading @@ -5334,6 +5341,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A commitVisibility(visible, performLayout, false /* fromTransition */); } void setNeedsLetterboxedAnimation(boolean needsLetterboxedAnimation) { mNeedsLetterboxedAnimation = needsLetterboxedAnimation; } boolean isNeedsLetterboxedAnimation() { return mNeedsLetterboxedAnimation; } boolean isInLetterboxAnimation() { return mNeedsLetterboxedAnimation && isAnimating(); } /** * Post process after applying an app transition animation. * Loading Loading @@ -7261,6 +7280,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A .setParent(getAnimationLeashParent()) .setName(getSurfaceControl() + " - animation-bounds") .setCallsite("ActivityRecord.createAnimationBoundsLayer"); if (mNeedsLetterboxedAnimation) { // Needs to be an effect layer to support rounded corners builder.setEffectLayer(); } final SurfaceControl boundsLayer = builder.build(); t.show(boundsLayer); return boundsLayer; Loading Loading @@ -7298,6 +7321,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAnimatingActivityRegistry.notifyStarting(this); } if (mNeedsLetterboxedAnimation) { updateLetterboxSurface(findMainWindow(), t); mNeedsAnimationBoundsLayer = true; } // If the animation needs to be cropped then an animation bounds layer is created as a // child of the root pinned task or animation layer. The leash is then reparented to this // new layer. Loading @@ -7320,6 +7348,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A t.setLayer(leash, 0); t.setLayer(mAnimationBoundsLayer, getLastLayer()); if (mNeedsLetterboxedAnimation) { final int cornerRadius = mLetterboxUiController .getRoundedCornersRadius(findMainWindow()); final Rect letterboxInnerBounds = new Rect(); getLetterboxInnerBounds(letterboxInnerBounds); t.setCornerRadius(mAnimationBoundsLayer, cornerRadius) .setCrop(mAnimationBoundsLayer, letterboxInnerBounds); } // Reparent leash to animation bounds layer. t.reparent(leash, mAnimationBoundsLayer); } Loading Loading @@ -7433,6 +7472,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAnimationBoundsLayer = null; } mNeedsAnimationBoundsLayer = false; if (mNeedsLetterboxedAnimation) { mNeedsLetterboxedAnimation = false; updateLetterboxSurface(findMainWindow(), t); } if (mAnimatingActivityRegistry != null) { mAnimatingActivityRegistry.notifyFinished(this); } Loading @@ -7445,7 +7490,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished"); mTransit = TRANSIT_OLD_UNSET; mTransitFlags = 0; mNeedsAnimationBoundsLayer = false; setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "ActivityRecord"); Loading
services/core/java/com/android/server/wm/AppTransitionController.java +28 −0 Original line number Diff line number Diff line Loading @@ -81,9 +81,11 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Rect; import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; import android.view.Display; import android.view.RemoteAnimationAdapter; Loading Loading @@ -1028,6 +1030,32 @@ public class AppTransitionController { return; } if (AppTransition.isActivityTransitOld(transit)) { final ArrayList<Pair<ActivityRecord, Rect>> closingLetterboxes = new ArrayList(); for (int i = 0; i < closingApps.size(); ++i) { ActivityRecord closingApp = closingApps.valueAt(i); if (closingApp.areBoundsLetterboxed()) { final Rect insets = closingApp.getLetterboxInsets(); closingLetterboxes.add(new Pair(closingApp, insets)); } } for (int i = 0; i < openingApps.size(); ++i) { ActivityRecord openingApp = openingApps.valueAt(i); if (openingApp.areBoundsLetterboxed()) { final Rect openingInsets = openingApp.getLetterboxInsets(); for (Pair<ActivityRecord, Rect> closingLetterbox : closingLetterboxes) { final Rect closingInsets = closingLetterbox.second; if (openingInsets.equals(closingInsets)) { ActivityRecord closingApp = closingLetterbox.first; openingApp.setNeedsLetterboxedAnimation(true); closingApp.setNeedsLetterboxedAnimation(true); } } } } } final ArraySet<WindowContainer> openingWcs = getAnimationTargets( openingApps, closingApps, true /* visible */); final ArraySet<WindowContainer> closingWcs = getAnimationTargets( Loading
services/core/java/com/android/server/wm/Letterbox.java +12 −6 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ public class Letterbox { private final Supplier<Boolean> mHasWallpaperBackgroundSupplier; private final Supplier<Integer> mBlurRadiusSupplier; private final Supplier<Float> mDarkScrimAlphaSupplier; private final Supplier<SurfaceControl> mParentSurfaceSupplier; private final Rect mOuter = new Rect(); private final Rect mInner = new Rect(); Loading Loading @@ -87,7 +88,8 @@ public class Letterbox { Supplier<Integer> blurRadiusSupplier, Supplier<Float> darkScrimAlphaSupplier, IntConsumer doubleTapCallbackX, IntConsumer doubleTapCallbackY) { IntConsumer doubleTapCallbackY, Supplier<SurfaceControl> parentSurface) { mSurfaceControlFactory = surfaceControlFactory; mTransactionFactory = transactionFactory; mAreCornersRounded = areCornersRounded; Loading @@ -97,6 +99,7 @@ public class Letterbox { mDarkScrimAlphaSupplier = darkScrimAlphaSupplier; mDoubleTapCallbackX = doubleTapCallbackX; mDoubleTapCallbackY = doubleTapCallbackY; mParentSurfaceSupplier = parentSurface; } /** Loading @@ -121,7 +124,6 @@ public class Letterbox { mFullWindowSurface.layout(outer.left, outer.top, outer.right, outer.bottom, surfaceOrigin); } /** * Gets the insets between the outer and inner rects. */ Loading Loading @@ -333,6 +335,7 @@ public class Letterbox { private SurfaceControl mSurface; private Color mColor; private boolean mHasWallpaperBackground; private SurfaceControl mParentSurface; private final Rect mSurfaceFrameRelative = new Rect(); private final Rect mLayoutFrameGlobal = new Rect(); Loading Loading @@ -403,10 +406,12 @@ public class Letterbox { } mColor = mColorSupplier.get(); mParentSurface = mParentSurfaceSupplier.get(); t.setColor(mSurface, getRgbColorArray()); t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top); t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(), mSurfaceFrameRelative.height()); t.reparent(mSurface, mParentSurface); mHasWallpaperBackground = mHasWallpaperBackgroundSupplier.get(); updateAlphaAndBlur(t); Loading Loading @@ -452,12 +457,13 @@ public class Letterbox { public boolean needsApplySurfaceChanges() { return !mSurfaceFrameRelative.equals(mLayoutFrameRelative) // If mSurfaceFrameRelative is empty then mHasWallpaperBackground and mColor // may never be updated in applySurfaceChanges but this doesn't mean that // update is needed. // If mSurfaceFrameRelative is empty then mHasWallpaperBackground, mColor, // and mParentSurface may never be updated in applySurfaceChanges but this // doesn't mean that update is needed. || !mSurfaceFrameRelative.isEmpty() && (mHasWallpaperBackgroundSupplier.get() != mHasWallpaperBackground || !mColorSupplier.get().equals(mColor)); || !mColorSupplier.get().equals(mColor) || mParentSurfaceSupplier.get() != mParentSurface); } } }
services/core/java/com/android/server/wm/LetterboxConfiguration.java +5 −5 Original line number Diff line number Diff line Loading @@ -265,7 +265,7 @@ final class LetterboxConfiguration { } /** * Overrides corners raidus for activities presented in the letterbox mode. If given value < 0, * Overrides corners radius for activities presented in the letterbox mode. If given value < 0, * both it and a value of {@link * com.android.internal.R.integer.config_letterboxActivityCornersRadius} will be ignored and * corners of the activity won't be rounded. Loading @@ -275,7 +275,7 @@ final class LetterboxConfiguration { } /** * Resets corners raidus for activities presented in the letterbox mode to {@link * Resets corners radius for activities presented in the letterbox mode to {@link * com.android.internal.R.integer.config_letterboxActivityCornersRadius}. */ void resetLetterboxActivityCornersRadius() { Loading @@ -291,7 +291,7 @@ final class LetterboxConfiguration { } /** * Gets corners raidus for activities presented in the letterbox mode. * Gets corners radius for activities presented in the letterbox mode. */ int getLetterboxActivityCornersRadius() { return mLetterboxActivityCornersRadius; Loading @@ -318,7 +318,7 @@ final class LetterboxConfiguration { /** * Sets color of letterbox background which is used when {@link * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as * fallback for other backfround types. * fallback for other background types. */ void setLetterboxBackgroundColor(Color color) { mLetterboxBackgroundColorOverride = color; Loading @@ -327,7 +327,7 @@ final class LetterboxConfiguration { /** * Sets color ID of letterbox background which is used when {@link * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as * fallback for other backfround types. * fallback for other background types. */ void setLetterboxBackgroundColorResourceId(int colorId) { mLetterboxBackgroundColorResourceIdOverride = colorId; Loading
services/core/java/com/android/server/wm/LetterboxUiController.java +99 −35 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ final class LetterboxUiController { // Taskbar expanded height. Used to determine whether to crop an app window to display rounded // corners above the taskbar. private float mExpandedTaskBarHeight; private final float mExpandedTaskBarHeight; private boolean mShowWallpaperForLetterboxBackground; Loading Loading @@ -120,7 +120,7 @@ final class LetterboxUiController { } } boolean hasWallpaperBackgroudForLetterbox() { boolean hasWallpaperBackgroundForLetterbox() { return mShowWallpaperForLetterboxBackground; } Loading @@ -137,6 +137,11 @@ final class LetterboxUiController { void getLetterboxInnerBounds(Rect outBounds) { if (mLetterbox != null) { outBounds.set(mLetterbox.getInnerFrame()); final WindowState w = mActivityRecord.findMainWindow(); if (w == null) { return; } adjustBoundsForTaskbar(w, outBounds); } else { outBounds.setEmpty(); } Loading @@ -160,13 +165,17 @@ final class LetterboxUiController { } void updateLetterboxSurface(WindowState winHint) { updateLetterboxSurface(winHint, mActivityRecord.getSyncTransaction()); } void updateLetterboxSurface(WindowState winHint, Transaction t) { final WindowState w = mActivityRecord.findMainWindow(); if (w != winHint && winHint != null && w != null) { return; } layoutLetterbox(winHint); if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) { mLetterbox.applySurfaceChanges(mActivityRecord.getSyncTransaction()); mLetterbox.applySurfaceChanges(t); } } Loading @@ -191,14 +200,22 @@ final class LetterboxUiController { mActivityRecord.mWmService.mTransactionFactory, this::shouldLetterboxHaveRoundedCorners, this::getLetterboxBackgroundColor, this::hasWallpaperBackgroudForLetterbox, this::hasWallpaperBackgroundForLetterbox, this::getLetterboxWallpaperBlurRadius, this::getLetterboxWallpaperDarkScrimAlpha, this::handleHorizontalDoubleTap, this::handleVerticalDoubleTap); this::handleVerticalDoubleTap, this::getLetterboxParentSurface); mLetterbox.attachInput(w); } if (mActivityRecord.isInLetterboxAnimation()) { // In this case we attach the letterbox to the task instead of the activity. mActivityRecord.getTask().getPosition(mTmpPoint); } else { mActivityRecord.getPosition(mTmpPoint); } // Get the bounds of the "space-to-fill". The transformed bounds have the highest // priority because the activity is launched in a rotated environment. In multi-window // mode, the task-level represents this. In fullscreen-mode, the task container does Loading @@ -215,6 +232,13 @@ final class LetterboxUiController { } } SurfaceControl getLetterboxParentSurface() { if (mActivityRecord.isInLetterboxAnimation()) { return mActivityRecord.getTask().getSurfaceControl(); } return mActivityRecord.getSurfaceControl(); } private boolean shouldLetterboxHaveRoundedCorners() { // TODO(b/214030873): remove once background is drawn for transparent activities // Letterbox shouldn't have rounded corners if the activity is transparent Loading Loading @@ -436,7 +460,7 @@ final class LetterboxUiController { } break; case LETTERBOX_BACKGROUND_WALLPAPER: if (hasWallpaperBackgroudForLetterbox()) { if (hasWallpaperBackgroundForLetterbox()) { // Color is used for translucent scrim that dims wallpaper. return Color.valueOf(Color.BLACK); } Loading @@ -459,15 +483,14 @@ final class LetterboxUiController { private void updateRoundedCorners(WindowState mainWindow) { final SurfaceControl windowSurface = mainWindow.getClientViewRootSurface(); if (windowSurface != null && windowSurface.isValid()) { Transaction transaction = mActivityRecord.getSyncTransaction(); final InsetsState insetsState = mainWindow.getInsetsState(); final InsetsSource taskbarInsetsSource = insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); if (!isLetterboxedNotForDisplayCutout(mainWindow) || !mLetterboxConfiguration.isLetterboxActivityCornersRounded() || taskbarInsetsSource == null) { final Transaction transaction = mActivityRecord.getSyncTransaction(); if (!requiresRoundedCorners(mainWindow) || mActivityRecord.isInLetterboxAnimation()) { // We don't want corner radius on the window. // In the case the ActivityRecord requires a letterboxed animation we never want // rounded corners on the window because rounded corners are applied at the // animation-bounds surface level and rounded corners on the window would interfere // with that leading to unexpected rounded corner positioning during the animation. transaction .setWindowCrop(windowSurface, null) .setCornerRadius(windowSurface, 0); Loading @@ -476,48 +499,89 @@ final class LetterboxUiController { Rect cropBounds = null; // Rounded corners should be displayed above the taskbar. When taskbar is hidden, // an insets frame is equal to a navigation bar which shouldn't affect position of // rounded corners since apps are expected to handle navigation bar inset. // This condition checks whether the taskbar is visible. // Do not crop the taskbar inset if the window is in immersive mode - the user can // swipe to show/hide the taskbar as an overlay. if (taskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight && taskbarInsetsSource.isVisible()) { if (hasVisibleTaskbar(mainWindow)) { cropBounds = new Rect(mActivityRecord.getBounds()); // Activity bounds are in screen coordinates while (0,0) for activity's surface // control is at the top left corner of an app window so offsetting bounds // accordingly. cropBounds.offsetTo(0, 0); // Rounded cornerners should be displayed above the taskbar. cropBounds.bottom = Math.min(cropBounds.bottom, taskbarInsetsSource.getFrame().top); if (mActivityRecord.inSizeCompatMode() && mActivityRecord.getSizeCompatScale() < 1.0f) { cropBounds.scale(1.0f / mActivityRecord.getSizeCompatScale()); } // Rounded corners should be displayed above the taskbar. adjustBoundsForTaskbarUnchecked(mainWindow, cropBounds); } transaction .setWindowCrop(windowSurface, cropBounds) .setCornerRadius(windowSurface, getRoundedCorners(insetsState)); .setCornerRadius(windowSurface, getRoundedCornersRadius(mainWindow)); } } // Returns rounded corners radius based on override in private boolean requiresRoundedCorners(WindowState mainWindow) { final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow); return isLetterboxedNotForDisplayCutout(mainWindow) && mLetterboxConfiguration.isLetterboxActivityCornersRounded() && taskbarInsetsSource != null; } // Returns rounded corners radius the letterboxed activity should have based on override in // R.integer.config_letterboxActivityCornersRadius or min device bottom corner radii. // Device corners can be different on the right and left sides but we use the same radius // for all corners for consistency and pick a minimal bottom one for consistency with a // taskbar rounded corners. private int getRoundedCorners(InsetsState insetsState) { int getRoundedCornersRadius(WindowState mainWindow) { if (!requiresRoundedCorners(mainWindow)) { return 0; } if (mLetterboxConfiguration.getLetterboxActivityCornersRadius() >= 0) { return mLetterboxConfiguration.getLetterboxActivityCornersRadius(); } final InsetsState insetsState = mainWindow.getInsetsState(); return Math.min( getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_LEFT), getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_RIGHT)); } /** * Returns whether the taskbar is visible. Returns false if the window is in immersive mode, * since the user can swipe to show/hide the taskbar as an overlay. */ private boolean hasVisibleTaskbar(WindowState mainWindow) { final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow); return taskbarInsetsSource != null && taskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight && taskbarInsetsSource.isVisible(); } private InsetsSource getTaskbarInsetsSource(WindowState mainWindow) { final InsetsState insetsState = mainWindow.getInsetsState(); return insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); } private void adjustBoundsForTaskbar(WindowState mainWindow, Rect bounds) { // Rounded corners should be displayed above the taskbar. When taskbar is hidden, // an insets frame is equal to a navigation bar which shouldn't affect position of // rounded corners since apps are expected to handle navigation bar inset. // This condition checks whether the taskbar is visible. // Do not crop the taskbar inset if the window is in immersive mode - the user can // swipe to show/hide the taskbar as an overlay. if (hasVisibleTaskbar(mainWindow)) { adjustBoundsForTaskbarUnchecked(mainWindow, bounds); } } private void adjustBoundsForTaskbarUnchecked(WindowState mainWindow, Rect bounds) { // Rounded corners should be displayed above the taskbar. bounds.bottom = Math.min(bounds.bottom, getTaskbarInsetsSource(mainWindow).getFrame().top); if (mActivityRecord.inSizeCompatMode() && mActivityRecord.getSizeCompatScale() < 1.0f) { bounds.scale(1.0f / mActivityRecord.getSizeCompatScale()); } } private int getInsetsStateCornerRadius( InsetsState insetsState, @RoundedCorner.Position int position) { RoundedCorner corner = insetsState.getRoundedCorners().getRoundedCorner(position); Loading Loading @@ -592,7 +656,7 @@ final class LetterboxUiController { + letterboxBackgroundTypeToString( mLetterboxConfiguration.getLetterboxBackgroundType())); pw.println(prefix + " letterboxCornerRadius=" + getRoundedCorners(mainWin.getInsetsState())); + getRoundedCornersRadius(mainWin)); if (mLetterboxConfiguration.getLetterboxBackgroundType() == LETTERBOX_BACKGROUND_WALLPAPER) { pw.println(prefix + " isLetterboxWallpaperBlurSupported=" Loading