From 957742cf046c838a60b4ff368794fb549fa119f1 Mon Sep 17 00:00:00 2001 From: yyalan Date: Fri, 1 Apr 2022 16:50:06 +0100 Subject: [PATCH] Update Split Shade's status bar font size When the system's Font Size is changed, the config listener in LargeScreenShadeHeaderController changes the font size of Clock, DateView, and the Carrier Group. Bug: 222695062 Test: manually, with different font size and display size + atest com.android.systemui.statusbar.phone.LargeScreenShadeHeaderControllerTest Change-Id: I535a3e3afd7b8539422eb44b90de87a251002195 --- .../com/android/systemui/FontSizeUtils.java | 22 +++++++- .../systemui/qs/carrier/QSCarrier.java | 6 ++ .../systemui/qs/carrier/QSCarrierGroup.java | 9 +++ .../phone/LargeScreenShadeHeaderController.kt | 24 +++++++- .../LargeScreenShadeHeaderControllerTest.kt | 55 +++++++++++++++++++ .../policy/FakeConfigurationController.kt | 4 ++ 6 files changed, 116 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java b/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java index 35a70a5ed52bc..0d1dc9d6a5dd9 100644 --- a/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java +++ b/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java @@ -16,6 +16,8 @@ package com.android.systemui; +import android.annotation.StyleRes; +import android.content.res.TypedArray; import android.util.TypedValue; import android.view.View; import android.widget.TextView; @@ -23,9 +25,9 @@ import android.widget.TextView; /** * Utility class to update the font size when the configuration has changed. */ -public class FontSizeUtils { +public final class FontSizeUtils { - public static final float LARGE_TEXT_SCALE = 1.3f; + private FontSizeUtils() {} public static void updateFontSize(View parent, int viewId, int dimensId) { updateFontSize((TextView) parent.findViewById(viewId), dimensId); @@ -37,4 +39,20 @@ public class FontSizeUtils { v.getResources().getDimensionPixelSize(dimensId)); } } + + /** + * Updates the font size according to the style given. + * + * @param v Text to update. + * @param resId Style applying to the text. + */ + public static void updateFontSizeFromStyle(TextView v, @StyleRes int resId) { + int[] attrs = {android.R.attr.textSize}; + int indexOfAttrTextSize = 0; + TypedArray ta = v.getContext().obtainStyledAttributes(resId, attrs); + int updatedTextPixelSize = ta.getDimensionPixelSize(indexOfAttrTextSize, + (int) v.getTextSize()); + v.setTextSize(TypedValue.COMPLEX_UNIT_PX, updatedTextPixelSize); + ta.recycle(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java index 2959c3b30eec4..592da6554b906 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java @@ -16,6 +16,7 @@ package com.android.systemui.qs.carrier; +import android.annotation.StyleRes; import android.content.Context; import android.content.res.ColorStateList; import android.text.TextUtils; @@ -30,6 +31,7 @@ import androidx.annotation.VisibleForTesting; import com.android.settingslib.Utils; import com.android.settingslib.graph.SignalDrawable; +import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import java.util.Objects; @@ -146,4 +148,8 @@ public class QSCarrier extends LinearLayout { public void setCarrierText(CharSequence text) { mCarrierText.setText(text); } + + public void updateTextAppearance(@StyleRes int resId) { + FontSizeUtils.updateFontSizeFromStyle(mCarrierText, resId); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java index d03563ffb3427..a36035b99b4fb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java @@ -16,12 +16,14 @@ package com.android.systemui.qs.carrier; +import android.annotation.StyleRes; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.systemui.FontSizeUtils; import com.android.systemui.R; /** @@ -55,4 +57,11 @@ public class QSCarrierGroup extends LinearLayout { View getCarrierDivider2() { return findViewById(R.id.qs_carrier_divider2); } + + public void updateTextAppearance(@StyleRes int resId) { + FontSizeUtils.updateFontSizeFromStyle(getNoSimTextView(), resId); + getCarrier1View().updateTextAppearance(resId); + getCarrier2View().updateTextAppearance(resId); + getCarrier3View().updateTextAppearance(resId); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt index 289dfc889e75c..178c17dd5694c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt @@ -18,9 +18,11 @@ package com.android.systemui.statusbar.phone import android.app.StatusBarManager import android.view.View +import android.widget.TextView import androidx.constraintlayout.motion.widget.MotionLayout import com.android.settingslib.Utils import com.android.systemui.Dumpable +import com.android.systemui.FontSizeUtils import com.android.systemui.R import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView @@ -30,10 +32,12 @@ import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.qs.ChipVisibilityListener import com.android.systemui.qs.HeaderPrivacyIconsController +import com.android.systemui.qs.carrier.QSCarrierGroup import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_BATTERY_CONTROLLER import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_SHADE_HEADER +import com.android.systemui.statusbar.policy.ConfigurationController import java.io.PrintWriter import javax.inject.Inject import javax.inject.Named @@ -43,6 +47,7 @@ class LargeScreenShadeHeaderController @Inject constructor( @Named(LARGE_SCREEN_SHADE_HEADER) private val header: View, private val statusBarIconController: StatusBarIconController, private val privacyIconsController: HeaderPrivacyIconsController, + private val configurationController: ConfigurationController, qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder, featureFlags: FeatureFlags, @Named(LARGE_SCREEN_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController, @@ -69,6 +74,9 @@ class LargeScreenShadeHeaderController @Inject constructor( private val iconContainer: StatusIconContainer private val carrierIconSlots: List private val qsCarrierGroupController: QSCarrierGroupController + private val clock: TextView = header.findViewById(R.id.clock) + private val date: TextView = header.findViewById(R.id.date) + private val qsCarrierGroup: QSCarrierGroup = header.findViewById(R.id.carrier_group) private var qsDisabled = false @@ -148,9 +156,9 @@ class LargeScreenShadeHeaderController @Inject constructor( .load(context, resources.getXml(R.xml.large_screen_shade_header)) privacyIconsController.chipVisibilityListener = chipVisibilityListener } - } - init { + bindConfigurationListener() + batteryMeterViewController.init() val batteryIcon: BatteryMeterView = header.findViewById(R.id.batteryRemainingIcon) @@ -194,6 +202,18 @@ class LargeScreenShadeHeaderController @Inject constructor( } } + private fun bindConfigurationListener() { + val listener = object : ConfigurationController.ConfigurationListener { + override fun onDensityOrFontScaleChanged() { + val qsStatusStyle = R.style.TextAppearance_QS_Status + FontSizeUtils.updateFontSizeFromStyle(clock, qsStatusStyle) + FontSizeUtils.updateFontSizeFromStyle(date, qsStatusStyle) + qsCarrierGroup.updateTextAppearance(qsStatusStyle) + } + } + configurationController.addCallback(listener) + } + private fun onShadeExpandedChanged() { if (shadeExpanded) { privacyIconsController.startListening() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt index 01e95950e45a2..80664013f95d9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt @@ -1,8 +1,12 @@ package com.android.systemui.statusbar.phone import android.app.StatusBarManager +import android.content.Context +import android.content.res.TypedArray import android.testing.AndroidTestingRunner +import android.util.TypedValue.COMPLEX_UNIT_PX import android.view.View +import android.widget.TextView import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase @@ -13,7 +17,9 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.qs.HeaderPrivacyIconsController +import com.android.systemui.qs.carrier.QSCarrierGroup import com.android.systemui.qs.carrier.QSCarrierGroupController +import com.android.systemui.statusbar.policy.FakeConfigurationController import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule @@ -22,6 +28,7 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @@ -36,19 +43,32 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder @Mock private lateinit var featureFlags: FeatureFlags + @Mock private lateinit var clock: TextView + @Mock private lateinit var date: TextView + @Mock private lateinit var carrierGroup: QSCarrierGroup @Mock private lateinit var batteryMeterView: BatteryMeterView @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController @Mock private lateinit var dumpManager: DumpManager + @Mock private lateinit var mockedContext: Context + @Mock private lateinit var typedArray: TypedArray + @JvmField @Rule val mockitoRule = MockitoJUnit.rule() var viewVisibility = View.GONE private lateinit var mLargeScreenShadeHeaderController: LargeScreenShadeHeaderController private lateinit var carrierIconSlots: List + private val configurationController = FakeConfigurationController() @Before fun setup() { + whenever(view.findViewById(R.id.clock)).thenReturn(clock) + whenever(clock.context).thenReturn(mockedContext) + whenever(mockedContext.obtainStyledAttributes(anyInt(), any())).thenReturn(typedArray) + whenever(view.findViewById(R.id.date)).thenReturn(date) + whenever(date.context).thenReturn(mockedContext) + whenever(view.findViewById(R.id.carrier_group)).thenReturn(carrierGroup) whenever(view.findViewById(R.id.batteryRemainingIcon)) .thenReturn(batteryMeterView) whenever(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons) @@ -67,6 +87,7 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() { view, statusBarIconController, privacyIconsController, + configurationController, qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController, @@ -138,4 +159,38 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() { mLargeScreenShadeHeaderController.active = true mLargeScreenShadeHeaderController.shadeExpanded = true } + + @Test + fun updateConfig_changesFontSize() { + val updatedTextPixelSize = 32 + setReturnTextSize(updatedTextPixelSize) + + configurationController.notifyDensityOrFontScaleChanged() + + verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize.toFloat()) + verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize.toFloat()) + verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status) + } + + @Test + fun updateConfig_changesFontSizeMultipleTimes() { + val updatedTextPixelSize1 = 32 + setReturnTextSize(updatedTextPixelSize1) + configurationController.notifyDensityOrFontScaleChanged() + verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize1.toFloat()) + verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize1.toFloat()) + verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status) + clearInvocations(carrierGroup) + + val updatedTextPixelSize2 = 42 + setReturnTextSize(updatedTextPixelSize2) + configurationController.notifyDensityOrFontScaleChanged() + verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize2.toFloat()) + verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize2.toFloat()) + verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status) + } + + private fun setReturnTextSize(resultTextSize: Int) { + whenever(typedArray.getDimensionPixelSize(anyInt(), anyInt())).thenReturn(resultTextSize) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt index 146b56e49e658..16a3268695620 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt @@ -23,6 +23,10 @@ class FakeConfigurationController : ConfigurationController { listeners.forEach { it.onThemeChanged() } } + fun notifyDensityOrFontScaleChanged() { + listeners.forEach { it.onDensityOrFontScaleChanged() } + } + fun notifyConfigurationChanged() { onConfigurationChanged(newConfiguration = null) }