Merge "Use RoundedCornerResDelegate to read rounded res" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-21 01:07:44 +00:00
committed by Android (Google) Code Review
4 changed files with 430 additions and 197 deletions

View File

@@ -37,13 +37,11 @@ import android.content.pm.ActivityInfo;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
@@ -53,14 +51,12 @@ import android.os.Handler;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.util.DisplayMetrics;
import android.util.DisplayUtils;
import android.util.Log;
import android.util.Size;
import android.view.DisplayCutout;
import android.view.DisplayCutout.BoundsPosition;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.RoundedCorners;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
@@ -81,6 +77,7 @@ import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.DecorProviderKt;
import com.android.systemui.decor.OverlayWindow;
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerResDelegate;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
@@ -139,11 +136,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
// corners. for now it is only supposed when reading the intrinsic size from the drawables with
// mIsRoundedCornerMultipleRadius is set
@VisibleForTesting
protected Point mRoundedDefault = new Point(0, 0);
@VisibleForTesting
protected Point mRoundedDefaultTop = new Point(0, 0);
@VisibleForTesting
protected Point mRoundedDefaultBottom = new Point(0, 0);
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
@VisibleForTesting
protected OverlayWindow[] mOverlays = null;
@Nullable
@@ -152,17 +145,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
ViewGroup mScreenDecorHwcWindow;
@VisibleForTesting
ScreenDecorHwcLayer mScreenDecorHwcLayer;
private float mDensity;
private WindowManager mWindowManager;
private int mRotation;
private SettingObserver mColorInversionSetting;
private DelayableExecutor mExecutor;
private Handler mHandler;
boolean mPendingRotationChange;
private boolean mIsRoundedCornerMultipleRadius;
private Drawable mRoundedCornerDrawable;
private Drawable mRoundedCornerDrawableTop;
private Drawable mRoundedCornerDrawableBottom;
@VisibleForTesting
String mDisplayUniqueId;
private int mTintColor = Color.BLACK;
@@ -302,7 +290,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
private void startOnScreenDecorationsThread() {
mRotation = mContext.getDisplay().getRotation();
mDisplayUniqueId = mContext.getDisplay().getUniqueId();
mIsRoundedCornerMultipleRadius = isRoundedCornerMultipleRadius(mContext, mDisplayUniqueId);
mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
mDisplayUniqueId);
mWindowManager = mContext.getSystemService(WindowManager.class);
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
@@ -359,8 +348,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
final String newUniqueId = mContext.getDisplay().getUniqueId();
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
mDisplayUniqueId = newUniqueId;
mIsRoundedCornerMultipleRadius =
isRoundedCornerMultipleRadius(mContext, mDisplayUniqueId);
mRoundedCornerResDelegate.reloadAll(newUniqueId);
final DisplayDecorationSupport newScreenDecorationSupport =
mContext.getDisplay().getDisplayDecorationSupport();
// When the value of mSupportHwcScreenDecoration is changed, re-setup the whole
@@ -457,9 +445,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
if (mIsRegistered) {
return;
}
DisplayMetrics metrics = new DisplayMetrics();
mContext.getDisplay().getMetrics(metrics);
mDensity = metrics.density;
mMainExecutor.execute(() -> mTunerService.addTunable(this, SIZE));
@@ -606,8 +591,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mScreenDecorHwcWindow.addView(mScreenDecorHwcLayer, new FrameLayout.LayoutParams(
MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.START));
mWindowManager.addView(mScreenDecorHwcWindow, getHwcWindowLayoutParams());
updateRoundedCornerSize(mRoundedDefault, mRoundedDefaultTop, mRoundedDefaultBottom);
updateRoundedCornerImageView();
updateHwLayerRoundedCornerSize();
updateHwLayerRoundedCornerDrawable();
mScreenDecorHwcWindow.getViewTreeObserver().addOnPreDrawListener(
new ValidatingPreDrawListener(mScreenDecorHwcWindow));
}
@@ -640,7 +625,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
// update rounded corner view rotation
updateRoundedCornerView(pos, R.id.left, cutout);
updateRoundedCornerView(pos, R.id.right, cutout);
updateRoundedCornerSize(mRoundedDefault, mRoundedDefaultTop, mRoundedDefaultBottom);
updateRoundedCornerSize(
mRoundedCornerResDelegate.getTopRoundedSize(),
mRoundedCornerResDelegate.getBottomRoundedSize());
updateRoundedCornerImageView();
// update cutout view rotation
@@ -844,7 +831,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("ScreenDecorations state:");
pw.println(" DEBUG_DISABLE_SCREEN_DECORATIONS:" + DEBUG_DISABLE_SCREEN_DECORATIONS);
pw.println(" mIsRoundedCornerMultipleRadius:" + mIsRoundedCornerMultipleRadius);
pw.println(" mIsPrivacyDotEnabled:" + isPrivacyDotEnabled());
pw.println(" mPendingRotationChange:" + mPendingRotationChange);
if (mHwcScreenDecorationSupport != null) {
@@ -862,16 +848,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
} else {
pw.println(" mScreenDecorHwcLayer: null");
}
pw.println(" mRoundedDefault(x,y)=(" + mRoundedDefault.x + "," + mRoundedDefault.y + ")");
pw.println(" mRoundedDefaultTop(x,y)=(" + mRoundedDefaultTop.x + "," + mRoundedDefaultTop.y
+ ")");
pw.println(" mRoundedDefaultBottom(x,y)=(" + mRoundedDefaultBottom.x + ","
+ mRoundedDefaultBottom.y + ")");
pw.println(" mOverlays(left,top,right,bottom)=("
+ (mOverlays != null && mOverlays[BOUNDS_POSITION_LEFT] != null) + ","
+ (mOverlays != null && mOverlays[BOUNDS_POSITION_TOP] != null) + ","
+ (mOverlays != null && mOverlays[BOUNDS_POSITION_RIGHT] != null) + ","
+ (mOverlays != null && mOverlays[BOUNDS_POSITION_BOTTOM] != null) + ")");
mRoundedCornerResDelegate.dump(fd, pw, args);
}
private void updateOrientation() {
@@ -912,119 +894,18 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
// upgrading all of the configs to contain (width, height) pairs. Instead assume that a
// device configured using the single integer config value is okay with drawing the corners
// as a square
final int newRoundedDefault = RoundedCorners.getRoundedCornerRadius(
mContext.getResources(), mDisplayUniqueId);
final int newRoundedDefaultTop = RoundedCorners.getRoundedCornerTopRadius(
mContext.getResources(), mDisplayUniqueId);
final int newRoundedDefaultBottom = RoundedCorners.getRoundedCornerBottomRadius(
mContext.getResources(), mDisplayUniqueId);
final Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
final boolean changed = mRoundedDefault.x != newRoundedDefault
|| mRoundedDefaultTop.x != newRoundedDefaultTop
|| mRoundedDefaultBottom.x != newRoundedDefaultBottom;
if (changed) {
// If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
// (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
if (mIsRoundedCornerMultipleRadius) {
mRoundedDefault.set(mRoundedCornerDrawable.getIntrinsicWidth(),
mRoundedCornerDrawable.getIntrinsicHeight());
mRoundedDefaultTop.set(mRoundedCornerDrawableTop.getIntrinsicWidth(),
mRoundedCornerDrawableTop.getIntrinsicHeight());
mRoundedDefaultBottom.set(mRoundedCornerDrawableBottom.getIntrinsicWidth(),
mRoundedCornerDrawableBottom.getIntrinsicHeight());
} else {
mRoundedDefault.set(newRoundedDefault, newRoundedDefault);
mRoundedDefaultTop.set(newRoundedDefaultTop, newRoundedDefaultTop);
mRoundedDefaultBottom.set(newRoundedDefaultBottom, newRoundedDefaultBottom);
}
if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth()
|| oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) {
onTuningChanged(SIZE, null);
}
}
/**
* Gets whether the rounded corners are multiple radii for current display.
*
* Loads the default config {@link R.bool#config_roundedCornerMultipleRadius} if
* {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
*/
private static boolean isRoundedCornerMultipleRadius(Context context, String displayUniqueId) {
final Resources res = context.getResources();
final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
final TypedArray array = res.obtainTypedArray(
R.array.config_roundedCornerMultipleRadiusArray);
boolean isMultipleRadius;
if (index >= 0 && index < array.length()) {
isMultipleRadius = array.getBoolean(index, false);
} else {
isMultipleRadius = res.getBoolean(R.bool.config_roundedCornerMultipleRadius);
}
array.recycle();
return isMultipleRadius;
}
/**
* Gets the rounded corner drawable for current display.
*
* Loads the default config {@link R.drawable#rounded} if
* {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
*/
private static Drawable getRoundedCornerDrawable(Context context, String displayUniqueId) {
final Resources res = context.getResources();
final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerDrawableArray);
Drawable drawable;
if (index >= 0 && index < array.length()) {
drawable = array.getDrawable(index);
} else {
drawable = context.getDrawable(R.drawable.rounded);
}
array.recycle();
return drawable;
}
/**
* Gets the rounded corner top drawable for current display.
*
* Loads the default config {@link R.drawable#rounded_corner_top} if
* {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
*/
private static Drawable getRoundedCornerTopDrawable(Context context, String displayUniqueId) {
final Resources res = context.getResources();
final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerTopDrawableArray);
Drawable drawable;
if (index >= 0 && index < array.length()) {
drawable = array.getDrawable(index);
} else {
drawable = context.getDrawable(R.drawable.rounded_corner_top);
}
array.recycle();
return drawable;
}
/**
* Gets the rounded corner bottom drawable for current display.
*
* Loads the default config {@link R.drawable#rounded_corner_bottom} if
* {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
*/
private static Drawable getRoundedCornerBottomDrawable(
Context context, String displayUniqueId) {
final Resources res = context.getResources();
final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
final TypedArray array = res.obtainTypedArray(
R.array.config_roundedCornerBottomDrawableArray);
Drawable drawable;
if (index >= 0 && index < array.length()) {
drawable = array.getDrawable(index);
} else {
drawable = context.getDrawable(R.drawable.rounded_corner_bottom);
}
array.recycle();
return drawable;
}
private void updateRoundedCornerView(@BoundsPosition int pos, int id,
@Nullable DisplayCutout cutout) {
final View rounded = mOverlays[pos].getRootView().findViewById(id);
@@ -1085,10 +966,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
}
private boolean hasRoundedCorners() {
return mRoundedDefault.x > 0
|| mRoundedDefaultBottom.x > 0
|| mRoundedDefaultTop.x > 0
|| mIsRoundedCornerMultipleRadius;
return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0
|| mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0
|| mRoundedCornerResDelegate.isMultipleRadius();
}
private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
@@ -1154,33 +1034,28 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mExecutor.execute(() -> {
if (mOverlays == null) return;
if (SIZE.equals(key)) {
Point size = mRoundedDefault;
Point sizeTop = mRoundedDefaultTop;
Point sizeBottom = mRoundedDefaultBottom;
if (newValue != null) {
try {
int s = (int) (Integer.parseInt(newValue) * mDensity);
size = new Point(s, s);
mRoundedCornerResDelegate.updateTuningSizeFactor(
Integer.parseInt(newValue));
} catch (Exception e) {
}
}
updateRoundedCornerSize(size, sizeTop, sizeBottom);
updateRoundedCornerSize(
mRoundedCornerResDelegate.getTopRoundedSize(),
mRoundedCornerResDelegate.getBottomRoundedSize());
}
});
}
private void updateRoundedCornerDrawable() {
mRoundedCornerDrawable = getRoundedCornerDrawable(mContext, mDisplayUniqueId);
mRoundedCornerDrawableTop = getRoundedCornerTopDrawable(mContext, mDisplayUniqueId);
mRoundedCornerDrawableBottom = getRoundedCornerBottomDrawable(mContext, mDisplayUniqueId);
mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
updateRoundedCornerImageView();
}
private void updateRoundedCornerImageView() {
final Drawable top = mRoundedCornerDrawableTop != null
? mRoundedCornerDrawableTop : mRoundedCornerDrawable;
final Drawable bottom = mRoundedCornerDrawableBottom != null
? mRoundedCornerDrawableBottom : mRoundedCornerDrawable;
final Drawable top = mRoundedCornerResDelegate.getTopRoundedDrawable();
final Drawable bottom = mRoundedCornerResDelegate.getBottomRoundedDrawable();
if (mScreenDecorHwcLayer != null) {
mScreenDecorHwcLayer.updateRoundedCornerDrawable(top, bottom);
@@ -1205,6 +1080,20 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
}
private void updateHwLayerRoundedCornerDrawable() {
if (mScreenDecorHwcLayer == null) {
return;
}
final Drawable topDrawable = mRoundedCornerResDelegate.getTopRoundedDrawable();
final Drawable bottomDrawable = mRoundedCornerResDelegate.getBottomRoundedDrawable();
if (topDrawable == null || bottomDrawable == null) {
return;
}
mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable);
}
@VisibleForTesting
boolean isTopRoundedCorner(@BoundsPosition int pos, int id) {
switch (pos) {
@@ -1224,19 +1113,21 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
}
private void updateRoundedCornerSize(
Point sizeDefault,
Point sizeTop,
Point sizeBottom) {
if (sizeTop.x == 0) {
sizeTop = sizeDefault;
}
if (sizeBottom.x == 0) {
sizeBottom = sizeDefault;
private void updateHwLayerRoundedCornerSize() {
if (mScreenDecorHwcLayer == null) {
return;
}
final int topWidth = mRoundedCornerResDelegate.getTopRoundedSize().getWidth();
final int bottomWidth = mRoundedCornerResDelegate.getBottomRoundedSize().getWidth();
mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth);
}
private void updateRoundedCornerSize(Size sizeTop, Size sizeBottom) {
if (mScreenDecorHwcLayer != null) {
mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.x, sizeBottom.x);
mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.getWidth(), sizeBottom.getWidth());
return;
}
@@ -1256,10 +1147,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
@VisibleForTesting
protected void setSize(View view, Point pixelSize) {
protected void setSize(View view, Size pixelSize) {
LayoutParams params = view.getLayoutParams();
params.width = pixelSize.x;
params.height = pixelSize.y;
params.width = pixelSize.getWidth();
params.height = pixelSize.getHeight();
view.setLayoutParams(params);
}

View File

@@ -0,0 +1,201 @@
/*
* 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.annotation.ArrayRes
import android.annotation.DrawableRes
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.util.DisplayUtils
import android.util.Size
import android.view.RoundedCorners
import com.android.systemui.Dumpable
import com.android.systemui.R
import java.io.FileDescriptor
import java.io.PrintWriter
class RoundedCornerResDelegate(
private val res: Resources,
private var displayUniqueId: String?
) : Dumpable {
private val density: Float
get() = res.displayMetrics.density
var isMultipleRadius: Boolean = false
private set
private var roundedDrawable: Drawable? = null
var topRoundedDrawable: Drawable? = null
private set
var bottomRoundedDrawable: Drawable? = null
private set
private var roundedSize = Size(0, 0)
var topRoundedSize = Size(0, 0)
private set
var bottomRoundedSize = Size(0, 0)
private set
init {
reloadDrawables()
reloadMeasures()
}
fun reloadAll(newDisplayUniqueId: String?) {
displayUniqueId = newDisplayUniqueId
reloadDrawables()
reloadMeasures()
}
private fun reloadDrawables() {
val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
isMultipleRadius = getIsMultipleRadius(configIdx)
roundedDrawable = getDrawable(
displayConfigIndex = configIdx,
arrayResId = R.array.config_roundedCornerDrawableArray,
backupDrawableId = R.drawable.rounded
)
topRoundedDrawable = getDrawable(
displayConfigIndex = configIdx,
arrayResId = R.array.config_roundedCornerTopDrawableArray,
backupDrawableId = R.drawable.rounded_corner_top
) ?: roundedDrawable
bottomRoundedDrawable = getDrawable(
displayConfigIndex = configIdx,
arrayResId = R.array.config_roundedCornerBottomDrawableArray,
backupDrawableId = R.drawable.rounded_corner_bottom
) ?: roundedDrawable
// If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
// (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
if (isMultipleRadius) {
roundedSize = Size(
roundedDrawable?.intrinsicWidth ?: 0,
roundedDrawable?.intrinsicHeight ?: 0)
topRoundedDrawable?.let {
topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
}
bottomRoundedDrawable?.let {
bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
}
} else {
val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId)
val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId)
val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId)
roundedSize = Size(defaultRadius, defaultRadius)
topRoundedSize = Size(topRadius, topRadius)
bottomRoundedSize = Size(bottomRadius, bottomRadius)
}
if (topRoundedSize.width == 0) {
topRoundedSize = roundedSize
}
if (bottomRoundedSize.width == 0) {
bottomRoundedSize = roundedSize
}
}
private fun reloadMeasures(roundedSizeFactor: Int? = null) {
// If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
// (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
if (isMultipleRadius) {
roundedSize = Size(
roundedDrawable?.intrinsicWidth ?: 0,
roundedDrawable?.intrinsicHeight ?: 0)
topRoundedDrawable?.let {
topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
}
bottomRoundedDrawable?.let {
bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
}
} else {
val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId)
val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId)
val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId)
roundedSize = Size(defaultRadius, defaultRadius)
topRoundedSize = Size(topRadius, topRadius)
bottomRoundedSize = Size(bottomRadius, bottomRadius)
}
roundedSizeFactor ?.let {
val length: Int = (it * density).toInt()
roundedSize = Size(length, length)
}
if (topRoundedSize.width == 0) {
topRoundedSize = roundedSize
}
if (bottomRoundedSize.width == 0) {
bottomRoundedSize = roundedSize
}
}
fun updateTuningSizeFactor(factor: Int) {
reloadMeasures(factor)
}
/**
* Gets whether the rounded corners are multiple radii for current display.
*
* Loads the default config {@link R.bool#config_roundedCornerMultipleRadius} if
* {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
*/
private fun getIsMultipleRadius(displayConfigIndex: Int): Boolean {
val isMultipleRadius: Boolean
res.obtainTypedArray(R.array.config_roundedCornerMultipleRadiusArray).let { array ->
isMultipleRadius = if (displayConfigIndex >= 0 && displayConfigIndex < array.length()) {
array.getBoolean(displayConfigIndex, false)
} else {
res.getBoolean(R.bool.config_roundedCornerMultipleRadius)
}
array.recycle()
}
return isMultipleRadius
}
private fun getDrawable(
displayConfigIndex: Int,
@ArrayRes arrayResId: Int,
@DrawableRes backupDrawableId: Int
): Drawable? {
val drawable: Drawable?
res.obtainTypedArray(arrayResId).let { array ->
drawable = if (displayConfigIndex >= 0 && displayConfigIndex < array.length()) {
array.getDrawable(displayConfigIndex)
} else {
res.getDrawable(backupDrawableId, null)
}
array.recycle()
}
return drawable
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("RoundedCornerResDelegate state:")
pw.println(" isMultipleRadius:$isMultipleRadius")
pw.println(" roundedSize(w,h)=(${roundedSize.width},${roundedSize.height})")
pw.println(" topRoundedSize(w,h)=(${topRoundedSize.width},${topRoundedSize.height})")
pw.println(" bottomRoundedSize(w,h)=(${bottomRoundedSize.width}," +
"${bottomRoundedSize.height})")
}
}

View File

@@ -48,7 +48,6 @@ import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.VectorDrawable;
import android.hardware.display.DisplayManager;
@@ -58,6 +57,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.util.RotationUtils;
import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.View;
@@ -73,6 +73,7 @@ import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.OverlayWindow;
import com.android.systemui.decor.PrivacyDotCornerDecorProviderImpl;
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerResDelegate;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.tuner.TunerService;
@@ -95,8 +96,6 @@ import java.util.ArrayList;
@SmallTest
public class ScreenDecorationsTest extends SysuiTestCase {
private static final Rect ZERO_RECT = new Rect();
private ScreenDecorations mScreenDecorations;
private WindowManager mWindowManager;
private DisplayManager mDisplayManager;
@@ -424,7 +423,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
@Test
public void testRoundingRadius_NoCutout() {
final Point testRadiusPoint = new Point(1, 1);
final Size testRadiusPoint = new Size(1, 1);
setupResources(1 /* radius */, 1 /* radiusTop */, 1 /* radiusBottom */,
0 /* roundedPadding */, false /* multipleRadius */,
false /* fillCutout */, true /* privacyDot */);
@@ -433,9 +432,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mScreenDecorations.start();
// Size of corner view should same as rounded_corner_radius{_top|_bottom}
assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(testRadiusPoint);
assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(testRadiusPoint);
assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(testRadiusPoint);
final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate;
assertThat(resDelegate.getTopRoundedSize()).isEqualTo(testRadiusPoint);
assertThat(resDelegate.getBottomRoundedSize()).isEqualTo(testRadiusPoint);
}
@Test
@@ -454,17 +453,17 @@ public class ScreenDecorationsTest extends SysuiTestCase {
View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
.findViewById(R.id.right);
verify(mScreenDecorations, atLeastOnce())
.setSize(leftRoundedCorner, new Point(testTopRadius, testTopRadius));
.setSize(leftRoundedCorner, new Size(testTopRadius, testTopRadius));
verify(mScreenDecorations, atLeastOnce())
.setSize(rightRoundedCorner, new Point(testTopRadius, testTopRadius));
.setSize(rightRoundedCorner, new Size(testTopRadius, testTopRadius));
leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
.findViewById(R.id.left);
rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
.findViewById(R.id.right);
verify(mScreenDecorations, atLeastOnce())
.setSize(leftRoundedCorner, new Point(testBottomRadius, testBottomRadius));
.setSize(leftRoundedCorner, new Size(testBottomRadius, testBottomRadius));
verify(mScreenDecorations, atLeastOnce())
.setSize(rightRoundedCorner, new Point(testBottomRadius, testBottomRadius));
.setSize(rightRoundedCorner, new Size(testBottomRadius, testBottomRadius));
}
@Test
@@ -480,8 +479,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
.when(mScreenDecorations).getCutout();
mScreenDecorations.start();
final Point topRadius = new Point(testTopRadius, testTopRadius);
final Point bottomRadius = new Point(testBottomRadius, testBottomRadius);
final Size topRadius = new Size(testTopRadius, testTopRadius);
final Size bottomRadius = new Size(testBottomRadius, testBottomRadius);
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
.findViewById(R.id.left);
boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left);
@@ -510,7 +509,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
@Test
public void testRoundingMultipleRadius_NoCutout_NoPrivacyDot() {
final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded);
final Point multipleRadiusSize = new Point(d.getIntrinsicWidth(), d.getIntrinsicHeight());
final Size multipleRadiusSize = new Size(d.getIntrinsicWidth(), d.getIntrinsicHeight());
setupResources(9999 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
9999 /* roundedPadding */, true /* multipleRadius */,
false /* fillCutout */, false /* privacyDot */);
@@ -536,15 +535,15 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verify(mDotViewController, never()).initialize(any(), any(), any(), any());
// Size of corner view should exactly match max(width, height) of R.drawable.rounded
assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(multipleRadiusSize);
assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(multipleRadiusSize);
assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(multipleRadiusSize);
final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate;
assertThat(resDelegate.getTopRoundedSize()).isEqualTo(multipleRadiusSize);
assertThat(resDelegate.getBottomRoundedSize()).isEqualTo(multipleRadiusSize);
}
@Test
public void testRoundingMultipleRadius_NoCutout_PrivacyDot() {
final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded);
final Point multipleRadiusSize = new Point(d.getIntrinsicWidth(), d.getIntrinsicHeight());
final Size multipleRadiusSize = new Size(d.getIntrinsicWidth(), d.getIntrinsicHeight());
setupResources(9999 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
9999 /* roundedPadding */, true /* multipleRadius */,
false /* fillCutout */, true /* privacyDot */);
@@ -571,9 +570,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
isA(View.class), isA(View.class), isA(View.class), isA(View.class));
// Size of corner view should exactly match max(width, height) of R.drawable.rounded
assertThat(mScreenDecorations.mRoundedDefault).isEqualTo(multipleRadiusSize);
assertThat(mScreenDecorations.mRoundedDefaultTop).isEqualTo(multipleRadiusSize);
assertThat(mScreenDecorations.mRoundedDefaultBottom).isEqualTo(multipleRadiusSize);
final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate;
assertThat(resDelegate.getTopRoundedSize()).isEqualTo(multipleRadiusSize);
assertThat(resDelegate.getBottomRoundedSize()).isEqualTo(multipleRadiusSize);
}
@Test
@@ -944,12 +943,15 @@ public class ScreenDecorationsTest extends SysuiTestCase {
false /* fillCutout */, true /* privacyDot */);
mScreenDecorations.start();
assertEquals(mScreenDecorations.mRoundedDefault, new Point(20, 20));
final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate;
assertEquals(resDelegate.getTopRoundedSize(), new Size(20, 20));
assertEquals(resDelegate.getBottomRoundedSize(), new Size(20, 20));
when(mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.rounded_corner_radius)).thenReturn(5);
mScreenDecorations.onConfigurationChanged(null);
assertEquals(mScreenDecorations.mRoundedDefault, new Point(5, 5));
assertEquals(resDelegate.getTopRoundedSize(), new Size(5, 5));
assertEquals(resDelegate.getBottomRoundedSize(), new Size(5, 5));
}
@Test
@@ -959,9 +961,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
false /* fillCutout */, true /* privacyDot */);
mScreenDecorations.start();
assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefault);
assertEquals(new Point(10, 10), mScreenDecorations.mRoundedDefaultTop);
assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefaultBottom);
final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate;
assertEquals(new Size(10, 10), resDelegate.getTopRoundedSize());
assertEquals(new Size(0, 0), resDelegate.getBottomRoundedSize());
}
@Test
@@ -971,9 +973,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
false /* fillCutout */, true /* privacyDot */);
mScreenDecorations.start();
assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefault);
assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefaultTop);
assertEquals(new Point(20, 20), mScreenDecorations.mRoundedDefaultBottom);
final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate;
assertEquals(new Size(0, 0), resDelegate.getTopRoundedSize());
assertEquals(new Size(20, 20), resDelegate.getBottomRoundedSize());
}
@Test

