diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 24da59a378f81..b129321008d83 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -95,8 +95,10 @@ 96dp 96dp - + 22dip + + 22sp 15dp diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml index d053a7a0d0bb3..28f98f4821fa0 100644 --- a/packages/SystemUI/res/values-sw720dp/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp/dimens.xml @@ -20,7 +20,7 @@ 10dp - 1dp + 1sp 28dp 40dp diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 3bd7a0664d5ab..e1e6c99026509 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -121,24 +121,26 @@ 0dp 6dp - + + @*android:dimen/status_bar_icon_size_sp + @*android:dimen/status_bar_icon_size - 2.5dp + 2.5sp - 13.0dp + 13.0sp - 7.8dp + so the width of the icon should be 13.0sp * (12.0 / 20.0) --> + 7.8sp - - 1dp + 1sp 14sp @@ -153,19 +155,26 @@ 0dp - 2dp + 2sp - 2.5dp + 2.5sp + + 17sp - @*android:dimen/status_bar_system_icon_size + 13sp + + + 17sp + + 13sp - 4dp + 4sp - 0dp + 0sp 1.0 @@ -335,7 +344,7 @@ 8dp - 0dp + 0sp 8dp @@ -347,10 +356,10 @@ 0dp - 2dp + 2sp - 3dp + 3sp @@ -838,7 +847,7 @@ - 2dp + 2sp @@ -1064,7 +1073,7 @@ 4dp - 16dp + 16sp 28dp diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt index c3b5db42e08dc..310d23407d5da 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt @@ -15,6 +15,8 @@ package com.android.systemui.privacy import android.content.Context +import android.content.pm.ActivityInfo +import android.content.res.Configuration import android.util.AttributeSet import android.view.Gravity.CENTER_VERTICAL import android.view.Gravity.END @@ -35,6 +37,7 @@ class OngoingPrivacyChip @JvmOverloads constructor( defStyleRes: Int = 0 ) : LaunchableFrameLayout(context, attrs, defStyleAttrs, defStyleRes), BackgroundAnimatableView { + private var configuration: Configuration private var iconMargin = 0 private var iconSize = 0 private var iconColor = 0 @@ -54,6 +57,7 @@ class OngoingPrivacyChip @JvmOverloads constructor( clipChildren = true clipToPadding = true iconsContainer = requireViewById(R.id.icons_container) + configuration = Configuration(context.resources.configuration) updateResources() } @@ -102,6 +106,17 @@ class OngoingPrivacyChip @JvmOverloads constructor( R.string.ongoing_privacy_chip_content_multiple_apps, typesText) } + override fun onConfigurationChanged(newConfig: Configuration?) { + super.onConfigurationChanged(newConfig) + if (newConfig != null) { + val diff = newConfig.diff(configuration) + configuration.setTo(newConfig) + if (diff.and(ActivityInfo.CONFIG_DENSITY.or(ActivityInfo.CONFIG_FONT_SCALE)) != 0) { + updateResources() + } + } + } + private fun updateResources() { iconMargin = context.resources .getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_margin) @@ -110,8 +125,11 @@ class OngoingPrivacyChip @JvmOverloads constructor( iconColor = Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary) + val height = context.resources + .getDimensionPixelSize(R.dimen.ongoing_appops_chip_height) val padding = context.resources .getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding) + iconsContainer.layoutParams.height = height iconsContainer.setPaddingRelative(padding, 0, padding, 0) iconsContainer.background = context.getDrawable(R.drawable.statusbar_privacy_chip_bg) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 4356a3fb29d80..cff71d2edd238 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -26,6 +26,7 @@ import android.annotation.IntDef; import android.app.ActivityManager; import android.app.Notification; import android.content.Context; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.res.ColorStateList; import android.content.res.Configuration; @@ -46,12 +47,14 @@ import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.ViewDebug; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.animation.Interpolator; import androidx.core.graphics.ColorUtils; import com.android.app.animation.Interpolators; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.util.ContrastColorUtil; import com.android.systemui.R; @@ -131,8 +134,11 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi }; private int mStatusBarIconDrawingSizeIncreased = 1; - private int mStatusBarIconDrawingSize = 1; - private int mStatusBarIconSize = 1; + @VisibleForTesting int mStatusBarIconDrawingSize = 1; + + @VisibleForTesting int mOriginalStatusBarIconSize = 1; + @VisibleForTesting int mNewStatusBarIconSize = 1; + @VisibleForTesting float mScaleToFitNewIconSize = 1; private StatusBarIcon mIcon; @ViewDebug.ExportedProperty private String mSlot; private Drawable mNumberBackground; @@ -142,7 +148,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi private String mNumberText; private StatusBarNotification mNotification; private final boolean mBlocked; - private int mDensity; + private Configuration mConfiguration; private boolean mNightMode; private float mIconScale = 1.0f; private final Paint mDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -196,9 +202,8 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi mNumberPain.setAntiAlias(true); setNotification(sbn); setScaleType(ScaleType.CENTER); - mDensity = context.getResources().getDisplayMetrics().densityDpi; - Configuration configuration = context.getResources().getConfiguration(); - mNightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK) + mConfiguration = new Configuration(context.getResources().getConfiguration()); + mNightMode = (mConfiguration.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; initializeDecorColor(); reloadDimens(); @@ -206,7 +211,8 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi } /** Should always be preceded by {@link #reloadDimens()} */ - private void maybeUpdateIconScaleDimens() { + @VisibleForTesting + public void maybeUpdateIconScaleDimens() { // We do not resize and scale system icons (on the right), only notification icons (on the // left). if (isNotification()) { @@ -217,22 +223,63 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi } private void updateIconScaleForNotifications() { + float iconScale; + // we need to scale the image size to be same as the original size + // (fit mOriginalStatusBarIconSize), then we can scale it with mScaleToFitNewIconSize + // to fit mNewStatusBarIconSize + float scaleToOriginalDrawingSize = 1.0f; + ViewGroup.LayoutParams lp = getLayoutParams(); + if (getDrawable() != null && (lp != null && lp.width > 0 && lp.height > 0)) { + final int iconViewWidth = lp.width; + final int iconViewHeight = lp.height; + // first we estimate the image exact size when put the drawable in scaled iconView size, + // then we can compute the scaleToOriginalDrawingSize to make the image size fit in + // mOriginalStatusBarIconSize + final int drawableWidth = getDrawable().getIntrinsicWidth(); + final int drawableHeight = getDrawable().getIntrinsicHeight(); + float scaleToFitIconView = Math.min( + (float) iconViewWidth / drawableWidth, + (float) iconViewHeight / drawableHeight); + // if the drawable size <= the icon view size, the drawable won't be scaled + if (scaleToFitIconView > 1.0f) { + scaleToFitIconView = 1.0f; + } + final float scaledImageWidth = drawableWidth * scaleToFitIconView; + final float scaledImageHeight = drawableHeight * scaleToFitIconView; + // if the scaled image size <= mOriginalStatusBarIconSize, we don't need to enlarge it + scaleToOriginalDrawingSize = Math.min( + (float) mOriginalStatusBarIconSize / scaledImageWidth, + (float) mOriginalStatusBarIconSize / scaledImageHeight); + if (scaleToOriginalDrawingSize > 1.0f) { + scaleToOriginalDrawingSize = 1.0f; + } + } + iconScale = scaleToOriginalDrawingSize; + final float imageBounds = mIncreasedSize ? mStatusBarIconDrawingSizeIncreased : mStatusBarIconDrawingSize; - final int outerBounds = mStatusBarIconSize; - mIconScale = imageBounds / (float)outerBounds; + final int originalOuterBounds = mOriginalStatusBarIconSize; + iconScale = iconScale * (imageBounds / (float) originalOuterBounds); + + // scale image to fit new icon size + mIconScale = iconScale * mScaleToFitNewIconSize; + updatePivot(); } // Makes sure that all icons are scaled to the same height (15dp). If we cannot get a height // for the icon, it uses the default SCALE (15f / 17f) which is the old behavior private void updateIconScaleForSystemIcons() { + float iconScale; float iconHeight = getIconHeight(); if (iconHeight != 0) { - mIconScale = mSystemIconDesiredHeight / iconHeight; + iconScale = mSystemIconDesiredHeight / iconHeight; } else { - mIconScale = mSystemIconDefaultScale; + iconScale = mSystemIconDefaultScale; } + + // scale image to fit new icon size + mIconScale = iconScale * mScaleToFitNewIconSize; } private float getIconHeight() { @@ -255,12 +302,10 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - int density = newConfig.densityDpi; - if (density != mDensity) { - mDensity = density; - reloadDimens(); - updateDrawable(); - maybeUpdateIconScaleDimens(); + final int configDiff = newConfig.diff(mConfiguration); + mConfiguration.setTo(newConfig); + if ((configDiff & (ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_FONT_SCALE)) != 0) { + updateIconDimens(); } boolean nightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; @@ -270,11 +315,22 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi } } + /** + * Update the icon dimens and drawable with current resources + */ + public void updateIconDimens() { + reloadDimens(); + updateDrawable(); + maybeUpdateIconScaleDimens(); + } + private void reloadDimens() { boolean applyRadius = mDotRadius == mStaticDotRadius; Resources res = getResources(); mStaticDotRadius = res.getDimensionPixelSize(R.dimen.overflow_dot_radius); - mStatusBarIconSize = res.getDimensionPixelSize(R.dimen.status_bar_icon_size); + mOriginalStatusBarIconSize = res.getDimensionPixelSize(R.dimen.status_bar_icon_size); + mNewStatusBarIconSize = res.getDimensionPixelSize(R.dimen.status_bar_icon_size_sp); + mScaleToFitNewIconSize = (float) mNewStatusBarIconSize / mOriginalStatusBarIconSize; mStatusBarIconDrawingSizeIncreased = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark); mStatusBarIconDrawingSize = @@ -482,12 +538,30 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi updateDrawable(); } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + if (!isNotification()) { + // for system icons, calculated measured width from super is for image drawable real + // width (17dp). We may scale the image with font scale, so we also need to scale the + // measured width so that scaled measured width and image width would be fit. + int measuredWidth = getMeasuredWidth(); + int measuredHeight = getMeasuredHeight(); + setMeasuredDimension((int) (measuredWidth * mScaleToFitNewIconSize), measuredHeight); + } + } + @Override protected void onDraw(Canvas canvas) { + // In this method, for width/height division computation we intend to discard the + // fractional part as the original behavior. if (mIconAppearAmount > 0.0f) { canvas.save(); + int px = getWidth() / 2; + int py = getHeight() / 2; canvas.scale(mIconScale * mIconAppearAmount, mIconScale * mIconAppearAmount, - getWidth() / 2, getHeight() / 2); + (float) px, (float) py); super.onDraw(canvas); canvas.restore(); } @@ -504,10 +578,15 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi } else { float fadeOutAmount = mDotAppearAmount - 1.0f; alpha = alpha * (1.0f - fadeOutAmount); - radius = NotificationUtils.interpolate(mDotRadius, getWidth() / 4, fadeOutAmount); + int end = getWidth() / 4; + radius = NotificationUtils.interpolate(mDotRadius, (float) end, fadeOutAmount); } mDotPaint.setAlpha((int) (alpha * 255)); - canvas.drawCircle(mStatusBarIconSize / 2, getHeight() / 2, radius, mDotPaint); + int cx = mNewStatusBarIconSize / 2; + int cy = getHeight() / 2; + canvas.drawCircle( + (float) cx, (float) cy, + radius, mDotPaint); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java index fdad101ae0f65..d6f6c2c281de7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java @@ -135,7 +135,7 @@ public class StatusBarMobileView extends BaseStatusBarFrameLayout implements Dar mDotView = new StatusBarIconView(mContext, mSlot, null); mDotView.setVisibleState(STATE_DOT); - int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size); + int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size_sp); LayoutParams lp = new LayoutParams(width, width); lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START; addView(mDotView, lp); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java index decc70d175b86..8d7214d6bd759 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java @@ -164,7 +164,7 @@ public class StatusBarWifiView extends BaseStatusBarFrameLayout implements DarkR mDotView = new StatusBarIconView(mContext, mSlot, null); mDotView.setVisibleState(STATE_DOT); - int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size); + int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size_sp); LayoutParams lp = new LayoutParams(width, width); lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START; addView(mDotView, lp); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java index 2fd244e1357f1..0fde3ab3d19ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java @@ -239,7 +239,7 @@ public class NotificationIconAreaController implements private void reloadDimens(Context context) { Resources res = context.getResources(); - mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size); + mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size_sp); mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_horizontal_margin); mAodIconAppearTranslation = res.getDimensionPixelSize( R.dimen.shelf_appear_translation); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java index bef422ce3004f..15ca37a222e52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -339,6 +339,7 @@ public class NotificationIconContainer extends ViewGroup { } } if (child instanceof StatusBarIconView) { + ((StatusBarIconView) child).updateIconDimens(); ((StatusBarIconView) child).setDozing(mDozing, false, 0); } } @@ -537,9 +538,10 @@ public class NotificationIconContainer extends ViewGroup { IconState iconState = mIconStates.get(mIsolatedIcon); if (iconState != null) { // Most of the time the icon isn't yet added when this is called but only happening - // later - iconState.setXTranslation(mIsolatedIconLocation.left - mAbsolutePosition[0] - - (1 - mIsolatedIcon.getIconScale()) * mIsolatedIcon.getWidth() / 2.0f); + // later. The isolated icon position left should equal to the mIsolatedIconLocation + // to ensure the icon be put at the center of the HUN icon placeholder, + // {@See HeadsUpAppearanceController#updateIsolatedIconLocation}. + iconState.setXTranslation(mIsolatedIconLocation.left - mAbsolutePosition[0]); iconState.visibleState = StatusBarIconView.STATE_ICON; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index b14fe90cd1b3b..59583ddf3e34a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -370,7 +370,7 @@ public interface StatusBarIconController { private final MobileIconsViewModel mMobileIconsViewModel; protected final Context mContext; - protected final int mIconSize; + protected int mIconSize; // Whether or not these icons show up in dumpsys protected boolean mShouldLog = false; private StatusBarIconController mController; @@ -395,10 +395,10 @@ public interface StatusBarIconController { mStatusBarPipelineFlags = statusBarPipelineFlags; mMobileContextProvider = mobileContextProvider; mContext = group.getContext(); - mIconSize = mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_icon_size); mLocation = location; + reloadDimens(); + if (statusBarPipelineFlags.runNewMobileIconsBackend()) { // This starts the flow for the new pipeline, and will notify us of changes if // {@link StatusBarPipelineFlags#useNewMobileIcons} is also true. @@ -609,13 +609,9 @@ public interface StatusBarIconController { mGroup.removeAllViews(); } - protected void onDensityOrFontScaleChanged() { - for (int i = 0; i < mGroup.getChildCount(); i++) { - View child = mGroup.getChildAt(i); - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize); - child.setLayoutParams(lp); - } + protected void reloadDimens() { + mIconSize = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.status_bar_icon_size_sp); } private void setHeightAndCenter(ImageView imageView, int height) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java index 3a184239ac436..80d5651a65dc0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java @@ -109,6 +109,7 @@ public class StatusBarIconControllerImpl implements Tunable, } group.setController(this); + group.reloadDimens(); mIconGroups.add(group); List allSlots = mStatusBarIconList.getSlots(); for (int i = 0; i < allSlots.size(); i++) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java index 604b1f5008db3..3074abec860d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java @@ -103,7 +103,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { private void initDimens() { // This is the same value that StatusBarIconView uses mIconDotFrameWidth = getResources().getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_icon_size); + com.android.internal.R.dimen.status_bar_icon_size_sp); mDotPadding = getResources().getDimensionPixelSize(R.dimen.overflow_icon_dot_padding); mIconSpacing = getResources().getDimensionPixelSize(R.dimen.status_bar_system_icon_spacing); int radius = getResources().getDimensionPixelSize(R.dimen.overflow_dot_radius); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt index 1a1340484bfc3..83738544ee84d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt @@ -118,7 +118,7 @@ open class ModernStatusBarView(context: Context, attrs: AttributeSet?) : it.visibleState = STATE_DOT } - val width = mContext.resources.getDimensionPixelSize(R.dimen.status_bar_icon_size) + val width = mContext.resources.getDimensionPixelSize(R.dimen.status_bar_icon_size_sp) val lp = LayoutParams(width, width) lp.gravity = Gravity.CENTER_VERTICAL or Gravity.START addView(dotView, lp) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java index 1b1f4e41f200d..8d016e30c0c12 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java @@ -45,6 +45,7 @@ import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.UserHandle; import android.service.notification.StatusBarNotification; +import android.view.ViewGroup; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -65,6 +66,8 @@ import org.mockito.ArgumentMatcher; @RunWith(AndroidJUnit4.class) public class StatusBarIconViewTest extends SysuiTestCase { + private static final int TEST_STATUS_BAR_HEIGHT = 150; + @Rule public ExpectedException mThrown = ExpectedException.none(); @@ -184,4 +187,218 @@ public class StatusBarIconViewTest extends SysuiTestCase { // no crash, good } + + @Test + public void testUpdateIconScale_constrainedDrawableSizeLessThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // the icon view layout size would be 60x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, dpIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 50x50. When put the drawable into iconView whose + // layout size is 60x150, the drawable size would not be constrained and thus keep 50x50 + setIconDrawableWithSize(/* width= */ 50, /* height= */ 50); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN both the constrained drawable width/height are less than dpIconSize, + // THEN the icon is scaled down from dpIconSize to fit the dpDrawingSize + float scaleToFitDrawingSize = (float) dpDrawingSize / dpIconSize; + assertEquals(scaleToFitDrawingSize, mIconView.getIconScale(), 0.01f); + } + + @Test + public void testUpdateIconScale_constrainedDrawableHeightLargerThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // the icon view layout size would be 60x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, dpIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 50x100. When put the drawable into iconView whose + // layout size is 60x150, the drawable size would not be constrained and thus keep 50x100 + setIconDrawableWithSize(/* width= */ 50, /* height= */ 100); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN constrained drawable larger side length 100 >= dpIconSize + // THEN the icon is scaled down from larger side length 100 to ensure both side + // length fit in dpDrawingSize. + float scaleToFitDrawingSize = (float) dpDrawingSize / 100; + assertEquals(scaleToFitDrawingSize, mIconView.getIconScale(), 0.01f); + } + + @Test + public void testUpdateIconScale_constrainedDrawableWidthLargerThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // the icon view layout size would be 60x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, dpIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 100x50. When put the drawable into iconView whose + // layout size is 60x150, the drawable size would be constrained to 60x30 + setIconDrawableWithSize(/* width= */ 100, /* height= */ 50); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN constrained drawable larger side length 60 >= dpIconSize + // THEN the icon is scaled down from larger side length 60 to ensure both side + // length fit in dpDrawingSize. + float scaleToFitDrawingSize = (float) dpDrawingSize / 60; + assertEquals(scaleToFitDrawingSize, mIconView.getIconScale(), 0.01f); + } + + @Test + public void testUpdateIconScale_smallerFontAndConstrainedDrawableSizeLessThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // smaller font scaling causes the spIconSize < dpIconSize + int spIconSize = 40; + // the icon view layout size would be 40x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, spIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 50x50. When put the drawable into iconView whose + // layout size is 40x150, the drawable size would be constrained to 40x40 + setIconDrawableWithSize(/* width= */ 50, /* height= */ 50); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN both the constrained drawable width/height are less than dpIconSize, + // THEN the icon is scaled down from dpIconSize to fit the dpDrawingSize + float scaleToFitDrawingSize = (float) dpDrawingSize / dpIconSize; + // THEN the scaled icon should be scaled down further to fit spIconSize + float scaleToFitSpIconSize = (float) spIconSize / dpIconSize; + assertEquals(scaleToFitDrawingSize * scaleToFitSpIconSize, mIconView.getIconScale(), 0.01f); + } + + @Test + public void testUpdateIconScale_smallerFontAndConstrainedDrawableHeightLargerThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // smaller font scaling causes the spIconSize < dpIconSize + int spIconSize = 40; + // the icon view layout size would be 40x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, spIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 50x100. When put the drawable into iconView whose + // layout size is 40x150, the drawable size would be constrained to 40x80 + setIconDrawableWithSize(/* width= */ 50, /* height= */ 100); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN constrained drawable larger side length 80 >= dpIconSize + // THEN the icon is scaled down from larger side length 80 to ensure both side + // length fit in dpDrawingSize. + float scaleToFitDrawingSize = (float) dpDrawingSize / 80; + // THEN the scaled icon should be scaled down further to fit spIconSize + float scaleToFitSpIconSize = (float) spIconSize / dpIconSize; + assertEquals(scaleToFitDrawingSize * scaleToFitSpIconSize, mIconView.getIconScale(), 0.01f); + } + + @Test + public void testUpdateIconScale_largerFontAndConstrainedDrawableSizeLessThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // larger font scaling causes the spIconSize > dpIconSize + int spIconSize = 80; + // the icon view layout size would be 80x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, spIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 50x50. When put the drawable into iconView whose + // layout size is 80x150, the drawable size would not be constrained and thus keep 50x50 + setIconDrawableWithSize(/* width= */ 50, /* height= */ 50); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN both the constrained drawable width/height are less than dpIconSize, + // THEN the icon is scaled down from dpIconSize to fit the dpDrawingSize + float scaleToFitDrawingSize = (float) dpDrawingSize / dpIconSize; + // THEN the scaled icon should be scaled up to fit spIconSize + float scaleToFitSpIconSize = (float) spIconSize / dpIconSize; + assertEquals(scaleToFitDrawingSize * scaleToFitSpIconSize, mIconView.getIconScale(), 0.01f); + } + + @Test + public void testUpdateIconScale_largerFontAndConstrainedDrawableHeightLargerThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // larger font scaling causes the spIconSize > dpIconSize + int spIconSize = 80; + // the icon view layout size would be 80x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, spIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 50x100. When put the drawable into iconView whose + // layout size is 80x150, the drawable size would not be constrained and thus keep 50x100 + setIconDrawableWithSize(/* width= */ 50, /* height= */ 100); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN constrained drawable larger side length 100 >= dpIconSize + // THEN the icon is scaled down from larger side length 100 to ensure both side + // length fit in dpDrawingSize. + float scaleToFitDrawingSize = (float) dpDrawingSize / 100; + // THEN the scaled icon should be scaled up to fit spIconSize + float scaleToFitSpIconSize = (float) spIconSize / dpIconSize; + assertEquals(scaleToFitDrawingSize * scaleToFitSpIconSize, mIconView.getIconScale(), 0.01f); + } + + @Test + public void testUpdateIconScale_largerFontAndConstrainedDrawableWidthLargerThanDpIconSize() { + int dpIconSize = 60; + int dpDrawingSize = 30; + // larger font scaling causes the spIconSize > dpIconSize + int spIconSize = 80; + // the icon view layout size would be 80x150 + // (the height is always 150 due to TEST_STATUS_BAR_HEIGHT) + setUpIconView(dpIconSize, dpDrawingSize, spIconSize); + mIconView.setNotification(mock(StatusBarNotification.class)); + // the raw drawable size is 100x50. When put the drawable into iconView whose + // layout size is 80x150, the drawable size would not be constrained and thus keep 80x40 + setIconDrawableWithSize(/* width= */ 100, /* height= */ 50); + mIconView.maybeUpdateIconScaleDimens(); + + // WHEN constrained drawable larger side length 80 >= dpIconSize + // THEN the icon is scaled down from larger side length 80 to ensure both side + // length fit in dpDrawingSize. + float scaleToFitDrawingSize = (float) dpDrawingSize / 80; + // THEN the scaled icon should be scaled up to fit spIconSize + float scaleToFitSpIconSize = (float) spIconSize / dpIconSize; + assertEquals(scaleToFitDrawingSize * scaleToFitSpIconSize, + mIconView.getIconScale(), 0.01f); + } + + /** + * Setup iconView dimens for testing. The result icon view layout width would + * be spIconSize and height would be 150. + * + * @param dpIconSize corresponding to status_bar_icon_size + * @param dpDrawingSize corresponding to status_bar_icon_drawing_size + * @param spIconSize corresponding to status_bar_icon_size_sp under different font scaling + */ + private void setUpIconView(int dpIconSize, int dpDrawingSize, int spIconSize) { + mIconView.setIncreasedSize(false); + mIconView.mOriginalStatusBarIconSize = dpIconSize; + mIconView.mStatusBarIconDrawingSize = dpDrawingSize; + + mIconView.mNewStatusBarIconSize = spIconSize; + mIconView.mScaleToFitNewIconSize = (float) spIconSize / dpIconSize; + + // the layout width would be spIconSize + 2 * iconPadding, and we assume iconPadding + // is 0 here. + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(spIconSize, TEST_STATUS_BAR_HEIGHT); + mIconView.setLayoutParams(lp); + } + + private void setIconDrawableWithSize(int width, int height) { + Bitmap bitmap = Bitmap.createBitmap( + width, height, Bitmap.Config.ARGB_8888); + Icon icon = Icon.createWithBitmap(bitmap); + mStatusBarIcon = new StatusBarIcon(UserHandle.ALL, "mockPackage", + icon, 0, 0, ""); + // Since we only want to verify icon scale logic here, we directly use + // {@link StatusBarIconView#setImageDrawable(Drawable)} to set the image drawable + // to iconView instead of call {@link StatusBarIconView#set(StatusBarIcon)}. It's to prevent + // the icon drawable size being scaled down when internally calling + // {@link StatusBarIconView#getIcon(Context,Context,StatusBarIcon)}. + mIconView.setImageDrawable(icon.loadDrawable(mContext)); + } }