diff options
4 files changed, 431 insertions, 198 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index ae41cae10bba..2f5292cec909 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -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 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); - } + final Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize(); + final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize(); + mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId); + final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize(); + final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize(); + + if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth() + || oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) { onTuningChanged(SIZE, null); } } - /** - * 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); } diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt new file mode 100644 index 000000000000..c817f89c7a9b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt @@ -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})") + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 70f325158624..ec92adb0f48c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -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 diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt new file mode 100644 index 000000000000..b536bfdb944e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt @@ -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) } +}
\ No newline at end of file |