diff options
| author | 2021-02-02 01:20:26 +0000 | |
|---|---|---|
| committer | 2021-02-02 23:54:25 +0000 | |
| commit | c0f663fd35ffb995371a816b0b74e1771abe443f (patch) | |
| tree | b15fd35eecdfa0d02965f23cbfb7462c33d3c6cf | |
| parent | 5e8177bf787c384f914fa9bb388a871afd6e25fa (diff) | |
Configurable letterbox background.
Allow three types of the letterbox wallpaper:
- Solid background using color specified in R.color.config_letterboxBackgroundColorSolid color
- Color specified in R.attr.colorBackground for the letterboxed application
- Color specified in R.attr.colorBackgroundFloating for the letterboxed application
Also, adding ADB commands for each config value:
- adb shell cmd window set-letterbox-background-color [reset|color]
- adb shell cmd window get-letterbox-background-color
- adb shell cmd window set-letterbox-background-type [reset|solid_color|app_color_background|app_color_background_floating]
- adb shell cmd window get-letterbox-background-type
Test: manual with ADB commands, atest LetterboxTest
Fix: 179088234
Change-Id: I23cf0b52c9f95d1f92255731bc7be165a575c7cd
| -rw-r--r-- | core/java/android/app/Activity.java | 7 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManager.java | 64 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 3 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 17 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 2 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/app/activity/ActivityManagerTest.java | 15 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityRecord.java | 36 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/Letterbox.java | 24 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/Task.java | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 148 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerShellCommand.java | 103 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java | 17 |
12 files changed, 365 insertions, 75 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index bdd541a2f0ac..4728f11a402d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -5090,6 +5090,13 @@ public class Activity extends ContextThemeWrapper mTaskDescription.setBackgroundColor(colorBackground); } + int colorBackgroundFloating = a.getColor( + com.android.internal.R.styleable.ActivityTaskDescription_colorBackgroundFloating, + 0); + if (colorBackgroundFloating != 0 && Color.alpha(colorBackgroundFloating) == 0xFF) { + mTaskDescription.setBackgroundColorFloating(colorBackgroundFloating); + } + final int statusBarColor = a.getColor( com.android.internal.R.styleable.ActivityTaskDescription_statusBarColor, 0); if (statusBarColor != 0) { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 520959cc40e7..43d0269beae2 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1072,13 +1072,15 @@ public class ActivityManager { private static final String ATTR_TASKDESCRIPTIONCOLOR_PRIMARY = ATTR_TASKDESCRIPTION_PREFIX + "color"; private static final String ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND = - ATTR_TASKDESCRIPTION_PREFIX + "colorBackground"; + ATTR_TASKDESCRIPTION_PREFIX + "color_background"; private static final String ATTR_TASKDESCRIPTIONICON_FILENAME = ATTR_TASKDESCRIPTION_PREFIX + "icon_filename"; private static final String ATTR_TASKDESCRIPTIONICON_RESOURCE = ATTR_TASKDESCRIPTION_PREFIX + "icon_resource"; private static final String ATTR_TASKDESCRIPTIONICON_RESOURCE_PACKAGE = ATTR_TASKDESCRIPTION_PREFIX + "icon_package"; + private static final String ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND_FLOATING = + ATTR_TASKDESCRIPTION_PREFIX + "color_background_floating"; private String mLabel; @Nullable @@ -1086,6 +1088,7 @@ public class ActivityManager { private String mIconFilename; private int mColorPrimary; private int mColorBackground; + private int mColorBackgroundFloating; private int mStatusBarColor; private int mNavigationBarColor; private boolean mEnsureStatusBarContrastWhenTransparent; @@ -1106,7 +1109,7 @@ public class ActivityManager { */ public TaskDescription(String label, @DrawableRes int iconRes, int colorPrimary) { this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes), - colorPrimary, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1); + colorPrimary, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0); if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) { throw new RuntimeException("A TaskDescription's primary color should be opaque"); } @@ -1121,7 +1124,7 @@ public class ActivityManager { */ public TaskDescription(String label, @DrawableRes int iconRes) { this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes), - 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1); + 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0); } /** @@ -1130,14 +1133,14 @@ public class ActivityManager { * @param label A label and description of the current state of this activity. */ public TaskDescription(String label) { - this(label, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1); + this(label, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0); } /** * Creates an empty TaskDescription. */ public TaskDescription() { - this(null, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1); + this(null, null, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0); } /** @@ -1152,7 +1155,7 @@ public class ActivityManager { @Deprecated public TaskDescription(String label, Bitmap icon, int colorPrimary) { this(label, icon != null ? Icon.createWithBitmap(icon) : null, colorPrimary, 0, 0, 0, - false, false, RESIZE_MODE_RESIZEABLE, -1, -1); + false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0); if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) { throw new RuntimeException("A TaskDescription's primary color should be opaque"); } @@ -1168,7 +1171,7 @@ public class ActivityManager { @Deprecated public TaskDescription(String label, Bitmap icon) { this(label, icon != null ? Icon.createWithBitmap(icon) : null, 0, 0, 0, 0, false, false, - RESIZE_MODE_RESIZEABLE, -1, -1); + RESIZE_MODE_RESIZEABLE, -1, -1, 0); } /** @hide */ @@ -1177,7 +1180,7 @@ public class ActivityManager { int statusBarColor, int navigationBarColor, boolean ensureStatusBarContrastWhenTransparent, boolean ensureNavigationBarContrastWhenTransparent, int resizeMode, int minWidth, - int minHeight) { + int minHeight, int colorBackgroundFloating) { mLabel = label; mIcon = icon; mColorPrimary = colorPrimary; @@ -1190,6 +1193,7 @@ public class ActivityManager { mResizeMode = resizeMode; mMinWidth = minWidth; mMinHeight = minHeight; + mColorBackgroundFloating = colorBackgroundFloating; } /** @@ -1217,6 +1221,7 @@ public class ActivityManager { mResizeMode = other.mResizeMode; mMinWidth = other.mMinWidth; mMinHeight = other.mMinHeight; + mColorBackgroundFloating = other.mColorBackgroundFloating; } /** @@ -1253,6 +1258,9 @@ public class ActivityManager { if (other.mMinHeight != -1) { mMinHeight = other.mMinHeight; } + if (other.mColorBackgroundFloating != 0) { + mColorBackgroundFloating = other.mColorBackgroundFloating; + } } private TaskDescription(Parcel source) { @@ -1292,6 +1300,19 @@ public class ActivityManager { } /** + * Sets the background color floating for this task description. + * @hide + */ + public void setBackgroundColorFloating(int backgroundColor) { + // Ensure that the given color is valid + if ((backgroundColor != 0) && (Color.alpha(backgroundColor) != 255)) { + throw new RuntimeException( + "A TaskDescription's background color floating should be opaque"); + } + mColorBackgroundFloating = backgroundColor; + } + + /** * @hide */ public void setStatusBarColor(int statusBarColor) { @@ -1461,6 +1482,14 @@ public class ActivityManager { } /** + * @return The background color floating. + * @hide + */ + public int getBackgroundColorFloating() { + return mColorBackgroundFloating; + } + + /** * @hide */ public int getStatusBarColor() { @@ -1537,6 +1566,10 @@ public class ActivityManager { if (mColorBackground != 0) { out.attributeIntHex(null, ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND, mColorBackground); } + if (mColorBackgroundFloating != 0) { + out.attributeIntHex(null, ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND_FLOATING, + mColorBackgroundFloating); + } if (mIconFilename != null) { out.attribute(null, ATTR_TASKDESCRIPTIONICON_FILENAME, mIconFilename); } @@ -1563,6 +1596,11 @@ public class ActivityManager { if (colorBackground != 0) { setBackgroundColor(colorBackground); } + final int colorBackgroundFloating = in.getAttributeIntHex(null, + ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND_FLOATING, 0); + if (colorBackgroundFloating != 0) { + setBackgroundColorFloating(colorBackgroundFloating); + } final String iconFilename = in.getAttributeValue(null, ATTR_TASKDESCRIPTIONICON_FILENAME); if (iconFilename != null) { @@ -1615,6 +1653,7 @@ public class ActivityManager { dest.writeInt(1); dest.writeString(mIconFilename); } + dest.writeInt(mColorBackgroundFloating); } public void readFromParcel(Parcel source) { @@ -1632,6 +1671,7 @@ public class ActivityManager { mMinWidth = source.readInt(); mMinHeight = source.readInt(); mIconFilename = source.readInt() > 0 ? source.readString() : null; + mColorBackgroundFloating = source.readInt(); } public static final @android.annotation.NonNull Creator<TaskDescription> CREATOR @@ -1655,7 +1695,8 @@ public class ActivityManager { + (mEnsureNavigationBarContrastWhenTransparent ? " (contrast when transparent)" : "") + " resizeMode: " + ActivityInfo.resizeModeToString(mResizeMode) - + " minWidth: " + mMinWidth + " minHeight: " + mMinHeight; + + " minWidth: " + mMinWidth + " minHeight: " + mMinHeight + + " colorBackgrounFloating: " + mColorBackgroundFloating; } @Override @@ -1678,7 +1719,8 @@ public class ActivityManager { == other.mEnsureNavigationBarContrastWhenTransparent && mResizeMode == other.mResizeMode && mMinWidth == other.mMinWidth - && mMinHeight == other.mMinHeight; + && mMinHeight == other.mMinHeight + && mColorBackgroundFloating == other.mColorBackgroundFloating; } /** @hide */ @@ -1826,6 +1868,8 @@ public class ActivityManager { pw.print(ActivityInfo.resizeModeToString(td.getResizeMode())); pw.print(" minWidth="); pw.print(td.getMinWidth()); pw.print(" minHeight="); pw.print(td.getMinHeight()); + pw.print(" colorBackgroundFloating=#"); + pw.print(Integer.toHexString(td.getBackgroundColorFloating())); pw.println(" }"); } } diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 14f1e0e20ef6..f13f859681e1 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -9193,6 +9193,9 @@ <!-- @hide From Theme.colorBackground, used for the TaskDescription background color. --> <attr name="colorBackground" /> + <!-- @hide From Theme.colorBackgroundFloating, used for the TaskDescription background + color floating. --> + <attr name="colorBackgroundFloating" /> <!-- @hide From Theme.statusBarColor, used for the TaskDescription status bar color. --> <attr name="statusBarColor"/> <!-- @hide From Theme.navigationBarColor, used for the TaskDescription navigation bar diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5e0cda69911b..57ea2b2aeca1 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4636,6 +4636,23 @@ corners of the activity won't be rounded. --> <integer name="config_letterboxActivityCornersRadius">0</integer> + <!-- Corners appearance of the letterbox background. + 0 - Solid background using color specified in R.color.config_letterboxBackgroundColor. + 1 - Color specified in R.attr.colorBackground for the letterboxed application. + 2 - Color specified in R.attr.colorBackgroundFloating for the letterboxed application. + If given value is outside of this range, the option 0 will be assummed. --> + <integer name="config_letterboxBackgroundType">0</integer> + + <!-- Color of the letterbox background if one following conditions is true + - Option 0 is selected for R.integer.config_letterboxBackgroundType. + - Option 1 is selected for R.integer.config_letterboxBackgroundType and + R.attr.colorBackground isn't specified for the app. + - Option 2 is selected for R.integer.config_letterboxBackgroundType and + R.attr.colorBackgroundFloating isn't specified for the app. + Defaults to black if not specified. + --> + <color name="config_letterboxBackgroundColor">#000</color> + <!-- If true, hide the display cutout with display area --> <bool name="config_hideDisplayCutoutWithDisplayArea">false</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index dfccdf4bd9a5..4611bf7e12e1 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4133,6 +4133,8 @@ <java-symbol type="dimen" name="config_taskLetterboxAspectRatio" /> <java-symbol type="integer" name="config_letterboxActivityCornersRadius" /> + <java-symbol type="integer" name="config_letterboxBackgroundType" /> + <java-symbol type="color" name="config_letterboxBackgroundColor" /> <java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" /> diff --git a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java index 0c351d149d8b..81eb213ce78a 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java @@ -132,7 +132,8 @@ public class ActivityManagerTest extends AndroidTestCase { true, // ensureNavigationBarContrastWhenTransparent RESIZE_MODE_RESIZEABLE, // resizeMode 10, // minWidth - 20 // minHeight + 20, // minHeight + 0 // colorBackgroundFloating ); TaskDescription td2 = new TaskDescription(); @@ -155,7 +156,8 @@ public class ActivityManagerTest extends AndroidTestCase { false, // ensureNavigationBarContrastWhenTransparent RESIZE_MODE_UNRESIZEABLE, // resizeMode 10, // minWidth - 20 // minHeight + 20, // minHeight + 0 // colorBackgroundFloating ); TaskDescription td2 = new TaskDescription( @@ -169,7 +171,8 @@ public class ActivityManagerTest extends AndroidTestCase { true, // ensureNavigationBarContrastWhenTransparent RESIZE_MODE_RESIZEABLE, // resizeMode 102, // minWidth - 202 // minHeight + 202, // minHeight + 0 // colorBackgroundFloating ); // Must overwrite all public and hidden fields, since other has all fields set. @@ -198,7 +201,8 @@ public class ActivityManagerTest extends AndroidTestCase { false, // ensureNavigationBarContrastWhenTransparent RESIZE_MODE_UNRESIZEABLE, // resizeMode 10, // minWidth - 20 // minHeight + 20, // minHeight + 0 // colorBackgroundFloating ); // Normal parceling should keep everything the same. @@ -219,7 +223,8 @@ public class ActivityManagerTest extends AndroidTestCase { false, // ensureNavigationBarContrastWhenTransparent RESIZE_MODE_UNRESIZEABLE, // resizeMode 10, // minWidth - 20 // minHeight + 20, // minHeight + 0 // colorBackgroundFloating ); // Recycled bitmap will be ignored while parceling. tdParcelled = new TaskDescription(parcelingRoundTrip(tdBitmapRecycled)); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b1da2f0fe888..f043a60d5c5e 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -204,6 +204,9 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 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.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY; @@ -249,6 +252,7 @@ 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; @@ -321,6 +325,7 @@ 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; @@ -859,6 +864,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.print(Integer.toHexString(taskDescription.getStatusBarColor())); pw.print(" navigationBarColor="); pw.println(Integer.toHexString(taskDescription.getNavigationBarColor())); + pw.print(" backgroundColorFloating="); + pw.println(Integer.toHexString( + taskDescription.getBackgroundColorFloating())); } } if (results != null) { @@ -1361,7 +1369,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mLetterbox == null) { mLetterbox = new Letterbox(() -> makeChildSurface(null), mWmService.mTransactionFactory, - mWmService::isLetterboxActivityCornersRounded); + mWmService::isLetterboxActivityCornersRounded, + this::getLetterboxBackgroundColor); mLetterbox.attachInput(w); } getPosition(mTmpPoint); @@ -1381,6 +1390,31 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } + 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()); + } + return mWmService.getLetterboxBackgroundColor(); + case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: + if (taskDescription != null && taskDescription.getBackgroundColor() != 0) { + return Color.valueOf(taskDescription.getBackgroundColor()); + } + // Falling through + case LETTERBOX_BACKGROUND_SOLID_COLOR: + return mWmService.getLetterboxBackgroundColor(); + } + throw new AssertionError( + "Unexpected letterbox background type: " + letterboxBackgroundType); + } + /** @return {@code true} when main window is letterboxed and activity isn't transparent. */ private boolean isLetterboxed(WindowState mainWindow) { return mainWindow.isLetterboxedAppWindow() && fillsParent(); diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java index 02a43b74aa33..2274a4a91595 100644 --- a/services/core/java/com/android/server/wm/Letterbox.java +++ b/services/core/java/com/android/server/wm/Letterbox.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.os.IInputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.view.SurfaceControl.HIDDEN; +import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; @@ -45,6 +46,8 @@ public class Letterbox { private final Supplier<SurfaceControl.Builder> mSurfaceControlFactory; private final Supplier<SurfaceControl.Transaction> mTransactionFactory; private final Supplier<Boolean> mAreCornersRounded; + private final Supplier<Color> mColorSupplier; + private final Rect mOuter = new Rect(); private final Rect mInner = new Rect(); private final LetterboxSurface mTop = new LetterboxSurface("top"); @@ -64,10 +67,12 @@ public class Letterbox { */ public Letterbox(Supplier<SurfaceControl.Builder> surfaceControlFactory, Supplier<SurfaceControl.Transaction> transactionFactory, - Supplier<Boolean> areCornersRounded) { + Supplier<Boolean> areCornersRounded, + Supplier<Color> colorSupplier) { mSurfaceControlFactory = surfaceControlFactory; mTransactionFactory = transactionFactory; mAreCornersRounded = areCornersRounded; + mColorSupplier = colorSupplier; } /** @@ -268,6 +273,7 @@ public class Letterbox { private final String mType; private SurfaceControl mSurface; + private Color mColor; private final Rect mSurfaceFrameRelative = new Rect(); private final Rect mLayoutFrameGlobal = new Rect(); @@ -292,9 +298,8 @@ public class Letterbox { .setColorLayer() .setCallsite("LetterboxSurface.createSurface") .build(); - t.setLayer(mSurface, -1) - .setColor(mSurface, new float[]{0, 0, 0}) - .setColorSpaceAgnostic(mSurface, true); + + t.setLayer(mSurface, -1).setColorSpaceAgnostic(mSurface, true); } void attachInput(WindowState win) { @@ -344,6 +349,14 @@ public class Letterbox { if (mSurface == null) { createSurface(t); } + + mColor = mColorSupplier.get(); + final float[] rgbTmpFloat = new float[3]; + rgbTmpFloat[0] = mColor.red(); + rgbTmpFloat[1] = mColor.green(); + rgbTmpFloat[2] = mColor.blue(); + t.setColor(mSurface, rgbTmpFloat); + t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top); t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(), mSurfaceFrameRelative.height()); @@ -358,7 +371,8 @@ public class Letterbox { } public boolean needsApplySurfaceChanges() { - return !mSurfaceFrameRelative.equals(mLayoutFrameRelative); + return !mSurfaceFrameRelative.equals(mLayoutFrameRelative) + || mColorSupplier.get() != mColor; } } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 6a3110f52c91..689442619a4a 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2090,7 +2090,9 @@ class Task extends WindowContainer<WindowContainer> { td.setEnsureNavigationBarContrastWhenTransparent( atd.getEnsureNavigationBarContrastWhenTransparent()); } - + if (td.getBackgroundColorFloating() == 0) { + td.setBackgroundColorFloating(atd.getBackgroundColorFloating()); + } } // End search once we get to root. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 931f52933e2a..b334c2a5516b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -160,6 +160,7 @@ 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; @@ -1010,10 +1011,30 @@ public class WindowManagerService extends IWindowManager.Stub // Aspect ratio of task level letterboxing, values <= MIN_TASK_LETTERBOX_ASPECT_RATIO will be // ignored. - private float mTaskLetterboxAspectRatio; + private volatile float mTaskLetterboxAspectRatio; + + /** Enum for Letterbox background type. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({LETTERBOX_BACKGROUND_SOLID_COLOR, LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND, + LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING}) + @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; // Corners radius for activities presented in the letterbox mode, values < 0 will be ignored. - private int mLetterboxActivityCornersRadius; + private volatile int mLetterboxActivityCornersRadius; + + // Color for {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} letterbox background type. + private volatile Color mLetterboxBackgroundColor; + + @LetterboxBackgroundType + private volatile int mLetterboxBackgroundType; final InputManagerService mInputManager; final DisplayManagerInternal mDisplayManagerInternal; @@ -1240,10 +1261,15 @@ public class WindowManagerService extends IWindowManager.Stub com.android.internal.R.bool.config_perDisplayFocusEnabled); mAssistantOnTopOfDream = context.getResources().getBoolean( com.android.internal.R.bool.config_assistantOnTopOfDream); + mTaskLetterboxAspectRatio = context.getResources().getFloat( com.android.internal.R.dimen.config_taskLetterboxAspectRatio); 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); + mInputManager = inputManager; // Must be before createDisplayContentLocked. mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); @@ -3901,14 +3927,7 @@ public class WindowManagerService extends IWindowManager.Stub * the framework implementation will be used to determine the aspect ratio. */ void setTaskLetterboxAspectRatio(float aspectRatio) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - mTaskLetterboxAspectRatio = aspectRatio; - } - } finally { - Binder.restoreCallingIdentity(origId); - } + mTaskLetterboxAspectRatio = aspectRatio; } /** @@ -3916,29 +3935,15 @@ public class WindowManagerService extends IWindowManager.Stub * com.android.internal.R.dimen.config_taskLetterboxAspectRatio}. */ void resetTaskLetterboxAspectRatio() { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - mTaskLetterboxAspectRatio = mContext.getResources().getFloat( - com.android.internal.R.dimen.config_taskLetterboxAspectRatio); - } - } finally { - Binder.restoreCallingIdentity(origId); - } + mTaskLetterboxAspectRatio = mContext.getResources().getFloat( + com.android.internal.R.dimen.config_taskLetterboxAspectRatio); } /** * Gets the aspect ratio of task level letterboxing. */ float getTaskLetterboxAspectRatio() { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - return mTaskLetterboxAspectRatio; - } - } finally { - Binder.restoreCallingIdentity(origId); - } + return mTaskLetterboxAspectRatio; } /** @@ -3948,14 +3953,7 @@ public class WindowManagerService extends IWindowManager.Stub * and corners of the activity won't be rounded. */ void setLetterboxActivityCornersRadius(int cornersRadius) { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - mLetterboxActivityCornersRadius = cornersRadius; - } - } finally { - Binder.restoreCallingIdentity(origId); - } + mLetterboxActivityCornersRadius = cornersRadius; } /** @@ -3963,15 +3961,8 @@ public class WindowManagerService extends IWindowManager.Stub * com.android.internal.R.integer.config_letterboxActivityCornersRadius}. */ void resetLetterboxActivityCornersRadius() { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - mLetterboxActivityCornersRadius = mContext.getResources().getInteger( - com.android.internal.R.integer.config_letterboxActivityCornersRadius); - } - } finally { - Binder.restoreCallingIdentity(origId); - } + mLetterboxActivityCornersRadius = mContext.getResources().getInteger( + com.android.internal.R.integer.config_letterboxActivityCornersRadius); } /** @@ -3985,14 +3976,67 @@ public class WindowManagerService extends IWindowManager.Stub * Gets corners raidus for activities presented in the letterbox mode. */ int getLetterboxActivityCornersRadius() { - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - return mLetterboxActivityCornersRadius; - } - } finally { - Binder.restoreCallingIdentity(origId); - } + 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_SOLID_COLOR; } @Override diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index badd29aba968..645786c02fc0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -18,6 +18,11 @@ package com.android.server.wm; import static android.os.Build.IS_USER; +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 android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.os.ParcelFileDescriptor; @@ -34,6 +39,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 java.io.IOException; import java.io.PrintWriter; @@ -119,6 +125,14 @@ public class WindowManagerShellCommand extends ShellCommand { 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 "reset": return runReset(pw); default: @@ -581,6 +595,79 @@ public class WindowManagerShellCommand extends ShellCommand { return 0; } + private int runSetLetterboxBackgroundType(PrintWriter pw) throws RemoteException { + @LetterboxBackgroundType final int backgroundType; + + String arg = getNextArgRequired(); + if ("reset".equals(arg)) { + 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; + default: + getErrPrintWriter().println( + "Error: 'reset', 'solid_color' or 'app_color_background' should " + + "be provided as an argument"); + return -1; + } + + mInternal.setLetterboxBackgroundType(backgroundType); + return 0; + } + + private int runGetLetterboxBackgroundType(PrintWriter pw) throws RemoteException { + @LetterboxBackgroundType final int backgroundType = mInternal.getLetterboxBackgroundType(); + switch (backgroundType) { + case LETTERBOX_BACKGROUND_SOLID_COLOR: + pw.println("Letterbox background type is 'solid_color'"); + break; + case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: + pw.println("Letterbox background type is 'app_color_background'"); + break; + case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING: + pw.println("Letterbox background type is 'app_color_background_floating'"); + break; + default: + throw new AssertionError("Unexpected letterbox background type: " + backgroundType); + } + return 0; + } + + private int runSetLetterboxBackgroundColor(PrintWriter pw) throws RemoteException { + final Color color; + String arg = getNextArgRequired(); + try { + if ("reset".equals(arg)) { + mInternal.resetLetterboxBackgroundColor(); + return 0; + } + 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); + return -1; + } + + mInternal.setLetterboxBackgroundColor(color); + return 0; + } + + private int runGetLetterboxBackgroundColor(PrintWriter pw) throws RemoteException { + final Color color = mInternal.getLetterboxBackgroundColor(); + pw.println("Letterbox background color is " + Integer.toHexString(color.toArgb())); + return 0; + } + private int runReset(PrintWriter pw) throws RemoteException { int displayId = getDisplayId(getNextArg()); @@ -611,6 +698,12 @@ public class WindowManagerShellCommand extends ShellCommand { // set-letterbox-activity-corners-radius mInternal.resetLetterboxActivityCornersRadius(); + // set-letterbox-background-type + mInternal.resetLetterboxBackgroundType(); + + // set-letterbox-background-color + mInternal.resetLetterboxBackgroundColor(); + pw.println("Reset all settings for displayId=" + displayId); return 0; } @@ -652,6 +745,16 @@ public class WindowManagerShellCommand extends ShellCommand { 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]"); + pw.println(" get-letterbox-background-type"); + pw.println(" Type of background used in the letterbox mode."); pw.println(" reset [-d DISPLAY_ID]"); pw.println(" Reset all override settings."); if (!IS_USER) { diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java index a045100c4cd8..fa3e3aefea3b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; @@ -51,11 +52,13 @@ public class LetterboxTest { SurfaceControl.Transaction mTransaction; private boolean mAreCornersRounded = false; + private int mColor = Color.BLACK; @Before public void setUp() throws Exception { mSurfaces = new SurfaceControlMocker(); - mLetterbox = new Letterbox(mSurfaces, StubTransaction::new, () -> mAreCornersRounded); + mLetterbox = new Letterbox(mSurfaces, StubTransaction::new, + () -> mAreCornersRounded, () -> Color.valueOf(mColor)); mTransaction = spy(StubTransaction.class); } @@ -171,6 +174,18 @@ public class LetterboxTest { } @Test + public void testApplySurfaceChanges_setColor() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + mLetterbox.applySurfaceChanges(mTransaction); + + verify(mTransaction).setColor(mSurfaces.top, new float[]{0, 0, 0}); + + mColor = Color.GREEN; + + assertTrue(mLetterbox.needsApplySurfaceChanges()); + } + + @Test public void testApplySurfaceChanges_cornersNotRounded_surfaceBehindNotCreated() { mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); mLetterbox.applySurfaceChanges(mTransaction); |