summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mariia Sandrikova <mariiasand@google.com> 2021-02-02 01:20:26 +0000
committer Mariia Sandrikova <mariiasand@google.com> 2021-02-02 23:54:25 +0000
commitc0f663fd35ffb995371a816b0b74e1771abe443f (patch)
treeb15fd35eecdfa0d02965f23cbfb7462c33d3c6cf
parent5e8177bf787c384f914fa9bb388a871afd6e25fa (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.java7
-rw-r--r--core/java/android/app/ActivityManager.java64
-rw-r--r--core/res/res/values/attrs.xml3
-rw-r--r--core/res/res/values/config.xml17
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityManagerTest.java15
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java36
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java24
-rw-r--r--services/core/java/com/android/server/wm/Task.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java148
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java103
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java17
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);