diff --git a/packages/SystemUI/res/drawable/rounded_corner_bottom.xml b/packages/SystemUI/res/drawable/rounded_corner_bottom.xml
new file mode 100644
index 0000000000000..ef1a82f9798c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/rounded_corner_bottom.xml
@@ -0,0 +1,16 @@
+
+
+
diff --git a/packages/SystemUI/res/drawable/rounded_corner_top.xml b/packages/SystemUI/res/drawable/rounded_corner_top.xml
new file mode 100644
index 0000000000000..79348928a7a8f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/rounded_corner_top.xml
@@ -0,0 +1,16 @@
+
+
+
diff --git a/packages/SystemUI/res/layout/rounded_corners.xml b/packages/SystemUI/res/layout/rounded_corners.xml
index 1849068d91b83..db892d78c5563 100644
--- a/packages/SystemUI/res/layout/rounded_corners.xml
+++ b/packages/SystemUI/res/layout/rounded_corners.xml
@@ -16,6 +16,7 @@
-->
+
+
+
+
+
diff --git a/packages/SystemUI/res/layout/rounded_corners_top.xml b/packages/SystemUI/res/layout/rounded_corners_top.xml
new file mode 100644
index 0000000000000..813c97d06f579
--- /dev/null
+++ b/packages/SystemUI/res/layout/rounded_corners_top.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 7861211e802da..6c06553a84a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -48,10 +48,11 @@ import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
-import android.graphics.drawable.VectorDrawable;
+import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.HandlerExecutor;
@@ -117,12 +118,15 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private DisplayManager.DisplayListener mDisplayListener;
private CameraAvailabilityListener mCameraListener;
+ //TODO: These are piecemeal being updated to Points for now to support non-square rounded
+ // corners. for now it is only supposed when reading the intrinsic size from the drawables with
+ // mIsRoundedCornerMultipleRadius is set
@VisibleForTesting
- protected int mRoundedDefault;
+ protected Point mRoundedDefault = new Point(0, 0);
@VisibleForTesting
- protected int mRoundedDefaultTop;
+ protected Point mRoundedDefaultTop = new Point(0, 0);
@VisibleForTesting
- protected int mRoundedDefaultBottom;
+ protected Point mRoundedDefaultBottom = new Point(0, 0);
@VisibleForTesting
protected View[] mOverlays;
@Nullable
@@ -375,8 +379,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
if (mOverlays[pos] != null) {
return;
}
- mOverlays[pos] = LayoutInflater.from(mContext)
- .inflate(R.layout.rounded_corners, null);
+ mOverlays[pos] = overlayForPosition(pos);
mCutoutViews[pos] = new DisplayCutoutView(mContext, pos, this);
((ViewGroup) mOverlays[pos]).addView(mCutoutViews[pos]);
@@ -405,6 +408,23 @@ public class ScreenDecorations extends SystemUI implements Tunable {
new ValidatingPreDrawListener(mOverlays[pos]));
}
+ /**
+ * Allow overrides for top/bottom positions
+ */
+ private View overlayForPosition(@BoundsPosition int pos) {
+ switch (pos) {
+ case BOUNDS_POSITION_TOP:
+ return LayoutInflater.from(mContext)
+ .inflate(R.layout.rounded_corners_top, null);
+ case BOUNDS_POSITION_BOTTOM:
+ return LayoutInflater.from(mContext)
+ .inflate(R.layout.rounded_corners_bottom, null);
+ default:
+ return LayoutInflater.from(mContext)
+ .inflate(R.layout.rounded_corners, null);
+ }
+ }
+
private void updateView(@BoundsPosition int pos) {
if (mOverlays == null || mOverlays[pos] == null) {
return;
@@ -590,27 +610,36 @@ public class ScreenDecorations extends SystemUI implements Tunable {
}
private void updateRoundedCornerRadii() {
+ // We should eventually move to just using the intrinsic size of the drawables since
+ // they should be sized to the exact pixels they want to cover. Therefore I'm purposely not
+ // upgrading all of the configs to contain (width, height) pairs. Instead assume that a
+ // device configured using the single integer config value is okay with drawing the corners
+ // as a square
final int newRoundedDefault = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.rounded_corner_radius);
final int newRoundedDefaultTop = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.rounded_corner_radius_top);
final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.rounded_corner_radius_bottom);
- final boolean roundedCornersChanged = mRoundedDefault != newRoundedDefault
- || mRoundedDefaultBottom != newRoundedDefaultBottom
- || mRoundedDefaultTop != newRoundedDefaultTop;
- if (roundedCornersChanged) {
+ final boolean changed = mRoundedDefault.x != newRoundedDefault
+ || mRoundedDefaultTop.x != newRoundedDefault
+ || mRoundedDefaultBottom.x != newRoundedDefault;
+
+ if (changed) {
// If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
- // max(width, height) size of drawable/rounded.xml instead of rounded_corner_radius
+ // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
if (mIsRoundedCornerMultipleRadius) {
- final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded);
- mRoundedDefault = Math.max(d.getIntrinsicWidth(), d.getIntrinsicHeight());
- mRoundedDefaultTop = mRoundedDefaultBottom = mRoundedDefault;
+ Drawable d = mContext.getDrawable(R.drawable.rounded);
+ mRoundedDefault.set(d.getIntrinsicWidth(), d.getIntrinsicHeight());
+ d = mContext.getDrawable(R.drawable.rounded_corner_top);
+ mRoundedDefaultTop.set(d.getIntrinsicWidth(), d.getIntrinsicHeight());
+ d = mContext.getDrawable(R.drawable.rounded_corner_bottom);
+ mRoundedDefaultBottom.set(d.getIntrinsicWidth(), d.getIntrinsicHeight());
} else {
- mRoundedDefault = newRoundedDefault;
- mRoundedDefaultTop = newRoundedDefaultTop;
- mRoundedDefaultBottom = newRoundedDefaultBottom;
+ mRoundedDefault.set(newRoundedDefault, newRoundedDefault);
+ mRoundedDefaultTop.set(newRoundedDefaultTop, newRoundedDefaultTop);
+ mRoundedDefaultBottom.set(newRoundedDefaultBottom, newRoundedDefaultBottom);
}
onTuningChanged(SIZE, null);
}
@@ -625,7 +654,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
if (shouldShowRoundedCorner(pos)) {
final int gravity = getRoundedCornerGravity(pos, id == R.id.left);
((FrameLayout.LayoutParams) rounded.getLayoutParams()).gravity = gravity;
- rounded.setRotation(getRoundedCornerRotation(gravity));
+ setRoundedCornerOrientation(rounded, gravity);
rounded.setVisibility(View.VISIBLE);
}
}
@@ -646,23 +675,38 @@ public class ScreenDecorations extends SystemUI implements Tunable {
}
}
- private int getRoundedCornerRotation(int gravity) {
+ /**
+ * Configures the rounded corner drawable's view matrix based on the gravity.
+ *
+ * The gravity describes which corner to configure for, and the drawable we are rotating is
+ * assumed to be oriented for the top-left corner of the device regardless of the target corner.
+ * Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or
+ * y-axis for the top-right and bottom-left corners.
+ */
+ private void setRoundedCornerOrientation(View corner, int gravity) {
+ corner.setRotation(0);
+ corner.setScaleX(1);
+ corner.setScaleY(1);
switch (gravity) {
case Gravity.TOP | Gravity.LEFT:
- return 0;
+ return;
case Gravity.TOP | Gravity.RIGHT:
- return 90;
+ corner.setScaleX(-1); // flip X axis
+ return;
case Gravity.BOTTOM | Gravity.LEFT:
- return 270;
+ corner.setScaleY(-1); // flip Y axis
+ return;
case Gravity.BOTTOM | Gravity.RIGHT:
- return 180;
+ corner.setRotation(180);
+ return;
default:
throw new IllegalArgumentException("Unsupported gravity: " + gravity);
}
}
-
private boolean hasRoundedCorners() {
- return mRoundedDefault > 0 || mRoundedDefaultBottom > 0 || mRoundedDefaultTop > 0
+ return mRoundedDefault.x > 0
+ || mRoundedDefaultBottom.x > 0
+ || mRoundedDefaultTop.x > 0
|| mIsRoundedCornerMultipleRadius;
}
@@ -712,12 +756,13 @@ public class ScreenDecorations extends SystemUI implements Tunable {
mHandler.post(() -> {
if (mOverlays == null) return;
if (SIZE.equals(key)) {
- int size = mRoundedDefault;
- int sizeTop = mRoundedDefaultTop;
- int sizeBottom = mRoundedDefaultBottom;
+ Point size = mRoundedDefault;
+ Point sizeTop = mRoundedDefaultTop;
+ Point sizeBottom = mRoundedDefaultBottom;
if (newValue != null) {
try {
- size = (int) (Integer.parseInt(newValue) * mDensity);
+ int s = (int) (Integer.parseInt(newValue) * mDensity);
+ size = new Point(s, s);
} catch (Exception e) {
}
}
@@ -726,14 +771,17 @@ public class ScreenDecorations extends SystemUI implements Tunable {
});
}
- private void updateRoundedCornerSize(int sizeDefault, int sizeTop, int sizeBottom) {
+ private void updateRoundedCornerSize(
+ Point sizeDefault,
+ Point sizeTop,
+ Point sizeBottom) {
if (mOverlays == null) {
return;
}
- if (sizeTop == 0) {
+ if (sizeTop.x == 0) {
sizeTop = sizeDefault;
}
- if (sizeBottom == 0) {
+ if (sizeBottom.x == 0) {
sizeBottom = sizeDefault;
}
@@ -760,10 +808,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
}
@VisibleForTesting
- protected void setSize(View view, int pixelSize) {
+ protected void setSize(View view, Point pixelSize) {
LayoutParams params = view.getLayoutParams();
- params.width = pixelSize;
- params.height = pixelSize;
+ params.width = pixelSize.x;
+ params.height = pixelSize.y;
view.setLayoutParams(params);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index b9ddff3a59ea8..d107f646bb6b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -44,6 +44,7 @@ import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.graphics.Insets;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.VectorDrawable;
import android.hardware.display.DisplayManager;
@@ -193,6 +194,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
@Test
public void testRoundingRadius_NoCutout() {
final int testRadius = 1;
+ final Point testRadiusPoint = new Point(1, 1);
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
mContext.getOrCreateTestableResources().addOverride(
@@ -209,9 +211,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mScreenDecorations.start();
// Size of corner view should same as rounded_corner_radius{_top|_bottom}
- assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(testRadius);
- assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(testRadius);
- assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(testRadius);
+ assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(testRadiusPoint);
+ assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(testRadiusPoint);
+ assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(testRadiusPoint);
}
@Test
@@ -237,14 +239,18 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].findViewById(R.id.left);
View rightRoundedCorner =
mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].findViewById(R.id.right);
- verify(mScreenDecorations, atLeastOnce()).setSize(leftRoundedCorner, testTopRadius);
- verify(mScreenDecorations, atLeastOnce()).setSize(rightRoundedCorner, testTopRadius);
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(leftRoundedCorner, new Point(testTopRadius, testTopRadius));
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(rightRoundedCorner, new Point(testTopRadius, testTopRadius));
leftRoundedCorner =
mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].findViewById(R.id.left);
rightRoundedCorner =
mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].findViewById(R.id.right);
- verify(mScreenDecorations, atLeastOnce()).setSize(leftRoundedCorner, testBottomRadius);
- verify(mScreenDecorations, atLeastOnce()).setSize(rightRoundedCorner, testBottomRadius);
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(leftRoundedCorner, new Point(testBottomRadius, testBottomRadius));
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(rightRoundedCorner, new Point(testBottomRadius, testBottomRadius));
}
@Test
@@ -276,20 +282,24 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].findViewById(R.id.left);
View rightRoundedCorner =
mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].findViewById(R.id.right);
- verify(mScreenDecorations, atLeastOnce()).setSize(leftRoundedCorner, testTopRadius);
- verify(mScreenDecorations, atLeastOnce()).setSize(rightRoundedCorner, testBottomRadius);
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(leftRoundedCorner, new Point(testTopRadius, testTopRadius));
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(rightRoundedCorner, new Point(testBottomRadius, testBottomRadius));
leftRoundedCorner =
mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].findViewById(R.id.left);
rightRoundedCorner =
mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].findViewById(R.id.right);
- verify(mScreenDecorations, atLeastOnce()).setSize(leftRoundedCorner, testTopRadius);
- verify(mScreenDecorations, atLeastOnce()).setSize(rightRoundedCorner, testBottomRadius);
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(leftRoundedCorner, new Point(testTopRadius, testTopRadius));
+ verify(mScreenDecorations, atLeastOnce())
+ .setSize(rightRoundedCorner, new Point(testBottomRadius, testBottomRadius));
}
@Test
public void testRoundingMultipleRadius_NoCutout() {
final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded);
- final int multipleRadiusSize = Math.max(d.getIntrinsicWidth(), d.getIntrinsicHeight());
+ final Point multipleRadiusSize = new Point(d.getIntrinsicWidth(), d.getIntrinsicHeight());
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
@@ -600,14 +610,15 @@ public class ScreenDecorationsTest extends SysuiTestCase {
.addOverride(R.bool.config_roundedCornerMultipleRadius, false);
mScreenDecorations.start();
- assertEquals(mScreenDecorations.mRoundedDefault, 20);
+ assertEquals(mScreenDecorations.mRoundedDefault, new Point(20, 20));
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.dimen.rounded_corner_radius, 5);
mScreenDecorations.onConfigurationChanged(null);
- assertEquals(mScreenDecorations.mRoundedDefault, 5);
+ assertEquals(mScreenDecorations.mRoundedDefault, new Point(5, 5));
}
+
@Test
public void testBoundingRectsToRegion() throws Exception {
Rect rect = new Rect(1, 2, 3, 4);