Merge "Polish activity transition for letterbox" into tm-qpr-dev am: c3a33cde83
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18320843 Change-Id: I92dc418580d4503ee80ae9d94520d4b5d2c92009 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 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) {
|
||||
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="
|
||||
|
||||
@@ -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,16 +458,20 @@ class SurfaceAnimationRunner {
|
||||
.setHidden(true)
|
||||
.setCallsite("DefaultTransitionHandler#startAnimation")
|
||||
.setOpaque(true)
|
||||
.setBufferSize(edgeBounds.width(), edgeBounds.height())
|
||||
.setBufferSize(extensionRect.width(), extensionRect.height())
|
||||
.build();
|
||||
|
||||
final Surface surface = new Surface(edgeExtensionLayer);
|
||||
surface.attachAndQueueBufferWithColorSpace(edgeBuffer.getHardwareBuffer(),
|
||||
edgeBuffer.getColorSpace());
|
||||
surface.release();
|
||||
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 float scaleX = getScaleXForExtensionSurface(edgeBounds, extensionRect);
|
||||
final float scaleY = getScaleYForExtensionSurface(edgeBounds, extensionRect);
|
||||
final Surface surface = new Surface(edgeExtensionLayer);
|
||||
Canvas c = surface.lockHardwareCanvas();
|
||||
c.drawRect(extensionRect, paint);
|
||||
surface.unlockCanvasAndPost(c);
|
||||
surface.release();
|
||||
|
||||
synchronized (mEdgeExtensionLock) {
|
||||
if (!mEdgeExtensions.containsKey(leash)) {
|
||||
@@ -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;
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -6053,7 +6053,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
boolean hasWallpaperForLetterboxBackground() {
|
||||
return mActivityRecord != null && mActivityRecord.hasWallpaperBackgroudForLetterbox();
|
||||
return mActivityRecord != null && mActivityRecord.hasWallpaperBackgroundForLetterbox();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -204,6 +206,22 @@ public class LetterboxTest {
|
||||
verify(mTransaction).setAlpha(mSurfaces.fullWindowSurface, mDarkScrimAlpha);
|
||||
}
|
||||
|
||||
@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));
|
||||
|
||||
Reference in New Issue
Block a user