Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c340fe5 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Use RoundedCornerResDelegate to read rounded res" into tm-dev am: 48b334a4

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17149332

Change-Id: I1940f1276b09b95001523f2a1539ffe2467fb68c
parents ccdaad12 48b334a4
Loading
Loading
Loading
Loading
+60 −169
Original line number Diff line number Diff line
@@ -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;
    private void updateHwLayerRoundedCornerSize() {
        if (mScreenDecorHwcLayer == null) {
            return;
        }
        if (sizeBottom.x == 0) {
            sizeBottom = sizeDefault;

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

+201 −0

File added.

Preview size limit exceeded, changes collapsed.

+31 −29

File changed.

Preview size limit exceeded, changes collapsed.

+139 −0
Original line number Diff line number Diff line
/*
 * 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