From 53f0dc4fdd66b3f75e4500e2e11f2f3960a94849 Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Sun, 7 Aug 2022 02:48:28 +0000 Subject: [PATCH 1/5] Allow manually specified time Additionally, disable layout animation from test Bug: 229771520 Test: Automated Change-Id: I2518d293f5b03e7bea7a45d8ef24ec6a998b5d30 (cherry picked from commit ed1efe9f3137395b2589dca9063d97dfcd4b3923) --- .../systemui/testing/screenshot/ViewScreenshotTestRule.kt | 7 +++++-- .../android/systemui/shared/clocks/AnimatableClockView.kt | 4 +++- .../src/com/android/keyguard/KeyguardClockSwitch.java | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt index 60130e1086ef0..47e2d2ccd13e7 100644 --- a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt +++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt @@ -44,9 +44,13 @@ import platform.test.screenshot.DeviceEmulationSpec import platform.test.screenshot.MaterialYouColorsRule import platform.test.screenshot.ScreenshotTestRule import platform.test.screenshot.getEmulatedDevicePathConfig +import platform.test.screenshot.matchers.BitmapMatcher /** A rule for View screenshot diff unit tests. */ -class ViewScreenshotTestRule(emulationSpec: DeviceEmulationSpec) : TestRule { +class ViewScreenshotTestRule( + emulationSpec: DeviceEmulationSpec, + private val matcher: BitmapMatcher = UnitTestBitmapMatcher +) : TestRule { private val colorsRule = MaterialYouColorsRule() private val deviceEmulationRule = DeviceEmulationRule(emulationSpec) private val screenshotRule = @@ -59,7 +63,6 @@ class ViewScreenshotTestRule(emulationSpec: DeviceEmulationSpec) : TestRule { .around(deviceEmulationRule) .around(screenshotRule) .around(activityRule) - private val matcher = UnitTestBitmapMatcher override fun apply(base: Statement, description: Description): Statement { return delegateRule.apply(base, description) diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt index a21a78b92d842..b51c84ab32903 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt @@ -77,6 +77,8 @@ class AnimatableClockView @JvmOverloads constructor( private var textAnimator: TextAnimator? = null private var onTextAnimatorInitialized: Runnable? = null + var timeOverrideInMillis: Long? = null + val dozingWeight: Int get() = if (useBoldedVersion()) dozingWeightInternal + 100 else dozingWeightInternal @@ -139,7 +141,7 @@ class AnimatableClockView @JvmOverloads constructor( } fun refreshTime() { - time.timeInMillis = System.currentTimeMillis() + time.timeInMillis = timeOverrideInMillis ?: System.currentTimeMillis() contentDescription = DateFormat.format(descFormat, time) val formattedText = DateFormat.format(format, time) // Setting text actually triggers a layout pass (because the text view is set to diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index e1fabdef36517..10d6d9fda548c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -68,6 +68,7 @@ public class KeyguardClockSwitch extends RelativeLayout { private int mClockSwitchYAmount; @VisibleForTesting boolean mChildrenAreLaidOut = false; + @VisibleForTesting boolean mAnimateOnLayout = true; public KeyguardClockSwitch(Context context, AttributeSet attrs) { super(context, attrs); @@ -214,7 +215,7 @@ public class KeyguardClockSwitch extends RelativeLayout { super.onLayout(changed, l, t, r, b); if (mDisplayedClockSize != null && !mChildrenAreLaidOut) { - post(() -> updateClockViews(mDisplayedClockSize == LARGE, /* animate */ true)); + post(() -> updateClockViews(mDisplayedClockSize == LARGE, mAnimateOnLayout)); } mChildrenAreLaidOut = true; From c254146e3cfcbd0baf2e88b9a44f2a580aed9489 Mon Sep 17 00:00:00 2001 From: Grace Date: Mon, 11 Jul 2022 21:03:24 +0000 Subject: [PATCH 2/5] Update DefaultClockProvider colors This is largely a cherry-pick of change I6b32776dac1853eeab87c2a65da69478e4da5b75 but with some notable changes to accomadate existing code differences in tm-qpr-dev. - We use a boolean instead of an enum for clock region darkness as the enum is in a different place in tm-qpr-dev. - We clean up some of the initialization code in ClockEventController to prevent testing issues and provide a dependency injection point to the screenshot test. - Pull the clock color setting from the theme when region sampling is disabled instead of defaulting to always dark. Test: Manually validated colors matched reference images on light and dark backgrounds with the region sampling feature both enabled and disabled. Bug: 229771520 Change-Id: I7906850b5de7f512f55e47e1122dfaacbc9c9406 (cherry picked from commit a724e0b753f710aef22c786bb089d3c8f7d7970a) --- packages/SystemUI/ktfmt_includes.txt | 7 +++ .../systemui/plugins/ClockProviderPlugin.kt | 7 ++- .../shared/clocks/DefaultClockProvider.kt | 20 +++---- .../shared/regionsampling/RegionDarkness.kt | 0 .../android/keyguard/ClockEventController.kt | 52 +++++++++++-------- .../keyguard/ClockEventControllerTest.kt | 1 + 6 files changed, 48 insertions(+), 39 deletions(-) rename packages/SystemUI/{plugin => shared}/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt (100%) diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt index 7c845ced66f8e..72757121d53fd 100644 --- a/packages/SystemUI/ktfmt_includes.txt +++ b/packages/SystemUI/ktfmt_includes.txt @@ -39,6 +39,7 @@ -packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt -packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt -packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt +-packages/SystemUI/src/com/android/keyguard/ClockEventController.kt -packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt -packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt -packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt @@ -156,6 +157,8 @@ -packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt -packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt -packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt +-packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt +-packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt -packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt -packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt -packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt @@ -246,6 +249,7 @@ -packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt -packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt @@ -575,6 +579,7 @@ -packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt -packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt -packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt +-packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt -packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt -packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt -packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt @@ -633,6 +638,7 @@ -packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt -packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt -packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt +-packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt -packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt -packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt -packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt @@ -720,6 +726,7 @@ -packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt -packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt -packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt +-packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt -packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt -packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt -packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt index 1ac1e3a9a7313..01e5d86549ebd 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt @@ -17,7 +17,6 @@ import android.content.res.Resources import android.graphics.drawable.Drawable import android.view.View import com.android.systemui.plugins.annotations.ProvidesInterface -import com.android.systemui.shared.regionsampling.RegionDarkness import java.io.PrintWriter import java.util.Locale import java.util.TimeZone @@ -62,7 +61,7 @@ interface Clock { /** Initializes various rendering parameters. If never called, provides reasonable defaults. */ fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) { - events.onColorPaletteChanged(resources, RegionDarkness.DEFAULT, RegionDarkness.DEFAULT) + events.onColorPaletteChanged(resources, true, true) animations.doze(dozeFraction) animations.fold(foldFraction) events.onTimeTick() @@ -92,8 +91,8 @@ interface ClockEvents { /** Call whenever the color palette should update */ fun onColorPaletteChanged( resources: Resources, - smallClockIsDark: RegionDarkness, - largeClockIsDark: RegionDarkness + smallClockIsDark: Boolean, + largeClockIsDark: Boolean ) { } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt index 6c491860ddde9..cfa483480632f 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt @@ -27,7 +27,6 @@ import com.android.systemui.plugins.ClockId import com.android.systemui.plugins.ClockMetadata import com.android.systemui.plugins.ClockProvider import com.android.systemui.shared.R -import com.android.systemui.shared.regionsampling.RegionDarkness import java.io.PrintWriter import java.util.Locale import java.util.TimeZone @@ -84,14 +83,11 @@ class DefaultClock( resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese) private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale) - private var smallRegionDarkness = RegionDarkness.DEFAULT - private var largeRegionDarkness = RegionDarkness.DEFAULT - - private fun updateClockColor(clock: AnimatableClockView, isRegionDark: RegionDarkness) { - val color = if (isRegionDark.isDark) { - resources.getColor(android.R.color.system_accent2_100) + private fun updateClockColor(clock: AnimatableClockView, isRegionDark: Boolean) { + val color = if (isRegionDark) { + resources.getColor(android.R.color.system_accent1_100) } else { - resources.getColor(android.R.color.system_accent1_600) + resources.getColor(android.R.color.system_accent2_600) } clock.setColors(DOZE_COLOR, color) clock.animateAppearOnLockscreen() @@ -120,8 +116,8 @@ class DefaultClock( override fun onColorPaletteChanged( resources: Resources, - smallClockIsDark: RegionDarkness, - largeClockIsDark: RegionDarkness + smallClockIsDark: Boolean, + largeClockIsDark: Boolean ) { if (smallRegionDarkness != smallClockIsDark) { smallRegionDarkness = smallClockIsDark @@ -217,8 +213,8 @@ class DefaultClock( animations = DefaultClockAnimations(dozeFraction, foldFraction) events.onColorPaletteChanged( resources, - RegionDarkness.DEFAULT, - RegionDarkness.DEFAULT + true, + true ) events.onTimeTick() } diff --git a/packages/SystemUI/plugin/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt similarity index 100% rename from packages/SystemUI/plugin/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt rename to packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 0d1158c959e52..0e1e0cb2adcf0 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -21,6 +21,8 @@ import android.content.Intent import android.content.IntentFilter import android.content.res.Resources import android.text.format.DateFormat +import android.util.TypedValue +import android.view.View import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -41,7 +43,7 @@ import javax.inject.Inject * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController]. */ -class ClockEventController @Inject constructor( +open class ClockEventController @Inject constructor( private val statusBarStateController: StatusBarStateController, private val broadcastDispatcher: BroadcastDispatcher, private val batteryController: BatteryController, @@ -74,18 +76,21 @@ class ClockEventController @Inject constructor( private val updateFun = object : RegionSamplingInstance.UpdateColorCallback { override fun updateColors() { - smallClockIsDark = smallRegionSamplingInstance.currentRegionDarkness() - largeClockIsDark = largeRegionSamplingInstance.currentRegionDarkness() - + if (regionSamplingEnabled) { + smallClockIsDark = smallRegionSamplingInstance.currentRegionDarkness().isDark + largeClockIsDark = largeRegionSamplingInstance.currentRegionDarkness().isDark + } else { + val isLightTheme = TypedValue() + context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true) + smallClockIsDark = isLightTheme.data == 0 + largeClockIsDark = isLightTheme.data == 0 + } clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark) } } fun updateRegionSamplers(currentClock: Clock?) { - smallRegionSamplingInstance.stopRegionSampler() - largeRegionSamplingInstance.stopRegionSampler() - - smallRegionSamplingInstance = RegionSamplingInstance( + smallRegionSamplingInstance = createRegionSampler( currentClock?.smallClock, mainExecutor, bgExecutor, @@ -93,7 +98,7 @@ class ClockEventController @Inject constructor( updateFun ) - largeRegionSamplingInstance = RegionSamplingInstance( + largeRegionSamplingInstance = createRegionSampler( currentClock?.largeClock, mainExecutor, bgExecutor, @@ -107,24 +112,26 @@ class ClockEventController @Inject constructor( updateFun.updateColors() } - var smallRegionSamplingInstance: RegionSamplingInstance = RegionSamplingInstance( - clock?.smallClock, + protected open fun createRegionSampler( + sampledView: View?, + mainExecutor: Executor?, + bgExecutor: Executor?, + regionSamplingEnabled: Boolean, + updateFun: RegionSamplingInstance.UpdateColorCallback + ): RegionSamplingInstance { + return RegionSamplingInstance( + sampledView, mainExecutor, bgExecutor, regionSamplingEnabled, - updateFun - ) + updateFun) + } - var largeRegionSamplingInstance: RegionSamplingInstance = RegionSamplingInstance( - clock?.largeClock, - mainExecutor, - bgExecutor, - regionSamplingEnabled, - updateFun - ) + lateinit var smallRegionSamplingInstance: RegionSamplingInstance + lateinit var largeRegionSamplingInstance: RegionSamplingInstance - private var smallClockIsDark = smallRegionSamplingInstance.currentRegionDarkness() - private var largeClockIsDark = largeRegionSamplingInstance.currentRegionDarkness() + private var smallClockIsDark = true + private var largeClockIsDark = true private val configListener = object : ConfigurationController.ConfigurationListener { override fun onThemeChanged() { @@ -179,7 +186,6 @@ class ClockEventController @Inject constructor( init { isDozing = statusBarStateController.isDozing - clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark) } fun registerListeners() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index 0ac4eda84eea1..914d94522e83f 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -259,6 +259,7 @@ class ClockEventControllerTest : SysuiTestCase() { @Test fun unregisterListeners_validate() { + clockEventController.clock = clock clockEventController.unregisterListeners() verify(broadcastDispatcher).unregisterReceiver(any()) verify(configurationController).removeCallback(any()) From 8d7ed90864ccaedd424e2aa91c2523b388f04103 Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Wed, 24 Aug 2022 16:24:18 +0000 Subject: [PATCH 3/5] Additional Tests for DefaultClock DefaultClock needed additional units as coverage of much of that class was too low. This additionally adds an animation disable flag into AnimatableClockView for use by the screenshot test. Bug: 229771520 Test: atest DefaultClockProviderTest Change-Id: I7d585cedb9b43ac0fb6405e36bec99ee8a246a61 (cherry picked from commit a823b466cc4f69446eb070303a1ee735d40c0c73) --- .../shared/clocks/AnimatableClockView.kt | 22 ++--- .../shared/clocks/DefaultClockProvider.kt | 6 +- .../shared/clocks/DefaultClockProviderTest.kt | 90 +++++++++++++++++-- 3 files changed, 102 insertions(+), 16 deletions(-) diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt index b51c84ab32903..34e2e83d76439 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt @@ -29,6 +29,7 @@ import android.util.AttributeSet import android.widget.TextView import com.android.internal.R.attr.contentDescription import com.android.internal.R.attr.format +import com.android.internal.annotations.VisibleForTesting import com.android.systemui.animation.GlyphCallback import com.android.systemui.animation.Interpolators import com.android.systemui.animation.TextAnimator @@ -77,7 +78,8 @@ class AnimatableClockView @JvmOverloads constructor( private var textAnimator: TextAnimator? = null private var onTextAnimatorInitialized: Runnable? = null - var timeOverrideInMillis: Long? = null + @VisibleForTesting var isAnimationEnabled: Boolean = true + @VisibleForTesting var timeOverrideInMillis: Long? = null val dozingWeight: Int get() = if (useBoldedVersion()) dozingWeightInternal + 100 else dozingWeightInternal @@ -217,7 +219,7 @@ class AnimatableClockView @JvmOverloads constructor( } fun animateAppearOnLockscreen() { - if (textAnimator == null) { + if (isAnimationEnabled && textAnimator == null) { return } setTextStyle( @@ -233,7 +235,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = lockScreenWeight, textSize = -1f, color = lockScreenColor, - animate = true, + animate = isAnimationEnabled, duration = APPEAR_ANIM_DURATION, delay = 0, onAnimationEnd = null @@ -241,7 +243,7 @@ class AnimatableClockView @JvmOverloads constructor( } fun animateFoldAppear(animate: Boolean = true) { - if (textAnimator == null) { + if (isAnimationEnabled && textAnimator == null) { return } setTextStyle( @@ -257,7 +259,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = dozingWeightInternal, textSize = -1f, color = dozingColor, - animate = animate, + animate = animate && isAnimationEnabled, interpolator = Interpolators.EMPHASIZED_DECELERATE, duration = ANIMATION_DURATION_FOLD_TO_AOD.toLong(), delay = 0, @@ -275,7 +277,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = if (isDozing()) dozingWeight else lockScreenWeight, textSize = -1f, color = null, - animate = true, + animate = isAnimationEnabled, duration = CHARGE_ANIM_DURATION_PHASE_1, delay = 0, onAnimationEnd = null @@ -285,7 +287,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = if (isDozing()) lockScreenWeight else dozingWeight, textSize = -1f, color = null, - animate = true, + animate = isAnimationEnabled, duration = CHARGE_ANIM_DURATION_PHASE_0, delay = chargeAnimationDelay.toLong(), onAnimationEnd = startAnimPhase2 @@ -297,7 +299,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = if (isDozing) dozingWeight else lockScreenWeight, textSize = -1f, color = if (isDozing) dozingColor else lockScreenColor, - animate = animate, + animate = animate && isAnimationEnabled, duration = DOZE_ANIM_DURATION, delay = 0, onAnimationEnd = null @@ -331,7 +333,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = weight, textSize = textSize, color = color, - animate = animate, + animate = animate && isAnimationEnabled, duration = duration, interpolator = interpolator, delay = delay, @@ -369,7 +371,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = weight, textSize = textSize, color = color, - animate = animate, + animate = animate && isAnimationEnabled, interpolator = null, duration = duration, delay = delay, diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt index cfa483480632f..763766e26df1a 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt @@ -19,6 +19,7 @@ import android.graphics.drawable.Drawable import android.icu.text.NumberFormat import android.util.TypedValue import android.view.LayoutInflater +import com.android.internal.annotations.VisibleForTesting import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.Clock import com.android.systemui.plugins.ClockAnimations @@ -83,6 +84,9 @@ class DefaultClock( resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese) private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale) + private var smallRegionDarkness = false + private var largeRegionDarkness = false + private fun updateClockColor(clock: AnimatableClockView, isRegionDark: Boolean) { val color = if (isRegionDark) { resources.getColor(android.R.color.system_accent1_100) @@ -227,7 +231,7 @@ class DefaultClock( override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) } companion object { - private const val DOZE_COLOR = Color.WHITE + @VisibleForTesting const val DOZE_COLOR = Color.WHITE private const val FORMAT_NUMBER = 1234567890 } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt index 78694480ad5b6..2f22455f8fe05 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt @@ -19,17 +19,27 @@ package com.android.systemui.shared.clocks import android.content.res.Resources import android.graphics.drawable.Drawable import android.testing.AndroidTestingRunner +import android.util.TypedValue import android.view.LayoutInflater import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.shared.clocks.DefaultClock.Companion.DOZE_COLOR +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.mock +import java.util.Locale +import java.util.TimeZone import junit.framework.Assert.assertEquals import junit.framework.Assert.assertNotNull import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyFloat +import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.times +import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit @@ -39,7 +49,8 @@ class DefaultClockProviderTest : SysuiTestCase() { @JvmField @Rule val mockito = MockitoJUnit.rule() - @Mock private lateinit var mockClockView: AnimatableClockView + @Mock private lateinit var mockSmallClockView: AnimatableClockView + @Mock private lateinit var mockLargeClockView: AnimatableClockView @Mock private lateinit var layoutInflater: LayoutInflater @Mock private lateinit var mockClockThumbnail: Drawable @Mock private lateinit var resources: Resources @@ -48,9 +59,9 @@ class DefaultClockProviderTest : SysuiTestCase() { @Before fun setUp() { whenever(layoutInflater.inflate(R.layout.clock_default_small, null)) - .thenReturn(mockClockView) + .thenReturn(mockSmallClockView) whenever(layoutInflater.inflate(R.layout.clock_default_large, null)) - .thenReturn(mockClockView) + .thenReturn(mockLargeClockView) whenever(resources.getDrawable(R.drawable.clock_default_thumbnail, null)) .thenReturn(mockClockThumbnail) @@ -71,7 +82,76 @@ class DefaultClockProviderTest : SysuiTestCase() { // Default clock provider must always provide the default clock val clock = provider.createClock(DEFAULT_CLOCK_ID) assertNotNull(clock) - assertEquals(clock.smallClock, mockClockView) - assertEquals(clock.largeClock, mockClockView) + assertEquals(clock.smallClock, mockSmallClockView) + assertEquals(clock.largeClock, mockLargeClockView) + } + + @Test + fun defaultClock_initialize() { + val clock = provider.createClock(DEFAULT_CLOCK_ID) + clock.initialize(resources, 0f, 0f) + + verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt()) + verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt()) + verify(mockSmallClockView).refreshTime() + verify(mockLargeClockView).refreshTime() + } + + @Test + fun defaultClock_events_onTimeTick() { + val clock = provider.createClock(DEFAULT_CLOCK_ID) + clock.events.onTimeTick() + + verify(mockSmallClockView).refreshTime() + verify(mockLargeClockView).refreshTime() + } + + @Test + fun defaultClock_events_onTimeFormatChanged() { + val clock = provider.createClock(DEFAULT_CLOCK_ID) + clock.events.onTimeFormatChanged(true) + + verify(mockSmallClockView).refreshFormat(true) + verify(mockLargeClockView).refreshFormat(true) + } + + @Test + fun defaultClock_events_onTimeZoneChanged() { + val timeZone = mock() + val clock = provider.createClock(DEFAULT_CLOCK_ID) + clock.events.onTimeZoneChanged(timeZone) + + verify(mockSmallClockView).onTimeZoneChanged(timeZone) + verify(mockLargeClockView).onTimeZoneChanged(timeZone) + } + + @Test + fun defaultClock_events_onFontSettingChanged() { + val clock = provider.createClock(DEFAULT_CLOCK_ID) + clock.events.onFontSettingChanged() + + verify(mockSmallClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat()) + verify(mockLargeClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat()) + verify(mockLargeClockView).setPadding(eq(0), anyInt(), eq(0), eq(0)) + } + + @Test + fun defaultClock_events_onColorPaletteChanged() { + val clock = provider.createClock(DEFAULT_CLOCK_ID) + clock.events.onColorPaletteChanged(resources, true, true) + + verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt()) + verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt()) + } + + @Test + fun defaultClock_events_onLocaleChanged() { + val clock = provider.createClock(DEFAULT_CLOCK_ID) + clock.events.onLocaleChanged(Locale.getDefault()) + + verify(mockSmallClockView, times(2)).setLineSpacingScale(anyFloat()) + verify(mockLargeClockView, times(2)).setLineSpacingScale(anyFloat()) + verify(mockSmallClockView, times(2)).refreshFormat() + verify(mockLargeClockView, times(2)).refreshFormat() } } From b06438380226e1bda60c5f065f83143696d6bc8d Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Tue, 2 Aug 2022 16:49:33 +0000 Subject: [PATCH 4/5] Correct large clock position This corrects the large clock positioning error that was introduced with Ia053aaec6987e00de980388a6c024d8bcf5203a2. It does this by rearranging the layout slightly to get back to the same position. Of note: - Previously the margin for the large clock was computed dynamically and applied to the large clock frame from a static resource and dynamic value based on the font. Now the static portion is applied directly from the resource to the clock frame in the layout resource. The dynamic portion is applied to the AnimatableClockView directly instead of it's parent as before. - ChildClipping has been disabled on the parent view as the dynamic portion of this margin moves the AnimatableClockView outside of it's parent's bounds. - The margin that is now applied to the AnimatableClockView is scaled by 0.5 to account produce the ccorrect placement after center-aligning the view in it's parent. Before the full value was applied to the parent, creating an equivalent effect. This also fixes the clock translation issue when the splitshade appears and disappears. They were both fundamentally layout issues with the refactored clock code. This change was manually tested by flashing each device and comparing the clock position in every configuration against a refenece image from a dogfood build. Additionally the motion of the clock was validated when the splitshade appears and disappears on a tablet in landscape. Test: Manual validated screenshots from several devices against reference images from a known good build. Additionally validated with a screenshot test, although golden images had to be updated. Bug: 229771520 Fixes: 241083568 Fixes: 241084042 Change-Id: I273c2996ff67c7b5f77c6bafb292d53275c7bc47 (cherry picked from commit 6a62f99b50598bc0c4d3383cd1ec0982489b73ba) --- .../layout/keyguard_clock_switch.xml | 10 +- packages/SystemUI/res/values/dimens.xml | 2 +- .../shared/res/layout/clock_default_small.xml | 2 +- .../shared/clocks/DefaultClockProvider.kt | 91 +++++++++++-------- .../android/keyguard/KeyguardClockSwitch.java | 7 +- .../KeyguardClockSwitchController.java | 5 +- .../shared/clocks/DefaultClockProviderTest.kt | 14 ++- 7 files changed, 72 insertions(+), 59 deletions(-) diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index 8b8ebf00e190d..3ad7c8c4369ca 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -23,6 +23,7 @@ android:id="@+id/keyguard_clock_container" android:layout_width="match_parent" android:layout_height="wrap_content" + android:clipChildren="false" android:layout_gravity="center_horizontal|top"> - + android:paddingStart="@dimen/clock_padding_start" /> - + android:layout_marginTop="@dimen/keyguard_large_clock_top_margin" + android:visibility="gone" /> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index a19145ddba6b6..a62007d1ee94a 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -669,7 +669,7 @@ 12dp - 100dp + -60dp 32dp diff --git a/packages/SystemUI/shared/res/layout/clock_default_small.xml b/packages/SystemUI/shared/res/layout/clock_default_small.xml index 390ff5e3ff787..ff6d7f9e22403 100644 --- a/packages/SystemUI/shared/res/layout/clock_default_small.xml +++ b/packages/SystemUI/shared/res/layout/clock_default_small.xml @@ -18,7 +18,7 @@ --> Date: Wed, 24 Aug 2022 16:01:45 +0000 Subject: [PATCH 5/5] Initialize TimeZone during DefaultClockProvider init This is a duplication of Ie8b08bec36bccfda5a1f1eb20c91a040c1f688ab for the refactored clock code. It's validated via unit test as it has proved somewhat tricky to reproduce manually. Test: atest DefaultClockProviderTest Fixes: 241729527 Change-Id: I0c664750190572790e71f6095a1ac8c4995c83ca (cherry picked from commit c6bfa32a24bf2d3bb6928b4ebc8a288d9bac497d) --- .../com/android/systemui/shared/clocks/DefaultClockProvider.kt | 1 + .../android/systemui/shared/clocks/DefaultClockProviderTest.kt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt index 4513256f492d3..19ac2e479bcb3 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt @@ -121,6 +121,7 @@ class DefaultClock( recomputePadding() animations = DefaultClockAnimations(dozeFraction, foldFraction) events.onColorPaletteChanged(resources, true, true) + events.onTimeZoneChanged(TimeZone.getDefault()) events.onTimeTick() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt index a978294c98eca..2b4a109282ce1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt @@ -40,6 +40,7 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyFloat import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.notNull import org.mockito.Mock import org.mockito.Mockito.times import org.mockito.Mockito.verify @@ -98,6 +99,8 @@ class DefaultClockProviderTest : SysuiTestCase() { verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt()) verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt()) + verify(mockSmallClockView).onTimeZoneChanged(notNull()) + verify(mockLargeClockView).onTimeZoneChanged(notNull()) verify(mockSmallClockView).refreshTime() verify(mockLargeClockView).refreshTime() verify(mockLargeClockView).setLayoutParams(any())