Move color and display info into DecorProvider

Original tint color and display info are handled inside
ScreenDecorations like specific cases. Move these info into interface of
DecorProvider.

Bug: 232874879
Test: atest ScreenDecorationsTest ScreenDecorHwcLayerTest \
            OverlayWindowTest RoundedCornerResDelegateTest
Test: fold/unfold/rotate/debugRoundedCornerSize/debugFlag on sw-layer
      devices
Test: rotate/debugRoundedCornerSize/debugFlag/resolutionChange/faceAnim
      on hw-layer devices
Change-Id: I1fdcbe4c5e8ee0a54eba03f59b9066e76e5c9a03
This commit is contained in:
Milton Wu
2022-06-21 10:05:18 +00:00
parent 42ff11f19d
commit 3353759edf
10 changed files with 197 additions and 164 deletions

View File

@@ -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 {

View File

@@ -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;
@@ -92,10 +91,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;
@@ -448,6 +445,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 +468,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,7 +477,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
if (mScreenDecorHwcLayer != null) { if (mScreenDecorHwcLayer != null) {
updateHwLayerRoundedCornerExistAndSize(); updateHwLayerRoundedCornerExistAndSize();
} }
updateOverlayProviderViews(); needToUpdateProviderViews = true;
}
if (needToUpdateProviderViews) {
updateOverlayProviderViews(null);
} else {
updateOverlayProviderViews(new Integer[] { mFaceScanningViewId });
} }
if (mCutoutViews != null) { if (mCutoutViews != null) {
@@ -490,18 +493,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
if (cutoutView == null) { if (cutoutView == null) {
continue; continue;
} }
cutoutView.onDisplayChanged(displayId); cutoutView.onDisplayChanged(newUniqueId);
} }
} }
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);
} }
} }
}; };
@@ -804,7 +801,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
@@ -954,24 +951,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return; return;
} }
// When the hwc supports screen decorations, the layer will use the A8 color mode which
// won't be affected by the color inversion. If the composition goes the client composition
// route, the color inversion will be handled by the RenderEngine.
final Set<Integer> viewsMayNeedColorUpdate = new HashSet<>();
if (mHwcScreenDecorationSupport == null) {
ColorStateList tintList = ColorStateList.valueOf(mTintColor);
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++) { for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
if (mOverlays[i] == null) { if (mOverlays[i] == null) {
continue; continue;
@@ -981,14 +960,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
View child; View child;
for (int j = 0; j < size; j++) { for (int j = 0; j < size; j++) {
child = overlayView.getChildAt(j); child = overlayView.getChildAt(j);
if (viewsMayNeedColorUpdate.contains(child.getId()) if (child instanceof DisplayCutoutView && child.getId() == R.id.display_cutout) {
&& child instanceof DisplayCutoutView) {
((DisplayCutoutView) child).setColor(mTintColor); ((DisplayCutoutView) child).setColor(mTintColor);
} }
} }
mOverlays[i].onReloadResAndMeasure(views, mProviderRefreshToken,
mRotation, mDisplayUniqueId);
} }
updateOverlayProviderViews(new Integer[] {
mFaceScanningViewId,
R.id.rounded_corner_top_left,
R.id.rounded_corner_top_right,
R.id.rounded_corner_bottom_left,
R.id.rounded_corner_bottom_right
});
} }
@VisibleForTesting @VisibleForTesting
@@ -1119,7 +1103,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
} }
// update all provider views inside overlay // update all provider views inside overlay
updateOverlayProviderViews(); updateOverlayProviderViews(null);
} }
FaceScanningOverlay faceScanningOverlay = FaceScanningOverlay faceScanningOverlay =
@@ -1191,7 +1175,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;
} }
@@ -1200,7 +1184,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);
} }
} }
@@ -1239,19 +1224,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();
}); });
} }

View File

@@ -33,7 +33,7 @@ abstract class DecorProvider {
/** The number of total aligned bounds */ /** The number of total aligned bounds */
val numOfAlignedEdge: Int val numOfAlignedEdge: 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,14 +46,16 @@ 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
} }

View File

@@ -109,19 +109,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,
@@ -129,6 +135,7 @@ class FaceScanningOverlayProviderImpl(
statusBarStateController, statusBarStateController,
keyguardUpdateMonitor) keyguardUpdateMonitor)
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)

View File

@@ -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
)
} }
} }
} }
@@ -111,4 +117,4 @@ class OverlayWindow(private val context: Context) {
pw.println(" child[$i]=$child") pw.println(" child[$i]=$child")
} }
} }
} }

View File

@@ -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 */)

View File

@@ -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
} }

View File

@@ -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")
} }
} }

View File

@@ -1382,7 +1382,7 @@ 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
@@ -1406,7 +1406,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mScreenDecorations.mDisplayListener.onDisplayChanged(1); mScreenDecorations.mDisplayListener.onDisplayChanged(1);
verify(cutoutView, times(1)).onDisplayChanged(1); verify(cutoutView, times(1)).onDisplayChanged(any());
} }
@Test @Test

View File

@@ -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)))
} }
} }