diff options
8 files changed, 901 insertions, 787 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index efe2961f3d2f..2bcc35b50b5b 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -189,6 +189,7 @@ import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; +import static com.android.server.wm.LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; @@ -215,14 +216,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_SOLID_COLOR; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_WALLPAPER; -import static com.android.server.wm.WindowManagerService.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; -import static com.android.server.wm.WindowManagerService.letterboxBackgroundTypeToString; import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY; import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_BEFORE_ANIM; @@ -268,7 +263,6 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; @@ -344,7 +338,6 @@ import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.Task.ActivityState; import com.android.server.wm.WindowManagerService.H; -import com.android.server.wm.WindowManagerService.LetterboxBackgroundType; import com.android.server.wm.utils.InsetUtils; import com.google.android.collect.Sets; @@ -642,7 +635,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ private boolean mWillCloseOrEnterPip; - private Letterbox mLetterbox; + @VisibleForTesting + final LetterboxUiController mLetterboxUiController; /** * The scale to fit at least one side of the activity to its parent. If the activity uses @@ -671,8 +665,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Nullable private Rect mLetterboxBoundsForFixedOrientationAndAspectRatio; - private boolean mShowWallpaperForLetterboxBackground; - // activity is not displayed? // TODO: rename to mNoDisplay @VisibleForTesting @@ -1097,61 +1089,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - dumpLetterboxInfo(pw, prefix); - } - - private void dumpLetterboxInfo(PrintWriter pw, String prefix) { - final WindowState mainWin = findMainWindow(); - if (mainWin == null) { - return; - } - - boolean areBoundsLetterboxed = mainWin.isLetterboxedAppWindow(); - pw.println(prefix + "areBoundsLetterboxed=" + areBoundsLetterboxed); - if (!areBoundsLetterboxed) { - return; - } - - pw.println(prefix + " letterboxReason=" + getLetterboxReasonString(mainWin)); - pw.println(prefix + " letterboxAspectRatio=" + computeAspectRatio(getBounds())); - - boolean isLetterboxUiShown = isLetterboxed(mainWin); - pw.println(prefix + "isLetterboxUiShown=" + isLetterboxUiShown); - - if (!isLetterboxUiShown) { - return; - } - pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString( - getLetterboxBackgroundColor().toArgb())); - pw.println(prefix + " letterboxBackgroundType=" - + letterboxBackgroundTypeToString(mWmService.getLetterboxBackgroundType())); - if (mWmService.getLetterboxBackgroundType() == LETTERBOX_BACKGROUND_WALLPAPER) { - pw.println(prefix + " isLetterboxWallpaperBlurSupported=" - + isLetterboxWallpaperBlurSupported()); - pw.println(prefix + " letterboxBackgroundWallpaperDarkScrimAlpha=" - + getLetterboxWallpaperDarkScrimAlpha()); - pw.println(prefix + " letterboxBackgroundWallpaperBlurRadius=" - + getLetterboxWallpaperBlurRadius()); - } - pw.println(prefix + " letterboxHorizontalPositionMultiplier=" - + mWmService.getLetterboxHorizontalPositionMultiplier()); - } - - /** - * Returns a string representing the reason for letterboxing. This method assumes the activity - * is letterboxed. - */ - private String getLetterboxReasonString(WindowState mainWin) { - if (inSizeCompatMode()) { - return "SIZE_COMPAT_MODE"; - } - if (isLetterboxedForFixedOrientationAndAspectRatio()) { - return "FIXED_ORIENTATION"; - } - if (mainWin.isLetterboxedForDisplayCutout()) { - return "DISPLAY_CUTOUT"; - } - return "UNKNOWN_REASON"; + mLetterboxUiController.dump(pw, prefix); } void setAppTimeTracker(AppTimeTracker att) { @@ -1417,183 +1355,29 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - if (mLetterbox != null) { - mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId()); - } + mLetterboxUiController.onMovedToDisplay(mDisplayContent.getDisplayId()); } - // TODO(b/183754168): Move letterbox UI logic into a separate class. void layoutLetterbox(WindowState winHint) { - final WindowState w = findMainWindow(); - if (w == null || winHint != null && w != winHint) { - return; - } - final boolean surfaceReady = w.isDrawn() // Regular case - || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface. - final boolean needsLetterbox = surfaceReady && isLetterboxed(w); - updateRoundedCorners(w); - updateWallpaperForLetterbox(w); - if (needsLetterbox) { - if (mLetterbox == null) { - mLetterbox = new Letterbox(() -> makeChildSurface(null), - mWmService.mTransactionFactory, - mWmService::isLetterboxActivityCornersRounded, - this::getLetterboxBackgroundColor, - this::hasWallpaperBackgroudForLetterbox, - this::getLetterboxWallpaperBlurRadius, - this::getLetterboxWallpaperDarkScrimAlpha); - mLetterbox.attachInput(w); - } - 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 - // (since the orientation letterbox is also applied to the task). - final Rect transformedBounds = getFixedRotationTransformDisplayBounds(); - final Rect spaceToFill = transformedBounds != null - ? transformedBounds - : inMultiWindowMode() - ? getRootTask().getBounds() - : getRootTask().getParent().getBounds(); - mLetterbox.layout(spaceToFill, w.getFrame(), mTmpPoint); - } else if (mLetterbox != null) { - mLetterbox.hide(); - } - } - - private Color getLetterboxBackgroundColor() { - final WindowState w = findMainWindow(); - if (w == null || w.isLetterboxedForDisplayCutout()) { - return Color.valueOf(Color.BLACK); - } - @LetterboxBackgroundType int letterboxBackgroundType = - mWmService.getLetterboxBackgroundType(); - switch (letterboxBackgroundType) { - case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING: - if (taskDescription != null && taskDescription.getBackgroundColorFloating() != 0) { - return Color.valueOf(taskDescription.getBackgroundColorFloating()); - } - break; - case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: - if (taskDescription != null && taskDescription.getBackgroundColor() != 0) { - return Color.valueOf(taskDescription.getBackgroundColor()); - } - break; - case LETTERBOX_BACKGROUND_WALLPAPER: - if (hasWallpaperBackgroudForLetterbox()) { - // Color is used for translucent scrim that dims wallpaper. - return Color.valueOf(Color.BLACK); - } - Slog.w(TAG, "Wallpaper option is selected for letterbox background but " - + "blur is not supported by a device or not supported in the current " - + "window configuration or both alpha scrim and blur radius aren't " - + "provided so using solid color background"); - break; - case LETTERBOX_BACKGROUND_SOLID_COLOR: - return mWmService.getLetterboxBackgroundColor(); - default: - throw new AssertionError( - "Unexpected letterbox background type: " + letterboxBackgroundType); - } - // If picked option configured incorrectly or not supported then default to a solid color - // background. - return mWmService.getLetterboxBackgroundColor(); - } - - /** - * @return {@code true} when the main window is letterboxed, this activity isn't transparent - * and doesn't show a wallpaper. - */ - @VisibleForTesting - boolean isLetterboxed(WindowState mainWindow) { - return mainWindow.isLetterboxedAppWindow() && fillsParent() - // Check for FLAG_SHOW_WALLPAPER explicitly instead of using - // WindowContainer#showWallpaper because the later will return true when this - // activity is using blurred wallpaper for letterbox backgroud. - && (mainWindow.mAttrs.flags & FLAG_SHOW_WALLPAPER) == 0; - } - - private void updateRoundedCorners(WindowState mainWindow) { - int cornersRadius = - // Don't round corners if letterboxed only for display cutout. - isLetterboxed(mainWindow) && !mainWindow.isLetterboxedForDisplayCutout() - ? Math.max(0, mWmService.getLetterboxActivityCornersRadius()) : 0; - setCornersRadius(mainWindow, cornersRadius); - } - - private void setCornersRadius(WindowState mainWindow, int cornersRadius) { - final SurfaceControl windowSurface = mainWindow.getClientViewRootSurface(); - if (windowSurface != null && windowSurface.isValid()) { - Transaction transaction = getSyncTransaction(); - transaction.setCornerRadius(windowSurface, cornersRadius); - } + mLetterboxUiController.layoutLetterbox(winHint); } boolean hasWallpaperBackgroudForLetterbox() { - return mShowWallpaperForLetterboxBackground; - } - - private void updateWallpaperForLetterbox(WindowState mainWindow) { - @LetterboxBackgroundType int letterboxBackgroundType = - mWmService.getLetterboxBackgroundType(); - boolean wallpaperShouldBeShown = - letterboxBackgroundType == LETTERBOX_BACKGROUND_WALLPAPER - && isLetterboxed(mainWindow) - // Don't use wallpaper as a background if letterboxed for display cutout. - && !mainWindow.isLetterboxedForDisplayCutout() - // Check that dark scrim alpha or blur radius are provided - && (getLetterboxWallpaperBlurRadius() > 0 - || getLetterboxWallpaperDarkScrimAlpha() > 0) - // Check that blur is supported by a device if blur radius is provided. - && (getLetterboxWallpaperBlurRadius() <= 0 - || isLetterboxWallpaperBlurSupported()); - if (mShowWallpaperForLetterboxBackground != wallpaperShouldBeShown) { - mShowWallpaperForLetterboxBackground = wallpaperShouldBeShown; - requestUpdateWallpaperIfNeeded(); - } - } - - private int getLetterboxWallpaperBlurRadius() { - int blurRadius = mWmService.getLetterboxBackgroundWallpaperBlurRadius(); - return blurRadius < 0 ? 0 : blurRadius; - } - - private float getLetterboxWallpaperDarkScrimAlpha() { - float alpha = mWmService.getLetterboxBackgroundWallpaperDarkScrimAlpha(); - // No scrim by default. - return (alpha < 0 || alpha >= 1) ? 0.0f : alpha; - } - - private boolean isLetterboxWallpaperBlurSupported() { - return mWmService.mContext.getSystemService(WindowManager.class).isCrossWindowBlurEnabled(); + return mLetterboxUiController.hasWallpaperBackgroudForLetterbox(); } void updateLetterboxSurface(WindowState winHint) { - final WindowState w = findMainWindow(); - if (w != winHint && winHint != null && w != null) { - return; - } - layoutLetterbox(winHint); - if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) { - mLetterbox.applySurfaceChanges(getSyncTransaction()); - } + mLetterboxUiController.updateLetterboxSurface(winHint); } + /** Gets the letterbox insets. The insets will be empty if there is no letterbox. */ Rect getLetterboxInsets() { - if (mLetterbox != null) { - return mLetterbox.getInsets(); - } else { - return new Rect(); - } + return mLetterboxUiController.getLetterboxInsets(); } /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */ void getLetterboxInnerBounds(Rect outBounds) { - if (mLetterbox != null) { - outBounds.set(mLetterbox.getInnerFrame()); - } else { - outBounds.setEmpty(); - } + mLetterboxUiController.getLetterboxInnerBounds(outBounds); } /** @@ -1601,7 +1385,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * when the current activity is displayed. */ boolean isFullyTransparentBarAllowed(Rect rect) { - return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect); + return mLetterboxUiController.isFullyTransparentBarAllowed(rect); } /** @@ -1609,7 +1393,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * the given {@code rect}. */ boolean isLetterboxOverlappingWith(Rect rect) { - return mLetterbox != null && mLetterbox.isOverlappingWith(rect); + return mLetterboxUiController.isLetterboxOverlappingWith(rect); } static class Token extends IApplicationToken.Stub { @@ -1858,6 +1642,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mPersistentState = persistentState; taskDescription = _taskDescription; + + mLetterboxUiController = new LetterboxUiController(mWmService, this); + if (_createTime > 0) { createTime = _createTime; } @@ -3689,10 +3476,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A dc.setFocusedApp(null); mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); } - if (mLetterbox != null) { - mLetterbox.destroy(); - mLetterbox = null; - } + + mLetterboxUiController.destroy(); if (!delayed) { updateReportedVisibilityLocked(); @@ -7113,7 +6898,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A offsetX = getHorizontalCenterOffset( parentAppBounds.width(), screenResolvedBounds.width()); } else { - float positionMultiplier = mWmService.getLetterboxHorizontalPositionMultiplier(); + float positionMultiplier = + mWmService.mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier(); positionMultiplier = (positionMultiplier < 0.0f || positionMultiplier > 1.0f) // Default to central position if invalid value is provided. @@ -7186,7 +6972,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with // set-fixed-orientation-letterbox-aspect-ratio. final float letterboxAspectRatioOverride = - mWmService.getFixedOrientationLetterboxAspectRatio(); + mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspect; @@ -7704,7 +7490,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A /** * Returns the aspect ratio of the given {@code rect}. */ - private static float computeAspectRatio(Rect rect) { + static float computeAspectRatio(Rect rect) { final int width = rect.width(); final int height = rect.height(); if (width == 0 || height == 0) { diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java new file mode 100644 index 000000000000..eb7087cbc722 --- /dev/null +++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.annotation.IntDef; +import android.content.Context; +import android.graphics.Color; + +import com.android.internal.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** Reads letterbox configs from resources and controls their overrides at runtime. */ +final class LetterboxConfiguration { + + /** + * Override of aspect ratio for fixed orientation letterboxing that is set via ADB with + * set-fixed-orientation-letterbox-aspect-ratio or via {@link + * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored + * if it is <= this value. + */ + static final float MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO = 1.0f; + + /** Enum for Letterbox background type. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({LETTERBOX_BACKGROUND_SOLID_COLOR, LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND, + LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING, LETTERBOX_BACKGROUND_WALLPAPER}) + @interface LetterboxBackgroundType {}; + /** Solid background using color specified in R.color.config_letterboxBackgroundColor. */ + static final int LETTERBOX_BACKGROUND_SOLID_COLOR = 0; + + /** Color specified in R.attr.colorBackground for the letterboxed application. */ + static final int LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND = 1; + + /** Color specified in R.attr.colorBackgroundFloating for the letterboxed application. */ + static final int LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING = 2; + + /** Using wallpaper as a background which can be blurred or dimmed with dark scrim. */ + static final int LETTERBOX_BACKGROUND_WALLPAPER = 3; + + final Context mContext; + + // Aspect ratio of letterbox for fixed orientation, values <= + // MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO will be ignored. + private float mFixedOrientationLetterboxAspectRatio; + + // Corners radius for activities presented in the letterbox mode, values < 0 will be ignored. + private int mLetterboxActivityCornersRadius; + + // Color for {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} letterbox background type. + private Color mLetterboxBackgroundColor; + + @LetterboxBackgroundType + private int mLetterboxBackgroundType; + + // Blur radius for LETTERBOX_BACKGROUND_WALLPAPER option in mLetterboxBackgroundType. + // Values <= 0 are ignored and 0 is used instead. + private int mLetterboxBackgroundWallpaperBlurRadius; + + // Alpha of a black scrim shown over wallpaper letterbox background when + // LETTERBOX_BACKGROUND_WALLPAPER option is selected for mLetterboxBackgroundType. + // Values < 0 or >= 1 are ignored and 0.0 (transparent) is used instead. + private float mLetterboxBackgroundWallpaperDarkScrimAlpha; + + // Horizontal position of a center of the letterboxed app window. 0 corresponds to the left + // side of the screen and 1.0 to the right side. + private float mLetterboxHorizontalPositionMultiplier; + + LetterboxConfiguration(Context context) { + mContext = context; + mFixedOrientationLetterboxAspectRatio = context.getResources().getFloat( + R.dimen.config_fixedOrientationLetterboxAspectRatio); + mLetterboxActivityCornersRadius = context.getResources().getInteger( + R.integer.config_letterboxActivityCornersRadius); + mLetterboxBackgroundColor = Color.valueOf(context.getResources().getColor( + R.color.config_letterboxBackgroundColor)); + mLetterboxBackgroundType = readLetterboxBackgroundTypeFromConfig(context); + mLetterboxBackgroundWallpaperBlurRadius = context.getResources().getDimensionPixelSize( + R.dimen.config_letterboxBackgroundWallpaperBlurRadius); + mLetterboxBackgroundWallpaperDarkScrimAlpha = context.getResources().getFloat( + R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha); + mLetterboxHorizontalPositionMultiplier = context.getResources().getFloat( + R.dimen.config_letterboxHorizontalPositionMultiplier); + } + + /** + * Overrides the aspect ratio of letterbox for fixed orientation. If given value is <= {@link + * #MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO}, both it and a value of {@link + * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored and + * the framework implementation will be used to determine the aspect ratio. + */ + void setFixedOrientationLetterboxAspectRatio(float aspectRatio) { + mFixedOrientationLetterboxAspectRatio = aspectRatio; + } + + /** + * Resets the aspect ratio of letterbox for fixed orientation to {@link + * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio}. + */ + void resetFixedOrientationLetterboxAspectRatio() { + mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio); + } + + /** + * Gets the aspect ratio of letterbox for fixed orientation. + */ + float getFixedOrientationLetterboxAspectRatio() { + return mFixedOrientationLetterboxAspectRatio; + } + + /** + * Overrides corners raidus 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 + * and corners of the activity won't be rounded. + */ + void setLetterboxActivityCornersRadius(int cornersRadius) { + mLetterboxActivityCornersRadius = cornersRadius; + } + + /** + * Resets corners raidus for activities presented in the letterbox mode to {@link + * com.android.internal.R.integer.config_letterboxActivityCornersRadius}. + */ + void resetLetterboxActivityCornersRadius() { + mLetterboxActivityCornersRadius = mContext.getResources().getInteger( + com.android.internal.R.integer.config_letterboxActivityCornersRadius); + } + + /** + * Whether corners of letterboxed activities are rounded. + */ + boolean isLetterboxActivityCornersRounded() { + return getLetterboxActivityCornersRadius() > 0; + } + + /** + * Gets corners raidus for activities presented in the letterbox mode. + */ + int getLetterboxActivityCornersRadius() { + return mLetterboxActivityCornersRadius; + } + + /** + * Gets color of letterbox background which is used when {@link + * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as + * fallback for other backfround types. + */ + Color getLetterboxBackgroundColor() { + return mLetterboxBackgroundColor; + } + + + /** + * Sets color of letterbox background which is used when {@link + * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as + * fallback for other backfround types. + */ + void setLetterboxBackgroundColor(Color color) { + mLetterboxBackgroundColor = color; + } + + /** + * Resets color of letterbox background to {@link + * com.android.internal.R.color.config_letterboxBackgroundColor}. + */ + void resetLetterboxBackgroundColor() { + mLetterboxBackgroundColor = Color.valueOf(mContext.getResources().getColor( + com.android.internal.R.color.config_letterboxBackgroundColor)); + } + + /** + * Gets {@link LetterboxBackgroundType} specified in {@link + * com.android.internal.R.integer.config_letterboxBackgroundType} or over via ADB command. + */ + @LetterboxBackgroundType + int getLetterboxBackgroundType() { + return mLetterboxBackgroundType; + } + + /** Sets letterbox background type. */ + void setLetterboxBackgroundType(@LetterboxBackgroundType int backgroundType) { + mLetterboxBackgroundType = backgroundType; + } + + /** + * Resets cletterbox background type to {@link + * com.android.internal.R.integer.config_letterboxBackgroundType}. + */ + void resetLetterboxBackgroundType() { + mLetterboxBackgroundType = readLetterboxBackgroundTypeFromConfig(mContext); + } + + /** Returns a string representing the given {@link LetterboxBackgroundType}. */ + static String letterboxBackgroundTypeToString( + @LetterboxBackgroundType int backgroundType) { + switch (backgroundType) { + case LETTERBOX_BACKGROUND_SOLID_COLOR: + return "LETTERBOX_BACKGROUND_SOLID_COLOR"; + case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: + return "LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND"; + case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING: + return "LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING"; + case LETTERBOX_BACKGROUND_WALLPAPER: + return "LETTERBOX_BACKGROUND_WALLPAPER"; + default: + return "unknown=" + backgroundType; + } + } + + @LetterboxBackgroundType + private static int readLetterboxBackgroundTypeFromConfig(Context context) { + int backgroundType = context.getResources().getInteger( + com.android.internal.R.integer.config_letterboxBackgroundType); + return backgroundType == LETTERBOX_BACKGROUND_SOLID_COLOR + || backgroundType == LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND + || backgroundType == LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING + || backgroundType == LETTERBOX_BACKGROUND_WALLPAPER + ? backgroundType : LETTERBOX_BACKGROUND_SOLID_COLOR; + } + + /** + * Overrides alpha of a black scrim shown over wallpaper for {@link + * #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link mLetterboxBackgroundType}. + * + * <p>If given value is < 0 or >= 1, both it and a value of {@link + * com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha} are ignored + * and 0.0 (transparent) is instead. + */ + void setLetterboxBackgroundWallpaperDarkScrimAlpha(float alpha) { + mLetterboxBackgroundWallpaperDarkScrimAlpha = alpha; + } + + /** + * Resets alpha of a black scrim shown over wallpaper letterbox background to {@link + * com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha}. + */ + void resetLetterboxBackgroundWallpaperDarkScrimAlpha() { + mLetterboxBackgroundWallpaperDarkScrimAlpha = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha); + } + + /** + * Gets alpha of a black scrim shown over wallpaper letterbox background. + */ + float getLetterboxBackgroundWallpaperDarkScrimAlpha() { + return mLetterboxBackgroundWallpaperDarkScrimAlpha; + } + + /** + * Overrides blur radius for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in + * {@link mLetterboxBackgroundType}. + * + * <p> If given value <= 0, both it and a value of {@link + * com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius} are ignored + * and 0 is used instead. + */ + void setLetterboxBackgroundWallpaperBlurRadius(int radius) { + mLetterboxBackgroundWallpaperBlurRadius = radius; + } + + /** + * Resets blur raidus for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link + * mLetterboxBackgroundType} to {@link + * com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius}. + */ + void resetLetterboxBackgroundWallpaperBlurRadius() { + mLetterboxBackgroundWallpaperBlurRadius = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius); + } + + /** + * Gets blur raidus for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link + * mLetterboxBackgroundType}. + */ + int getLetterboxBackgroundWallpaperBlurRadius() { + return mLetterboxBackgroundWallpaperBlurRadius; + } + + /* + * Gets horizontal position of a center of the letterboxed app window specified + * in {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier} + * or via an ADB command. 0 corresponds to the left side of the screen and 1 to the + * right side. + * + * <p>This value can be outside of [0, 1] range so clients need to check and default to the + * central position (0.5). + */ + float getLetterboxHorizontalPositionMultiplier() { + return mLetterboxHorizontalPositionMultiplier; + } + + /** + * Overrides horizontal position of a center of the letterboxed app window. If given value < 0 + * or > 1, then it and a value of {@link + * com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier} are ignored and + * central position (0.5) is used. + */ + void setLetterboxHorizontalPositionMultiplier(float multiplier) { + mLetterboxHorizontalPositionMultiplier = multiplier; + } + + /** + * Resets horizontal position of a center of the letterboxed app window to {@link + * com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier}. + */ + void resetLetterboxHorizontalPositionMultiplier() { + mLetterboxHorizontalPositionMultiplier = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier); + } + +} diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java new file mode 100644 index 000000000000..130f68097331 --- /dev/null +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; + +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; +import static com.android.server.wm.LetterboxConfiguration.letterboxBackgroundTypeToString; + +import android.annotation.Nullable; +import android.app.ActivityManager.TaskDescription; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.Rect; +import android.util.Slog; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; +import android.view.WindowManager; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; + +import java.io.PrintWriter; + +/** Controls behaviour of the letterbox UI for {@link mActivityRecord}. */ +// TODO(b/185262487): Improve test coverage of this class. Parts of it are tested in +// SizeCompatTests and LetterboxTests but not all. +// TODO(b/185264020): Consider making LetterboxUiController applicable to any level of the +// hierarchy in addition to ActivityRecord (Task, DisplayArea, ...). +final class LetterboxUiController { + + private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM; + + private final Point mTmpPoint = new Point(); + + private final LetterboxConfiguration mLetterboxConfiguration; + private final ActivityRecord mActivityRecord; + + private boolean mShowWallpaperForLetterboxBackground; + + @Nullable + private Letterbox mLetterbox; + + LetterboxUiController(WindowManagerService wmService, ActivityRecord activityRecord) { + mLetterboxConfiguration = wmService.mLetterboxConfiguration; + // Given activityRecord may not be fully constructed since LetterboxUiController + // is created in its constructor. It shouldn't be used in this constructor but it's safe + // to use it after since controller is only used in ActivityRecord. + mActivityRecord = activityRecord; + } + + /** Cleans up {@link Letterbox} if it exists.*/ + void destroy() { + if (mLetterbox != null) { + mLetterbox.destroy(); + mLetterbox = null; + } + } + + void onMovedToDisplay(int displayId) { + if (mLetterbox != null) { + mLetterbox.onMovedToDisplay(displayId); + } + } + + boolean hasWallpaperBackgroudForLetterbox() { + return mShowWallpaperForLetterboxBackground; + } + + /** Gets the letterbox insets. The insets will be empty if there is no letterbox. */ + Rect getLetterboxInsets() { + if (mLetterbox != null) { + return mLetterbox.getInsets(); + } else { + return new Rect(); + } + } + + /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */ + void getLetterboxInnerBounds(Rect outBounds) { + if (mLetterbox != null) { + outBounds.set(mLetterbox.getInnerFrame()); + } else { + outBounds.setEmpty(); + } + } + + /** + * @return {@code true} if bar shown within a given rectangle is allowed to be fully transparent + * when the current activity is displayed. + */ + boolean isFullyTransparentBarAllowed(Rect rect) { + return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect); + } + + /** + * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with + * the given {@code rect}. + */ + boolean isLetterboxOverlappingWith(Rect rect) { + return mLetterbox != null && mLetterbox.isOverlappingWith(rect); + } + + void updateLetterboxSurface(WindowState winHint) { + final WindowState w = mActivityRecord.findMainWindow(); + if (w != winHint && winHint != null && w != null) { + return; + } + layoutLetterbox(winHint); + if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) { + mLetterbox.applySurfaceChanges(mActivityRecord.getSyncTransaction()); + } + } + + void layoutLetterbox(WindowState winHint) { + final WindowState w = mActivityRecord.findMainWindow(); + if (w == null || winHint != null && w != winHint) { + return; + } + final boolean surfaceReady = w.isDrawn() // Regular case + || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface. + final boolean needsLetterbox = surfaceReady && isLetterboxed(w); + updateRoundedCorners(w); + updateWallpaperForLetterbox(w); + if (needsLetterbox) { + if (mLetterbox == null) { + mLetterbox = new Letterbox(() -> mActivityRecord.makeChildSurface(null), + mActivityRecord.mWmService.mTransactionFactory, + mLetterboxConfiguration::isLetterboxActivityCornersRounded, + this::getLetterboxBackgroundColor, + this::hasWallpaperBackgroudForLetterbox, + this::getLetterboxWallpaperBlurRadius, + this::getLetterboxWallpaperDarkScrimAlpha); + mLetterbox.attachInput(w); + } + 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 + // (since the orientation letterbox is also applied to the task). + final Rect transformedBounds = mActivityRecord.getFixedRotationTransformDisplayBounds(); + final Rect spaceToFill = transformedBounds != null + ? transformedBounds + : mActivityRecord.inMultiWindowMode() + ? mActivityRecord.getRootTask().getBounds() + : mActivityRecord.getRootTask().getParent().getBounds(); + mLetterbox.layout(spaceToFill, w.getFrame(), mTmpPoint); + } else if (mLetterbox != null) { + mLetterbox.hide(); + } + } + + /** + * @return {@code true} when the main window is letterboxed, this activity isn't transparent + * and doesn't show a wallpaper. + */ + @VisibleForTesting + boolean isLetterboxed(WindowState mainWindow) { + return mainWindow.isLetterboxedAppWindow() && mActivityRecord.fillsParent() + // Check for FLAG_SHOW_WALLPAPER explicitly instead of using + // WindowContainer#showWallpaper because the later will return true when this + // activity is using blurred wallpaper for letterbox backgroud. + && (mainWindow.mAttrs.flags & FLAG_SHOW_WALLPAPER) == 0; + } + + private Color getLetterboxBackgroundColor() { + final WindowState w = mActivityRecord.findMainWindow(); + if (w == null || w.isLetterboxedForDisplayCutout()) { + return Color.valueOf(Color.BLACK); + } + @LetterboxBackgroundType int letterboxBackgroundType = + mLetterboxConfiguration.getLetterboxBackgroundType(); + TaskDescription taskDescription = mActivityRecord.taskDescription; + switch (letterboxBackgroundType) { + case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING: + if (taskDescription != null && taskDescription.getBackgroundColorFloating() != 0) { + return Color.valueOf(taskDescription.getBackgroundColorFloating()); + } + break; + case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: + if (taskDescription != null && taskDescription.getBackgroundColor() != 0) { + return Color.valueOf(taskDescription.getBackgroundColor()); + } + break; + case LETTERBOX_BACKGROUND_WALLPAPER: + if (hasWallpaperBackgroudForLetterbox()) { + // Color is used for translucent scrim that dims wallpaper. + return Color.valueOf(Color.BLACK); + } + Slog.w(TAG, "Wallpaper option is selected for letterbox background but " + + "blur is not supported by a device or not supported in the current " + + "window configuration or both alpha scrim and blur radius aren't " + + "provided so using solid color background"); + break; + case LETTERBOX_BACKGROUND_SOLID_COLOR: + return mLetterboxConfiguration.getLetterboxBackgroundColor(); + default: + throw new AssertionError( + "Unexpected letterbox background type: " + letterboxBackgroundType); + } + // If picked option configured incorrectly or not supported then default to a solid color + // background. + return mLetterboxConfiguration.getLetterboxBackgroundColor(); + } + + private void updateRoundedCorners(WindowState mainWindow) { + int cornersRadius = + // Don't round corners if letterboxed only for display cutout. + isLetterboxed(mainWindow) + && !mainWindow.isLetterboxedForDisplayCutout() + ? Math.max(0, mLetterboxConfiguration.getLetterboxActivityCornersRadius()) + : 0; + setCornersRadius(mainWindow, cornersRadius); + } + + private void setCornersRadius(WindowState mainWindow, int cornersRadius) { + final SurfaceControl windowSurface = mainWindow.getClientViewRootSurface(); + if (windowSurface != null && windowSurface.isValid()) { + Transaction transaction = mActivityRecord.getSyncTransaction(); + transaction.setCornerRadius(windowSurface, cornersRadius); + } + } + + private void updateWallpaperForLetterbox(WindowState mainWindow) { + @LetterboxBackgroundType int letterboxBackgroundType = + mLetterboxConfiguration.getLetterboxBackgroundType(); + boolean wallpaperShouldBeShown = + letterboxBackgroundType == LETTERBOX_BACKGROUND_WALLPAPER + && isLetterboxed(mainWindow) + // Don't use wallpaper as a background if letterboxed for display cutout. + && !mainWindow.isLetterboxedForDisplayCutout() + // Check that dark scrim alpha or blur radius are provided + && (getLetterboxWallpaperBlurRadius() > 0 + || getLetterboxWallpaperDarkScrimAlpha() > 0) + // Check that blur is supported by a device if blur radius is provided. + && (getLetterboxWallpaperBlurRadius() <= 0 + || isLetterboxWallpaperBlurSupported()); + if (mShowWallpaperForLetterboxBackground != wallpaperShouldBeShown) { + mShowWallpaperForLetterboxBackground = wallpaperShouldBeShown; + mActivityRecord.requestUpdateWallpaperIfNeeded(); + } + } + + private int getLetterboxWallpaperBlurRadius() { + int blurRadius = mLetterboxConfiguration.getLetterboxBackgroundWallpaperBlurRadius(); + return blurRadius < 0 ? 0 : blurRadius; + } + + private float getLetterboxWallpaperDarkScrimAlpha() { + float alpha = mLetterboxConfiguration.getLetterboxBackgroundWallpaperDarkScrimAlpha(); + // No scrim by default. + return (alpha < 0 || alpha >= 1) ? 0.0f : alpha; + } + + private boolean isLetterboxWallpaperBlurSupported() { + return mLetterboxConfiguration.mContext.getSystemService(WindowManager.class) + .isCrossWindowBlurEnabled(); + } + + void dump(PrintWriter pw, String prefix) { + final WindowState mainWin = mActivityRecord.findMainWindow(); + if (mainWin == null) { + return; + } + + boolean areBoundsLetterboxed = mainWin.isLetterboxedAppWindow(); + pw.println(prefix + "areBoundsLetterboxed=" + areBoundsLetterboxed); + if (!areBoundsLetterboxed) { + return; + } + + pw.println(prefix + " letterboxReason=" + getLetterboxReasonString(mainWin)); + pw.println(prefix + " letterboxAspectRatio=" + + mActivityRecord.computeAspectRatio(mActivityRecord.getBounds())); + + boolean isLetterboxUiShown = isLetterboxed(mainWin); + pw.println(prefix + "isLetterboxUiShown=" + isLetterboxUiShown); + + if (!isLetterboxUiShown) { + return; + } + pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString( + getLetterboxBackgroundColor().toArgb())); + pw.println(prefix + " letterboxBackgroundType=" + + letterboxBackgroundTypeToString( + mLetterboxConfiguration.getLetterboxBackgroundType())); + if (mLetterboxConfiguration.getLetterboxBackgroundType() + == LETTERBOX_BACKGROUND_WALLPAPER) { + pw.println(prefix + " isLetterboxWallpaperBlurSupported=" + + isLetterboxWallpaperBlurSupported()); + pw.println(prefix + " letterboxBackgroundWallpaperDarkScrimAlpha=" + + getLetterboxWallpaperDarkScrimAlpha()); + pw.println(prefix + " letterboxBackgroundWallpaperBlurRadius=" + + getLetterboxWallpaperBlurRadius()); + } + pw.println(prefix + " letterboxHorizontalPositionMultiplier=" + + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier()); + } + + /** + * Returns a string representing the reason for letterboxing. This method assumes the activity + * is letterboxed. + */ + private String getLetterboxReasonString(WindowState mainWin) { + if (mActivityRecord.inSizeCompatMode()) { + return "SIZE_COMPAT_MODE"; + } + if (mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio()) { + return "FIXED_ORIENTATION"; + } + if (mainWin.isLetterboxedForDisplayCutout()) { + return "DISPLAY_CUTOUT"; + } + return "UNKNOWN_REASON"; + } + +} diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 959c6946053a..37765d70b916 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -159,7 +159,6 @@ import android.content.res.Configuration; import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.Bitmap; -import android.graphics.Color; import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.Point; @@ -977,56 +976,7 @@ public class WindowManagerService extends IWindowManager.Stub private boolean mAnimationsDisabled = false; boolean mPointerLocationEnabled = false; - /** - * Override of aspect ratio for fixed orientation letterboxing that is set via ADB with - * set-fixed-orientation-letterbox-aspect-ratio or via {@link - * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored - * if it is <= this value. - */ - static final float MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO = 1.0f; - - /** Enum for Letterbox background type. */ - @Retention(RetentionPolicy.SOURCE) - @IntDef({LETTERBOX_BACKGROUND_SOLID_COLOR, LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND, - LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING, LETTERBOX_BACKGROUND_WALLPAPER}) - @interface LetterboxBackgroundType {}; - /** Solid background using color specified in R.color.config_letterboxBackgroundColor. */ - static final int LETTERBOX_BACKGROUND_SOLID_COLOR = 0; - - /** Color specified in R.attr.colorBackground for the letterboxed application. */ - static final int LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND = 1; - - /** Color specified in R.attr.colorBackgroundFloating for the letterboxed application. */ - static final int LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING = 2; - - /** Using wallpaper as a background which can be blurred or dimmed with dark scrim. */ - static final int LETTERBOX_BACKGROUND_WALLPAPER = 3; - - // Aspect ratio of letterbox for fixed orientation, values <= - // MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO will be ignored. - private float mFixedOrientationLetterboxAspectRatio; - - // Corners radius for activities presented in the letterbox mode, values < 0 will be ignored. - private int mLetterboxActivityCornersRadius; - - // Color for {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} letterbox background type. - private Color mLetterboxBackgroundColor; - - @LetterboxBackgroundType - private int mLetterboxBackgroundType; - - // Blur radius for LETTERBOX_BACKGROUND_WALLPAPER option in mLetterboxBackgroundType. - // Values <= 0 are ignored and 0 is used instead. - private int mLetterboxBackgroundWallpaperBlurRadius; - - // Alpha of a black scrim shown over wallpaper letterbox background when - // LETTERBOX_BACKGROUND_WALLPAPER option is selected for mLetterboxBackgroundType. - // Values < 0 or >= 1 are ignored and 0.0 (transparent) is used instead. - private float mLetterboxBackgroundWallpaperDarkScrimAlpha; - - // horizontal position of a center of the letterboxed app window. 0 corresponds to the left - // side of the screen and 1.0 to the right side. - private float mLetterboxHorizontalPositionMultiplier; + final LetterboxConfiguration mLetterboxConfiguration; final InputManagerService mInputManager; final DisplayManagerInternal mDisplayManagerInternal; @@ -1258,19 +1208,7 @@ public class WindowManagerService extends IWindowManager.Stub mAssistantOnTopOfDream = context.getResources().getBoolean( com.android.internal.R.bool.config_assistantOnTopOfDream); - mFixedOrientationLetterboxAspectRatio = context.getResources().getFloat( - com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio); - mLetterboxActivityCornersRadius = context.getResources().getInteger( - com.android.internal.R.integer.config_letterboxActivityCornersRadius); - mLetterboxBackgroundColor = Color.valueOf(context.getResources().getColor( - com.android.internal.R.color.config_letterboxBackgroundColor)); - mLetterboxBackgroundType = readLetterboxBackgroundTypeFromConfig(context); - mLetterboxBackgroundWallpaperBlurRadius = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius); - mLetterboxBackgroundWallpaperDarkScrimAlpha = context.getResources().getFloat( - com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha); - mLetterboxHorizontalPositionMultiplier = context.getResources().getFloat( - com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier); + mLetterboxConfiguration = new LetterboxConfiguration(context); mInputManager = inputManager; // Must be before createDisplayContentLocked. mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); @@ -3864,233 +3802,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - /** - * Overrides the aspect ratio of letterbox for fixed orientation. If given value is <= {@link - * #MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO}, both it and a value of {@link - * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored and - * the framework implementation will be used to determine the aspect ratio. - */ - void setFixedOrientationLetterboxAspectRatio(float aspectRatio) { - mFixedOrientationLetterboxAspectRatio = aspectRatio; - } - - /** - * Resets the aspect ratio of letterbox for fixed orientation to {@link - * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio}. - */ - void resetFixedOrientationLetterboxAspectRatio() { - mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat( - com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio); - } - - /** - * Gets the aspect ratio of letterbox for fixed orientation. - */ - float getFixedOrientationLetterboxAspectRatio() { - return mFixedOrientationLetterboxAspectRatio; - } - - /** - * Overrides corners raidus 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 - * and corners of the activity won't be rounded. - */ - void setLetterboxActivityCornersRadius(int cornersRadius) { - mLetterboxActivityCornersRadius = cornersRadius; - } - - /** - * Resets corners raidus for activities presented in the letterbox mode to {@link - * com.android.internal.R.integer.config_letterboxActivityCornersRadius}. - */ - void resetLetterboxActivityCornersRadius() { - mLetterboxActivityCornersRadius = mContext.getResources().getInteger( - com.android.internal.R.integer.config_letterboxActivityCornersRadius); - } - - /** - * Whether corners of letterboxed activities are rounded. - */ - boolean isLetterboxActivityCornersRounded() { - return getLetterboxActivityCornersRadius() > 0; - } - - /** - * Gets corners raidus for activities presented in the letterbox mode. - */ - int getLetterboxActivityCornersRadius() { - return mLetterboxActivityCornersRadius; - } - - /** - * Gets color of letterbox background which is used when {@link - * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as - * fallback for other backfround types. - */ - Color getLetterboxBackgroundColor() { - return mLetterboxBackgroundColor; - } - - - /** - * Sets color of letterbox background which is used when {@link - * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as - * fallback for other backfround types. - */ - void setLetterboxBackgroundColor(Color color) { - mLetterboxBackgroundColor = color; - } - - /** - * Resets color of letterbox background to {@link - * com.android.internal.R.color.config_letterboxBackgroundColor}. - */ - void resetLetterboxBackgroundColor() { - mLetterboxBackgroundColor = Color.valueOf(mContext.getResources().getColor( - com.android.internal.R.color.config_letterboxBackgroundColor)); - } - - /** - * Gets {@link LetterboxBackgroundType} specified in {@link - * com.android.internal.R.integer.config_letterboxBackgroundType} or over via ADB command. - */ - @LetterboxBackgroundType - int getLetterboxBackgroundType() { - return mLetterboxBackgroundType; - } - - /** Sets letterbox background type. */ - void setLetterboxBackgroundType(@LetterboxBackgroundType int backgroundType) { - mLetterboxBackgroundType = backgroundType; - } - - /** - * Resets cletterbox background type to {@link - * com.android.internal.R.integer.config_letterboxBackgroundType}. - */ - void resetLetterboxBackgroundType() { - mLetterboxBackgroundType = readLetterboxBackgroundTypeFromConfig(mContext); - } - - @LetterboxBackgroundType - private static int readLetterboxBackgroundTypeFromConfig(Context context) { - int backgroundType = context.getResources().getInteger( - com.android.internal.R.integer.config_letterboxBackgroundType); - return backgroundType == LETTERBOX_BACKGROUND_SOLID_COLOR - || backgroundType == LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND - || backgroundType == LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING - || backgroundType == LETTERBOX_BACKGROUND_WALLPAPER - ? backgroundType : LETTERBOX_BACKGROUND_SOLID_COLOR; - } - - /** Returns a string representing the given {@link LetterboxBackgroundType}. */ - static String letterboxBackgroundTypeToString( - @LetterboxBackgroundType int backgroundType) { - switch (backgroundType) { - case LETTERBOX_BACKGROUND_SOLID_COLOR: - return "LETTERBOX_BACKGROUND_SOLID_COLOR"; - case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: - return "LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND"; - case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING: - return "LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING"; - case LETTERBOX_BACKGROUND_WALLPAPER: - return "LETTERBOX_BACKGROUND_WALLPAPER"; - default: - return "unknown=" + backgroundType; - } - } - - /** - * Overrides alpha of a black scrim shown over wallpaper for {@link - * #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link mLetterboxBackgroundType}. - * - * <p>If given value is < 0 or >= 1, both it and a value of {@link - * com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha} are ignored - * and 0.0 (transparent) is instead. - */ - void setLetterboxBackgroundWallpaperDarkScrimAlpha(float alpha) { - mLetterboxBackgroundWallpaperDarkScrimAlpha = alpha; - } - - /** - * Resets alpha of a black scrim shown over wallpaper letterbox background to {@link - * com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha}. - */ - void resetLetterboxBackgroundWallpaperDarkScrimAlpha() { - mLetterboxBackgroundWallpaperDarkScrimAlpha = mContext.getResources().getFloat( - com.android.internal.R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha); - } - - /** - * Gets alpha of a black scrim shown over wallpaper letterbox background. - */ - float getLetterboxBackgroundWallpaperDarkScrimAlpha() { - return mLetterboxBackgroundWallpaperDarkScrimAlpha; - } - - /** - * Overrides blur radius for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in - * {@link mLetterboxBackgroundType}. - * - * <p> If given value <= 0, both it and a value of {@link - * com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius} are ignored - * and 0 is used instead. - */ - void setLetterboxBackgroundWallpaperBlurRadius(int radius) { - mLetterboxBackgroundWallpaperBlurRadius = radius; - } - - /** - * Resets blur raidus for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link - * mLetterboxBackgroundType} to {@link - * com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius}. - */ - void resetLetterboxBackgroundWallpaperBlurRadius() { - mLetterboxBackgroundWallpaperBlurRadius = mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.config_letterboxBackgroundWallpaperBlurRadius); - } - - /** - * Gets blur raidus for {@link #LETTERBOX_BACKGROUND_WALLPAPER} option in {@link - * mLetterboxBackgroundType}. - */ - int getLetterboxBackgroundWallpaperBlurRadius() { - return mLetterboxBackgroundWallpaperBlurRadius; - } - - /* - * Gets horizontal position of a center of the letterboxed app window specified - * in {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier} - * or via an ADB command. 0 corresponds to the left side of the screen and 1 to the - * right side. - * - * <p>This value can be outside of [0, 1] range so clients need to check and default to the - * central position (0.5). - */ - float getLetterboxHorizontalPositionMultiplier() { - return mLetterboxHorizontalPositionMultiplier; - } - - /** - * Overrides horizontal position of a center of the letterboxed app window. If given value < 0 - * or > 1, then it and a value of {@link - * com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier} are ignored and - * central position (0.5) is used. - */ - void setLetterboxHorizontalPositionMultiplier(float multiplier) { - mLetterboxHorizontalPositionMultiplier = multiplier; - } - - /** - * Resets horizontal position of a center of the letterboxed app window to {@link - * com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier}. - */ - void resetLetterboxHorizontalPositionMultiplier() { - mLetterboxHorizontalPositionMultiplier = mContext.getResources().getFloat( - com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier); - } - @Override public void setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest) { if (!checkCallingPermission( diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 68257d4adb7f..1b578d1d452c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -19,10 +19,10 @@ package com.android.server.wm; import static android.os.Build.IS_USER; import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_SOLID_COLOR; -import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_WALLPAPER; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; import android.graphics.Color; import android.graphics.Point; @@ -41,7 +41,7 @@ import com.android.internal.os.ByteTransferPipe; import com.android.internal.protolog.ProtoLogImpl; import com.android.server.LocalServices; import com.android.server.statusbar.StatusBarManagerInternal; -import com.android.server.wm.WindowManagerService.LetterboxBackgroundType; +import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; import java.io.IOException; import java.io.PrintWriter; @@ -64,10 +64,12 @@ public class WindowManagerShellCommand extends ShellCommand { // Internal service impl -- must perform security checks before touching. private final WindowManagerService mInternal; + private final LetterboxConfiguration mLetterboxConfiguration; public WindowManagerShellCommand(WindowManagerService service) { mInterface = service; mInternal = service; + mLetterboxConfiguration = service.mLetterboxConfiguration; } @Override @@ -119,34 +121,12 @@ public class WindowManagerShellCommand extends ShellCommand { return runGetIgnoreOrientationRequest(pw); case "dump-visible-window-views": return runDumpVisibleWindowViews(pw); - case "set-fixed-orientation-letterbox-aspect-ratio": - return runSetFixedOrientationLetterboxAspectRatio(pw); - case "get-fixed-orientation-letterbox-aspect-ratio": - return runGetFixedOrientationLetterboxAspectRatio(pw); - case "set-letterbox-activity-corners-radius": - return runSetLetterboxActivityCornersRadius(pw); - case "get-letterbox-activity-corners-radius": - return runGetLetterboxActivityCornersRadius(pw); - case "set-letterbox-background-type": - return runSetLetterboxBackgroundType(pw); - case "get-letterbox-background-type": - return runGetLetterboxBackgroundType(pw); - case "set-letterbox-background-color": - return runSetLetterboxBackgroundColor(pw); - case "get-letterbox-background-color": - return runGetLetterboxBackgroundColor(pw); - case "set-letterbox-background-wallpaper-blur-radius": - return runSetLetterboxBackgroundWallpaperBlurRadius(pw); - case "get-letterbox-background-wallpaper-blur-radius": - return runGetLetterboxBackgroundWallpaperBlurRadius(pw); - case "set-letterbox-background-wallpaper-dark-scrim-alpha": - return runSetLetterboxBackgroundWallpaperDarkScrimAlpha(pw); - case "get-letterbox-background-wallpaper-dark-scrim-alpha": - return runGetLetterboxBackgroundWallpaperDarkScrimAlpha(pw); - case "set-letterbox-horizontal-position-multiplier": - return runSeLetterboxHorizontalPositionMultiplier(pw); - case "get-letterbox-horizontal-position-multiplier": - return runGetLetterboxHorizontalPositionMultiplier(pw); + case "set-letterbox-style": + return runSetLetterboxStyle(pw); + case "get-letterbox-style": + return runGetLetterboxStyle(pw); + case "reset-letterbox-style": + return runResetLetterboxStyle(pw); case "set-sandbox-display-apis": return runSandboxDisplayApis(pw); case "reset": @@ -611,12 +591,6 @@ public class WindowManagerShellCommand extends ShellCommand { final float aspectRatio; try { String arg = getNextArgRequired(); - if ("reset".equals(arg)) { - synchronized (mInternal.mGlobalLock) { - mInternal.resetFixedOrientationLetterboxAspectRatio(); - } - return 0; - } aspectRatio = Float.parseFloat(arg); } catch (NumberFormatException e) { getErrPrintWriter().println("Error: bad aspect ratio format " + e); @@ -627,19 +601,7 @@ public class WindowManagerShellCommand extends ShellCommand { return -1; } synchronized (mInternal.mGlobalLock) { - mInternal.setFixedOrientationLetterboxAspectRatio(aspectRatio); - } - return 0; - } - - private int runGetFixedOrientationLetterboxAspectRatio(PrintWriter pw) throws RemoteException { - synchronized (mInternal.mGlobalLock) { - final float aspectRatio = mInternal.getFixedOrientationLetterboxAspectRatio(); - if (aspectRatio <= WindowManagerService.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { - pw.println("Letterbox aspect ratio is not set"); - } else { - pw.println("Letterbox aspect ratio is " + aspectRatio); - } + mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(aspectRatio); } return 0; } @@ -648,12 +610,6 @@ public class WindowManagerShellCommand extends ShellCommand { final int cornersRadius; try { String arg = getNextArgRequired(); - if ("reset".equals(arg)) { - synchronized (mInternal.mGlobalLock) { - mInternal.resetLetterboxActivityCornersRadius(); - } - return 0; - } cornersRadius = Integer.parseInt(arg); } catch (NumberFormatException e) { getErrPrintWriter().println("Error: bad corners radius format " + e); @@ -664,110 +620,59 @@ public class WindowManagerShellCommand extends ShellCommand { return -1; } synchronized (mInternal.mGlobalLock) { - mInternal.setLetterboxActivityCornersRadius(cornersRadius); - } - return 0; - } - - private int runGetLetterboxActivityCornersRadius(PrintWriter pw) throws RemoteException { - synchronized (mInternal.mGlobalLock) { - final int cornersRadius = mInternal.getLetterboxActivityCornersRadius(); - if (cornersRadius < 0) { - pw.println("Letterbox corners radius is not set"); - } else { - pw.println("Letterbox corners radius is " + cornersRadius); - } + mLetterboxConfiguration.setLetterboxActivityCornersRadius(cornersRadius); } return 0; } private int runSetLetterboxBackgroundType(PrintWriter pw) throws RemoteException { @LetterboxBackgroundType final int backgroundType; - - String arg = getNextArgRequired(); - if ("reset".equals(arg)) { - synchronized (mInternal.mGlobalLock) { - mInternal.resetLetterboxBackgroundType(); - } - return 0; - } - switch (arg) { - case "solid_color": - backgroundType = LETTERBOX_BACKGROUND_SOLID_COLOR; - break; - case "app_color_background": - backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; - break; - case "app_color_background_floating": - backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; - break; - case "wallpaper": - backgroundType = LETTERBOX_BACKGROUND_WALLPAPER; - break; - default: - getErrPrintWriter().println( - "Error: 'reset', 'solid_color', 'app_color_background' or " - + "'wallpaper' should be provided as an argument"); - return -1; - } - synchronized (mInternal.mGlobalLock) { - mInternal.setLetterboxBackgroundType(backgroundType); - } - return 0; - } - - private int runGetLetterboxBackgroundType(PrintWriter pw) throws RemoteException { - synchronized (mInternal.mGlobalLock) { - @LetterboxBackgroundType final int backgroundType = - mInternal.getLetterboxBackgroundType(); - switch (backgroundType) { - case LETTERBOX_BACKGROUND_SOLID_COLOR: - pw.println("Letterbox background type is 'solid_color'"); + try { + String arg = getNextArgRequired(); + switch (arg) { + case "solid_color": + backgroundType = LETTERBOX_BACKGROUND_SOLID_COLOR; break; - case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: - pw.println("Letterbox background type is 'app_color_background'"); + case "app_color_background": + backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; break; - case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING: - pw.println("Letterbox background type is 'app_color_background_floating'"); + case "app_color_background_floating": + backgroundType = LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; break; - case LETTERBOX_BACKGROUND_WALLPAPER: - pw.println("Letterbox background type is 'wallpaper'"); + case "wallpaper": + backgroundType = LETTERBOX_BACKGROUND_WALLPAPER; break; default: - throw new AssertionError( - "Unexpected letterbox background type: " + backgroundType); + getErrPrintWriter().println( + "Error: 'reset', 'solid_color', 'app_color_background' or " + + "'wallpaper' should be provided as an argument"); + return -1; } + } catch (IllegalArgumentException e) { + getErrPrintWriter().println( + "Error: 'reset', 'solid_color', 'app_color_background' or " + + "'wallpaper' should be provided as an argument" + e); + return -1; + } + synchronized (mInternal.mGlobalLock) { + mLetterboxConfiguration.setLetterboxBackgroundType(backgroundType); } return 0; } private int runSetLetterboxBackgroundColor(PrintWriter pw) throws RemoteException { final Color color; - String arg = getNextArgRequired(); try { - if ("reset".equals(arg)) { - synchronized (mInternal.mGlobalLock) { - mInternal.resetLetterboxBackgroundColor(); - } - return 0; - } + String arg = getNextArgRequired(); color = Color.valueOf(Color.parseColor(arg)); } catch (IllegalArgumentException e) { getErrPrintWriter().println( "Error: 'reset' or color in #RRGGBB format should be provided as " - + "an argument " + e + " but got " + arg); + + "an argument " + e); return -1; } synchronized (mInternal.mGlobalLock) { - mInternal.setLetterboxBackgroundColor(color); - } - return 0; - } - - private int runGetLetterboxBackgroundColor(PrintWriter pw) throws RemoteException { - synchronized (mInternal.mGlobalLock) { - final Color color = mInternal.getLetterboxBackgroundColor(); - pw.println("Letterbox background color is " + Integer.toHexString(color.toArgb())); + mLetterboxConfiguration.setLetterboxBackgroundColor(color); } return 0; } @@ -777,12 +682,6 @@ public class WindowManagerShellCommand extends ShellCommand { final int radius; try { String arg = getNextArgRequired(); - if ("reset".equals(arg)) { - synchronized (mInternal.mGlobalLock) { - mInternal.resetLetterboxBackgroundWallpaperBlurRadius(); - } - return 0; - } radius = Integer.parseInt(arg); } catch (NumberFormatException e) { getErrPrintWriter().println("Error: blur radius format " + e); @@ -793,20 +692,7 @@ public class WindowManagerShellCommand extends ShellCommand { return -1; } synchronized (mInternal.mGlobalLock) { - mInternal.setLetterboxBackgroundWallpaperBlurRadius(radius); - } - return 0; - } - - private int runGetLetterboxBackgroundWallpaperBlurRadius(PrintWriter pw) - throws RemoteException { - synchronized (mInternal.mGlobalLock) { - final int radius = mInternal.getLetterboxBackgroundWallpaperBlurRadius(); - if (radius <= 0) { - pw.println("Letterbox background wallpaper blur radius is not set"); - } else { - pw.println("Letterbox background wallpaper blur radius is " + radius); - } + mLetterboxConfiguration.setLetterboxBackgroundWallpaperBlurRadius(radius); } return 0; } @@ -816,12 +702,6 @@ public class WindowManagerShellCommand extends ShellCommand { final float alpha; try { String arg = getNextArgRequired(); - if ("reset".equals(arg)) { - synchronized (mInternal.mGlobalLock) { - mInternal.resetLetterboxBackgroundWallpaperDarkScrimAlpha(); - } - return 0; - } alpha = Float.parseFloat(arg); } catch (NumberFormatException e) { getErrPrintWriter().println("Error: bad alpha format " + e); @@ -832,20 +712,7 @@ public class WindowManagerShellCommand extends ShellCommand { return -1; } synchronized (mInternal.mGlobalLock) { - mInternal.setLetterboxBackgroundWallpaperDarkScrimAlpha(alpha); - } - return 0; - } - - private int runGetLetterboxBackgroundWallpaperDarkScrimAlpha(PrintWriter pw) - throws RemoteException { - synchronized (mInternal.mGlobalLock) { - final float alpha = mInternal.getLetterboxBackgroundWallpaperDarkScrimAlpha(); - if (alpha < 0 || alpha >= 1) { - pw.println("Letterbox dark scrim alpha is not set"); - } else { - pw.println("Letterbox dark scrim alpha is " + alpha); - } + mLetterboxConfiguration.setLetterboxBackgroundWallpaperDarkScrimAlpha(alpha); } return 0; } @@ -854,12 +721,6 @@ public class WindowManagerShellCommand extends ShellCommand { final float multiplier; try { String arg = getNextArgRequired(); - if ("reset".equals(arg)) { - synchronized (mInternal.mGlobalLock) { - mInternal.resetLetterboxHorizontalPositionMultiplier(); - } - return 0; - } multiplier = Float.parseFloat(arg); } catch (NumberFormatException e) { getErrPrintWriter().println("Error: bad multiplier format " + e); @@ -870,23 +731,121 @@ public class WindowManagerShellCommand extends ShellCommand { return -1; } synchronized (mInternal.mGlobalLock) { - mInternal.setLetterboxHorizontalPositionMultiplier(multiplier); + mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(multiplier); + } + return 0; + } + + private int runSetLetterboxStyle(PrintWriter pw) throws RemoteException { + if (peekNextArg() == null) { + getErrPrintWriter().println("Error: No arguments provided."); + } + while (peekNextArg() != null) { + String arg = getNextArg(); + switch (arg) { + case "--aspectRatio": + runSetFixedOrientationLetterboxAspectRatio(pw); + break; + case "--cornerRadius": + runSetLetterboxActivityCornersRadius(pw); + break; + case "--backgroundType": + runSetLetterboxBackgroundType(pw); + break; + case "--backgroundColor": + runSetLetterboxBackgroundColor(pw); + break; + case "--wallpaperBlurRadius": + runSetLetterboxBackgroundWallpaperBlurRadius(pw); + break; + case "--wallpaperDarkScrimAlpha": + runSetLetterboxBackgroundWallpaperDarkScrimAlpha(pw); + break; + case "--horizontalPositionMultiplier": + runSeLetterboxHorizontalPositionMultiplier(pw); + break; + default: + getErrPrintWriter().println( + "Error: Unrecognized letterbox style option: " + arg); + return -1; + } } return 0; } - private int runGetLetterboxHorizontalPositionMultiplier(PrintWriter pw) throws RemoteException { + private int runResetLetterboxStyle(PrintWriter pw) throws RemoteException { + if (peekNextArg() == null) { + resetLetterboxStyle(); + } synchronized (mInternal.mGlobalLock) { - final float multiplier = mInternal.getLetterboxHorizontalPositionMultiplier(); - if (multiplier < 0) { - pw.println("Letterbox horizontal position multiplier is not set"); - } else { - pw.println("Letterbox horizontal position multiplier is " + multiplier); + while (peekNextArg() != null) { + String arg = getNextArg(); + switch (arg) { + case "aspectRatio": + mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio(); + break; + case "cornerRadius": + mLetterboxConfiguration.resetLetterboxActivityCornersRadius(); + break; + case "backgroundType": + mLetterboxConfiguration.resetLetterboxBackgroundType(); + break; + case "backgroundColor": + mLetterboxConfiguration.resetLetterboxBackgroundColor(); + break; + case "wallpaperBlurRadius": + mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadius(); + break; + case "wallpaperDarkScrimAlpha": + mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha(); + break; + case "horizontalPositionMultiplier": + mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier(); + break; + default: + getErrPrintWriter().println( + "Error: Unrecognized letterbox style option: " + arg); + return -1; + } } } return 0; } + private void resetLetterboxStyle() { + synchronized (mInternal.mGlobalLock) { + mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio(); + mLetterboxConfiguration.resetLetterboxActivityCornersRadius(); + mLetterboxConfiguration.resetLetterboxBackgroundType(); + mLetterboxConfiguration.resetLetterboxBackgroundColor(); + mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadius(); + mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha(); + mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier(); + } + } + + private int runGetLetterboxStyle(PrintWriter pw) throws RemoteException { + synchronized (mInternal.mGlobalLock) { + pw.println("Corner radius: " + + mLetterboxConfiguration.getLetterboxActivityCornersRadius()); + pw.println("Horizontal position multiplier: " + + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier()); + pw.println("Aspect ratio: " + + mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio()); + + pw.println("Background type: " + + LetterboxConfiguration.letterboxBackgroundTypeToString( + mLetterboxConfiguration.getLetterboxBackgroundType())); + pw.println(" Background color: " + Integer.toHexString( + mLetterboxConfiguration.getLetterboxBackgroundColor().toArgb())); + pw.println(" Wallpaper blur radius: " + + mLetterboxConfiguration.getLetterboxBackgroundWallpaperBlurRadius()); + pw.println(" Wallpaper dark scrim alpha: " + + mLetterboxConfiguration.getLetterboxBackgroundWallpaperDarkScrimAlpha()); + } + return 0; + } + private int runReset(PrintWriter pw) throws RemoteException { int displayId = getDisplayId(getNextArg()); @@ -911,26 +870,8 @@ public class WindowManagerShellCommand extends ShellCommand { // set-ignore-orientation-request mInterface.setIgnoreOrientationRequest(displayId, false /* ignoreOrientationRequest */); - // set-fixed-orientation-letterbox-aspect-ratio - mInternal.resetFixedOrientationLetterboxAspectRatio(); - - // set-letterbox-activity-corners-radius - mInternal.resetLetterboxActivityCornersRadius(); - - // set-letterbox-background-type - mInternal.resetLetterboxBackgroundType(); - - // set-letterbox-background-color - mInternal.resetLetterboxBackgroundColor(); - - // set-letterbox-background-wallpaper-blur-radius - mInternal.resetLetterboxBackgroundWallpaperBlurRadius(); - - // set-letterbox-background-wallpaper-dark-scrim-alpha - mInternal.resetLetterboxBackgroundWallpaperDarkScrimAlpha(); - - // set-letterbox-horizontal-position-multiplier - mInternal.resetLetterboxHorizontalPositionMultiplier(); + // set-letterbox-style + resetLetterboxStyle(); // set-sandbox-display-apis mInternal.setSandboxDisplayApis(displayId, /* sandboxDisplayApis= */ true); @@ -966,47 +907,13 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" set-ignore-orientation-request [-d DISPLAY_ID] [true|1|false|0]"); pw.println(" get-ignore-orientation-request [-d DISPLAY_ID] "); pw.println(" If app requested orientation should be ignored."); - pw.println(" set-fixed-orientation-letterbox-aspect-ratio [reset|aspectRatio]"); - pw.println(" get-fixed-orientation-letterbox-aspect-ratio"); - pw.println(" Aspect ratio of letterbox for fixed orientation. If aspectRatio <= " - + WindowManagerService.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO); - pw.println(" both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will be"); - pw.println(" ignored and framework implementation will determine aspect ratio."); - pw.println(" set-letterbox-activity-corners-radius [reset|cornersRadius]"); - pw.println(" get-letterbox-activity-corners-radius"); - pw.println(" Corners radius for activities in the letterbox mode. If radius < 0,"); - pw.println(" both it and R.integer.config_letterboxActivityCornersRadius will be"); - pw.println(" ignored and corners of the activity won't be rounded."); - pw.println(" set-letterbox-background-color [reset|colorName|'\\#RRGGBB']"); - pw.println(" get-letterbox-background-color"); - pw.println(" Color of letterbox background which is be used when letterbox background"); - pw.println(" type is 'solid-color'. Use get(set)-letterbox-background-type to check"); - pw.println(" and control letterbox background type. See Color#parseColor for allowed"); - pw.println(" color formats (#RRGGBB and some colors by name, e.g. magenta or olive). "); - pw.println(" set-letterbox-background-type [reset|solid_color|app_color_background"); - pw.println(" |app_color_background_floating|wallpaper]"); - pw.println(" get-letterbox-background-type"); - pw.println(" Type of background used in the letterbox mode."); - pw.println(" set-letterbox-background-wallpaper-blur-radius [reset|radius]"); - pw.println(" get-letterbox-background-wallpaper-blur-radius"); - pw.println(" Blur radius for 'wallpaper' letterbox background. If radius <= 0"); - pw.println(" both it and R.dimen.config_letterboxBackgroundWallpaperBlurRadius are "); - pw.println(" ignored and 0 is used."); - pw.println(" set-letterbox-background-wallpaper-dark-scrim-alpha [reset|alpha]"); - pw.println(" get-letterbox-background-wallpaper-dark-scrim-alpha"); - pw.println(" Alpha of a black translucent scrim shown over 'wallpaper'"); - pw.println(" letterbox background. If alpha < 0 or >= 1 both it and"); - pw.println(" R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha are ignored and "); - pw.println(" 0.0 (transparent) is used instead."); - pw.println(" set-letterbox-horizontal-position-multiplier [reset|multiplier]"); - pw.println(" get-letterbox-horizontal-position-multiplier"); - pw.println(" horizontal position of a center of a letterboxed app. If it < 0 or > 1"); - pw.println(" then both it and R.dimen.config_letterboxHorizontalPositionMultiplier"); - pw.println(" are ignored and central position (0.5) is used."); pw.println(" set-sandbox-display-apis [true|1|false|0]"); pw.println(" Sets override of Display APIs getRealSize / getRealMetrics to reflect "); pw.println(" DisplayArea of the activity, or the window bounds if in letterbox or"); pw.println(" Size Compat Mode."); + + printLetterboxHelp(pw); + pw.println(" reset [-d DISPLAY_ID]"); pw.println(" Reset all override settings."); if (!IS_USER) { @@ -1016,4 +923,47 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" Logging settings."); } } + + private void printLetterboxHelp(PrintWriter pw) { + pw.println(" set-letterbox-style"); + pw.println(" Sets letterbox style using the following options:"); + pw.println(" --aspectRatio aspectRatio"); + pw.println(" Aspect ratio of letterbox for fixed orientation. If aspectRatio <= " + + LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO); + pw.println(" both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will"); + pw.println(" be ignored and framework implementation will determine aspect ratio."); + pw.println(" --cornerRadius radius"); + pw.println(" Corners radius for activities in the letterbox mode. If radius < 0,"); + pw.println(" both it and R.integer.config_letterboxActivityCornersRadius will be"); + pw.println(" ignored and corners of the activity won't be rounded."); + pw.println(" --backgroundType [reset|solid_color|app_color_background"); + pw.println(" |app_color_background_floating|wallpaper]"); + pw.println(" Type of background used in the letterbox mode."); + pw.println(" --backgroundColor color"); + pw.println(" Color of letterbox which is be used when letterbox background type"); + pw.println(" is 'solid-color'. Use (set)get-letterbox-style to check and control"); + pw.println(" letterbox background type. See Color#parseColor for allowed color"); + pw.println(" formats (#RRGGBB and some colors by name, e.g. magenta or olive)."); + pw.println(" --wallpaperBlurRadius radius"); + pw.println(" Blur radius for 'wallpaper' letterbox background. If radius <= 0"); + pw.println(" both it and R.dimen.config_letterboxBackgroundWallpaperBlurRadius"); + pw.println(" are ignored and 0 is used."); + pw.println(" --wallpaperDarkScrimAlpha alpha"); + pw.println(" Alpha of a black translucent scrim shown over 'wallpaper'"); + pw.println(" letterbox background. If alpha < 0 or >= 1 both it and"); + pw.println(" R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha are ignored"); + pw.println(" and 0.0 (transparent) is used instead."); + pw.println(" --horizontalPositionMultiplier multiplier"); + pw.println(" Horizontal position of app window center. If multiplier < 0 or > 1,"); + pw.println(" both it and R.dimen.config_letterboxHorizontalPositionMultiplier"); + pw.println(" are ignored and central position (0.5) is used."); + pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType"); + pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha"); + pw.println(" |horizontalPositionMultiplier]"); + pw.println(" Resets overrides to default values for specified properties separated"); + pw.println(" by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'."); + pw.println(" If no arguments provided, all values will be reset."); + pw.println(" get-letterbox-style"); + pw.println(" Prints letterbox style configuration."); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 0afd39f1ed01..2f5235249168 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1971,7 +1971,8 @@ public class DisplayContentTests extends WindowTestsBase { // test misc display overrides assertEquals(ignoreOrientationRequests, testDisplayContent.mIgnoreOrientationRequest); - assertEquals(fixedOrientationLetterboxRatio, mWm.getFixedOrientationLetterboxAspectRatio(), + assertEquals(fixedOrientationLetterboxRatio, + mWm.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(), 0 /* delta */); } @@ -2011,7 +2012,8 @@ public class DisplayContentTests extends WindowTestsBase { // test misc display overrides assertEquals(ignoreOrientationRequests, testDisplayContent.mIgnoreOrientationRequest); - assertEquals(fixedOrientationLetterboxRatio, mWm.getFixedOrientationLetterboxAspectRatio(), + assertEquals(fixedOrientationLetterboxRatio, + mWm.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(), 0 /* delta */); } diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index ee1d39328555..95b74430e4ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -335,11 +335,11 @@ public class SizeCompatTests extends WindowTestsBase { final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window"); assertEquals(window, mActivity.findMainWindow()); - assertTrue(mActivity.isLetterboxed(mActivity.findMainWindow())); + assertTrue(mActivity.mLetterboxUiController.isLetterboxed(mActivity.findMainWindow())); window.mAttrs.flags |= FLAG_SHOW_WALLPAPER; - assertFalse(mActivity.isLetterboxed(mActivity.findMainWindow())); + assertFalse(mActivity.mLetterboxUiController.isLetterboxed(mActivity.findMainWindow())); } @Test @@ -1023,7 +1023,7 @@ public class SizeCompatTests extends WindowTestsBase { // Portrait fixed app with min aspect ratio higher that aspect ratio override for fixed // orientation letterbox. - mActivity.mWmService.setFixedOrientationLetterboxAspectRatio(1.1f); + mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f); mActivity.info.setMinAspectRatio(3); prepareUnresizable(mActivity, /* maxAspect= */ 0, SCREEN_ORIENTATION_PORTRAIT); @@ -1054,7 +1054,7 @@ public class SizeCompatTests extends WindowTestsBase { // Portrait fixed app with max aspect ratio lower that aspect ratio override for fixed // orientation letterbox. - mActivity.mWmService.setFixedOrientationLetterboxAspectRatio(3); + mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(3); prepareUnresizable(mActivity, /* maxAspect= */ 2, SCREEN_ORIENTATION_PORTRAIT); final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds()); @@ -1085,7 +1085,7 @@ public class SizeCompatTests extends WindowTestsBase { // Portrait fixed app with min aspect ratio higher that aspect ratio override for fixed // orientation letterbox. final float fixedOrientationLetterboxAspectRatio = 1.1f; - mActivity.mWmService.setFixedOrientationLetterboxAspectRatio( + mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio( fixedOrientationLetterboxAspectRatio); prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT); @@ -1586,7 +1586,7 @@ public class SizeCompatTests extends WindowTestsBase { setUpDisplaySizeWithApp(2800, 1400); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); - mActivity.mWmService.setLetterboxHorizontalPositionMultiplier( + mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier( letterboxHorizontalPositionMultiplier); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); @@ -1624,7 +1624,7 @@ public class SizeCompatTests extends WindowTestsBase { setUpDisplaySizeWithApp(2800, 1400); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); - mActivity.mWmService.setLetterboxHorizontalPositionMultiplier( + mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier( letterboxHorizontalPositionMultiplier); prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index ae12062987cd..2d4e4efd74ea 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -208,11 +208,11 @@ class WindowTestsBase extends SystemServiceTestsBase { // Ensure letterbox aspect ratio is not overridden on any device target. // {@link com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio}, is set // on some device form factors. - mAtm.mWindowManager.setFixedOrientationLetterboxAspectRatio(0); + mAtm.mWindowManager.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(0); // Ensure letterbox position multiplier is not overridden on any device target. // {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier}, // may be set on some device form factors. - mAtm.mWindowManager.setLetterboxHorizontalPositionMultiplier(0.5f); + mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0.5f); checkDeviceSpecificOverridesNotApplied(); } @@ -220,10 +220,10 @@ class WindowTestsBase extends SystemServiceTestsBase { @After public void tearDown() throws Exception { // Revert back to device overrides. - mAtm.mWindowManager.setFixedOrientationLetterboxAspectRatio( + mAtm.mWindowManager.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio( mContext.getResources().getFloat( com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio)); - mAtm.mWindowManager.setLetterboxHorizontalPositionMultiplier( + mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier( mContext.getResources().getFloat( com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier)); } @@ -235,7 +235,8 @@ class WindowTestsBase extends SystemServiceTestsBase { private void checkDeviceSpecificOverridesNotApplied() { // Check global overrides if (!sGlobalOverridesChecked) { - assertEquals(0, mWm.getFixedOrientationLetterboxAspectRatio(), 0 /* delta */); + assertEquals(0, mWm.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(), + 0 /* delta */); sGlobalOverridesChecked = true; } // Check display-specific overrides |