summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Pablo Gamito <pablogamito@google.com> 2022-08-22 17:01:37 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-08-22 17:01:37 +0000
commitc3a33cde83195ae4af0b27f545fda19751565044 (patch)
treea61985b359433beb54622fbe90dd5d6a8f2c2720
parentbc18e29662ae488b5c6990d33719d6f4b9d17868 (diff)
parent6576af6bbee4126ab9ed3c05b5731ae6cabe5aee (diff)
Merge "Polish activity transition for letterbox" into tm-qpr-dev
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java50
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java28
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java18
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java10
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java134
-rw-r--r--services/core/java/com/android/server/wm/SurfaceAnimationRunner.java52
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java20
9 files changed, 244 insertions, 74 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index bd88c41b5268..2e3096265b53 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -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()
*/
@@ -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) {
@@ -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.
*
@@ -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;
@@ -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.
@@ -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);
}
@@ -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);
}
@@ -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");
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index fb9d7e602210..5ac5f2e4bdaf 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -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;
@@ -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(
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index df3109ad33c7..27550d9e8186 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -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();
@@ -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;
@@ -97,6 +99,7 @@ public class Letterbox {
mDarkScrimAlphaSupplier = darkScrimAlphaSupplier;
mDoubleTapCallbackX = doubleTapCallbackX;
mDoubleTapCallbackY = doubleTapCallbackY;
+ mParentSurfaceSupplier = parentSurface;
}
/**
@@ -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.
*/
@@ -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();
@@ -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);
@@ -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);
}
}
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 57c60f4ffc33..a469c6b39e7f 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -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.
@@ -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() {
@@ -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;
@@ -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;
@@ -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;
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index c8ed602b0f1d..317c93e63459 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -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;
@@ -120,7 +120,7 @@ final class LetterboxUiController {
}
}
- boolean hasWallpaperBackgroudForLetterbox() {
+ boolean hasWallpaperBackgroundForLetterbox() {
return mShowWallpaperForLetterboxBackground;
}
@@ -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();
}
@@ -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);
}
}
@@ -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);
}
- mActivityRecord.getPosition(mTmpPoint);
+
+ 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
@@ -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
@@ -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);
}
@@ -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);
@@ -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);
@@ -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="
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index c7f8a1e2068a..f3670e49f01e 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -27,7 +27,10 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
import android.graphics.Insets;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.power.Boost;
@@ -374,43 +377,45 @@ class SurfaceAnimationRunner {
final int targetSurfaceWidth = bounds.width();
if (maxExtensionInsets.left < 0) {
- final Rect edgeBounds = new Rect(0, 0, 1, targetSurfaceHeight);
+ final Rect edgeBounds = new Rect(bounds.left, bounds.top, bounds.left + 1,
+ bounds.bottom);
final Rect extensionRect = new Rect(0, 0,
-maxExtensionInsets.left, targetSurfaceHeight);
- final int xPos = maxExtensionInsets.left;
- final int yPos = 0;
+ final int xPos = bounds.left + maxExtensionInsets.left;
+ final int yPos = bounds.top;
createExtensionSurface(leash, edgeBounds,
extensionRect, xPos, yPos, "Left Edge Extension", transaction);
}
if (maxExtensionInsets.top < 0) {
- final Rect edgeBounds = new Rect(0, 0, targetSurfaceWidth, 1);
+ final Rect edgeBounds = new Rect(bounds.left, bounds.top, targetSurfaceWidth,
+ bounds.top + 1);
final Rect extensionRect = new Rect(0, 0,
targetSurfaceWidth, -maxExtensionInsets.top);
- final int xPos = 0;
- final int yPos = maxExtensionInsets.top;
+ final int xPos = bounds.left;
+ final int yPos = bounds.top + maxExtensionInsets.top;
createExtensionSurface(leash, edgeBounds,
extensionRect, xPos, yPos, "Top Edge Extension", transaction);
}
if (maxExtensionInsets.right < 0) {
- final Rect edgeBounds = new Rect(targetSurfaceWidth - 1, 0,
- targetSurfaceWidth, targetSurfaceHeight);
+ final Rect edgeBounds = new Rect(bounds.right - 1, bounds.top, bounds.right,
+ bounds.bottom);
final Rect extensionRect = new Rect(0, 0,
-maxExtensionInsets.right, targetSurfaceHeight);
- final int xPos = targetSurfaceWidth;
- final int yPos = 0;
+ final int xPos = bounds.right;
+ final int yPos = bounds.top;
createExtensionSurface(leash, edgeBounds,
extensionRect, xPos, yPos, "Right Edge Extension", transaction);
}
if (maxExtensionInsets.bottom < 0) {
- final Rect edgeBounds = new Rect(0, targetSurfaceHeight - 1,
- targetSurfaceWidth, targetSurfaceHeight);
+ final Rect edgeBounds = new Rect(bounds.left, bounds.bottom - 1,
+ bounds.right, bounds.bottom);
final Rect extensionRect = new Rect(0, 0,
targetSurfaceWidth, -maxExtensionInsets.bottom);
- final int xPos = maxExtensionInsets.left;
- final int yPos = targetSurfaceHeight;
+ final int xPos = bounds.left;
+ final int yPos = bounds.bottom;
createExtensionSurface(leash, edgeBounds,
extensionRect, xPos, yPos, "Bottom Edge Extension", transaction);
}
@@ -453,17 +458,21 @@ class SurfaceAnimationRunner {
.setHidden(true)
.setCallsite("DefaultTransitionHandler#startAnimation")
.setOpaque(true)
- .setBufferSize(edgeBounds.width(), edgeBounds.height())
+ .setBufferSize(extensionRect.width(), extensionRect.height())
.build();
+ BitmapShader shader = new BitmapShader(edgeBuffer.asBitmap(),
+ android.graphics.Shader.TileMode.CLAMP,
+ android.graphics.Shader.TileMode.CLAMP);
+ final Paint paint = new Paint();
+ paint.setShader(shader);
+
final Surface surface = new Surface(edgeExtensionLayer);
- surface.attachAndQueueBufferWithColorSpace(edgeBuffer.getHardwareBuffer(),
- edgeBuffer.getColorSpace());
+ Canvas c = surface.lockHardwareCanvas();
+ c.drawRect(extensionRect, paint);
+ surface.unlockCanvasAndPost(c);
surface.release();
- final float scaleX = getScaleXForExtensionSurface(edgeBounds, extensionRect);
- final float scaleY = getScaleYForExtensionSurface(edgeBounds, extensionRect);
-
synchronized (mEdgeExtensionLock) {
if (!mEdgeExtensions.containsKey(leash)) {
// The animation leash has already been removed, so we don't want to attach the
@@ -472,7 +481,6 @@ class SurfaceAnimationRunner {
return;
}
- startTransaction.setScale(edgeExtensionLayer, scaleX, scaleY);
startTransaction.reparent(edgeExtensionLayer, leash);
startTransaction.setLayer(edgeExtensionLayer, Integer.MIN_VALUE);
startTransaction.setPosition(edgeExtensionLayer, xPos, yPos);
@@ -508,8 +516,6 @@ class SurfaceAnimationRunner {
throw new RuntimeException("Unexpected edgeBounds and extensionRect heights");
}
-
-
private static final class RunningAnimation {
final AnimationSpec mAnimSpec;
final SurfaceControl mLeash;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 25193d0b5ba3..797904890f74 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3015,6 +3015,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
final float windowCornerRadius = !inMultiWindowMode()
? getDisplayContent().getWindowCornerRadius()
: 0;
+ if (asActivityRecord() != null
+ && asActivityRecord().isNeedsLetterboxedAnimation()) {
+ asActivityRecord().getLetterboxInnerBounds(mTmpRect);
+ }
AnimationAdapter adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
getDisplayContent().mAppTransition.canSkipFirstFrame(),
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 45eb80613646..2432afbc03ef 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -6053,7 +6053,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
boolean hasWallpaperForLetterboxBackground() {
- return mActivityRecord != null && mActivityRecord.hasWallpaperBackgroudForLetterbox();
+ return mActivityRecord != null && mActivityRecord.hasWallpaperBackgroundForLetterbox();
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index e502f2fbd173..d400a4c9daca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -56,6 +56,7 @@ public class LetterboxTest {
private boolean mHasWallpaperBackground = false;
private int mBlurRadius = 0;
private float mDarkScrimAlpha = 0.5f;
+ private SurfaceControl mParentSurface = mock(SurfaceControl.class);
@Before
public void setUp() throws Exception {
@@ -63,7 +64,8 @@ public class LetterboxTest {
mLetterbox = new Letterbox(mSurfaces, StubTransaction::new,
() -> mAreCornersRounded, () -> Color.valueOf(mColor),
() -> mHasWallpaperBackground, () -> mBlurRadius, () -> mDarkScrimAlpha,
- /* doubleTapCallbackX= */ x -> {}, /* doubleTapCallbackY= */ y -> {});
+ /* doubleTapCallbackX= */ x -> {}, /* doubleTapCallbackY= */ y -> {},
+ () -> mParentSurface);
mTransaction = spy(StubTransaction.class);
}
@@ -205,6 +207,22 @@ public class LetterboxTest {
}
@Test
+ public void testNeedsApplySurfaceChanges_setParentSurface() {
+ mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
+ mLetterbox.applySurfaceChanges(mTransaction);
+
+ verify(mTransaction).reparent(mSurfaces.top, mParentSurface);
+ assertFalse(mLetterbox.needsApplySurfaceChanges());
+
+ mParentSurface = mock(SurfaceControl.class);
+
+ assertTrue(mLetterbox.needsApplySurfaceChanges());
+
+ mLetterbox.applySurfaceChanges(mTransaction);
+ verify(mTransaction).reparent(mSurfaces.top, mParentSurface);
+ }
+
+ @Test
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);