View File

@@ -0,0 +1,139 @@
/*
* 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.TypedArray
import android.graphics.drawable.VectorDrawable
import android.testing.AndroidTestingRunner
import android.testing.TestableResources
import android.util.Size
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
class RoundedCornerResDelegateTest : SysuiTestCase() {
private lateinit var roundedCornerResDelegate: RoundedCornerResDelegate
@Mock private lateinit var mockTypedArray: TypedArray
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
}
@Test
fun testReloadAllAndDefaultRadius() {
mContext.orCreateTestableResources.addOverrides(
mockTypeArray = mockTypedArray,
radius = 3,
radiusTop = 0,
radiusBottom = 4,
multipleRadius = false)
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(4, 4), roundedCornerResDelegate.bottomRoundedSize)
assertEquals(false, roundedCornerResDelegate.isMultipleRadius)
mContext.orCreateTestableResources.addOverrides(
mockTypeArray = mockTypedArray,
radius = 5,
radiusTop = 6,
radiusBottom = 0)
roundedCornerResDelegate.reloadAll("test")
assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
}
@Test
fun testUpdateTuningSizeFactor() {
mContext.orCreateTestableResources.addOverrides(
mockTypeArray = mockTypedArray,
radiusTop = 0,
radiusBottom = 0,
multipleRadius = false)
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
val factor = 5
roundedCornerResDelegate.updateTuningSizeFactor(factor)
val length = (factor * mContext.resources.displayMetrics.density).toInt()
assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(length, length), roundedCornerResDelegate.bottomRoundedSize)
}
@Test
fun testReadDefaultRadiusWhen0() {
mContext.orCreateTestableResources.addOverrides(
mockTypeArray = mockTypedArray,
radius = 3,
radiusTop = 0,
radiusBottom = 0,
multipleRadius = false)
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(3, 3), roundedCornerResDelegate.bottomRoundedSize)
}
@Test
fun testReadMultipleRadius() {
val d = mContext.getDrawable(R.drawable.rounded) as VectorDrawable
val multipleRadiusSize = Size(d.intrinsicWidth, d.intrinsicHeight)
mContext.orCreateTestableResources.addOverrides(
mockTypeArray = mockTypedArray,
multipleRadius = true)
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
assertEquals(multipleRadiusSize, roundedCornerResDelegate.topRoundedSize)
assertEquals(multipleRadiusSize, roundedCornerResDelegate.bottomRoundedSize)
}
}
private fun TestableResources.addOverrides(
mockTypeArray: TypedArray,
radius: Int? = null,
radiusTop: Int? = null,
radiusBottom: Int? = null,
multipleRadius: Boolean? = null
) {
addOverride(com.android.internal.R.array.config_displayUniqueIdArray, arrayOf<String>())
addOverride(com.android.internal.R.array.config_roundedCornerRadiusArray, mockTypeArray)
addOverride(com.android.internal.R.array.config_roundedCornerTopRadiusArray, mockTypeArray)
addOverride(com.android.internal.R.array.config_roundedCornerBottomRadiusArray, mockTypeArray)
addOverride(R.array.config_roundedCornerDrawableArray, mockTypeArray)
addOverride(R.array.config_roundedCornerTopDrawableArray, mockTypeArray)
addOverride(R.array.config_roundedCornerBottomDrawableArray, mockTypeArray)
addOverride(R.array.config_roundedCornerMultipleRadiusArray, mockTypeArray)
radius?.let { addOverride(com.android.internal.R.dimen.rounded_corner_radius, it) }
radiusTop?.let { addOverride(com.android.internal.R.dimen.rounded_corner_radius_top, it) }
radiusBottom?.let { addOverride(com.android.internal.R.dimen.rounded_corner_radius_bottom, it) }
multipleRadius?.let { addOverride(R.bool.config_roundedCornerMultipleRadius, it) }
}