Merge changes from topic "cutoutProvider" into tm-qpr-dev
* changes: Re-land ScreenDecorations Cutout Provider Move color and display info into DecorProvider
This commit is contained in:
@@ -131,7 +131,11 @@
|
|||||||
<!-- For StatusIconContainer to tag its icon views -->
|
<!-- For StatusIconContainer to tag its icon views -->
|
||||||
<item type="id" name="status_bar_view_state_tag" />
|
<item type="id" name="status_bar_view_state_tag" />
|
||||||
|
|
||||||
|
<!-- Default display cutout on the physical top of screen -->
|
||||||
<item type="id" name="display_cutout" />
|
<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" />
|
<item type="id" name="row_tag_for_content_view" />
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ import com.android.systemui.animation.Interpolators
|
|||||||
open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
||||||
|
|
||||||
private var shouldDrawCutout: Boolean = DisplayCutout.getFillBuiltInDisplayCutout(
|
private var shouldDrawCutout: Boolean = DisplayCutout.getFillBuiltInDisplayCutout(
|
||||||
context.resources, context.display?.uniqueId)
|
context.resources, context.display?.uniqueId
|
||||||
|
)
|
||||||
private var displayUniqueId: String? = null
|
private var displayUniqueId: String? = null
|
||||||
private var displayMode: Display.Mode? = null
|
private var displayMode: Display.Mode? = null
|
||||||
protected val location = IntArray(2)
|
protected val location = IntArray(2)
|
||||||
@@ -74,8 +75,8 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
|
||||||
: super(context, attrs, defStyleAttr)
|
super(context, attrs, defStyleAttr)
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
super.onAttachedToWindow()
|
super.onAttachedToWindow()
|
||||||
@@ -85,7 +86,7 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
onUpdate()
|
onUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDisplayChanged(displayId: Int) {
|
fun onDisplayChanged(newDisplayUniqueId: String?) {
|
||||||
val oldMode: Display.Mode? = displayMode
|
val oldMode: Display.Mode? = displayMode
|
||||||
val display: Display? = context.display
|
val display: Display? = context.display
|
||||||
displayMode = display?.mode
|
displayMode = display?.mode
|
||||||
@@ -93,7 +94,8 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
if (displayUniqueId != display?.uniqueId) {
|
if (displayUniqueId != display?.uniqueId) {
|
||||||
displayUniqueId = display?.uniqueId
|
displayUniqueId = display?.uniqueId
|
||||||
shouldDrawCutout = DisplayCutout.getFillBuiltInDisplayCutout(
|
shouldDrawCutout = DisplayCutout.getFillBuiltInDisplayCutout(
|
||||||
context.resources, displayUniqueId)
|
context.resources, displayUniqueId
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if display mode or cutout hasn't changed.
|
// Skip if display mode or cutout hasn't changed.
|
||||||
@@ -101,7 +103,7 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
display?.cutout == displayInfo.displayCutout) {
|
display?.cutout == displayInfo.displayCutout) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (displayId == display?.displayId) {
|
if (newDisplayUniqueId == display?.uniqueId) {
|
||||||
updateCutout()
|
updateCutout()
|
||||||
updateProtectionBoundingPath()
|
updateProtectionBoundingPath()
|
||||||
onUpdate()
|
onUpdate()
|
||||||
@@ -147,8 +149,9 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
cutoutBounds.translate(-location[0], -location[1])
|
cutoutBounds.translate(-location[0], -location[1])
|
||||||
|
|
||||||
// Intersect with window's frame
|
// Intersect with window's frame
|
||||||
cutoutBounds.op(rootView.left, rootView.top, rootView.right, rootView.bottom,
|
cutoutBounds.op(
|
||||||
Region.Op.INTERSECT)
|
rootView.left, rootView.top, rootView.right, rootView.bottom, Region.Op.INTERSECT
|
||||||
|
)
|
||||||
return cutoutBounds
|
return cutoutBounds
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +174,12 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
|
|
||||||
protected open fun drawCutoutProtection(canvas: Canvas) {
|
protected open fun drawCutoutProtection(canvas: Canvas) {
|
||||||
if (cameraProtectionProgress > HIDDEN_CAMERA_PROTECTION_SCALE &&
|
if (cameraProtectionProgress > HIDDEN_CAMERA_PROTECTION_SCALE &&
|
||||||
!protectionRect.isEmpty) {
|
!protectionRect.isEmpty
|
||||||
canvas.scale(cameraProtectionProgress, cameraProtectionProgress,
|
) {
|
||||||
protectionRect.centerX(), protectionRect.centerY())
|
canvas.scale(
|
||||||
|
cameraProtectionProgress, cameraProtectionProgress, protectionRect.centerX(),
|
||||||
|
protectionRect.centerY()
|
||||||
|
)
|
||||||
canvas.drawPath(protectionPath, paint)
|
canvas.drawPath(protectionPath, paint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,14 +211,17 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
requestLayout()
|
requestLayout()
|
||||||
}
|
}
|
||||||
cameraProtectionAnimator?.cancel()
|
cameraProtectionAnimator?.cancel()
|
||||||
cameraProtectionAnimator = ValueAnimator.ofFloat(cameraProtectionProgress,
|
cameraProtectionAnimator = ValueAnimator.ofFloat(
|
||||||
if (showProtection) 1.0f else HIDDEN_CAMERA_PROTECTION_SCALE).setDuration(750)
|
cameraProtectionProgress,
|
||||||
|
if (showProtection) 1.0f else HIDDEN_CAMERA_PROTECTION_SCALE
|
||||||
|
).setDuration(750)
|
||||||
cameraProtectionAnimator?.interpolator = Interpolators.DECELERATE_QUINT
|
cameraProtectionAnimator?.interpolator = Interpolators.DECELERATE_QUINT
|
||||||
cameraProtectionAnimator?.addUpdateListener(ValueAnimator.AnimatorUpdateListener {
|
cameraProtectionAnimator?.addUpdateListener(
|
||||||
animation: ValueAnimator ->
|
ValueAnimator.AnimatorUpdateListener { animation: ValueAnimator ->
|
||||||
cameraProtectionProgress = animation.animatedValue as Float
|
cameraProtectionProgress = animation.animatedValue as Float
|
||||||
invalidate()
|
invalidate()
|
||||||
})
|
}
|
||||||
|
)
|
||||||
cameraProtectionAnimator?.addListener(object : AnimatorListenerAdapter() {
|
cameraProtectionAnimator?.addListener(object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationEnd(animation: Animator) {
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
cameraProtectionAnimator = null
|
cameraProtectionAnimator = null
|
||||||
@@ -245,8 +254,10 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
// Apply rotation.
|
// Apply rotation.
|
||||||
val lw: Int = displayInfo.logicalWidth
|
val lw: Int = displayInfo.logicalWidth
|
||||||
val lh: Int = displayInfo.logicalHeight
|
val lh: Int = displayInfo.logicalHeight
|
||||||
val flipped = (displayInfo.rotation == Surface.ROTATION_90 ||
|
val flipped = (
|
||||||
displayInfo.rotation == Surface.ROTATION_270)
|
displayInfo.rotation == Surface.ROTATION_90 ||
|
||||||
|
displayInfo.rotation == Surface.ROTATION_270
|
||||||
|
)
|
||||||
val dw = if (flipped) lh else lw
|
val dw = if (flipped) lh else lw
|
||||||
val dh = if (flipped) lw else lh
|
val dh = if (flipped) lw else lh
|
||||||
transformPhysicalToLogicalCoordinates(displayInfo.rotation, dw, dh, m)
|
transformPhysicalToLogicalCoordinates(displayInfo.rotation, dw, dh, m)
|
||||||
@@ -275,7 +286,7 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
// We purposely ignore refresh rate and id changes here, because we don't need to
|
// We purposely ignore refresh rate and id changes here, because we don't need to
|
||||||
// invalidate for those, and they can trigger the refresh rate to increase
|
// invalidate for those, and they can trigger the refresh rate to increase
|
||||||
return oldMode?.physicalHeight != newMode?.physicalHeight ||
|
return oldMode?.physicalHeight != newMode?.physicalHeight ||
|
||||||
oldMode?.physicalWidth != newMode?.physicalWidth
|
oldMode?.physicalWidth != newMode?.physicalWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.res.ColorStateList;
|
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@@ -73,6 +72,7 @@ import com.android.settingslib.Utils;
|
|||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.decor.CutoutDecorProviderFactory;
|
||||||
import com.android.systemui.decor.DecorProvider;
|
import com.android.systemui.decor.DecorProvider;
|
||||||
import com.android.systemui.decor.DecorProviderFactory;
|
import com.android.systemui.decor.DecorProviderFactory;
|
||||||
import com.android.systemui.decor.DecorProviderKt;
|
import com.android.systemui.decor.DecorProviderKt;
|
||||||
@@ -92,10 +92,8 @@ import com.android.systemui.util.settings.SecureSettings;
|
|||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -121,6 +119,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
private static final boolean VERBOSE = false;
|
private static final boolean VERBOSE = false;
|
||||||
static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
|
static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
|
||||||
|
|
||||||
|
private static final int[] DISPLAY_CUTOUT_IDS = {
|
||||||
|
R.id.display_cutout,
|
||||||
|
R.id.display_cutout_left,
|
||||||
|
R.id.display_cutout_right,
|
||||||
|
R.id.display_cutout_bottom
|
||||||
|
};
|
||||||
|
|
||||||
private DisplayManager mDisplayManager;
|
private DisplayManager mDisplayManager;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected boolean mIsRegistered;
|
protected boolean mIsRegistered;
|
||||||
@@ -142,13 +147,11 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
|
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected DecorProviderFactory mRoundedCornerFactory;
|
protected DecorProviderFactory mRoundedCornerFactory;
|
||||||
|
private CutoutDecorProviderFactory mCutoutFactory;
|
||||||
private int mProviderRefreshToken = 0;
|
private int mProviderRefreshToken = 0;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected OverlayWindow[] mOverlays = null;
|
protected OverlayWindow[] mOverlays = null;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@Nullable
|
|
||||||
DisplayCutoutView[] mCutoutViews;
|
|
||||||
@VisibleForTesting
|
|
||||||
ViewGroup mScreenDecorHwcWindow;
|
ViewGroup mScreenDecorHwcWindow;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
ScreenDecorHwcLayer mScreenDecorHwcLayer;
|
ScreenDecorHwcLayer mScreenDecorHwcLayer;
|
||||||
@@ -190,18 +193,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCutoutViews == null) {
|
int setProtectionCnt = 0;
|
||||||
Log.w(TAG, "DisplayCutoutView not initialized onApplyCameraProtection");
|
for (int id: DISPLAY_CUTOUT_IDS) {
|
||||||
return;
|
final View view = getOverlayView(id);
|
||||||
}
|
if (!(view instanceof DisplayCutoutView)) {
|
||||||
|
continue;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
++setProtectionCnt;
|
||||||
|
final DisplayCutoutView dcv = (DisplayCutoutView) view;
|
||||||
|
dcv.setProtection(protectionPath, bounds);
|
||||||
|
dcv.enableShowProtection(true);
|
||||||
|
}
|
||||||
|
if (setProtectionCnt == 0) {
|
||||||
|
Log.e(TAG, "CutoutView not initialized showCameraProtection");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,16 +226,17 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCutoutViews == null) {
|
int setProtectionCnt = 0;
|
||||||
Log.w(TAG, "DisplayCutoutView not initialized onHideCameraProtection");
|
for (int id: DISPLAY_CUTOUT_IDS) {
|
||||||
return;
|
final View view = getOverlayView(id);
|
||||||
}
|
if (!(view instanceof DisplayCutoutView)) {
|
||||||
// Go back to the regular anti-aliasing
|
continue;
|
||||||
for (DisplayCutoutView dcv : mCutoutViews) {
|
|
||||||
// Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
|
|
||||||
if (dcv != null) {
|
|
||||||
dcv.enableShowProtection(false);
|
|
||||||
}
|
}
|
||||||
|
++setProtectionCnt;
|
||||||
|
((DisplayCutoutView) view).enableShowProtection(false);
|
||||||
|
}
|
||||||
|
if (setProtectionCnt == 0) {
|
||||||
|
Log.e(TAG, "CutoutView not initialized hideCameraProtection");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,6 +343,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
decorProviders.addAll(mFaceScanningFactory.getProviders());
|
decorProviders.addAll(mFaceScanningFactory.getProviders());
|
||||||
if (!hasHwLayer) {
|
if (!hasHwLayer) {
|
||||||
decorProviders.addAll(mRoundedCornerFactory.getProviders());
|
decorProviders.addAll(mRoundedCornerFactory.getProviders());
|
||||||
|
decorProviders.addAll(mCutoutFactory.getProviders());
|
||||||
}
|
}
|
||||||
return decorProviders;
|
return decorProviders;
|
||||||
}
|
}
|
||||||
@@ -382,6 +388,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
|
mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
|
||||||
getPhysicalPixelDisplaySizeRatio());
|
getPhysicalPixelDisplaySizeRatio());
|
||||||
mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
|
mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
|
||||||
|
mCutoutFactory = getCutoutFactory();
|
||||||
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
|
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
|
||||||
updateHwLayerRoundedCornerDrawable();
|
updateHwLayerRoundedCornerDrawable();
|
||||||
setupDecorations();
|
setupDecorations();
|
||||||
@@ -448,6 +455,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean needToUpdateProviderViews = false;
|
||||||
final String newUniqueId = mDisplayInfo.uniqueId;
|
final String newUniqueId = mDisplayInfo.uniqueId;
|
||||||
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
|
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
|
||||||
mDisplayUniqueId = newUniqueId;
|
mDisplayUniqueId = newUniqueId;
|
||||||
@@ -470,8 +478,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
updateHwLayerRoundedCornerDrawable();
|
updateHwLayerRoundedCornerDrawable();
|
||||||
updateHwLayerRoundedCornerExistAndSize();
|
updateHwLayerRoundedCornerExistAndSize();
|
||||||
}
|
}
|
||||||
|
needToUpdateProviderViews = true;
|
||||||
updateOverlayProviderViews();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final float newRatio = getPhysicalPixelDisplaySizeRatio();
|
final float newRatio = getPhysicalPixelDisplaySizeRatio();
|
||||||
@@ -480,28 +487,23 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
if (mScreenDecorHwcLayer != null) {
|
if (mScreenDecorHwcLayer != null) {
|
||||||
updateHwLayerRoundedCornerExistAndSize();
|
updateHwLayerRoundedCornerExistAndSize();
|
||||||
}
|
}
|
||||||
updateOverlayProviderViews();
|
needToUpdateProviderViews = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCutoutViews != null) {
|
if (needToUpdateProviderViews) {
|
||||||
final int size = mCutoutViews.length;
|
updateOverlayProviderViews(null);
|
||||||
for (int i = 0; i < size; i++) {
|
} else {
|
||||||
final DisplayCutoutView cutoutView = mCutoutViews[i];
|
updateOverlayProviderViews(new Integer[] {
|
||||||
if (cutoutView == null) {
|
mFaceScanningViewId,
|
||||||
continue;
|
R.id.display_cutout,
|
||||||
}
|
R.id.display_cutout_left,
|
||||||
cutoutView.onDisplayChanged(displayId);
|
R.id.display_cutout_right,
|
||||||
}
|
R.id.display_cutout_bottom,
|
||||||
}
|
});
|
||||||
|
|
||||||
DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView(mFaceScanningViewId);
|
|
||||||
if (overlay != null) {
|
|
||||||
// handle display resolution changes
|
|
||||||
overlay.onDisplayChanged(displayId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mScreenDecorHwcLayer != null) {
|
if (mScreenDecorHwcLayer != null) {
|
||||||
mScreenDecorHwcLayer.onDisplayChanged(displayId);
|
mScreenDecorHwcLayer.onDisplayChanged(newUniqueId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -510,8 +512,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
updateConfiguration();
|
updateConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
@Nullable
|
@Nullable
|
||||||
private View getOverlayView(@IdRes int id) {
|
View getOverlayView(@IdRes int id) {
|
||||||
if (mOverlays == null) {
|
if (mOverlays == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -568,18 +571,18 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
removeHwcOverlay();
|
removeHwcOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
final DisplayCutout cutout = getCutout();
|
boolean[] hasCreatedOverlay = new boolean[BOUNDS_POSITION_LENGTH];
|
||||||
final boolean shouldOptimizeVisibility = shouldOptimizeVisibility();
|
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++) {
|
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
|
||||||
if (shouldShowSwLayerCutout(i, cutout)
|
if (!hasCreatedOverlay[i]) {
|
||||||
|| 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);
|
removeOverlay(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,9 +645,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
// For unit test to override
|
||||||
DisplayCutout getCutout() {
|
protected CutoutDecorProviderFactory getCutoutFactory() {
|
||||||
return mContext.getDisplay().getCutout();
|
return new CutoutDecorProviderFactory(mContext.getResources(),
|
||||||
|
mContext.getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -734,16 +738,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
overlayView.setAlpha(0);
|
overlayView.setAlpha(0);
|
||||||
overlayView.setForceDarkAllowed(false);
|
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));
|
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
|
||||||
|
|
||||||
overlayView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
|
overlayView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
|
||||||
@@ -804,7 +798,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeOverlayView(provider.getViewId());
|
removeOverlayView(provider.getViewId());
|
||||||
overlay.addDecorProvider(provider, mRotation);
|
overlay.addDecorProvider(provider, mRotation, mTintColor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Use visibility of privacy dot views & face scanning view to determine the overlay's
|
// Use visibility of privacy dot views & face scanning view to determine the overlay's
|
||||||
@@ -923,6 +917,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupCameraListener() {
|
private void setupCameraListener() {
|
||||||
|
// TODO(b/238143614) Support dual screen camera protection
|
||||||
Resources res = mContext.getResources();
|
Resources res = mContext.getResources();
|
||||||
boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection);
|
boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
@@ -951,45 +946,17 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mTintColor = Color.RED;
|
mTintColor = Color.RED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mOverlays == null) {
|
updateOverlayProviderViews(new Integer[] {
|
||||||
return;
|
mFaceScanningViewId,
|
||||||
}
|
R.id.display_cutout,
|
||||||
|
R.id.display_cutout_left,
|
||||||
// When the hwc supports screen decorations, the layer will use the A8 color mode which
|
R.id.display_cutout_right,
|
||||||
// won't be affected by the color inversion. If the composition goes the client composition
|
R.id.display_cutout_bottom,
|
||||||
// route, the color inversion will be handled by the RenderEngine.
|
R.id.rounded_corner_top_left,
|
||||||
final Set<Integer> viewsMayNeedColorUpdate = new HashSet<>();
|
R.id.rounded_corner_top_right,
|
||||||
if (mHwcScreenDecorationSupport == null) {
|
R.id.rounded_corner_bottom_left,
|
||||||
ColorStateList tintList = ColorStateList.valueOf(mTintColor);
|
R.id.rounded_corner_bottom_right
|
||||||
mRoundedCornerResDelegate.setColorTintList(tintList);
|
});
|
||||||
viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_left);
|
|
||||||
viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_right);
|
|
||||||
viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_left);
|
|
||||||
viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_right);
|
|
||||||
viewsMayNeedColorUpdate.add(R.id.display_cutout);
|
|
||||||
}
|
|
||||||
if (getOverlayView(mFaceScanningViewId) != null) {
|
|
||||||
viewsMayNeedColorUpdate.add(mFaceScanningViewId);
|
|
||||||
}
|
|
||||||
final Integer[] views = new Integer[viewsMayNeedColorUpdate.size()];
|
|
||||||
viewsMayNeedColorUpdate.toArray(views);
|
|
||||||
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 (viewsMayNeedColorUpdate.contains(child.getId())
|
|
||||||
&& child instanceof DisplayCutoutView) {
|
|
||||||
((DisplayCutoutView) child).setColor(mTintColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mOverlays[i].onReloadResAndMeasure(views, mProviderRefreshToken,
|
|
||||||
mRotation, mDisplayUniqueId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -1109,18 +1076,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
updateHwLayerRoundedCornerDrawable();
|
updateHwLayerRoundedCornerDrawable();
|
||||||
}
|
}
|
||||||
updateLayoutParams();
|
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
|
// update all provider views inside overlay
|
||||||
updateOverlayProviderViews();
|
updateOverlayProviderViews(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
FaceScanningOverlay faceScanningOverlay =
|
FaceScanningOverlay faceScanningOverlay =
|
||||||
@@ -1136,46 +1094,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
return mRoundedCornerFactory.getHasProviders();
|
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() {
|
private boolean shouldOptimizeVisibility() {
|
||||||
return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders())
|
return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders())
|
||||||
&& (mHwcScreenDecorationSupport != null
|
&& (mHwcScreenDecorationSupport != null
|
||||||
@@ -1184,7 +1102,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldDrawCutout() {
|
private boolean shouldDrawCutout() {
|
||||||
return shouldDrawCutout(mContext);
|
return mCutoutFactory.getHasProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean shouldDrawCutout(Context context) {
|
static boolean shouldDrawCutout(Context context) {
|
||||||
@@ -1192,7 +1110,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
context.getResources(), context.getDisplay().getUniqueId());
|
context.getResources(), context.getDisplay().getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOverlayProviderViews() {
|
private void updateOverlayProviderViews(@Nullable Integer[] filterIds) {
|
||||||
if (mOverlays == null) {
|
if (mOverlays == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1201,7 +1119,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
if (overlay == null) {
|
if (overlay == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
|
overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation, mTintColor,
|
||||||
|
mDisplayUniqueId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1240,19 +1159,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
mRoundedCornerResDelegate.setTuningSizeFactor(null);
|
mRoundedCornerResDelegate.setTuningSizeFactor(null);
|
||||||
}
|
}
|
||||||
Integer[] filterIds = {
|
updateOverlayProviderViews(new Integer[] {
|
||||||
R.id.rounded_corner_top_left,
|
R.id.rounded_corner_top_left,
|
||||||
R.id.rounded_corner_top_right,
|
R.id.rounded_corner_top_right,
|
||||||
R.id.rounded_corner_bottom_left,
|
R.id.rounded_corner_bottom_left,
|
||||||
R.id.rounded_corner_bottom_right
|
R.id.rounded_corner_bottom_right
|
||||||
};
|
});
|
||||||
for (final OverlayWindow overlay: mOverlays) {
|
|
||||||
if (overlay == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
|
|
||||||
mDisplayUniqueId);
|
|
||||||
}
|
|
||||||
updateHwLayerRoundedCornerExistAndSize();
|
updateHwLayerRoundedCornerExistAndSize();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1306,7 +1218,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
|
|
||||||
paint.setColor(mColor);
|
paint.setColor(mColor);
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Paint.Style.FILL);
|
||||||
setId(R.id.display_cutout);
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
|
getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
|
||||||
getWindowTitleByPos(pos) + " drawn in rot " + mRotation));
|
getWindowTitleByPos(pos) + " drawn in rot " + mRotation));
|
||||||
@@ -1314,6 +1225,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setColor(int color) {
|
public void setColor(int color) {
|
||||||
|
if (color == mColor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mColor = color;
|
mColor = color;
|
||||||
paint.setColor(mColor);
|
paint.setColor(mColor);
|
||||||
invalidate();
|
invalidate();
|
||||||
@@ -1321,6 +1235,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateRotation(int rotation) {
|
public void updateRotation(int rotation) {
|
||||||
|
// updateRotation() is called inside CutoutDecorProviderImpl::onReloadResAndMeasure()
|
||||||
|
// during onDisplayChanged. In order to prevent reloading cutout info in super class,
|
||||||
|
// check mRotation at first
|
||||||
|
if (rotation == mRotation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mRotation = rotation;
|
mRotation = rotation;
|
||||||
super.updateRotation(rotation);
|
super.updateRotation(rotation);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,8 +32,8 @@ abstract class DecorProvider {
|
|||||||
abstract val viewId: Int
|
abstract val viewId: Int
|
||||||
|
|
||||||
/** The number of total aligned bounds */
|
/** The number of total aligned bounds */
|
||||||
val numOfAlignedEdge: Int
|
val numOfAlignedBound: Int
|
||||||
get() = alignedBounds.size
|
get() = alignedBounds.size
|
||||||
|
|
||||||
/** The aligned bounds for the view which is created through inflateView() */
|
/** The aligned bounds for the view which is created through inflateView() */
|
||||||
abstract val alignedBounds: List<Int>
|
abstract val alignedBounds: List<Int>
|
||||||
@@ -46,25 +46,19 @@ abstract class DecorProvider {
|
|||||||
view: View,
|
view: View,
|
||||||
reloadToken: Int,
|
reloadToken: Int,
|
||||||
@Surface.Rotation rotation: Int,
|
@Surface.Rotation rotation: Int,
|
||||||
displayUniqueId: String? = null
|
tintColor: Int,
|
||||||
|
displayUniqueId: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Inflate view into parent as current rotation */
|
/** Inflate view into parent as current rotation */
|
||||||
abstract fun inflateView(
|
abstract fun inflateView(
|
||||||
context: Context,
|
context: Context,
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
@Surface.Rotation rotation: Int
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int
|
||||||
): View
|
): 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) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,3 +86,61 @@ abstract class BoundDecorProvider : DecorProvider() {
|
|||||||
listOf(alignedBound)
|
listOf(alignedBound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split list to 2 sub-lists, 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -115,19 +115,25 @@ class FaceScanningOverlayProviderImpl(
|
|||||||
override fun onReloadResAndMeasure(
|
override fun onReloadResAndMeasure(
|
||||||
view: View,
|
view: View,
|
||||||
reloadToken: Int,
|
reloadToken: Int,
|
||||||
rotation: Int,
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int,
|
||||||
displayUniqueId: String?
|
displayUniqueId: String?
|
||||||
) {
|
) {
|
||||||
(view.layoutParams as FrameLayout.LayoutParams).let {
|
(view.layoutParams as FrameLayout.LayoutParams).let {
|
||||||
updateLayoutParams(it, rotation)
|
updateLayoutParams(it, rotation)
|
||||||
view.layoutParams = it
|
view.layoutParams = it
|
||||||
|
(view as? FaceScanningOverlay)?.let { overlay ->
|
||||||
|
overlay.setColor(tintColor)
|
||||||
|
overlay.onDisplayChanged(displayUniqueId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inflateView(
|
override fun inflateView(
|
||||||
context: Context,
|
context: Context,
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
@Surface.Rotation rotation: Int
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int
|
||||||
): View {
|
): View {
|
||||||
val view = FaceScanningOverlay(
|
val view = FaceScanningOverlay(
|
||||||
context,
|
context,
|
||||||
@@ -137,6 +143,7 @@ class FaceScanningOverlayProviderImpl(
|
|||||||
mainExecutor
|
mainExecutor
|
||||||
)
|
)
|
||||||
view.id = viewId
|
view.id = viewId
|
||||||
|
view.setColor(tintColor)
|
||||||
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT).let {
|
ViewGroup.LayoutParams.MATCH_PARENT).let {
|
||||||
updateLayoutParams(it, rotation)
|
updateLayoutParams(it, rotation)
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ class OverlayWindow(private val context: Context) {
|
|||||||
|
|
||||||
fun addDecorProvider(
|
fun addDecorProvider(
|
||||||
decorProvider: DecorProvider,
|
decorProvider: DecorProvider,
|
||||||
@Surface.Rotation rotation: Int
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int
|
||||||
) {
|
) {
|
||||||
val view = decorProvider.inflateView(context, rootView, rotation)
|
val view = decorProvider.inflateView(context, rootView, rotation, tintColor)
|
||||||
viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
|
viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ class OverlayWindow(private val context: Context) {
|
|||||||
*/
|
*/
|
||||||
fun hasSameProviders(newProviders: List<DecorProvider>): Boolean {
|
fun hasSameProviders(newProviders: List<DecorProvider>): Boolean {
|
||||||
return (newProviders.size == viewProviderMap.size) &&
|
return (newProviders.size == viewProviderMap.size) &&
|
||||||
newProviders.all { getView(it.viewId) != null }
|
newProviders.all { getView(it.viewId) != null }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,23 +83,28 @@ class OverlayWindow(private val context: Context) {
|
|||||||
filterIds: Array<Int>? = null,
|
filterIds: Array<Int>? = null,
|
||||||
reloadToken: Int,
|
reloadToken: Int,
|
||||||
@Surface.Rotation rotation: Int,
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int,
|
||||||
displayUniqueId: String? = null
|
displayUniqueId: String? = null
|
||||||
) {
|
) {
|
||||||
filterIds?.forEach { id ->
|
filterIds?.forEach { id ->
|
||||||
viewProviderMap[id]?.let {
|
viewProviderMap[id]?.let {
|
||||||
it.second.onReloadResAndMeasure(
|
it.second.onReloadResAndMeasure(
|
||||||
view = it.first,
|
view = it.first,
|
||||||
reloadToken = reloadToken,
|
reloadToken = reloadToken,
|
||||||
displayUniqueId = displayUniqueId,
|
rotation = rotation,
|
||||||
rotation = rotation)
|
tintColor = tintColor,
|
||||||
|
displayUniqueId = displayUniqueId
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} ?: run {
|
} ?: run {
|
||||||
viewProviderMap.values.forEach {
|
viewProviderMap.values.forEach {
|
||||||
it.second.onReloadResAndMeasure(
|
it.second.onReloadResAndMeasure(
|
||||||
view = it.first,
|
view = it.first,
|
||||||
reloadToken = reloadToken,
|
reloadToken = reloadToken,
|
||||||
displayUniqueId = displayUniqueId,
|
rotation = rotation,
|
||||||
rotation = rotation)
|
tintColor = tintColor,
|
||||||
|
displayUniqueId = displayUniqueId
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +114,8 @@ class OverlayWindow(private val context: Context) {
|
|||||||
pw.println(" rootView=$rootView")
|
pw.println(" rootView=$rootView")
|
||||||
for (i in 0 until rootView.childCount) {
|
for (i in 0 until rootView.childCount) {
|
||||||
val child = rootView.getChildAt(i)
|
val child = rootView.getChildAt(i)
|
||||||
pw.println(" child[$i]=$child")
|
val provider = viewProviderMap[child.id]?.second
|
||||||
|
pw.println(" child[$i]=$child $provider")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import android.content.Context
|
|||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Surface
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Surface
|
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.dagger.qualifiers.Main
|
import com.android.systemui.dagger.qualifiers.Main
|
||||||
@@ -85,6 +85,7 @@ class PrivacyDotCornerDecorProviderImpl(
|
|||||||
view: View,
|
view: View,
|
||||||
reloadToken: Int,
|
reloadToken: Int,
|
||||||
rotation: Int,
|
rotation: Int,
|
||||||
|
tintColor: Int,
|
||||||
displayUniqueId: String?
|
displayUniqueId: String?
|
||||||
) {
|
) {
|
||||||
// Do nothing here because it is handled inside PrivacyDotViewController
|
// Do nothing here because it is handled inside PrivacyDotViewController
|
||||||
@@ -93,7 +94,8 @@ class PrivacyDotCornerDecorProviderImpl(
|
|||||||
override fun inflateView(
|
override fun inflateView(
|
||||||
context: Context,
|
context: Context,
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
@Surface.Rotation rotation: Int
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int
|
||||||
): View {
|
): View {
|
||||||
LayoutInflater.from(context).inflate(layoutId, parent, true)
|
LayoutInflater.from(context).inflate(layoutId, parent, true)
|
||||||
return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
|
return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.systemui.decor
|
package com.android.systemui.decor
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.ColorStateList
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
@@ -38,12 +39,13 @@ class RoundedCornerDecorProviderImpl(
|
|||||||
override fun inflateView(
|
override fun inflateView(
|
||||||
context: Context,
|
context: Context,
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
@Surface.Rotation rotation: Int
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int
|
||||||
): View {
|
): View {
|
||||||
return ImageView(context).also { view ->
|
return ImageView(context).also { view ->
|
||||||
// View
|
// View
|
||||||
view.id = viewId
|
view.id = viewId
|
||||||
initView(view, rotation)
|
initView(view, rotation, tintColor)
|
||||||
|
|
||||||
// LayoutParams
|
// LayoutParams
|
||||||
val layoutSize = if (isTop) {
|
val layoutSize = if (isTop) {
|
||||||
@@ -52,31 +54,36 @@ class RoundedCornerDecorProviderImpl(
|
|||||||
roundedCornerResDelegate.bottomRoundedSize
|
roundedCornerResDelegate.bottomRoundedSize
|
||||||
}
|
}
|
||||||
val params = FrameLayout.LayoutParams(
|
val params = FrameLayout.LayoutParams(
|
||||||
layoutSize.width,
|
layoutSize.width,
|
||||||
layoutSize.height,
|
layoutSize.height,
|
||||||
alignedBound1.toLayoutGravity(rotation) or
|
alignedBound1.toLayoutGravity(rotation) or alignedBound2.toLayoutGravity(rotation)
|
||||||
alignedBound2.toLayoutGravity(rotation))
|
)
|
||||||
|
|
||||||
// AddView
|
// AddView
|
||||||
parent.addView(view, params)
|
parent.addView(view, params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView(view: ImageView, @Surface.Rotation rotation: Int) {
|
private fun initView(
|
||||||
|
view: ImageView,
|
||||||
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int
|
||||||
|
) {
|
||||||
view.setRoundedCornerImage(roundedCornerResDelegate, isTop)
|
view.setRoundedCornerImage(roundedCornerResDelegate, isTop)
|
||||||
view.adjustRotation(alignedBounds, rotation)
|
view.adjustRotation(alignedBounds, rotation)
|
||||||
view.imageTintList = roundedCornerResDelegate.colorTintList
|
view.imageTintList = ColorStateList.valueOf(tintColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReloadResAndMeasure(
|
override fun onReloadResAndMeasure(
|
||||||
view: View,
|
view: View,
|
||||||
reloadToken: Int,
|
reloadToken: Int,
|
||||||
@Surface.Rotation rotation: Int,
|
@Surface.Rotation rotation: Int,
|
||||||
|
tintColor: Int,
|
||||||
displayUniqueId: String?
|
displayUniqueId: String?
|
||||||
) {
|
) {
|
||||||
roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken)
|
roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken)
|
||||||
|
|
||||||
initView((view as ImageView), rotation)
|
initView((view as ImageView), rotation, tintColor)
|
||||||
|
|
||||||
val layoutSize = if (isTop) {
|
val layoutSize = if (isTop) {
|
||||||
roundedCornerResDelegate.topRoundedSize
|
roundedCornerResDelegate.topRoundedSize
|
||||||
@@ -87,7 +94,7 @@ class RoundedCornerDecorProviderImpl(
|
|||||||
it.width = layoutSize.width
|
it.width = layoutSize.width
|
||||||
it.height = layoutSize.height
|
it.height = layoutSize.height
|
||||||
it.gravity = alignedBound1.toLayoutGravity(rotation) or
|
it.gravity = alignedBound1.toLayoutGravity(rotation) or
|
||||||
alignedBound2.toLayoutGravity(rotation)
|
alignedBound2.toLayoutGravity(rotation)
|
||||||
view.setLayoutParams(it)
|
view.setLayoutParams(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,10 +141,10 @@ private fun ImageView.setRoundedCornerImage(
|
|||||||
setImageDrawable(drawable)
|
setImageDrawable(drawable)
|
||||||
} else {
|
} else {
|
||||||
setImageResource(
|
setImageResource(
|
||||||
if (isTop)
|
if (isTop)
|
||||||
R.drawable.rounded_corner_top
|
R.drawable.rounded_corner_top
|
||||||
else
|
else
|
||||||
R.drawable.rounded_corner_bottom
|
R.drawable.rounded_corner_bottom
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,4 +194,4 @@ private fun ImageView.adjustRotation(alignedBounds: List<Int>, @Surface.Rotation
|
|||||||
this.rotation = newRotation
|
this.rotation = newRotation
|
||||||
this.scaleX = newScaleX
|
this.scaleX = newScaleX
|
||||||
this.scaleY = newScaleY
|
this.scaleY = newScaleY
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ package com.android.systemui.decor
|
|||||||
|
|
||||||
import android.annotation.ArrayRes
|
import android.annotation.ArrayRes
|
||||||
import android.annotation.DrawableRes
|
import android.annotation.DrawableRes
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.DisplayUtils
|
import android.util.DisplayUtils
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
@@ -57,8 +55,6 @@ class RoundedCornerResDelegate(
|
|||||||
var bottomRoundedSize = Size(0, 0)
|
var bottomRoundedSize = Size(0, 0)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var colorTintList = ColorStateList.valueOf(Color.BLACK)
|
|
||||||
|
|
||||||
var tuningSizeFactor: Int? = null
|
var tuningSizeFactor: Int? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field == value) {
|
if (field == value) {
|
||||||
@@ -107,19 +103,19 @@ class RoundedCornerResDelegate(
|
|||||||
|
|
||||||
val hasDefaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) > 0
|
val hasDefaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) > 0
|
||||||
hasTop = hasDefaultRadius ||
|
hasTop = hasDefaultRadius ||
|
||||||
(RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
|
(RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) > 0)
|
||||||
hasBottom = hasDefaultRadius ||
|
hasBottom = hasDefaultRadius ||
|
||||||
(RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
|
(RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) > 0)
|
||||||
|
|
||||||
topRoundedDrawable = getDrawable(
|
topRoundedDrawable = getDrawable(
|
||||||
displayConfigIndex = configIdx,
|
displayConfigIndex = configIdx,
|
||||||
arrayResId = R.array.config_roundedCornerTopDrawableArray,
|
arrayResId = R.array.config_roundedCornerTopDrawableArray,
|
||||||
backupDrawableId = R.drawable.rounded_corner_top
|
backupDrawableId = R.drawable.rounded_corner_top
|
||||||
)
|
)
|
||||||
bottomRoundedDrawable = getDrawable(
|
bottomRoundedDrawable = getDrawable(
|
||||||
displayConfigIndex = configIdx,
|
displayConfigIndex = configIdx,
|
||||||
arrayResId = R.array.config_roundedCornerBottomDrawableArray,
|
arrayResId = R.array.config_roundedCornerBottomDrawableArray,
|
||||||
backupDrawableId = R.drawable.rounded_corner_bottom
|
backupDrawableId = R.drawable.rounded_corner_bottom
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,13 +143,15 @@ class RoundedCornerResDelegate(
|
|||||||
if (physicalPixelDisplaySizeRatio != 1f) {
|
if (physicalPixelDisplaySizeRatio != 1f) {
|
||||||
if (topRoundedSize.width != 0) {
|
if (topRoundedSize.width != 0) {
|
||||||
topRoundedSize = Size(
|
topRoundedSize = Size(
|
||||||
(physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
|
(physicalPixelDisplaySizeRatio * topRoundedSize.width + 0.5f).toInt(),
|
||||||
(physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt())
|
(physicalPixelDisplaySizeRatio * topRoundedSize.height + 0.5f).toInt()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (bottomRoundedSize.width != 0) {
|
if (bottomRoundedSize.width != 0) {
|
||||||
bottomRoundedSize = Size(
|
bottomRoundedSize = Size(
|
||||||
(physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
|
(physicalPixelDisplaySizeRatio * bottomRoundedSize.width + 0.5f).toInt(),
|
||||||
(physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt())
|
(physicalPixelDisplaySizeRatio * bottomRoundedSize.height + 0.5f).toInt()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,8 +178,9 @@ class RoundedCornerResDelegate(
|
|||||||
pw.println(" hasTop=$hasTop")
|
pw.println(" hasTop=$hasTop")
|
||||||
pw.println(" hasBottom=$hasBottom")
|
pw.println(" hasBottom=$hasBottom")
|
||||||
pw.println(" topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})")
|
pw.println(" topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})")
|
||||||
pw.println(" bottomRoundedSize(w,h)=(${bottomRoundedSize.width}," +
|
pw.println(
|
||||||
"${bottomRoundedSize.height})")
|
" bottomRoundedSize(w,h)=(${bottomRoundedSize.width},${bottomRoundedSize.height})"
|
||||||
|
)
|
||||||
pw.println(" physicalPixelDisplaySizeRatio=$physicalPixelDisplaySizeRatio")
|
pw.println(" physicalPixelDisplaySizeRatio=$physicalPixelDisplaySizeRatio")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ package com.android.systemui;
|
|||||||
|
|
||||||
import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
|
import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
|
||||||
import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
|
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_RIGHT;
|
||||||
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
|
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
|
||||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
|
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
|
||||||
@@ -36,6 +35,7 @@ import static org.junit.Assert.fail;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.isA;
|
import static org.mockito.ArgumentMatchers.isA;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
@@ -49,7 +49,6 @@ import android.annotation.IdRes;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Insets;
|
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -60,7 +59,6 @@ import android.os.Handler;
|
|||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
import android.testing.TestableLooper.RunWithLooper;
|
import android.testing.TestableLooper.RunWithLooper;
|
||||||
import android.util.RotationUtils;
|
|
||||||
import android.util.Size;
|
import android.util.Size;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.DisplayCutout;
|
import android.view.DisplayCutout;
|
||||||
@@ -80,6 +78,8 @@ import com.android.keyguard.KeyguardUpdateMonitor;
|
|||||||
import com.android.systemui.biometrics.AuthController;
|
import com.android.systemui.biometrics.AuthController;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.decor.CornerDecorProvider;
|
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.DecorProvider;
|
||||||
import com.android.systemui.decor.DecorProviderFactory;
|
import com.android.systemui.decor.DecorProviderFactory;
|
||||||
import com.android.systemui.decor.FaceScanningOverlayProviderImpl;
|
import com.android.systemui.decor.FaceScanningOverlayProviderImpl;
|
||||||
@@ -157,6 +157,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private DisplayInfo mDisplayInfo;
|
private DisplayInfo mDisplayInfo;
|
||||||
private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener;
|
private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener;
|
||||||
|
@Mock
|
||||||
|
private CutoutDecorProviderFactory mCutoutFactory;
|
||||||
|
private List<DecorProvider> mMockCutoutList;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
@@ -206,6 +209,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
DisplayCutout.BOUNDS_POSITION_RIGHT,
|
DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||||
R.layout.privacy_dot_bottom_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(
|
mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl(
|
||||||
BOUNDS_POSITION_TOP,
|
BOUNDS_POSITION_TOP,
|
||||||
mAuthController,
|
mAuthController,
|
||||||
@@ -239,6 +247,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
super.updateOverlayWindowVisibilityIfViewExists(view);
|
super.updateOverlayWindowVisibilityIfViewExists(view);
|
||||||
mExecutor.runAllReady();
|
mExecutor.runAllReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CutoutDecorProviderFactory getCutoutFactory() {
|
||||||
|
return ScreenDecorationsTest.this.mCutoutFactory;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
mScreenDecorations.mDisplayInfo = mDisplayInfo;
|
mScreenDecorations.mDisplayInfo = mDisplayInfo;
|
||||||
doReturn(1f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio();
|
doReturn(1f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio();
|
||||||
@@ -429,11 +442,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
|
public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// no cutout
|
// no cutout (default)
|
||||||
doReturn(null).when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// No views added.
|
// No views added.
|
||||||
@@ -448,11 +459,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() {
|
public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// no cutout
|
// no cutout (default)
|
||||||
doReturn(null).when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -484,11 +493,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
|
public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
|
20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// no cutout
|
// no cutout (default)
|
||||||
doReturn(null).when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -516,11 +523,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() {
|
public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// no cutout
|
// no cutout (default)
|
||||||
doReturn(null).when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -555,10 +560,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
/* roundedTopDrawable */,
|
/* roundedTopDrawable */,
|
||||||
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
|
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
|
||||||
/* roundedBottomDrawable */,
|
/* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
// no cutout
|
// no cutout (default)
|
||||||
doReturn(null).when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Size of corner view should same as rounded_corner_radius{_top|_bottom}
|
// Size of corner view should same as rounded_corner_radius{_top|_bottom}
|
||||||
@@ -574,11 +578,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
/* roundedTopDrawable */,
|
/* roundedTopDrawable */,
|
||||||
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
|
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
|
||||||
/* roundedBottomDrawable */,
|
/* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// no cutout
|
// no cutout (default)
|
||||||
doReturn(null).when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
||||||
@@ -611,13 +613,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
/* roundedTopDrawable */,
|
/* roundedTopDrawable */,
|
||||||
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
|
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
|
||||||
/* roundedBottomDrawable */,
|
/* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// left cutout
|
// left cutout
|
||||||
final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
||||||
@@ -647,13 +646,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_CutoutShortEdge_NoPrivacyDot() {
|
public void testNoRounding_CutoutShortEdge_NoPrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Top window is created for top cutout.
|
// Top window is created for top cutout.
|
||||||
@@ -671,13 +667,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_CutoutShortEdge_PrivacyDot() {
|
public void testNoRounding_CutoutShortEdge_PrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Top window is created for top cutout.
|
// Top window is created for top cutout.
|
||||||
@@ -706,13 +699,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_CutoutLongEdge_NoPrivacyDot() {
|
public void testNoRounding_CutoutLongEdge_NoPrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// left cutout
|
// left cutout
|
||||||
final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Left window is created for left cutout.
|
// Left window is created for left cutout.
|
||||||
@@ -734,13 +724,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_CutoutLongEdge_PrivacyDot() {
|
public void testNoRounding_CutoutLongEdge_PrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// left cutout
|
// left cutout
|
||||||
final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Left window is created for left cutout.
|
// Left window is created for left cutout.
|
||||||
@@ -762,13 +749,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_CutoutShortEdge_NoPrivacyDot() {
|
public void testRounding_CutoutShortEdge_NoPrivacyDot() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Top window is created for rounded corner and top cutout.
|
// Top window is created for rounded corner and top cutout.
|
||||||
@@ -791,13 +775,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_CutoutShortEdge_PrivacyDot() {
|
public void testRounding_CutoutShortEdge_PrivacyDot() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Top window is created for rounded corner and top cutout.
|
// Top window is created for rounded corner and top cutout.
|
||||||
@@ -823,13 +804,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_CutoutLongEdge_NoPrivacyDot() {
|
public void testRounding_CutoutLongEdge_NoPrivacyDot() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// left cutout
|
// left cutout
|
||||||
final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Left window is created for rounded corner and left cutout.
|
// Left window is created for rounded corner and left cutout.
|
||||||
@@ -842,13 +820,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_CutoutLongEdge_PrivacyDot() {
|
public void testRounding_CutoutLongEdge_PrivacyDot() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// left cutout
|
// left cutout
|
||||||
final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Left window is created for rounded corner, left cutout, and privacy.
|
// Left window is created for rounded corner, left cutout, and privacy.
|
||||||
@@ -863,13 +838,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() {
|
public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top and left cutout
|
// top and left cutout
|
||||||
final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Top window is created for rounded corner and top cutout.
|
// Top window is created for rounded corner and top cutout.
|
||||||
@@ -883,13 +856,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testRounding_CutoutShortAndLongEdge_PrivacyDot() {
|
public void testRounding_CutoutShortAndLongEdge_PrivacyDot() {
|
||||||
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top and left cutout
|
// top and left cutout
|
||||||
final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Top window is created for rounded corner and top cutout.
|
// Top window is created for rounded corner and top cutout.
|
||||||
@@ -905,21 +876,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() {
|
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// Set to short edge cutout(top).
|
// Set to short edge cutout(top).
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE);
|
verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE);
|
||||||
|
|
||||||
// Switch to long edge cutout(left).
|
// Switch to long edge cutout(left).
|
||||||
final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
|
mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.onConfigurationChanged(new Configuration());
|
mScreenDecorations.onConfigurationChanged(new Configuration());
|
||||||
verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE);
|
verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE);
|
||||||
@@ -929,13 +895,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() {
|
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// Set to short edge cutout(top).
|
// Set to short edge cutout(top).
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
||||||
@@ -943,9 +906,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verify(mDotViewController, times(1)).setShowingListener(null);
|
verify(mDotViewController, times(1)).setShowingListener(null);
|
||||||
|
|
||||||
// Switch to long edge cutout(left).
|
// Switch to long edge cutout(left).
|
||||||
final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
|
mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.onConfigurationChanged(new Configuration());
|
mScreenDecorations.onConfigurationChanged(new Configuration());
|
||||||
verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE);
|
verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE);
|
||||||
@@ -973,20 +934,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testDelayedCutout_NoPrivacyDot() {
|
public void testDelayedCutout_NoPrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// No cutout (default)
|
||||||
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();
|
mScreenDecorations.start();
|
||||||
verifyOverlaysExistAndAdded(false, false, false, false, null);
|
verifyOverlaysExistAndAdded(false, false, false, false, null);
|
||||||
|
|
||||||
when(mContext.getResources().getBoolean(
|
// top cutout
|
||||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
.thenReturn(true);
|
|
||||||
mScreenDecorations.onConfigurationChanged(new Configuration());
|
mScreenDecorations.onConfigurationChanged(new Configuration());
|
||||||
|
|
||||||
// Only top windows should be added.
|
// Only top windows should be added.
|
||||||
@@ -997,13 +954,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testDelayedCutout_PrivacyDot() {
|
public void testDelayedCutout_PrivacyDot() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// no cutout (default)
|
||||||
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();
|
mScreenDecorations.start();
|
||||||
// Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
|
// Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
|
||||||
@@ -1015,9 +968,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verify(mDotViewController, times(1)).setShowingListener(
|
verify(mDotViewController, times(1)).setShowingListener(
|
||||||
mScreenDecorations.mPrivacyDotShowingListener);
|
mScreenDecorations.mPrivacyDotShowingListener);
|
||||||
|
|
||||||
when(mContext.getResources().getBoolean(
|
// top cutout
|
||||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
.thenReturn(true);
|
|
||||||
mScreenDecorations.onConfigurationChanged(new Configuration());
|
mScreenDecorations.onConfigurationChanged(new Configuration());
|
||||||
|
|
||||||
// Both top and bottom windows should be added with VISIBLE because of privacy dot and
|
// Both top and bottom windows should be added with VISIBLE because of privacy dot and
|
||||||
@@ -1043,8 +996,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
/* roundedTopDrawable */,
|
/* roundedTopDrawable */,
|
||||||
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
|
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
|
||||||
/* roundedBottomDrawable */,
|
/* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
|
||||||
false /* faceScanning*/);
|
|
||||||
mDisplayInfo.rotation = Surface.ROTATION_0;
|
mDisplayInfo.rotation = Surface.ROTATION_0;
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
@@ -1058,8 +1010,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
/* roundedTopDrawable */,
|
/* roundedTopDrawable */,
|
||||||
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
|
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
|
||||||
/* roundedBottomDrawable */,
|
/* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
|
||||||
false /* faceScanning*/);
|
|
||||||
mDisplayInfo.rotation = Surface.ROTATION_270;
|
mDisplayInfo.rotation = Surface.ROTATION_270;
|
||||||
|
|
||||||
mScreenDecorations.onConfigurationChanged(null);
|
mScreenDecorations.onConfigurationChanged(null);
|
||||||
@@ -1072,8 +1023,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testOnlyRoundedCornerRadiusTop() {
|
public void testOnlyRoundedCornerRadiusTop() {
|
||||||
setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -1094,8 +1044,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testOnlyRoundedCornerRadiusBottom() {
|
public void testOnlyRoundedCornerRadiusBottom() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -1166,13 +1115,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testSupportHwcLayer_SwitchFrom_NotSupport() {
|
public void testSupportHwcLayer_SwitchFrom_NotSupport() {
|
||||||
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// should only inflate mOverlays when the hwc doesn't support screen decoration
|
// should only inflate mOverlays when the hwc doesn't support screen decoration
|
||||||
@@ -1195,16 +1141,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testNotSupportHwcLayer_SwitchFrom_Support() {
|
public void testNotSupportHwcLayer_SwitchFrom_Support() {
|
||||||
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
||||||
decorationSupport.format = PixelFormat.R_8;
|
decorationSupport.format = PixelFormat.R_8;
|
||||||
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// should only inflate hwc layer when the hwc supports screen decoration
|
// should only inflate hwc layer when the hwc supports screen decoration
|
||||||
@@ -1234,16 +1177,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
/* roundedTopDrawable */,
|
/* roundedTopDrawable */,
|
||||||
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
|
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
|
||||||
/* roundedBottomDrawable */,
|
/* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
|
||||||
true /* faceScanning */);
|
|
||||||
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
||||||
decorationSupport.format = PixelFormat.R_8;
|
decorationSupport.format = PixelFormat.R_8;
|
||||||
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
|
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
|
||||||
@@ -1277,11 +1217,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() {
|
public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
|
||||||
true /* faceScanning */);
|
|
||||||
|
|
||||||
// no cutout
|
// no cutout (default)
|
||||||
doReturn(null).when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
|
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
|
||||||
@@ -1315,16 +1253,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testHwcLayer_noPrivacyDot_noFaceScanning() {
|
public void testHwcLayer_noPrivacyDot_noFaceScanning() {
|
||||||
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
||||||
decorationSupport.format = PixelFormat.R_8;
|
decorationSupport.format = PixelFormat.R_8;
|
||||||
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -1337,16 +1272,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testHwcLayer_PrivacyDot_FaceScanning() {
|
public void testHwcLayer_PrivacyDot_FaceScanning() {
|
||||||
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
|
||||||
true /* faceScanning */);
|
|
||||||
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
||||||
decorationSupport.format = PixelFormat.R_8;
|
decorationSupport.format = PixelFormat.R_8;
|
||||||
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -1364,16 +1296,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testOnDisplayChanged_hwcLayer() {
|
public void testOnDisplayChanged_hwcLayer() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
|
||||||
decorationSupport.format = PixelFormat.R_8;
|
decorationSupport.format = PixelFormat.R_8;
|
||||||
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -1383,39 +1312,36 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
|
|
||||||
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
|
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
|
||||||
|
|
||||||
verify(hwcLayer, times(1)).onDisplayChanged(1);
|
verify(hwcLayer, times(1)).onDisplayChanged(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnDisplayChanged_nonHwcLayer() {
|
public void testOnDisplayChanged_nonHwcLayer() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
// top cutout
|
// top cutout
|
||||||
final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
|
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
|
||||||
doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
|
|
||||||
.when(mScreenDecorations).getCutout();
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
final ScreenDecorations.DisplayCutoutView cutoutView =
|
final ScreenDecorations.DisplayCutoutView cutoutView = (ScreenDecorations.DisplayCutoutView)
|
||||||
mScreenDecorations.mCutoutViews[BOUNDS_POSITION_TOP];
|
mScreenDecorations.getOverlayView(R.id.display_cutout);
|
||||||
|
assertNotNull(cutoutView);
|
||||||
spyOn(cutoutView);
|
spyOn(cutoutView);
|
||||||
doReturn(mDisplay).when(cutoutView).getDisplay();
|
doReturn(mDisplay).when(cutoutView).getDisplay();
|
||||||
|
|
||||||
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
|
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
|
||||||
|
|
||||||
verify(cutoutView, times(1)).onDisplayChanged(1);
|
verify(cutoutView, times(1)).onDisplayChanged(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHasSameProvidersWithNullOverlays() {
|
public void testHasSameProvidersWithNullOverlays() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
|
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -1433,8 +1359,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
public void testHasSameProvidersWithPrivacyDots() {
|
public void testHasSameProvidersWithPrivacyDots() {
|
||||||
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
|
||||||
0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
|
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
|
||||||
false /* faceScanning */);
|
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
|
|
||||||
@@ -1471,7 +1396,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
|
|
||||||
private void setupResources(int radius, int radiusTop, int radiusBottom,
|
private void setupResources(int radius, int radiusTop, int radiusBottom,
|
||||||
@Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable,
|
@Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable,
|
||||||
int roundedPadding, boolean fillCutout, boolean privacyDot, boolean faceScanning) {
|
int roundedPadding, boolean privacyDot, boolean faceScanning) {
|
||||||
mContext.getOrCreateTestableResources().addOverride(
|
mContext.getOrCreateTestableResources().addOverride(
|
||||||
com.android.internal.R.array.config_displayUniqueIdArray,
|
com.android.internal.R.array.config_displayUniqueIdArray,
|
||||||
new String[]{});
|
new String[]{});
|
||||||
@@ -1511,8 +1436,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
mContext.getOrCreateTestableResources().addOverride(
|
mContext.getOrCreateTestableResources().addOverride(
|
||||||
R.dimen.rounded_corner_content_padding, roundedPadding);
|
R.dimen.rounded_corner_content_padding, roundedPadding);
|
||||||
mContext.getOrCreateTestableResources().addOverride(
|
|
||||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
|
|
||||||
|
|
||||||
mPrivacyDecorProviders = new ArrayList<>();
|
mPrivacyDecorProviders = new ArrayList<>();
|
||||||
if (privacyDot) {
|
if (privacyDot) {
|
||||||
@@ -1531,19 +1454,4 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
|
when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
|
||||||
when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(faceScanning);
|
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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* 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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.decor
|
package com.android.systemui.decor
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper.RunWithLooper
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
@@ -51,35 +52,45 @@ class OverlayWindowTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
decorProvider1 = spy(PrivacyDotCornerDecorProviderImpl(
|
decorProvider1 = spy(
|
||||||
|
PrivacyDotCornerDecorProviderImpl(
|
||||||
viewId = TEST_DECOR_VIEW_ID_1,
|
viewId = TEST_DECOR_VIEW_ID_1,
|
||||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
|
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
|
||||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
||||||
layoutId = R.layout.privacy_dot_top_left))
|
layoutId = R.layout.privacy_dot_top_left
|
||||||
decorProvider2 = spy(PrivacyDotCornerDecorProviderImpl(
|
)
|
||||||
|
)
|
||||||
|
decorProvider2 = spy(
|
||||||
|
PrivacyDotCornerDecorProviderImpl(
|
||||||
viewId = TEST_DECOR_VIEW_ID_2,
|
viewId = TEST_DECOR_VIEW_ID_2,
|
||||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
||||||
layoutId = R.layout.privacy_dot_bottom_left))
|
layoutId = R.layout.privacy_dot_bottom_left
|
||||||
decorProvider3 = spy(PrivacyDotCornerDecorProviderImpl(
|
)
|
||||||
|
)
|
||||||
|
decorProvider3 = spy(
|
||||||
|
PrivacyDotCornerDecorProviderImpl(
|
||||||
viewId = TEST_DECOR_VIEW_ID_3,
|
viewId = TEST_DECOR_VIEW_ID_3,
|
||||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||||
layoutId = R.layout.privacy_dot_bottom_right))
|
layoutId = R.layout.privacy_dot_bottom_right
|
||||||
|
)
|
||||||
|
)
|
||||||
overlay = OverlayWindow(mContext)
|
overlay = OverlayWindow(mContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAddProvider() {
|
fun testAddProvider() {
|
||||||
@Surface.Rotation val rotation = Surface.ROTATION_270
|
@Surface.Rotation val rotation = Surface.ROTATION_270
|
||||||
overlay.addDecorProvider(decorProvider1, rotation)
|
overlay.addDecorProvider(decorProvider1, rotation, Color.BLACK)
|
||||||
overlay.addDecorProvider(decorProvider2, rotation)
|
overlay.addDecorProvider(decorProvider2, rotation, Color.YELLOW)
|
||||||
|
|
||||||
verify(decorProvider1, times(1)).inflateView(
|
verify(decorProvider1, times(1)).inflateView(
|
||||||
mContext, overlay.rootView, rotation)
|
mContext, overlay.rootView, rotation, Color.BLACK
|
||||||
|
)
|
||||||
verify(decorProvider2, times(1)).inflateView(
|
verify(decorProvider2, times(1)).inflateView(
|
||||||
mContext, overlay.rootView, rotation)
|
mContext, overlay.rootView, rotation, Color.YELLOW
|
||||||
|
)
|
||||||
|
|
||||||
val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
|
val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
|
||||||
Assert.assertNotNull(view1FoundFromRootView)
|
Assert.assertNotNull(view1FoundFromRootView)
|
||||||
@@ -91,8 +102,8 @@ class OverlayWindowTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRemoveView() {
|
fun testRemoveView() {
|
||||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
|
||||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
|
||||||
overlay.removeView(TEST_DECOR_VIEW_ID_1)
|
overlay.removeView(TEST_DECOR_VIEW_ID_1)
|
||||||
|
|
||||||
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
|
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
|
||||||
@@ -102,39 +113,47 @@ class OverlayWindowTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testOnReloadResAndMeasureWithoutIds() {
|
fun testOnReloadResAndMeasureWithoutIds() {
|
||||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
|
||||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
|
||||||
|
|
||||||
overlay.onReloadResAndMeasure(
|
overlay.onReloadResAndMeasure(
|
||||||
reloadToken = 1,
|
reloadToken = 1,
|
||||||
rotation = Surface.ROTATION_90,
|
rotation = Surface.ROTATION_90,
|
||||||
displayUniqueId = null)
|
tintColor = Color.BLACK,
|
||||||
|
displayUniqueId = null
|
||||||
|
)
|
||||||
verify(decorProvider1, times(1)).onReloadResAndMeasure(
|
verify(decorProvider1, times(1)).onReloadResAndMeasure(
|
||||||
overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
|
overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
|
||||||
|
)
|
||||||
verify(decorProvider2, times(1)).onReloadResAndMeasure(
|
verify(decorProvider2, times(1)).onReloadResAndMeasure(
|
||||||
overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
|
overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testOnReloadResAndMeasureWithIds() {
|
fun testOnReloadResAndMeasureWithIds() {
|
||||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
|
||||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
|
||||||
|
|
||||||
overlay.onReloadResAndMeasure(
|
overlay.onReloadResAndMeasure(
|
||||||
filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
|
filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
|
||||||
reloadToken = 1,
|
reloadToken = 1,
|
||||||
rotation = Surface.ROTATION_90,
|
rotation = Surface.ROTATION_90,
|
||||||
displayUniqueId = null)
|
tintColor = Color.BLACK,
|
||||||
|
displayUniqueId = null
|
||||||
|
)
|
||||||
verify(decorProvider1, never()).onReloadResAndMeasure(
|
verify(decorProvider1, never()).onReloadResAndMeasure(
|
||||||
overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
|
overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
|
||||||
|
)
|
||||||
verify(decorProvider2, times(1)).onReloadResAndMeasure(
|
verify(decorProvider2, times(1)).onReloadResAndMeasure(
|
||||||
overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
|
overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRemoveRedundantViewsWithNullParameter() {
|
fun testRemoveRedundantViewsWithNullParameter() {
|
||||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
|
||||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
|
||||||
|
|
||||||
overlay.removeRedundantViews(null)
|
overlay.removeRedundantViews(null)
|
||||||
|
|
||||||
@@ -146,13 +165,15 @@ class OverlayWindowTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRemoveRedundantViewsWith2Providers() {
|
fun testRemoveRedundantViewsWith2Providers() {
|
||||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
|
||||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
|
||||||
|
|
||||||
overlay.removeRedundantViews(IntArray(2).apply {
|
overlay.removeRedundantViews(
|
||||||
this[0] = TEST_DECOR_VIEW_ID_3
|
IntArray(2).apply {
|
||||||
this[1] = TEST_DECOR_VIEW_ID_1
|
this[0] = TEST_DECOR_VIEW_ID_3
|
||||||
})
|
this[1] = TEST_DECOR_VIEW_ID_1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
Assert.assertNotNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
|
Assert.assertNotNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
|
||||||
Assert.assertNotNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
|
Assert.assertNotNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
|
||||||
@@ -167,16 +188,16 @@ class OverlayWindowTest : SysuiTestCase() {
|
|||||||
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
||||||
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
||||||
|
|
||||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
|
||||||
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
|
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
|
||||||
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider1)))
|
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider1)))
|
||||||
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
||||||
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
||||||
|
|
||||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
|
||||||
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
|
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
|
||||||
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
|
||||||
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
||||||
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user