diff --git a/packages/SystemUI/res/layout/rounded_corners_bottom.xml b/packages/SystemUI/res/layout/rounded_corners_bottom.xml
deleted file mode 100644
index bb6d4bddf25ad..0000000000000
--- a/packages/SystemUI/res/layout/rounded_corners_bottom.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/packages/SystemUI/res/layout/rounded_corners_top.xml b/packages/SystemUI/res/layout/rounded_corners_top.xml
deleted file mode 100644
index 46648c88d921e..0000000000000
--- a/packages/SystemUI/res/layout/rounded_corners_top.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 926734c2749f0..096b9a0c47905 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -167,5 +167,11 @@
+
+
+
+
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
index 1094622a8ef08..ae4c365ff2708 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
@@ -365,10 +365,15 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec
* Update the rounded corner size.
*/
fun updateRoundedCornerSize(top: Int, bottom: Int) {
+ if (roundedCornerTopSize == top && roundedCornerBottomSize == bottom) {
+ return
+ }
roundedCornerTopSize = top
roundedCornerBottomSize = bottom
updateRoundedCornerDrawableBounds()
- invalidate()
+
+ // Use requestLayout() to trigger transparent region recalculated
+ requestLayout()
}
private fun updateRoundedCornerDrawableBounds() {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 2f5292cec9098..5de09b13bf6a6 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -77,6 +77,7 @@ import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.DecorProviderKt;
import com.android.systemui.decor.OverlayWindow;
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
+import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerResDelegate;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.settings.UserTracker;
@@ -138,6 +139,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
@VisibleForTesting
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
@VisibleForTesting
+ protected DecorProviderFactory mRoundedCornerFactory;
+ private int mProviderRefreshToken = 0;
+ @VisibleForTesting
protected OverlayWindow[] mOverlays = null;
@Nullable
private DisplayCutoutView[] mCutoutViews;
@@ -292,11 +296,11 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mDisplayUniqueId = mContext.getDisplay().getUniqueId();
mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
mDisplayUniqueId);
+ mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
mWindowManager = mContext.getSystemService(WindowManager.class);
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
- updateRoundedCornerDrawable();
- updateRoundedCornerRadii();
+ updateHwLayerRoundedCornerDrawable();
setupDecorations();
setupCameraListener();
@@ -348,7 +352,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
final String newUniqueId = mContext.getDisplay().getUniqueId();
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
mDisplayUniqueId = newUniqueId;
- mRoundedCornerResDelegate.reloadAll(newUniqueId);
+ mRoundedCornerResDelegate.updateDisplayUniqueId(newUniqueId, null);
final DisplayDecorationSupport newScreenDecorationSupport =
mContext.getDisplay().getDisplayDecorationSupport();
// When the value of mSupportHwcScreenDecoration is changed, re-setup the whole
@@ -359,12 +363,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
setupDecorations();
return;
}
- updateRoundedCornerDrawable();
+ updateHwLayerRoundedCornerDrawable();
}
if (mScreenDecorHwcLayer != null) {
mScreenDecorHwcLayer.onDisplayChanged(displayId);
}
- updateOrientation();
+ updateView();
}
};
@@ -406,22 +410,22 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
private void setupDecorations() {
- List decorProviders = mDotFactory.getProviders();
-
- if (hasRoundedCorners() || shouldDrawCutout() || !decorProviders.isEmpty()) {
+ if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()) {
+ List decorProviders = new ArrayList<>(mDotFactory.getProviders());
if (mHwcScreenDecorationSupport != null) {
createHwcOverlay();
} else {
removeHwcOverlay();
+ decorProviders.addAll(mRoundedCornerFactory.getProviders());
}
final DisplayCutout cutout = getCutout();
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (shouldShowCutout(i, cutout) || shouldShowRoundedCorner(i, cutout)
- || shouldShowPrivacyDot(i, cutout)) {
+ if (shouldShowSwLayerCutout(i, cutout) || shouldShowSwLayerRoundedCorner(i, cutout)
+ || shouldShowSwLayerPrivacyDot(i, cutout)) {
Pair, List> pair =
DecorProviderKt.partitionAlignedBound(decorProviders, i);
decorProviders = pair.getSecond();
- createOverlay(i, cutout, pair.getFirst());
+ createOverlay(i, pair.getFirst());
} else {
removeOverlay(i);
}
@@ -522,7 +526,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
private void createOverlay(
@BoundsPosition int pos,
- @Nullable DisplayCutout cutout,
@NonNull List decorProviders) {
if (mOverlays == null) {
mOverlays = new OverlayWindow[BOUNDS_POSITION_LENGTH];
@@ -547,7 +550,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
mCutoutViews[pos].setColor(mTintColor);
overlayView.addView(mCutoutViews[pos]);
- updateView(pos, cutout);
+ mCutoutViews[pos].updateRotation(mRotation);
}
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
@@ -603,7 +606,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
private OverlayWindow overlayForPosition(
@BoundsPosition int pos,
@NonNull List decorProviders) {
- final OverlayWindow currentOverlay = new OverlayWindow(LayoutInflater.from(mContext), pos);
+ final OverlayWindow currentOverlay = new OverlayWindow(mContext);
decorProviders.forEach(provider -> {
removeOverlayView(provider.getViewId());
currentOverlay.addDecorProvider(provider, mRotation);
@@ -617,22 +620,16 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return currentOverlay;
}
- private void updateView(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
- if (mOverlays == null || mOverlays[pos] == null || mHwcScreenDecorationSupport != null) {
+ private void updateView() {
+ if (mOverlays == null) {
return;
}
-
- // update rounded corner view rotation
- updateRoundedCornerView(pos, R.id.left, cutout);
- updateRoundedCornerView(pos, R.id.right, cutout);
- updateRoundedCornerSize(
- mRoundedCornerResDelegate.getTopRoundedSize(),
- mRoundedCornerResDelegate.getBottomRoundedSize());
- updateRoundedCornerImageView();
-
- // update cutout view rotation
- if (mCutoutViews != null && mCutoutViews[pos] != null) {
- mCutoutViews[pos].updateRotation(mRotation);
+ ++mProviderRefreshToken;
+ for (final OverlayWindow overlay: mOverlays) {
+ if (overlay == null) {
+ continue;
+ }
+ overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
}
}
@@ -806,7 +803,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
int oldRotation = mRotation;
mPendingRotationChange = false;
updateOrientation();
- updateRoundedCornerRadii();
if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
setupDecorations();
if (mOverlays != null) {
@@ -866,109 +862,32 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mDotViewController.setNewRotation(newRotation);
}
- if (mPendingRotationChange) {
- return;
- }
- if (newRotation != mRotation) {
+ if (!mPendingRotationChange && newRotation != mRotation) {
mRotation = newRotation;
if (mScreenDecorHwcLayer != null) {
mScreenDecorHwcLayer.pendingRotationChange = false;
mScreenDecorHwcLayer.updateRotation(mRotation);
+ updateHwLayerRoundedCornerSize();
+ updateHwLayerRoundedCornerDrawable();
}
- if (mOverlays != null) {
- updateLayoutParams();
- final DisplayCutout cutout = getCutout();
- for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (mOverlays[i] == null) {
+ updateLayoutParams();
+ // update cutout view rotation
+ if (mCutoutViews != null) {
+ for (final DisplayCutoutView cutoutView: mCutoutViews) {
+ if (cutoutView == null) {
continue;
}
- updateView(i, cutout);
+ cutoutView.updateRotation(mRotation);
}
}
}
+
+ // update views
+ updateView();
}
- 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 Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
- final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
- mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
- final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
- final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
-
- if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth()
- || oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) {
- onTuningChanged(SIZE, null);
- }
- }
-
- private void updateRoundedCornerView(@BoundsPosition int pos, int id,
- @Nullable DisplayCutout cutout) {
- final View rounded = mOverlays[pos].getRootView().findViewById(id);
- if (rounded == null) {
- return;
- }
- rounded.setVisibility(View.GONE);
- if (shouldShowRoundedCorner(pos, cutout)) {
- final int gravity = getRoundedCornerGravity(pos, id == R.id.left);
- ((FrameLayout.LayoutParams) rounded.getLayoutParams()).gravity = gravity;
- setRoundedCornerOrientation(rounded, gravity);
- rounded.setVisibility(View.VISIBLE);
- }
- }
-
- private int getRoundedCornerGravity(@BoundsPosition int pos, boolean isStart) {
- final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
- switch (rotatedPos) {
- case BOUNDS_POSITION_LEFT:
- return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.BOTTOM | Gravity.LEFT;
- case BOUNDS_POSITION_TOP:
- return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.TOP | Gravity.RIGHT;
- case BOUNDS_POSITION_RIGHT:
- return isStart ? Gravity.TOP | Gravity.RIGHT : Gravity.BOTTOM | Gravity.RIGHT;
- case BOUNDS_POSITION_BOTTOM:
- return isStart ? Gravity.BOTTOM | Gravity.LEFT : Gravity.BOTTOM | Gravity.RIGHT;
- default:
- throw new IllegalArgumentException("Incorrect position: " + rotatedPos);
- }
- }
-
- /**
- * 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;
- case Gravity.TOP | Gravity.RIGHT:
- corner.setScaleX(-1); // flip X axis
- return;
- case Gravity.BOTTOM | Gravity.LEFT:
- corner.setScaleY(-1); // flip Y axis
- return;
- case Gravity.BOTTOM | Gravity.RIGHT:
- corner.setRotation(180);
- return;
- default:
- throw new IllegalArgumentException("Unsupported gravity: " + gravity);
- }
- }
private boolean hasRoundedCorners() {
- return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0
- || mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0
- || mRoundedCornerResDelegate.isMultipleRadius();
+ return mRoundedCornerFactory.getHasProviders();
}
private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
@@ -987,17 +906,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
}
- private boolean shouldShowRoundedCorner(@BoundsPosition int pos,
+ private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
@Nullable DisplayCutout cutout) {
return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
&& mHwcScreenDecorationSupport == null;
}
- private boolean shouldShowPrivacyDot(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
+ private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
+ @Nullable DisplayCutout cutout) {
return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
}
- private boolean shouldShowCutout(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
+ private boolean shouldShowSwLayerCutout(@BoundsPosition int pos,
+ @Nullable DisplayCutout cutout) {
final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll();
final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
return (bounds != null && !bounds[rotatedPos].isEmpty()
@@ -1032,54 +953,33 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return;
}
mExecutor.execute(() -> {
- if (mOverlays == null) return;
- if (SIZE.equals(key)) {
- if (newValue != null) {
- try {
- mRoundedCornerResDelegate.updateTuningSizeFactor(
- Integer.parseInt(newValue));
- } catch (Exception e) {
- }
+ if (mOverlays == null || !SIZE.equals(key)) {
+ return;
+ }
+ ++mProviderRefreshToken;
+ try {
+ final int sizeFactor = Integer.parseInt(newValue);
+ mRoundedCornerResDelegate.updateTuningSizeFactor(sizeFactor, mProviderRefreshToken);
+ } catch (NumberFormatException e) {
+ mRoundedCornerResDelegate.updateTuningSizeFactor(null, mProviderRefreshToken);
+ }
+ Integer[] filterIds = {
+ R.id.rounded_corner_top_left,
+ R.id.rounded_corner_top_right,
+ R.id.rounded_corner_bottom_left,
+ R.id.rounded_corner_bottom_right
+ };
+ for (final OverlayWindow overlay: mOverlays) {
+ if (overlay == null) {
+ continue;
}
- updateRoundedCornerSize(
- mRoundedCornerResDelegate.getTopRoundedSize(),
- mRoundedCornerResDelegate.getBottomRoundedSize());
+ overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
+ mDisplayUniqueId);
}
+ updateHwLayerRoundedCornerSize();
});
}
- private void updateRoundedCornerDrawable() {
- mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
- updateRoundedCornerImageView();
- }
-
- private void updateRoundedCornerImageView() {
- final Drawable top = mRoundedCornerResDelegate.getTopRoundedDrawable();
- final Drawable bottom = mRoundedCornerResDelegate.getBottomRoundedDrawable();
-
- if (mScreenDecorHwcLayer != null) {
- mScreenDecorHwcLayer.updateRoundedCornerDrawable(top, bottom);
- return;
- }
-
- if (mOverlays == null) {
- return;
- }
- final ColorStateList colorStateList = ColorStateList.valueOf(mTintColor);
- for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (mOverlays[i] == null) {
- continue;
- }
- final ViewGroup overlayView = mOverlays[i].getRootView();
- ((ImageView) overlayView.findViewById(R.id.left)).setImageTintList(colorStateList);
- ((ImageView) overlayView.findViewById(R.id.right)).setImageTintList(colorStateList);
- ((ImageView) overlayView.findViewById(R.id.left)).setImageDrawable(
- isTopRoundedCorner(i, R.id.left) ? top : bottom);
- ((ImageView) overlayView.findViewById(R.id.right)).setImageDrawable(
- isTopRoundedCorner(i, R.id.right) ? top : bottom);
- }
- }
-
private void updateHwLayerRoundedCornerDrawable() {
if (mScreenDecorHwcLayer == null) {
return;
@@ -1094,25 +994,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable);
}
- @VisibleForTesting
- boolean isTopRoundedCorner(@BoundsPosition int pos, int id) {
- switch (pos) {
- case BOUNDS_POSITION_LEFT:
- case BOUNDS_POSITION_RIGHT:
- if (mRotation == ROTATION_270) {
- return id == R.id.left ? false : true;
- } else {
- return id == R.id.left ? true : false;
- }
- case BOUNDS_POSITION_TOP:
- return true;
- case BOUNDS_POSITION_BOTTOM:
- return false;
- default:
- throw new IllegalArgumentException("Unknown bounds position");
- }
- }
-
private void updateHwLayerRoundedCornerSize() {
if (mScreenDecorHwcLayer == null) {
return;
@@ -1124,28 +1005,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth);
}
- private void updateRoundedCornerSize(Size sizeTop, Size sizeBottom) {
-
- if (mScreenDecorHwcLayer != null) {
- mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.getWidth(), sizeBottom.getWidth());
- return;
- }
-
- if (mOverlays == null) {
- return;
- }
- for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (mOverlays[i] == null) {
- continue;
- }
- final ViewGroup overlayView = mOverlays[i].getRootView();
- setSize(overlayView.findViewById(R.id.left),
- isTopRoundedCorner(i, R.id.left) ? sizeTop : sizeBottom);
- setSize(overlayView.findViewById(R.id.right),
- isTopRoundedCorner(i, R.id.right) ? sizeTop : sizeBottom);
- }
- }
-
@VisibleForTesting
protected void setSize(View view, Size pixelSize) {
LayoutParams params = view.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
index 3543bb4ab9e96..03ee8b11ab415 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
@@ -15,8 +15,8 @@
*/
package com.android.systemui.decor
+import android.content.Context
import android.view.DisplayCutout
-import android.view.LayoutInflater
import android.view.Surface
import android.view.View
import android.view.ViewGroup
@@ -38,9 +38,20 @@ abstract class DecorProvider {
/** The aligned bounds for the view which is created through inflateView() */
abstract val alignedBounds: List
+ /**
+ * Called when res info changed.
+ * Child provider needs to implement it if its view needs to be updated.
+ */
+ abstract fun onReloadResAndMeasure(
+ view: View,
+ reloadToken: Int,
+ @Surface.Rotation rotation: Int,
+ displayUniqueId: String? = null
+ )
+
/** Inflate view into parent as current rotation */
abstract fun inflateView(
- inflater: LayoutInflater,
+ context: Context,
parent: ViewGroup,
@Surface.Rotation rotation: Int
): View
diff --git a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
index 9f8679cdea4a9..f38ff14726ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
@@ -16,31 +16,22 @@
package com.android.systemui.decor
import android.annotation.IdRes
-import android.view.DisplayCutout
-import android.view.LayoutInflater
+import android.content.Context
import android.view.Surface
import android.view.View
import android.view.ViewGroup
-import com.android.systemui.R
-import java.util.HashMap
+import com.android.systemui.RegionInterceptingFrameLayout
-class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos: Int) {
+class OverlayWindow(private val context: Context) {
- private val layoutId: Int
- get() {
- return if (pos == DisplayCutout.BOUNDS_POSITION_LEFT ||
- pos == DisplayCutout.BOUNDS_POSITION_TOP) {
- R.layout.rounded_corners_top
- } else {
- R.layout.rounded_corners_bottom
- }
- }
+ val rootView = RegionInterceptingFrameLayout(context) as ViewGroup
+ private val viewProviderMap = mutableMapOf>()
- val rootView = layoutInflater.inflate(layoutId, null) as ViewGroup
- private val viewProviderMap: MutableMap> = HashMap()
-
- fun addDecorProvider(decorProvider: DecorProvider, @Surface.Rotation rotation: Int) {
- val view = decorProvider.inflateView(layoutInflater, rootView, rotation)
+ fun addDecorProvider(
+ decorProvider: DecorProvider,
+ @Surface.Rotation rotation: Int
+ ) {
+ val view = decorProvider.inflateView(context, rootView, rotation)
viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
}
@@ -56,4 +47,35 @@ class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos:
viewProviderMap.remove(id)
}
}
+
+ /**
+ * Apply new configuration info into views.
+ * @param filterIds target view ids. Apply to all if null.
+ * @param rotation current or new rotation direction.
+ * @param displayUniqueId new displayUniqueId if any.
+ */
+ fun onReloadResAndMeasure(
+ filterIds: Array? = null,
+ reloadToken: Int,
+ @Surface.Rotation rotation: Int,
+ displayUniqueId: String? = null
+ ) {
+ filterIds?.forEach { id ->
+ viewProviderMap[id]?.let {
+ it.second.onReloadResAndMeasure(
+ view = it.first,
+ reloadToken = reloadToken,
+ displayUniqueId = displayUniqueId,
+ rotation = rotation)
+ }
+ } ?: run {
+ viewProviderMap.values.forEach {
+ it.second.onReloadResAndMeasure(
+ view = it.first,
+ reloadToken = reloadToken,
+ displayUniqueId = displayUniqueId,
+ rotation = rotation)
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
index 7afd7e0eedc51..136f135af7599 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
@@ -16,6 +16,7 @@
package com.android.systemui.decor
+import android.content.Context
import android.content.res.Resources
import android.view.DisplayCutout
import android.view.LayoutInflater
@@ -76,12 +77,21 @@ class PrivacyDotCornerDecorProviderImpl(
private val layoutId: Int
) : CornerDecorProvider() {
+ override fun onReloadResAndMeasure(
+ view: View,
+ reloadToken: Int,
+ rotation: Int,
+ displayUniqueId: String?
+ ) {
+ // Do nothing here because it is handled inside PrivacyDotViewController
+ }
+
override fun inflateView(
- inflater: LayoutInflater,
+ context: Context,
parent: ViewGroup,
@Surface.Rotation rotation: Int
): View {
- inflater.inflate(layoutId, parent, true)
+ LayoutInflater.from(context).inflate(layoutId, parent, true)
return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt
new file mode 100644
index 0000000000000..4388b8b3b92dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.view.DisplayCutout
+import com.android.systemui.R
+
+class RoundedCornerDecorProviderFactory(
+ private val roundedCornerResDelegate: RoundedCornerResDelegate
+) : DecorProviderFactory() {
+
+ override val hasProviders: Boolean
+ get() = roundedCornerResDelegate.run {
+ // We don't consider isMultipleRadius here because it makes no sense if size is zero.
+ topRoundedSize.width > 0 || bottomRoundedSize.width > 0
+ }
+
+ override val providers: List
+ get() {
+ val hasTop = roundedCornerResDelegate.topRoundedSize.width > 0
+ val hasBottom = roundedCornerResDelegate.bottomRoundedSize.width > 0
+ return when {
+ hasTop && hasBottom -> listOf(
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_top_left,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
+ roundedCornerResDelegate = roundedCornerResDelegate),
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_top_right,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
+ roundedCornerResDelegate = roundedCornerResDelegate),
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_bottom_left,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
+ roundedCornerResDelegate = roundedCornerResDelegate),
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_bottom_right,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
+ roundedCornerResDelegate = roundedCornerResDelegate)
+ )
+ hasTop -> listOf(
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_top_left,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
+ roundedCornerResDelegate = roundedCornerResDelegate),
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_top_right,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
+ roundedCornerResDelegate = roundedCornerResDelegate)
+ )
+ hasBottom -> listOf(
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_bottom_left,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
+ roundedCornerResDelegate = roundedCornerResDelegate),
+ RoundedCornerDecorProviderImpl(
+ viewId = R.id.rounded_corner_bottom_right,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
+ roundedCornerResDelegate = roundedCornerResDelegate)
+ )
+ else -> emptyList()
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
new file mode 100644
index 0000000000000..90ff950406b46
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.content.Context
+import android.view.DisplayCutout
+import android.view.Gravity
+import android.view.Surface
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.ImageView
+import com.android.systemui.R
+
+class RoundedCornerDecorProviderImpl(
+ override val viewId: Int,
+ @DisplayCutout.BoundsPosition override val alignedBound1: Int,
+ @DisplayCutout.BoundsPosition override val alignedBound2: Int,
+ private val roundedCornerResDelegate: RoundedCornerResDelegate
+) : CornerDecorProvider() {
+
+ private val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
+
+ override fun inflateView(
+ context: Context,
+ parent: ViewGroup,
+ @Surface.Rotation rotation: Int
+ ): View {
+ return ImageView(context).also { view ->
+ // View
+ view.id = viewId
+ initView(view, rotation)
+
+ // LayoutParams
+ val layoutSize = if (isTop) {
+ roundedCornerResDelegate.topRoundedSize
+ } else {
+ roundedCornerResDelegate.bottomRoundedSize
+ }
+ val params = FrameLayout.LayoutParams(
+ layoutSize.width,
+ layoutSize.height,
+ alignedBound1.toLayoutGravity(rotation) or
+ alignedBound2.toLayoutGravity(rotation))
+
+ // AddView
+ parent.addView(view, params)
+ }
+ }
+
+ private fun initView(view: ImageView, @Surface.Rotation rotation: Int) {
+ view.setRoundedCornerImage(roundedCornerResDelegate, isTop)
+ view.adjustRotation(alignedBounds, rotation)
+ view.setColorFilter(IMAGE_TINT_COLOR)
+ }
+
+ override fun onReloadResAndMeasure(
+ view: View,
+ reloadToken: Int,
+ @Surface.Rotation rotation: Int,
+ displayUniqueId: String?
+ ) {
+ roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken)
+
+ initView((view as ImageView), rotation)
+
+ val layoutSize = if (isTop) {
+ roundedCornerResDelegate.topRoundedSize
+ } else {
+ roundedCornerResDelegate.bottomRoundedSize
+ }
+ (view.layoutParams as FrameLayout.LayoutParams).let {
+ it.width = layoutSize.width
+ it.height = layoutSize.height
+ it.gravity = alignedBound1.toLayoutGravity(rotation) or
+ alignedBound2.toLayoutGravity(rotation)
+ view.setLayoutParams(it)
+ }
+ }
+}
+
+private const val IMAGE_TINT_COLOR: Int = 0xFF000000.toInt()
+
+@DisplayCutout.BoundsPosition
+private fun Int.toLayoutGravity(@Surface.Rotation rotation: Int): Int = when (rotation) {
+ Surface.ROTATION_0 -> when (this) {
+ DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.LEFT
+ DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.TOP
+ DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.RIGHT
+ else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.BOTTOM
+ }
+ Surface.ROTATION_90 -> when (this) {
+ DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.BOTTOM
+ DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.LEFT
+ DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.TOP
+ else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT
+ }
+ Surface.ROTATION_270 -> when (this) {
+ DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.TOP
+ DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.RIGHT
+ DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.BOTTOM
+ else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT
+ }
+ else /* Surface.ROTATION_180 */ -> when (this) {
+ DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.RIGHT
+ DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.BOTTOM
+ DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.LEFT
+ else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.TOP
+ }
+}
+
+private fun ImageView.setRoundedCornerImage(
+ resDelegate: RoundedCornerResDelegate,
+ isTop: Boolean
+) {
+ val drawable = if (isTop)
+ resDelegate.topRoundedDrawable
+ else
+ resDelegate.bottomRoundedDrawable
+
+ if (drawable != null) {
+ setImageDrawable(drawable)
+ } else {
+ setImageResource(
+ if (isTop)
+ R.drawable.rounded_corner_top
+ else
+ R.drawable.rounded_corner_bottom
+ )
+ }
+}
+
+/**
+ * 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 fun ImageView.adjustRotation(alignedBounds: List, @Surface.Rotation rotation: Int) {
+ var newRotation = 0F
+ var newScaleX = 1F
+ var newScaleY = 1F
+
+ val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
+ val isLeft = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT)
+ when (rotation) {
+ Surface.ROTATION_0 -> when {
+ isTop && isLeft -> {}
+ isTop && !isLeft -> { newScaleX = -1F }
+ !isTop && isLeft -> { newScaleY = -1F }
+ else /* !isTop && !isLeft */ -> { newRotation = 180F }
+ }
+ Surface.ROTATION_90 -> when {
+ isTop && isLeft -> { newScaleY = -1F }
+ isTop && !isLeft -> {}
+ !isTop && isLeft -> { newRotation = 180F }
+ else /* !isTop && !isLeft */ -> { newScaleX = -1F }
+ }
+ Surface.ROTATION_270 -> when {
+ isTop && isLeft -> { newScaleX = -1F }
+ isTop && !isLeft -> { newRotation = 180F }
+ !isTop && isLeft -> {}
+ else /* !isTop && !isLeft */ -> { newScaleY = -1F }
+ }
+ else /* Surface.ROTATION_180 */ -> when {
+ isTop && isLeft -> { newRotation = 180F }
+ isTop && !isLeft -> { newScaleY = -1F }
+ !isTop && isLeft -> { newScaleX = -1F }
+ else /* !isTop && !isLeft */ -> {}
+ }
+ }
+
+ this.rotation = newRotation
+ this.scaleX = newScaleX
+ this.scaleY = newScaleY
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
index c817f89c7a9bc..256c6751c443b 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
@@ -36,6 +36,8 @@ class RoundedCornerResDelegate(
private val density: Float
get() = res.displayMetrics.density
+ private var reloadToken: Int = 0
+
var isMultipleRadius: Boolean = false
private set
@@ -60,12 +62,26 @@ class RoundedCornerResDelegate(
reloadMeasures()
}
- fun reloadAll(newDisplayUniqueId: String?) {
- displayUniqueId = newDisplayUniqueId
+ private fun reloadAll(newReloadToken: Int) {
+ if (reloadToken == newReloadToken) {
+ return
+ }
+ reloadToken = newReloadToken
reloadDrawables()
reloadMeasures()
}
+ fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) {
+ if (displayUniqueId != newDisplayUniqueId) {
+ displayUniqueId = newDisplayUniqueId
+ newReloadToken ?.let { reloadToken = it }
+ reloadDrawables()
+ reloadMeasures()
+ } else {
+ newReloadToken?.let { reloadAll(it) }
+ }
+ }
+
private fun reloadDrawables() {
val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
isMultipleRadius = getIsMultipleRadius(configIdx)
@@ -85,34 +101,6 @@ class RoundedCornerResDelegate(
arrayResId = R.array.config_roundedCornerBottomDrawableArray,
backupDrawableId = R.drawable.rounded_corner_bottom
) ?: roundedDrawable
-
- // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
- // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
- if (isMultipleRadius) {
- roundedSize = Size(
- roundedDrawable?.intrinsicWidth ?: 0,
- roundedDrawable?.intrinsicHeight ?: 0)
- topRoundedDrawable?.let {
- topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
- }
- bottomRoundedDrawable?.let {
- bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
- }
- } else {
- val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId)
- val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId)
- val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId)
- roundedSize = Size(defaultRadius, defaultRadius)
- topRoundedSize = Size(topRadius, topRadius)
- bottomRoundedSize = Size(bottomRadius, bottomRadius)
- }
-
- if (topRoundedSize.width == 0) {
- topRoundedSize = roundedSize
- }
- if (bottomRoundedSize.width == 0) {
- bottomRoundedSize = roundedSize
- }
}
private fun reloadMeasures(roundedSizeFactor: Int? = null) {
@@ -137,8 +125,8 @@ class RoundedCornerResDelegate(
bottomRoundedSize = Size(bottomRadius, bottomRadius)
}
- roundedSizeFactor ?.let {
- val length: Int = (it * density).toInt()
+ if (roundedSizeFactor != null && roundedSizeFactor > 0) {
+ val length: Int = (roundedSizeFactor * density).toInt()
roundedSize = Size(length, length)
}
@@ -150,7 +138,11 @@ class RoundedCornerResDelegate(
}
}
- fun updateTuningSizeFactor(factor: Int) {
+ fun updateTuningSizeFactor(factor: Int?, newReloadToken: Int) {
+ if (reloadToken == newReloadToken) {
+ return
+ }
+ reloadToken = newReloadToken
reloadMeasures(factor)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index ec92adb0f48cf..ac78626ff1263 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -33,7 +33,6 @@ import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -61,9 +60,11 @@ import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowMetrics;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
@@ -102,7 +103,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
private SecureSettings mSecureSettings;
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
private FakeThreadFactory mThreadFactory;
- private ArrayList mDecorProviders;
+ private ArrayList mPrivacyDecorProviders;
@Mock
private Display mDisplay;
@Mock
@@ -197,17 +198,43 @@ public class ScreenDecorationsTest extends SysuiTestCase {
reset(mTunerService);
}
+ @NonNull
+ private int[] getRoundCornerIdsFromOverlayId(@DisplayCutout.BoundsPosition int overlayId) {
+ switch (overlayId) {
+ case BOUNDS_POSITION_LEFT:
+ return new int[] {
+ R.id.rounded_corner_top_left,
+ R.id.rounded_corner_top_left };
+ case BOUNDS_POSITION_TOP:
+ return new int[] {
+ R.id.rounded_corner_top_left,
+ R.id.rounded_corner_top_right };
+ case BOUNDS_POSITION_RIGHT:
+ return new int[] {
+ R.id.rounded_corner_top_right,
+ R.id.rounded_corner_bottom_right };
+ case BOUNDS_POSITION_BOTTOM:
+ return new int[] {
+ R.id.rounded_corner_bottom_left,
+ R.id.rounded_corner_bottom_right };
+ default:
+ throw new IllegalArgumentException("unknown overlayId: " + overlayId);
+ }
+ }
- private void verifyRoundedCornerViewsVisibility(
+ private void verifyRoundedCornerViewsExist(
@DisplayCutout.BoundsPosition final int overlayId,
- @View.Visibility final int visibility) {
+ @View.Visibility final boolean isExist) {
final View overlay = mScreenDecorations.mOverlays[overlayId].getRootView();
- final View left = overlay.findViewById(R.id.left);
- final View right = overlay.findViewById(R.id.right);
- assertNotNull(left);
- assertNotNull(right);
- assertThat(left.getVisibility()).isEqualTo(visibility);
- assertThat(right.getVisibility()).isEqualTo(visibility);
+ for (int id: getRoundCornerIdsFromOverlayId(overlayId)) {
+ final View view = overlay.findViewById(id);
+ if (isExist) {
+ assertNotNull(view);
+ assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
+ } else {
+ assertNull(view);
+ }
+ }
}
@Nullable
@@ -351,8 +378,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(false, true, false, true);
// Rounded corner views shall not exist
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
// Privacy dots shall exist but invisible
verifyDotViewsVisibility(View.INVISIBLE);
@@ -380,8 +407,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(false, true, false, true);
// Rounded corner views shall exist
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
// Privacy dots shall not exist
verifyDotViewsNullable(true);
@@ -408,8 +435,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(false, true, false, true);
// Rounded corner views shall exist
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
// Privacy dots shall exist but invisible
verifyDotViewsVisibility(View.INVISIBLE);
@@ -449,21 +476,26 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mScreenDecorations.start();
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
- .findViewById(R.id.left);
+ .findViewById(R.id.rounded_corner_top_left);
View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
- .findViewById(R.id.right);
- verify(mScreenDecorations, atLeastOnce())
- .setSize(leftRoundedCorner, new Size(testTopRadius, testTopRadius));
- verify(mScreenDecorations, atLeastOnce())
- .setSize(rightRoundedCorner, new Size(testTopRadius, testTopRadius));
+ .findViewById(R.id.rounded_corner_top_right);
+ ViewGroup.LayoutParams leftParams = leftRoundedCorner.getLayoutParams();
+ ViewGroup.LayoutParams rightParams = rightRoundedCorner.getLayoutParams();
+ assertEquals(leftParams.width, testTopRadius);
+ assertEquals(leftParams.height, testTopRadius);
+ assertEquals(rightParams.width, testTopRadius);
+ assertEquals(rightParams.height, testTopRadius);
+
leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
- .findViewById(R.id.left);
+ .findViewById(R.id.rounded_corner_bottom_left);
rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
- .findViewById(R.id.right);
- verify(mScreenDecorations, atLeastOnce())
- .setSize(leftRoundedCorner, new Size(testBottomRadius, testBottomRadius));
- verify(mScreenDecorations, atLeastOnce())
- .setSize(rightRoundedCorner, new Size(testBottomRadius, testBottomRadius));
+ .findViewById(R.id.rounded_corner_bottom_right);
+ leftParams = leftRoundedCorner.getLayoutParams();
+ rightParams = rightRoundedCorner.getLayoutParams();
+ assertEquals(leftParams.width, testBottomRadius);
+ assertEquals(leftParams.height, testBottomRadius);
+ assertEquals(rightParams.width, testBottomRadius);
+ assertEquals(rightParams.height, testBottomRadius);
}
@Test
@@ -479,31 +511,27 @@ public class ScreenDecorationsTest extends SysuiTestCase {
.when(mScreenDecorations).getCutout();
mScreenDecorations.start();
- final Size topRadius = new Size(testTopRadius, testTopRadius);
- final Size bottomRadius = new Size(testBottomRadius, testBottomRadius);
- View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
- .findViewById(R.id.left);
- boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left);
- verify(mScreenDecorations, atLeastOnce())
- .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
+ View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
+ .findViewById(R.id.rounded_corner_top_left);
+ View bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
+ .findViewById(R.id.rounded_corner_bottom_left);
+ ViewGroup.LayoutParams topParams = topRoundedCorner.getLayoutParams();
+ ViewGroup.LayoutParams bottomParams = bottomRoundedCorner.getLayoutParams();
+ assertEquals(topParams.width, testTopRadius);
+ assertEquals(topParams.height, testTopRadius);
+ assertEquals(bottomParams.width, testBottomRadius);
+ assertEquals(bottomParams.height, testBottomRadius);
- View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
- .findViewById(R.id.right);
- isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.right);
- verify(mScreenDecorations, atLeastOnce())
- .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
-
- leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
- .findViewById(R.id.left);
- isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.left);
- verify(mScreenDecorations, atLeastOnce())
- .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
-
- rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
- .findViewById(R.id.right);
- isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.right);
- verify(mScreenDecorations, atLeastOnce())
- .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
+ topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
+ .findViewById(R.id.rounded_corner_top_right);
+ bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
+ .findViewById(R.id.rounded_corner_bottom_right);
+ topParams = topRoundedCorner.getLayoutParams();
+ bottomParams = bottomRoundedCorner.getLayoutParams();
+ assertEquals(topParams.width, testTopRadius);
+ assertEquals(topParams.height, testTopRadius);
+ assertEquals(bottomParams.width, testBottomRadius);
+ assertEquals(bottomParams.height, testBottomRadius);
}
@Test
@@ -523,8 +551,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(false, true, false, true);
// Rounded corner views shall exist
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
// Privacy dots shall not exist
verifyDotViewsNullable(true);
@@ -557,8 +585,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(false, true, false, true);
// Rounded corner views shall exist
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
// Privacy dots shall exist but invisible
verifyDotViewsVisibility(View.INVISIBLE);
@@ -617,10 +645,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
// Top rounded corner views shall exist because of cutout
// but be gone because of no rounded corner
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
// Bottom rounded corner views shall exist because of privacy dot
// but be gone because of no rounded corner
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
// Privacy dots shall exist but invisible
verifyDotViewsVisibility(View.INVISIBLE);
@@ -648,7 +676,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
// Left rounded corner views shall exist because of cutout
// but be gone because of no rounded corner
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_LEFT, View.GONE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_LEFT, false);
// Top privacy dots shall not exist because of no privacy
verifyDotViewsNullable(true);
@@ -700,8 +728,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(false, true, false, true);
// Rounded corner views shall exist
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
// Top privacy dots shall not exist because of no privacy dot
verifyDotViewsNullable(true);
@@ -728,8 +756,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(false, true, false, true);
// Rounded corner views shall exist
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
// Top privacy dots shall exist but invisible
verifyDotViewsVisibility(View.INVISIBLE);
@@ -859,7 +887,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyOverlaysExistAndAdded(true, false, true, false);
// Verify each privacy dot id appears only once
- mDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
+ mPrivacyDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
int findCount = 0;
for (OverlayWindow overlay: mScreenDecorations.mOverlays) {
if (overlay == null) {
@@ -913,8 +941,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
// Both top and bottom windows should be added because of privacy dot,
// but their visibility shall be gone because of no rounding.
verifyOverlaysExistAndAdded(false, true, false, true);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
when(mContext.getResources().getBoolean(
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
@@ -925,8 +953,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
// Both top and bottom windows should be added because of privacy dot,
// but their visibility shall be gone because of no rounding.
verifyOverlaysExistAndAdded(false, true, false, true);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
- verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
+ verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
}
@Test
@@ -1174,14 +1202,14 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
- mDecorProviders = new ArrayList<>();
+ mPrivacyDecorProviders = new ArrayList<>();
if (privacyDot) {
- mDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
- mDecorProviders.add(mPrivacyDotTopRightDecorProvider);
- mDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
- mDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
+ mPrivacyDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
+ mPrivacyDecorProviders.add(mPrivacyDotTopRightDecorProvider);
+ mPrivacyDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
+ mPrivacyDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
}
- when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mDecorProviders);
+ when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mPrivacyDecorProviders);
when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
index ca74df0a23c59..5182210b95679 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
@@ -19,25 +19,19 @@ package com.android.systemui.decor
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.DisplayCutout
-import android.view.LayoutInflater
import android.view.Surface
import android.view.View
-import android.view.ViewGroup
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.util.mockito.eq
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.never
import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
@@ -45,62 +39,88 @@ import org.mockito.Mockito.`when` as whenever
class OverlayWindowTest : SysuiTestCase() {
companion object {
- private val TEST_DECOR_VIEW_ID = R.id.privacy_dot_bottom_right_container
- private val TEST_DECOR_LAYOUT_ID = R.layout.privacy_dot_bottom_right
+ private val TEST_DECOR_VIEW_ID_1 = R.id.privacy_dot_top_left_container
+ private val TEST_DECOR_VIEW_ID_2 = R.id.privacy_dot_bottom_right_container
}
private lateinit var overlay: OverlayWindow
-
- @Mock private lateinit var layoutInflater: LayoutInflater
- @Mock private lateinit var decorProvider: DecorProvider
+ private lateinit var decorProvider1: DecorProvider
+ private lateinit var decorProvider2: DecorProvider
@Before
fun setUp() {
- MockitoAnnotations.initMocks(this)
+ decorProvider1 = spy(PrivacyDotCornerDecorProviderImpl(
+ viewId = TEST_DECOR_VIEW_ID_1,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
+ layoutId = R.layout.privacy_dot_top_left))
+ decorProvider2 = spy(PrivacyDotCornerDecorProviderImpl(
+ viewId = TEST_DECOR_VIEW_ID_2,
+ alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
+ alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
+ layoutId = R.layout.privacy_dot_bottom_right))
- layoutInflater = spy(LayoutInflater.from(mContext))
-
- overlay = OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT)
-
- whenever(decorProvider.viewId).thenReturn(TEST_DECOR_VIEW_ID)
- whenever(decorProvider.inflateView(
- eq(layoutInflater),
- eq(overlay.rootView),
- anyInt())
- ).then {
- val layoutInflater = it.getArgument(0)
- val parent = it.getArgument(1)
- layoutInflater.inflate(TEST_DECOR_LAYOUT_ID, parent)
- return@then parent.getChildAt(parent.childCount - 1)
- }
- }
-
- @Test
- fun testAnyBoundsPositionShallNoExceptionForConstructor() {
- OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_LEFT)
- OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_TOP)
- OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT)
- OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_BOTTOM)
+ overlay = OverlayWindow(mContext)
}
@Test
fun testAddProvider() {
@Surface.Rotation val rotation = Surface.ROTATION_270
- overlay.addDecorProvider(decorProvider, rotation)
- verify(decorProvider, Mockito.times(1)).inflateView(
- eq(layoutInflater), eq(overlay.rootView), eq(rotation))
- val viewFoundFromRootView = overlay.rootView.findViewById(TEST_DECOR_VIEW_ID)
- Assert.assertNotNull(viewFoundFromRootView)
- Assert.assertEquals(viewFoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID))
+ overlay.addDecorProvider(decorProvider1, rotation)
+ overlay.addDecorProvider(decorProvider2, rotation)
+
+ verify(decorProvider1, times(1)).inflateView(
+ mContext, overlay.rootView, rotation)
+ verify(decorProvider2, times(1)).inflateView(
+ mContext, overlay.rootView, rotation)
+
+ val view1FoundFromRootView = overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1)
+ Assert.assertNotNull(view1FoundFromRootView)
+ Assert.assertEquals(view1FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_1))
+ val view2FoundFromRootView = overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_2)
+ Assert.assertNotNull(view2FoundFromRootView)
+ Assert.assertEquals(view2FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_2))
}
@Test
fun testRemoveView() {
- @Surface.Rotation val rotation = Surface.ROTATION_270
- overlay.addDecorProvider(decorProvider, rotation)
- overlay.removeView(TEST_DECOR_VIEW_ID)
- val viewFoundFromRootView = overlay.rootView.findViewById(TEST_DECOR_VIEW_ID)
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
+ overlay.removeView(TEST_DECOR_VIEW_ID_1)
+
+ val viewFoundFromRootView = overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1)
Assert.assertNull(viewFoundFromRootView)
- Assert.assertNull(overlay.getView(TEST_DECOR_LAYOUT_ID))
+ Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
+ }
+
+ @Test
+ fun testOnReloadResAndMeasureWithoutIds() {
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+
+ overlay.onReloadResAndMeasure(
+ reloadToken = 1,
+ rotation = Surface.ROTATION_90,
+ displayUniqueId = null)
+ verify(decorProvider1, times(1)).onReloadResAndMeasure(
+ overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
+ verify(decorProvider2, times(1)).onReloadResAndMeasure(
+ overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
+ }
+
+ @Test
+ fun testOnReloadResAndMeasureWithIds() {
+ overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
+ overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
+
+ overlay.onReloadResAndMeasure(
+ filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
+ reloadToken = 1,
+ rotation = Surface.ROTATION_90,
+ displayUniqueId = null)
+ verify(decorProvider1, never()).onReloadResAndMeasure(
+ overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
+ verify(decorProvider2, times(1)).onReloadResAndMeasure(
+ overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
index bac08176d2ebc..171b76748d26d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
@@ -18,7 +18,6 @@ package com.android.systemui.decor
import android.content.res.Resources
import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
import android.view.DisplayCutout
import androidx.test.filters.SmallTest
import com.android.systemui.R
@@ -32,7 +31,6 @@ import org.mockito.Mockito.spy
import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
@SmallTest
class PrivacyDotDecorProviderFactoryTest : SysuiTestCase() {
private lateinit var mPrivacyDotDecorProviderFactory: PrivacyDotDecorProviderFactory
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
new file mode 100644
index 0000000000000..621bcf69bb038
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.testing.AndroidTestingRunner
+import android.util.Size
+import android.view.DisplayCutout
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.spy
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class RoundedCornerDecorProviderFactoryTest : SysuiTestCase() {
+
+ @Mock private lateinit var roundedCornerResDelegate: RoundedCornerResDelegate
+ private lateinit var roundedCornerDecorProviderFactory: RoundedCornerDecorProviderFactory
+
+ @Before
+ fun setUp() {
+ roundedCornerResDelegate = spy(RoundedCornerResDelegate(mContext.resources, null))
+ }
+
+ @Test
+ fun testNoRoundedCorners() {
+ Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize
+ Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize
+ Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
+
+ roundedCornerDecorProviderFactory =
+ RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
+
+ Assert.assertEquals(false, roundedCornerDecorProviderFactory.hasProviders)
+ Assert.assertEquals(0, roundedCornerDecorProviderFactory.providers.size)
+ }
+
+ @Test
+ fun testHasRoundedCornersIfTopWidthLargerThan0() {
+ Mockito.doReturn(Size(1, 0)).`when`(roundedCornerResDelegate).topRoundedSize
+ Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize
+ Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
+
+ roundedCornerDecorProviderFactory =
+ RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
+
+ Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
+ roundedCornerDecorProviderFactory.providers.let { providers ->
+ Assert.assertEquals(2, providers.size)
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_top_left)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
+ })
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_top_right)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
+ })
+ }
+ }
+
+ @Test
+ fun testHasRoundedCornersIfBottomWidthLargerThan0() {
+ Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize
+ Mockito.doReturn(Size(1, 1)).`when`(roundedCornerResDelegate).bottomRoundedSize
+ Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
+
+ roundedCornerDecorProviderFactory =
+ RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
+
+ Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
+ roundedCornerDecorProviderFactory.providers.let { providers ->
+ Assert.assertEquals(2, providers.size)
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_bottom_left)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
+ })
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_bottom_right)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
+ })
+ }
+ }
+
+ @Test
+ fun test4CornerDecorProvidersInfo() {
+ Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).topRoundedSize
+ Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).bottomRoundedSize
+ Mockito.doReturn(true).`when`(roundedCornerResDelegate).isMultipleRadius
+
+ roundedCornerDecorProviderFactory =
+ RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
+
+ Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
+ roundedCornerDecorProviderFactory.providers.let { providers ->
+ Assert.assertEquals(4, providers.size)
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_top_left)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
+ })
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_top_right)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
+ })
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_bottom_left)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
+ })
+ Assert.assertEquals(1, providers.count {
+ ((it.viewId == R.id.rounded_corner_bottom_right)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
+ and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
index b536bfdb944eb..fb6ff76a4e381 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
@@ -45,7 +45,7 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
}
@Test
- fun testReloadAllAndDefaultRadius() {
+ fun testUpdateDisplayUniqueId() {
mContext.orCreateTestableResources.addOverrides(
mockTypeArray = mockTypedArray,
radius = 3,
@@ -65,7 +65,34 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
radiusTop = 6,
radiusBottom = 0)
- roundedCornerResDelegate.reloadAll("test")
+ roundedCornerResDelegate.updateDisplayUniqueId("test", null)
+
+ assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
+ assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
+ }
+
+ @Test
+ fun testNotUpdateDisplayUniqueIdButChangeRefreshToken() {
+ mContext.orCreateTestableResources.addOverrides(
+ mockTypeArray = mockTypedArray,
+ radius = 3,
+ radiusTop = 0,
+ radiusBottom = 4,
+ multipleRadius = false)
+
+ roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
+
+ assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize)
+ assertEquals(Size(4, 4), roundedCornerResDelegate.bottomRoundedSize)
+ assertEquals(false, roundedCornerResDelegate.isMultipleRadius)
+
+ mContext.orCreateTestableResources.addOverrides(
+ mockTypeArray = mockTypedArray,
+ radius = 5,
+ radiusTop = 6,
+ radiusBottom = 0)
+
+ roundedCornerResDelegate.updateDisplayUniqueId(null, 1)
assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
@@ -82,11 +109,21 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
val factor = 5
- roundedCornerResDelegate.updateTuningSizeFactor(factor)
+ roundedCornerResDelegate.updateTuningSizeFactor(factor, 1)
val length = (factor * mContext.resources.displayMetrics.density).toInt()
assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(length, length), roundedCornerResDelegate.bottomRoundedSize)
+
+ mContext.orCreateTestableResources.addOverrides(
+ mockTypeArray = mockTypedArray,
+ radiusTop = 1,
+ radiusBottom = 2,
+ multipleRadius = false)
+ roundedCornerResDelegate.updateTuningSizeFactor(null, 2)
+
+ assertEquals(Size(1, 1), roundedCornerResDelegate.topRoundedSize)
+ assertEquals(Size(2, 2), roundedCornerResDelegate.bottomRoundedSize)
}
@Test