summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/values/ids.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java205
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt69
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java282
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt200
8 files changed, 326 insertions, 561 deletions
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index f013f9b49955..dca5ea836fa4 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -132,9 +132,6 @@
<item type="id" name="status_bar_view_state_tag" />
<item type="id" name="display_cutout" />
- <item type="id" name="display_cutout_left" />
- <item type="id" name="display_cutout_right" />
- <item type="id" name="display_cutout_bottom" />
<item type="id" name="row_tag_for_content_view" />
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 9fab2ea34193..aaaa3f77924a 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -43,7 +43,6 @@ import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.graphics.common.AlphaInterpretation;
import android.hardware.graphics.common.DisplayDecorationSupport;
-import android.os.Build;
import android.os.Handler;
import android.os.SystemProperties;
import android.os.Trace;
@@ -73,7 +72,6 @@ import com.android.settingslib.Utils;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.decor.CutoutDecorProviderFactory;
import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.DecorProviderKt;
@@ -141,11 +139,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
@VisibleForTesting
protected DecorProviderFactory mRoundedCornerFactory;
- private CutoutDecorProviderFactory mCutoutFactory;
private int mProviderRefreshToken = 0;
@VisibleForTesting
protected OverlayWindow[] mOverlays = null;
@VisibleForTesting
+ @Nullable
+ DisplayCutoutView[] mCutoutViews;
+ @VisibleForTesting
ViewGroup mScreenDecorHwcWindow;
@VisibleForTesting
ScreenDecorHwcLayer mScreenDecorHwcLayer;
@@ -187,28 +187,17 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return;
}
- final int[] ids = {
- R.id.display_cutout,
- R.id.display_cutout_left,
- R.id.display_cutout_right,
- R.id.display_cutout_bottom
- };
- int setProtectionCnt = 0;
- for (int id: ids) {
- final View view = getOverlayView(id);
- if (!(view instanceof DisplayCutoutView)) {
- continue;
- }
- ++setProtectionCnt;
- final DisplayCutoutView dcv = (DisplayCutoutView) view;
- dcv.setProtection(protectionPath, bounds);
- dcv.enableShowProtection(true);
- }
- if (setProtectionCnt == 0) {
- if (Build.isDebuggable()) {
- throw new RuntimeException("CutoutView not initialized showCameraProtection");
- } else {
- Log.e(TAG, "CutoutView not initialized showCameraProtection");
+ if (mCutoutViews == null) {
+ Log.w(TAG, "DisplayCutoutView not initialized onApplyCameraProtection");
+ return;
+ }
+
+ // Show the extra protection around the front facing camera if necessary
+ for (DisplayCutoutView dcv : mCutoutViews) {
+ // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
+ if (dcv != null) {
+ dcv.setProtection(protectionPath, bounds);
+ dcv.enableShowProtection(true);
}
}
}
@@ -230,26 +219,15 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return;
}
- final int[] ids = {
- R.id.display_cutout,
- R.id.display_cutout_left,
- R.id.display_cutout_right,
- R.id.display_cutout_bottom
- };
- int setProtectionCnt = 0;
- for (int id: ids) {
- final View view = getOverlayView(id);
- if (!(view instanceof DisplayCutoutView)) {
- continue;
- }
- ++setProtectionCnt;
- ((DisplayCutoutView) view).enableShowProtection(false);
+ if (mCutoutViews == null) {
+ Log.w(TAG, "DisplayCutoutView not initialized onHideCameraProtection");
+ return;
}
- if (setProtectionCnt == 0) {
- if (Build.isDebuggable()) {
- throw new RuntimeException("CutoutView not initialized hideCameraProtection");
- } else {
- Log.e(TAG, "CutoutView not initialized hideCameraProtection");
+ // Go back to the regular anti-aliasing
+ for (DisplayCutoutView dcv : mCutoutViews) {
+ // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
+ if (dcv != null) {
+ dcv.enableShowProtection(false);
}
}
}
@@ -357,7 +335,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
decorProviders.addAll(mFaceScanningFactory.getProviders());
if (!hasHwLayer) {
decorProviders.addAll(mRoundedCornerFactory.getProviders());
- decorProviders.addAll(mCutoutFactory.getProviders());
}
return decorProviders;
}
@@ -402,7 +379,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
getPhysicalPixelDisplaySizeRatio());
mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
- mCutoutFactory = getCutoutFactory();
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
updateHwLayerRoundedCornerDrawable();
setupDecorations();
@@ -507,13 +483,18 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
if (needToUpdateProviderViews) {
updateOverlayProviderViews(null);
} else {
- updateOverlayProviderViews(new Integer[] {
- mFaceScanningViewId,
- R.id.display_cutout,
- R.id.display_cutout_left,
- R.id.display_cutout_right,
- R.id.display_cutout_bottom,
- });
+ updateOverlayProviderViews(new Integer[] { mFaceScanningViewId });
+ }
+
+ if (mCutoutViews != null) {
+ final int size = mCutoutViews.length;
+ for (int i = 0; i < size; i++) {
+ final DisplayCutoutView cutoutView = mCutoutViews[i];
+ if (cutoutView == null) {
+ continue;
+ }
+ cutoutView.onDisplayChanged(newUniqueId);
+ }
}
if (mScreenDecorHwcLayer != null) {
@@ -526,9 +507,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
updateConfiguration();
}
- @VisibleForTesting
@Nullable
- View getOverlayView(@IdRes int id) {
+ private View getOverlayView(@IdRes int id) {
if (mOverlays == null) {
return null;
}
@@ -585,18 +565,18 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
removeHwcOverlay();
}
- boolean[] hasCreatedOverlay = new boolean[BOUNDS_POSITION_LENGTH];
+ final DisplayCutout cutout = getCutout();
final boolean shouldOptimizeVisibility = shouldOptimizeVisibility();
- Integer bound;
- while ((bound = DecorProviderKt.getProperBound(decorProviders)) != null) {
- hasCreatedOverlay[bound] = true;
- Pair<List<DecorProvider>, List<DecorProvider>> pair =
- DecorProviderKt.partitionAlignedBound(decorProviders, bound);
- decorProviders = pair.getSecond();
- createOverlay(bound, pair.getFirst(), shouldOptimizeVisibility);
- }
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (!hasCreatedOverlay[i]) {
+ if (shouldShowSwLayerCutout(i, cutout)
+ || shouldShowSwLayerFaceScan(i, cutout)
+ || shouldShowSwLayerRoundedCorner(i, cutout)
+ || shouldShowSwLayerPrivacyDot(i, cutout)) {
+ Pair<List<DecorProvider>, List<DecorProvider>> pair =
+ DecorProviderKt.partitionAlignedBound(decorProviders, i);
+ decorProviders = pair.getSecond();
+ createOverlay(i, pair.getFirst(), shouldOptimizeVisibility);
+ } else {
removeOverlay(i);
}
}
@@ -659,10 +639,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
}
- // For unit test to override
- protected CutoutDecorProviderFactory getCutoutFactory() {
- return new CutoutDecorProviderFactory(mContext.getResources(),
- mContext.getDisplay());
+ @VisibleForTesting
+ DisplayCutout getCutout() {
+ return mContext.getDisplay().getCutout();
}
@VisibleForTesting
@@ -752,6 +731,16 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
overlayView.setAlpha(0);
overlayView.setForceDarkAllowed(false);
+ // Only show cutout in mOverlays when hwc doesn't support screen decoration
+ if (mHwcScreenDecorationSupport == null) {
+ if (mCutoutViews == null) {
+ mCutoutViews = new DisplayCutoutView[BOUNDS_POSITION_LENGTH];
+ }
+ mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
+ overlayView.addView(mCutoutViews[pos]);
+ mCutoutViews[pos].updateRotation(mRotation);
+ }
+
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
overlayView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -958,12 +947,27 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mTintColor = Color.RED;
}
+ if (mOverlays == null) {
+ return;
+ }
+
+ for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+ if (mOverlays[i] == null) {
+ continue;
+ }
+ final ViewGroup overlayView = mOverlays[i].getRootView();
+ final int size = overlayView.getChildCount();
+ View child;
+ for (int j = 0; j < size; j++) {
+ child = overlayView.getChildAt(j);
+ if (child instanceof DisplayCutoutView && child.getId() == R.id.display_cutout) {
+ ((DisplayCutoutView) child).setColor(mTintColor);
+ }
+ }
+ }
+
updateOverlayProviderViews(new Integer[] {
mFaceScanningViewId,
- R.id.display_cutout,
- R.id.display_cutout_left,
- R.id.display_cutout_right,
- R.id.display_cutout_bottom,
R.id.rounded_corner_top_left,
R.id.rounded_corner_top_right,
R.id.rounded_corner_bottom_left,
@@ -1088,6 +1092,15 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
updateHwLayerRoundedCornerDrawable();
}
updateLayoutParams();
+ // update cutout view rotation
+ if (mCutoutViews != null) {
+ for (final DisplayCutoutView cutoutView: mCutoutViews) {
+ if (cutoutView == null) {
+ continue;
+ }
+ cutoutView.updateRotation(mRotation);
+ }
+ }
// update all provider views inside overlay
updateOverlayProviderViews(null);
@@ -1106,6 +1119,46 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return mRoundedCornerFactory.getHasProviders();
}
+ private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
+ @Nullable DisplayCutout cutout) {
+ // for cutout is null or cutout with only waterfall.
+ final boolean emptyBoundsOrWaterfall = cutout == null || cutout.isBoundsEmpty();
+ // Shows rounded corner on left and right overlays only when there is no top or bottom
+ // cutout.
+ final int rotatedTop = getBoundPositionFromRotation(BOUNDS_POSITION_TOP, mRotation);
+ final int rotatedBottom = getBoundPositionFromRotation(BOUNDS_POSITION_BOTTOM, mRotation);
+ if (emptyBoundsOrWaterfall || !cutout.getBoundingRectsAll()[rotatedTop].isEmpty()
+ || !cutout.getBoundingRectsAll()[rotatedBottom].isEmpty()) {
+ return pos == BOUNDS_POSITION_TOP || pos == BOUNDS_POSITION_BOTTOM;
+ } else {
+ return pos == BOUNDS_POSITION_LEFT || pos == BOUNDS_POSITION_RIGHT;
+ }
+ }
+
+ private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
+ @Nullable DisplayCutout cutout) {
+ return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
+ && mHwcScreenDecorationSupport == null;
+ }
+
+ private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
+ @Nullable DisplayCutout cutout) {
+ return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
+ }
+
+ private boolean shouldShowSwLayerFaceScan(@BoundsPosition int pos,
+ @Nullable DisplayCutout cutout) {
+ return mFaceScanningFactory.getHasProviders() && isDefaultShownOverlayPos(pos, 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()
+ && mHwcScreenDecorationSupport == null);
+ }
+
private boolean shouldOptimizeVisibility() {
return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders())
&& (mHwcScreenDecorationSupport != null
@@ -1114,7 +1167,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
private boolean shouldDrawCutout() {
- return mCutoutFactory.getHasProviders();
+ return shouldDrawCutout(mContext);
}
static boolean shouldDrawCutout(Context context) {
@@ -1230,6 +1283,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
paint.setColor(mColor);
paint.setStyle(Paint.Style.FILL);
+ setId(R.id.display_cutout);
if (DEBUG) {
getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
getWindowTitleByPos(pos) + " drawn in rot " + mRotation));
@@ -1237,9 +1291,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
public void setColor(int color) {
- if (color == mColor) {
- return;
- }
mColor = color;
paint.setColor(mColor);
invalidate();
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
deleted file mode 100644
index cbed21cf65d6..000000000000
--- a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.res.Resources
-import android.util.Log
-import android.view.Display
-import android.view.DisplayCutout
-import android.view.DisplayInfo
-
-class CutoutDecorProviderFactory constructor(
- private val res: Resources,
- private val display: Display?,
-) : DecorProviderFactory() {
-
- val displayInfo = DisplayInfo()
-
- override val hasProviders: Boolean
- get() {
- display?.getDisplayInfo(displayInfo) ?: run {
- Log.w(TAG, "display is null, can't update displayInfo")
- }
- return DisplayCutout.getFillBuiltInDisplayCutout(res, displayInfo.uniqueId)
- }
-
- override val providers: List<DecorProvider>
- get() {
- if (!hasProviders) {
- return emptyList()
- }
-
- return ArrayList<DecorProvider>().also { list ->
- // We need to update displayInfo before using it, but it has already updated during
- // accessing hasProviders field
- displayInfo.displayCutout?.getBoundBaseOnCurrentRotation()?.let { bounds ->
- for (bound in bounds) {
- list.add(
- CutoutDecorProviderImpl(bound.baseOnRotation0(displayInfo.rotation))
- )
- }
- }
- }
- }
-}
-
-private const val TAG = "CutoutDecorProviderFactory"
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
deleted file mode 100644
index 991b54e8035e..000000000000
--- a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.Surface
-import android.view.View
-import android.view.ViewGroup
-import com.android.systemui.R
-import com.android.systemui.ScreenDecorations.DisplayCutoutView
-
-class CutoutDecorProviderImpl(
- @DisplayCutout.BoundsPosition override val alignedBound: Int
-) : BoundDecorProvider() {
-
- override val viewId: Int = when (alignedBound) {
- DisplayCutout.BOUNDS_POSITION_TOP -> R.id.display_cutout
- DisplayCutout.BOUNDS_POSITION_LEFT -> R.id.display_cutout_left
- DisplayCutout.BOUNDS_POSITION_RIGHT -> R.id.display_cutout_right
- else -> R.id.display_cutout_bottom
- }
-
- override fun inflateView(
- context: Context,
- parent: ViewGroup,
- @Surface.Rotation rotation: Int,
- tintColor: Int
- ): View {
- return DisplayCutoutView(context, alignedBound).also { view ->
- view.id = viewId
- view.setColor(tintColor)
- parent.addView(view)
- view.updateRotation(rotation)
- }
- }
-
- override fun onReloadResAndMeasure(
- view: View,
- reloadToken: Int,
- @Surface.Rotation rotation: Int,
- tintColor: Int,
- displayUniqueId: String?
- ) {
- (view as? DisplayCutoutView)?.let { cutoutView ->
- cutoutView.setColor(tintColor)
- cutoutView.updateRotation(rotation)
- cutoutView.onDisplayChanged(displayUniqueId)
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
index 260c4b5a7830..de6d7278971c 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
@@ -32,7 +32,7 @@ abstract class DecorProvider {
abstract val viewId: Int
/** The number of total aligned bounds */
- val numOfAlignedBound: Int
+ val numOfAlignedEdge: Int
get() = alignedBounds.size
/** The aligned bounds for the view which is created through inflateView() */
@@ -57,8 +57,16 @@ abstract class DecorProvider {
@Surface.Rotation rotation: Int,
tintColor: Int
): View
+}
- override fun toString() = "${javaClass.simpleName}{alignedBounds=$alignedBounds}"
+/**
+ * Split list to 2 list, and return it back as Pair<>. The providers on the first list contains this
+ * alignedBound element. The providers on the second list do not contain this alignedBound element
+ */
+fun List<DecorProvider>.partitionAlignedBound(
+ @DisplayCutout.BoundsPosition alignedBound: Int
+): Pair<List<DecorProvider>, List<DecorProvider>> {
+ return partition { it.alignedBounds.contains(alignedBound) }
}
/**
@@ -86,60 +94,3 @@ abstract class BoundDecorProvider : DecorProvider() {
listOf(alignedBound)
}
}
-
-/**
- * Split list to 2 list, and return it back as Pair<>. The providers on the first list contains this
- * alignedBound element. The providers on the second list do not contain this alignedBound element
- */
-fun List<DecorProvider>.partitionAlignedBound(
- @DisplayCutout.BoundsPosition alignedBound: Int
-): Pair<List<DecorProvider>, List<DecorProvider>> {
- return partition { it.alignedBounds.contains(alignedBound) }
-}
-
-/**
- * Get the proper bound from DecorProvider list
- * Time complexity: O(N), N is the number of providers
- *
- * Choose order
- * 1. Return null if list is empty
- * 2. If list contains BoundDecorProvider, return its alignedBound[0] because it is a must-have
- * bound
- * 3. Return the bound with most DecorProviders
- */
-fun List<DecorProvider>.getProperBound(): Int? {
- // Return null if list is empty
- if (isEmpty()) {
- return null
- }
-
- // Choose alignedBounds[0] of BoundDecorProvider if any
- val singleBoundProvider = firstOrNull { it.numOfAlignedBound == 1 }
- if (singleBoundProvider != null) {
- return singleBoundProvider.alignedBounds[0]
- }
-
- // Return the bound with most DecorProviders
- val boundCount = intArrayOf(0, 0, 0, 0)
- for (provider in this) {
- for (bound in provider.alignedBounds) {
- boundCount[bound]++
- }
- }
- var maxCount = 0
- var maxCountBound: Int? = null
- val bounds = arrayOf(
- // Put top and bottom at first to get the highest priority to be chosen
- DisplayCutout.BOUNDS_POSITION_TOP,
- DisplayCutout.BOUNDS_POSITION_BOTTOM,
- DisplayCutout.BOUNDS_POSITION_LEFT,
- DisplayCutout.BOUNDS_POSITION_RIGHT
- )
- for (bound in bounds) {
- if (boundCount[bound] > maxCount) {
- maxCountBound = bound
- maxCount = boundCount[bound]
- }
- }
- return maxCountBound
-}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
index 45b8a08a9b45..dfb0b5aad912 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
@@ -114,8 +114,7 @@ class OverlayWindow(private val context: Context) {
pw.println(" rootView=$rootView")
for (i in 0 until rootView.childCount) {
val child = rootView.getChildAt(i)
- val provider = viewProviderMap[child.id]?.second
- pw.println(" child[$i]=$child $provider")
+ pw.println(" child[$i]=$child")
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index df10dfe9f160..64a7986d05b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -16,6 +16,7 @@ package com.android.systemui;
import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
+import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
@@ -35,7 +36,6 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -49,6 +49,7 @@ import android.annotation.IdRes;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.graphics.Insets;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -59,6 +60,7 @@ import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+import android.util.RotationUtils;
import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
@@ -78,8 +80,6 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.decor.CornerDecorProvider;
-import com.android.systemui.decor.CutoutDecorProviderFactory;
-import com.android.systemui.decor.CutoutDecorProviderImpl;
import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.FaceScanningOverlayProviderImpl;
@@ -157,9 +157,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
@Mock
private DisplayInfo mDisplayInfo;
private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener;
- @Mock
- private CutoutDecorProviderFactory mCutoutFactory;
- private List<DecorProvider> mMockCutoutList;
@Before
public void setup() {
@@ -209,11 +206,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
DisplayCutout.BOUNDS_POSITION_RIGHT,
R.layout.privacy_dot_bottom_right));
- // Default no cutout
- mMockCutoutList = new ArrayList<>();
- doAnswer(it -> !(mMockCutoutList.isEmpty())).when(mCutoutFactory).getHasProviders();
- doReturn(mMockCutoutList).when(mCutoutFactory).getProviders();
-
mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl(
BOUNDS_POSITION_TOP,
mAuthController,
@@ -247,11 +239,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
super.updateOverlayWindowVisibilityIfViewExists(view);
mExecutor.runAllReady();
}
-
- @Override
- protected CutoutDecorProviderFactory getCutoutFactory() {
- return ScreenDecorationsTest.this.mCutoutFactory;
- }
});
mScreenDecorations.mDisplayInfo = mDisplayInfo;
doReturn(1f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio();
@@ -442,9 +429,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
- // no cutout (default)
+ // no cutout
+ doReturn(null).when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// No views added.
@@ -459,9 +448,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
- // no cutout (default)
+ // no cutout
+ doReturn(null).when(mScreenDecorations).getCutout();
mScreenDecorations.start();
@@ -493,9 +484,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
- // no cutout (default)
+ // no cutout
+ doReturn(null).when(mScreenDecorations).getCutout();
mScreenDecorations.start();
@@ -523,9 +516,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
- // no cutout (default)
+ // no cutout
+ doReturn(null).when(mScreenDecorations).getCutout();
mScreenDecorations.start();
@@ -560,9 +555,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
-
- // no cutout (default)
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
+ // no cutout
+ doReturn(null).when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Size of corner view should same as rounded_corner_radius{_top|_bottom}
@@ -578,9 +574,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
- // no cutout (default)
+ // no cutout
+ doReturn(null).when(mScreenDecorations).getCutout();
mScreenDecorations.start();
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
@@ -613,10 +611,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
// left cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
@@ -646,10 +647,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutShortEdge_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Top window is created for top cutout.
@@ -667,10 +671,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutShortEdge_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Top window is created for top cutout.
@@ -699,10 +706,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutLongEdge_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// left cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Left window is created for left cutout.
@@ -724,10 +734,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutLongEdge_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
// left cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Left window is created for left cutout.
@@ -749,10 +762,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -775,10 +791,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -804,10 +823,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutLongEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// left cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Left window is created for rounded corner and left cutout.
@@ -820,10 +842,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutLongEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
// left cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Left window is created for rounded corner, left cutout, and privacy.
@@ -838,11 +863,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// top and left cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -856,11 +883,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortAndLongEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
// top and left cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -876,16 +905,21 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// Set to short edge cutout(top).
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE);
// Switch to long edge cutout(left).
- mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.onConfigurationChanged(new Configuration());
verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE);
@@ -895,10 +929,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
// Set to short edge cutout(top).
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
@@ -906,7 +943,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verify(mDotViewController, times(1)).setShowingListener(null);
// Switch to long edge cutout(left).
- mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.onConfigurationChanged(new Configuration());
verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE);
@@ -934,16 +973,20 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testDelayedCutout_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
- // No cutout (default)
+ // top cutout
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, false, false, false, null);
- // top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
-
+ when(mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
+ .thenReturn(true);
mScreenDecorations.onConfigurationChanged(new Configuration());
// Only top windows should be added.
@@ -954,9 +997,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testDelayedCutout_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
- // no cutout (default)
+ // top cutout
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
@@ -968,9 +1015,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verify(mDotViewController, times(1)).setShowingListener(
mScreenDecorations.mPrivacyDotShowingListener);
- // top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
-
+ when(mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
+ .thenReturn(true);
mScreenDecorations.onConfigurationChanged(new Configuration());
// Both top and bottom windows should be added with VISIBLE because of privacy dot and
@@ -996,7 +1043,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning*/);
mDisplayInfo.rotation = Surface.ROTATION_0;
mScreenDecorations.start();
@@ -1010,7 +1058,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning*/);
mDisplayInfo.rotation = Surface.ROTATION_270;
mScreenDecorations.onConfigurationChanged(null);
@@ -1023,7 +1072,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnlyRoundedCornerRadiusTop() {
setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
mScreenDecorations.start();
@@ -1044,7 +1094,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnlyRoundedCornerRadiusBottom() {
setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
mScreenDecorations.start();
@@ -1115,10 +1166,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testSupportHwcLayer_SwitchFrom_NotSupport() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// should only inflate mOverlays when the hwc doesn't support screen decoration
@@ -1141,13 +1195,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNotSupportHwcLayer_SwitchFrom_Support() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// should only inflate hwc layer when the hwc supports screen decoration
@@ -1177,13 +1234,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ true /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1217,9 +1277,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
+ true /* faceScanning */);
- // no cutout (default)
+ // no cutout
+ doReturn(null).when(mScreenDecorations).getCutout();
mScreenDecorations.start();
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1253,13 +1315,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHwcLayer_noPrivacyDot_noFaceScanning() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
@@ -1272,13 +1337,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHwcLayer_PrivacyDot_FaceScanning() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ true /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
@@ -1296,13 +1364,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnDisplayChanged_hwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
@@ -1319,16 +1390,18 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnDisplayChanged_nonHwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
// top cutout
- mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+ final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+ doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+ .when(mScreenDecorations).getCutout();
mScreenDecorations.start();
- final ScreenDecorations.DisplayCutoutView cutoutView = (ScreenDecorations.DisplayCutoutView)
- mScreenDecorations.getOverlayView(R.id.display_cutout);
- assertNotNull(cutoutView);
+ final ScreenDecorations.DisplayCutoutView cutoutView =
+ mScreenDecorations.mCutoutViews[BOUNDS_POSITION_TOP];
spyOn(cutoutView);
doReturn(mDisplay).when(cutoutView).getDisplay();
@@ -1341,7 +1414,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHasSameProvidersWithNullOverlays() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
+ false /* faceScanning */);
mScreenDecorations.start();
@@ -1359,7 +1433,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHasSameProvidersWithPrivacyDots() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+ 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
+ false /* faceScanning */);
mScreenDecorations.start();
@@ -1396,7 +1471,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
private void setupResources(int radius, int radiusTop, int radiusBottom,
@Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable,
- int roundedPadding, boolean privacyDot, boolean faceScanning) {
+ int roundedPadding, boolean fillCutout, boolean privacyDot, boolean faceScanning) {
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.array.config_displayUniqueIdArray,
new String[]{});
@@ -1436,6 +1511,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
}
mContext.getOrCreateTestableResources().addOverride(
R.dimen.rounded_corner_content_padding, roundedPadding);
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
mPrivacyDecorProviders = new ArrayList<>();
if (privacyDot) {
@@ -1454,4 +1531,19 @@ public class ScreenDecorationsTest extends SysuiTestCase {
when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(faceScanning);
}
+
+ private DisplayCutout getDisplayCutoutForRotation(Insets safeInsets, Rect[] cutoutBounds) {
+ final int rotation = mContext.getDisplay().getRotation();
+ final Insets insets = RotationUtils.rotateInsets(safeInsets, rotation);
+ final Rect[] sorted = new Rect[BOUNDS_POSITION_LENGTH];
+ for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+ final int rotatedPos = ScreenDecorations.getBoundPositionFromRotation(i, rotation);
+ if (cutoutBounds[i] != null) {
+ RotationUtils.rotateBounds(cutoutBounds[i], new Rect(0, 0, 100, 200), rotation);
+ }
+ sorted[rotatedPos] = cutoutBounds[i];
+ }
+ return new DisplayCutout(insets, sorted[BOUNDS_POSITION_LEFT], sorted[BOUNDS_POSITION_TOP],
+ sorted[BOUNDS_POSITION_RIGHT], sorted[BOUNDS_POSITION_BOTTOM]);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
deleted file mode 100644
index 1040ec453a7c..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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.graphics.Insets
-import android.graphics.Rect
-import android.testing.AndroidTestingRunner
-import android.testing.TestableResources
-import android.util.RotationUtils
-import android.util.Size
-import android.view.Display
-import android.view.DisplayCutout
-import android.view.DisplayCutout.BOUNDS_POSITION_LENGTH
-import android.view.DisplayInfo
-import android.view.Surface
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.util.mockito.any
-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.doAnswer
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-class CutoutDecorProviderFactoryTest : SysuiTestCase() {
-
- @Mock private lateinit var display: Display
- private var testableRes: TestableResources? = null
- private lateinit var factory: CutoutDecorProviderFactory
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
- testableRes = mContext.orCreateTestableResources
- factory = CutoutDecorProviderFactory(testableRes!!.resources, display)
- }
-
- private fun setupFillCutout(fillCutout: Boolean) {
- testableRes!!.addOverride(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout
- )
- }
-
- private fun setupDisplayInfo(
- displayCutout: DisplayCutout? = null,
- @Surface.Rotation rotation: Int = Surface.ROTATION_0,
- displayId: Int = -1
- ) {
- doAnswer {
- it.getArgument<DisplayInfo>(0).let { info ->
- info.displayCutout = displayCutout
- info.rotation = rotation
- info.displayId = displayId
- }
- true
- }.`when`(display).getDisplayInfo(any<DisplayInfo>())
- }
-
- private fun getCutout(
- safeInsets: Insets,
- cutoutBounds: Array<Rect?>,
- @Surface.Rotation rotation: Int = Surface.ROTATION_0,
- cutoutParentSizeForRotate: Size = Size(100, 200)
- ): DisplayCutout {
- val insets = RotationUtils.rotateInsets(safeInsets, rotation)
- val sorted = arrayOfNulls<Rect>(BOUNDS_POSITION_LENGTH)
- for (pos in 0 until BOUNDS_POSITION_LENGTH) {
- val rotatedPos = (pos - rotation + BOUNDS_POSITION_LENGTH) % BOUNDS_POSITION_LENGTH
- if (cutoutBounds[pos] != null) {
- RotationUtils.rotateBounds(
- cutoutBounds[pos],
- cutoutParentSizeForRotate.width,
- cutoutParentSizeForRotate.height,
- rotation
- )
- }
- sorted[rotatedPos] = cutoutBounds[pos]
- }
- return DisplayCutout(
- insets,
- sorted[DisplayCutout.BOUNDS_POSITION_LEFT],
- sorted[DisplayCutout.BOUNDS_POSITION_TOP],
- sorted[DisplayCutout.BOUNDS_POSITION_RIGHT],
- sorted[DisplayCutout.BOUNDS_POSITION_BOTTOM]
- )
- }
-
- @Test
- fun testGetNothingIfNoCutout() {
- setupFillCutout(false)
-
- Assert.assertFalse(factory.hasProviders)
- Assert.assertEquals(0, factory.providers.size)
- }
-
- @Test
- fun testGetTopCutoutProvider() {
- setupFillCutout(true)
- setupDisplayInfo(
- getCutout(
- safeInsets = Insets.of(0, 1, 0, 0),
- cutoutBounds = arrayOf(null, Rect(9, 0, 10, 1), null, null)
- )
- )
-
- Assert.assertTrue(factory.hasProviders)
-
- val providers = factory.providers
- Assert.assertEquals(1, providers.size)
- Assert.assertEquals(1, providers[0].numOfAlignedBound)
- Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, providers[0].alignedBounds[0])
- }
-
- @Test
- fun testGetBottomCutoutProviderOnLandscape() {
- setupFillCutout(true)
- setupDisplayInfo(
- getCutout(
- safeInsets = Insets.of(0, 0, 0, 1),
- cutoutBounds = arrayOf(null, null, null, Rect(45, 199, 55, 200)),
- rotation = Surface.ROTATION_90
- ),
- Surface.ROTATION_90
- )
-
- Assert.assertTrue(factory.hasProviders)
-
- val providers = factory.providers
- Assert.assertEquals(1, providers.size)
- Assert.assertEquals(1, providers[0].numOfAlignedBound)
- Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_BOTTOM, providers[0].alignedBounds[0])
- }
-
- @Test
- fun testGetLeftCutoutProviderOnSeascape() {
- setupFillCutout(true)
- setupDisplayInfo(
- getCutout(
- safeInsets = Insets.of(1, 0, 0, 0),
- cutoutBounds = arrayOf(Rect(0, 20, 1, 40), null, null, null),
- rotation = Surface.ROTATION_270
- ),
- Surface.ROTATION_270
- )
-
- Assert.assertTrue(factory.hasProviders)
-
- val providers = factory.providers
- Assert.assertEquals(1, providers.size)
- Assert.assertEquals(1, providers[0].numOfAlignedBound)
- Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_LEFT, providers[0].alignedBounds[0])
- }
-
- @Test
- fun testGetTopRightCutoutProviderOnReverse() {
- setupFillCutout(true)
- setupDisplayInfo(
- getCutout(
- safeInsets = Insets.of(0, 1, 1, 0),
- cutoutBounds = arrayOf(
- null,
- Rect(9, 0, 10, 1),
- Rect(99, 40, 100, 60),
- null
- ),
- rotation = Surface.ROTATION_180
- ),
- Surface.ROTATION_180
- )
-
- Assert.assertTrue(factory.hasProviders)
-
- val providers = factory.providers
- Assert.assertEquals(2, providers.size)
- Assert.assertEquals(1, providers[0].numOfAlignedBound)
- Assert.assertEquals(1, providers[1].numOfAlignedBound)
- providers.sortedBy { it.alignedBounds[0] }.let {
- Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, it[0].alignedBounds[0])
- Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_RIGHT, it[1].alignedBounds[0])
- }
- }
-}