From 843cd5ea892a030fe6c18617c9d468b34c2b1bd5 Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Mon, 8 Aug 2022 19:02:01 +0000 Subject: [PATCH 1/7] [DO NOT MERGE] Revert "[DO NOT MERGE]Revert "Migrate KeyguardClockSwitch to new..." Revert "[DO NOT MERGE]Revert "Expose the clock version of google..." Revert "[DO NOT MERGE]Revert "Changes to SystemUIGoogle to suppo..." Revert submission 19508951-revert-19451291-cherrypick-clock_migration-tvip0m638i-BKWSUCNJAV Reason for revert: Double Revert w/ fixes Reverted Changes: Iccd8d2e19:[DO NOT MERGE]Revert "Add clock version of google-... I432d3d814:[DO NOT MERGE]Revert "Migrate KeyguardClockSwitch ... Ifd0aa59df:[DO NOT MERGE]Revert "Expose the clock version of ... I9a6ca6349:[DO NOT MERGE]Revert "Changes to SystemUIGoogle to... To minimize merge issues, this topic consists of just cherry-picks from master. Fixes for bugs are provided as downstream commits and will be merged back to master as those bugs exist there as well. The commits in this topic weren't tested in isolation beyond automated testing. Additionally, I've updated the ktfmt exclude list to include new files from this cherry-pick instead of reformatting those files. Test: Screenshot test and manually validated each downstream fix mostly by comparing reference images from known good builds to test builds. Change-Id: Iff1d0ee8c6d09c77185be1ca5bbbe1aa5870e0c7 --- packages/SystemUI/ktfmt_includes.txt | 7 + .../systemui/plugins/ClockProviderPlugin.kt | 21 +- packages/SystemUI/res-keyguard/font/clock.xml | 28 -- .../layout/keyguard_clock_switch.xml | 32 +-- .../dream_overlay_complication_clock_time.xml | 2 +- packages/SystemUI/res/values/dimens.xml | 13 +- .../shared/res/layout/clock_default_large.xml | 1 - .../shared/res/layout/clock_default_small.xml | 2 +- .../shared/clocks/AnimatableClockView.kt | 18 ++ .../systemui/shared/clocks/ClockRegistry.kt | 20 +- .../shared/clocks/DefaultClockProvider.kt | 40 ++- .../keyguard/AnimatableClockController.java | 12 - .../android/keyguard/ClockEventController.kt | 153 +++++++++++ .../android/keyguard/KeyguardClockSwitch.java | 182 ++---------- .../KeyguardClockSwitchController.java | 214 +++++---------- .../android/keyguard/KeyguardStatusView.java | 9 - .../KeyguardStatusViewController.java | 47 +--- .../NotificationPanelViewController.java | 24 +- .../fragment/CollapsedStatusBarFragment.java | 8 - .../keyguard/ClockEventControllerTest.kt | 259 ++++++++++++++++++ .../KeyguardClockSwitchControllerTest.java | 65 ++--- .../keyguard/KeyguardClockSwitchTest.java | 220 +++++---------- .../shared/clocks/ClockRegistryTest.kt | 32 ++- .../CollapsedStatusBarFragmentTest.java | 40 +-- 24 files changed, 709 insertions(+), 740 deletions(-) delete mode 100644 packages/SystemUI/res-keyguard/font/clock.xml create mode 100644 packages/SystemUI/src/com/android/keyguard/ClockEventController.kt create mode 100644 packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt index 3ca8dfe4fd382..51cc1954299fc 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 0c1916074e0c5..cafdc86761733 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt @@ -13,9 +13,9 @@ */ package com.android.systemui.plugins +import android.content.res.Resources import android.graphics.drawable.Drawable import android.view.View -import com.android.internal.colorextraction.ColorExtractor import com.android.systemui.plugins.annotations.ProvidesInterface import java.io.PrintWriter import java.util.Locale @@ -57,7 +57,15 @@ interface Clock { val events: ClockEvents /** Triggers for various animations */ - val animation: ClockAnimation + val animations: ClockAnimations + + /** Initializes various rendering parameters. If never called, provides reasonable defaults. */ + fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) { + events.onColorPaletteChanged(resources) + animations.doze(dozeFraction) + animations.fold(foldFraction) + events.onTimeTick() + } /** Optional method for dumping debug information */ fun dump(pw: PrintWriter) { } @@ -80,15 +88,12 @@ interface ClockEvents { /** Call whenever font settings change */ fun onFontSettingChanged() { } - /** Call whenever the color pallete should update */ - fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) { } + /** Call whenever the color palette should update */ + fun onColorPaletteChanged(resources: Resources) { } } /** Methods which trigger various clock animations */ -interface ClockAnimation { - /** Initializes the doze & fold animation positions. Defaults to neither folded nor dozing. */ - fun initialize(dozeFraction: Float, foldFraction: Float) { } - +interface ClockAnimations { /** Runs an enter animation (if any) */ fun enter() { } diff --git a/packages/SystemUI/res-keyguard/font/clock.xml b/packages/SystemUI/res-keyguard/font/clock.xml deleted file mode 100644 index 0137dc39921fe..0000000000000 --- a/packages/SystemUI/res-keyguard/font/clock.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index 6a38507b2ad75..8b8ebf00e190d 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -31,42 +31,14 @@ android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:paddingStart="@dimen/clock_padding_start"> - - 12dp - -60dp - - - - .7 - - 1 + 100dp 32dp @@ -895,11 +889,6 @@ burn-in on AOD. --> 42dp - - - 150dp - 86dp - 15dp diff --git a/packages/SystemUI/shared/res/layout/clock_default_large.xml b/packages/SystemUI/shared/res/layout/clock_default_large.xml index 8510a0a8b5500..0139d50dcfba2 100644 --- a/packages/SystemUI/shared/res/layout/clock_default_large.xml +++ b/packages/SystemUI/shared/res/layout/clock_default_large.xml @@ -18,7 +18,6 @@ --> Unit - /** ClockRegistry aggregates providers and plugins */ open class ClockRegistry( val context: Context, @@ -51,6 +49,11 @@ open class ClockRegistry( defaultClockProvider: DefaultClockProvider ) : this(context, pluginManager, handler, defaultClockProvider as ClockProvider) { } + // Usually this would be a typealias, but a SAM provides better java interop + fun interface ClockChangeListener { + fun onClockChanged() + } + var isEnabled: Boolean = false private val gson = Gson() @@ -58,7 +61,7 @@ open class ClockRegistry( private val clockChangeListeners = mutableListOf() private val settingObserver = object : ContentObserver(handler) { override fun onChange(selfChange: Boolean, uris: Collection, flags: Int, userId: Int) = - clockChangeListeners.forEach { it() } + clockChangeListeners.forEach { it.onClockChanged() } } private val pluginListener = object : PluginListener { @@ -117,8 +120,11 @@ open class ClockRegistry( val id = clock.clockId val current = availableClocks[id] if (current != null) { - Log.e(TAG, "Clock Id conflict: $id is registered by both " + - "${provider::class.simpleName} and ${current.provider::class.simpleName}") + Log.e( + TAG, + "Clock Id conflict: $id is registered by both " + + "${provider::class.simpleName} and ${current.provider::class.simpleName}" + ) return } @@ -127,7 +133,7 @@ open class ClockRegistry( if (DEBUG) { Log.i(TAG, "Current clock ($currentId) was connected") } - clockChangeListeners.forEach { it() } + clockChangeListeners.forEach { it.onClockChanged() } } } } @@ -139,7 +145,7 @@ open class ClockRegistry( if (currentId == clock.clockId) { Log.w(TAG, "Current clock ($currentId) was disconnected") - clockChangeListeners.forEach { it() } + clockChangeListeners.forEach { it.onClockChanged() } } } } 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 5d8da59857686..1d8abe3fdf420 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,10 +19,9 @@ import android.graphics.drawable.Drawable import android.icu.text.NumberFormat import android.util.TypedValue import android.view.LayoutInflater -import com.android.internal.colorextraction.ColorExtractor import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.Clock -import com.android.systemui.plugins.ClockAnimation +import com.android.systemui.plugins.ClockAnimations import com.android.systemui.plugins.ClockEvents import com.android.systemui.plugins.ClockId import com.android.systemui.plugins.ClockMetadata @@ -102,10 +101,13 @@ class DefaultClock( TypedValue.COMPLEX_UNIT_PX, resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat() ) + recomputePadding() } - override fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) = - clocks.forEach { it.setColors(DOZE_COLOR, palette.mainColor) } + override fun onColorPaletteChanged(resources: Resources) { + val color = resources.getColor(android.R.color.system_accent1_100) + clocks.forEach { it.setColors(DOZE_COLOR, color) } + } override fun onLocaleChanged(locale: Locale) { val nf = NumberFormat.getInstance(locale) @@ -119,8 +121,17 @@ class DefaultClock( } } - override val animation = object : ClockAnimation { - override fun initialize(dozeFraction: Float, foldFraction: Float) { + override var animations = DefaultClockAnimations(0f, 0f) + private set + + inner class DefaultClockAnimations( + dozeFraction: Float, + foldFraction: Float + ) : ClockAnimations { + private var foldState = AnimationState(0f) + private var dozeState = AnimationState(0f) + + init { dozeState = AnimationState(dozeFraction) foldState = AnimationState(foldFraction) @@ -132,14 +143,13 @@ class DefaultClock( } override fun enter() { - if (dozeState.isActive) { + if (!dozeState.isActive) { clocks.forEach { it.animateAppearOnLockscreen() } } } override fun charge() = clocks.forEach { it.animateCharge { dozeState.isActive } } - private var foldState = AnimationState(0f) override fun fold(fraction: Float) { val (hasChanged, hasJumped) = foldState.update(fraction) if (hasChanged) { @@ -147,7 +157,6 @@ class DefaultClock( } } - private var dozeState = AnimationState(0f) override fun doze(fraction: Float) { val (hasChanged, hasJumped) = dozeState.update(fraction) if (hasChanged) { @@ -172,6 +181,19 @@ class DefaultClock( init { events.onLocaleChanged(Locale.getDefault()) + clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) } + } + + override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) { + recomputePadding() + animations = DefaultClockAnimations(dozeFraction, foldFraction) + events.onColorPaletteChanged(resources) + events.onTimeTick() + } + + private fun recomputePadding() { + val topPadding = -1 * (largeClock.bottom.toInt() - 180) + largeClock.setPadding(0, topPadding, 0, 0) } override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) } diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java index 3c68c0daf4894..dd69f334c783e 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java @@ -182,18 +182,6 @@ public class AnimatableClockController extends ViewController dozeAmount + dozeAmount = linear + } + } + + private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { + override fun onKeyguardVisibilityChanged(showing: Boolean) { + isKeyguardShowing = showing + if (!isKeyguardShowing) { + clock?.animations?.doze(if (isDozing) 1f else 0f) + } + } + + override fun onTimeFormatChanged(timeFormat: String) { + clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context)) + } + + override fun onTimeZoneChanged(timeZone: TimeZone) { + clock?.events?.onTimeZoneChanged(timeZone) + } + + override fun onUserSwitchComplete(userId: Int) { + clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context)) + } + } + + init { + isDozing = statusBarStateController.isDozing + } + + fun registerListeners() { + dozeAmount = statusBarStateController.dozeAmount + isDozing = statusBarStateController.isDozing || dozeAmount != 0f + + broadcastDispatcher.registerReceiver( + localeBroadcastReceiver, + IntentFilter(Intent.ACTION_LOCALE_CHANGED) + ) + configurationController.addCallback(configListener) + batteryController.addCallback(batteryCallback) + keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) + statusBarStateController.addCallback(statusBarStateListener) + } + + fun unregisterListeners() { + broadcastDispatcher.unregisterReceiver(localeBroadcastReceiver) + configurationController.removeCallback(configListener) + batteryController.removeCallback(batteryCallback) + keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback) + statusBarStateController.removeCallback(statusBarStateListener) + } + + /** + * Dump information for debugging + */ + fun dump(pw: PrintWriter) { + pw.println(this) + clock?.dump(pw) + } + + companion object { + private val TAG = ClockEventController::class.simpleName + private const val FORMAT_NUMBER = 1234567890 + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 916410856b20c..10d6d9fda548c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -5,10 +5,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; -import android.graphics.Paint; -import android.graphics.Paint.Style; import android.util.AttributeSet; -import android.util.TypedValue; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -17,19 +15,14 @@ import android.widget.RelativeLayout; import androidx.annotation.IntDef; import androidx.annotation.VisibleForTesting; -import com.android.internal.colorextraction.ColorExtractor; import com.android.keyguard.dagger.KeyguardStatusViewScope; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; -import com.android.systemui.plugins.ClockPlugin; -import com.android.systemui.shared.clocks.AnimatableClockView; +import com.android.systemui.plugins.Clock; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.Arrays; -import java.util.TimeZone; - /** * Switch to show plugin clock when plugin is connected, otherwise it will show default clock. */ @@ -49,18 +42,11 @@ public class KeyguardClockSwitch extends RelativeLayout { public static final int LARGE = 0; public static final int SMALL = 1; - /** - * Optional/alternative clock injected via plugin. - */ - private ClockPlugin mClockPlugin; - /** * Frame for small/large clocks */ - private FrameLayout mClockFrame; + private FrameLayout mSmallClockFrame; private FrameLayout mLargeClockFrame; - private AnimatableClockView mClockView; - private AnimatableClockView mLargeClockView; private View mStatusArea; private int mSmartspaceTopOffset; @@ -80,12 +66,6 @@ public class KeyguardClockSwitch extends RelativeLayout { @VisibleForTesting AnimatorSet mClockOutAnim = null; private ObjectAnimator mStatusAreaAnim = null; - /** - * If the Keyguard Slice has a header (big center-aligned text.) - */ - private boolean mSupportsDarkText; - private int[] mColorPalette; - private int mClockSwitchYAmount; @VisibleForTesting boolean mChildrenAreLaidOut = false; @VisibleForTesting boolean mAnimateOnLayout = true; @@ -98,97 +78,38 @@ public class KeyguardClockSwitch extends RelativeLayout { * Apply dp changes on font/scale change */ public void onDensityOrFontScaleChanged() { - mLargeClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources() - .getDimensionPixelSize(R.dimen.large_clock_text_size)); - mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources() - .getDimensionPixelSize(R.dimen.clock_text_size)); - mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize( R.dimen.keyguard_clock_switch_y_shift); - mSmartspaceTopOffset = mContext.getResources().getDimensionPixelSize( R.dimen.keyguard_smartspace_top_offset); } - /** - * Returns if this view is presenting a custom clock, or the default implementation. - */ - public boolean hasCustomClock() { - return mClockPlugin != null; - } - @Override protected void onFinishInflate() { super.onFinishInflate(); - mClockFrame = findViewById(R.id.lockscreen_clock_view); - mClockView = findViewById(R.id.animatable_clock_view); + mSmallClockFrame = findViewById(R.id.lockscreen_clock_view); mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large); - mLargeClockView = findViewById(R.id.animatable_clock_view_large); mStatusArea = findViewById(R.id.keyguard_status_area); onDensityOrFontScaleChanged(); } - void setClockPlugin(ClockPlugin plugin, int statusBarState) { + void setClock(Clock clock, int statusBarState) { // Disconnect from existing plugin. - if (mClockPlugin != null) { - View smallClockView = mClockPlugin.getView(); - if (smallClockView != null && smallClockView.getParent() == mClockFrame) { - mClockFrame.removeView(smallClockView); - } - View bigClockView = mClockPlugin.getBigClockView(); - if (bigClockView != null && bigClockView.getParent() == mLargeClockFrame) { - mLargeClockFrame.removeView(bigClockView); - } - mClockPlugin.onDestroyView(); - mClockPlugin = null; - } - if (plugin == null) { - mClockView.setVisibility(View.VISIBLE); - mLargeClockView.setVisibility(View.VISIBLE); + mSmallClockFrame.removeAllViews(); + mLargeClockFrame.removeAllViews(); + + if (clock == null) { + Log.e(TAG, "No clock being shown"); return; } + // Attach small and big clock views to hierarchy. - View smallClockView = plugin.getView(); - if (smallClockView != null) { - mClockFrame.addView(smallClockView, -1, - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); - mClockView.setVisibility(View.GONE); - } - View bigClockView = plugin.getBigClockView(); - if (bigClockView != null) { - mLargeClockFrame.addView(bigClockView); - mLargeClockView.setVisibility(View.GONE); - } - - // Initialize plugin parameters. - mClockPlugin = plugin; - mClockPlugin.setStyle(getPaint().getStyle()); - mClockPlugin.setTextColor(getCurrentTextColor()); - mClockPlugin.setDarkAmount(mDarkAmount); - if (mColorPalette != null) { - mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette); - } - } - - /** - * It will also update plugin setStyle if plugin is connected. - */ - public void setStyle(Style style) { - if (mClockPlugin != null) { - mClockPlugin.setStyle(style); - } - } - - /** - * It will also update plugin setTextColor if plugin is connected. - */ - public void setTextColor(int color) { - if (mClockPlugin != null) { - mClockPlugin.setTextColor(color); - } + mSmallClockFrame.addView(clock.getSmallClock(), -1, + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT)); + mLargeClockFrame.addView(clock.getLargeClock()); } private void updateClockViews(boolean useLargeClock, boolean animate) { @@ -204,14 +125,14 @@ public class KeyguardClockSwitch extends RelativeLayout { int direction = 1; float statusAreaYTranslation; if (useLargeClock) { - out = mClockFrame; + out = mSmallClockFrame; in = mLargeClockFrame; if (indexOfChild(in) == -1) addView(in); direction = -1; - statusAreaYTranslation = mClockFrame.getTop() - mStatusArea.getTop() + statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop() + mSmartspaceTopOffset; } else { - in = mClockFrame; + in = mSmallClockFrame; out = mLargeClockFrame; statusAreaYTranslation = 0f; @@ -269,18 +190,6 @@ public class KeyguardClockSwitch extends RelativeLayout { mStatusAreaAnim.start(); } - /** - * Set the amount (ratio) that the device has transitioned to doze. - * - * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake. - */ - public void setDarkAmount(float darkAmount) { - mDarkAmount = darkAmount; - if (mClockPlugin != null) { - mClockPlugin.setDarkAmount(darkAmount); - } - } - /** * Display the desired clock and hide the other one * @@ -312,64 +221,11 @@ public class KeyguardClockSwitch extends RelativeLayout { mChildrenAreLaidOut = true; } - public Paint getPaint() { - return mClockView.getPaint(); - } - - public int getCurrentTextColor() { - return mClockView.getCurrentTextColor(); - } - - public float getTextSize() { - return mClockView.getTextSize(); - } - - /** - * Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm. - */ - public void refresh() { - if (mClockPlugin != null) { - mClockPlugin.onTimeTick(); - } - } - - /** - * Notifies that the time zone has changed. - */ - public void onTimeZoneChanged(TimeZone timeZone) { - if (mClockPlugin != null) { - mClockPlugin.onTimeZoneChanged(timeZone); - } - } - - /** - * Notifies that the time format has changed. - * - * @param timeFormat "12" for 12-hour format, "24" for 24-hour format - */ - public void onTimeFormatChanged(String timeFormat) { - if (mClockPlugin != null) { - mClockPlugin.onTimeFormatChanged(timeFormat); - } - } - - void updateColors(ColorExtractor.GradientColors colors) { - mSupportsDarkText = colors.supportsDarkText(); - mColorPalette = colors.getColorPalette(); - if (mClockPlugin != null) { - mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette); - } - } - public void dump(PrintWriter pw, String[] args) { pw.println("KeyguardClockSwitch:"); - pw.println(" mClockPlugin: " + mClockPlugin); - pw.println(" mClockFrame: " + mClockFrame); + pw.println(" mClockFrame: " + mSmallClockFrame); pw.println(" mLargeClockFrame: " + mLargeClockFrame); pw.println(" mStatusArea: " + mStatusArea); - pw.println(" mDarkAmount: " + mDarkAmount); - pw.println(" mSupportsDarkText: " + mSupportsDarkText); - pw.println(" mColorPalette: " + Arrays.toString(mColorPalette)); pw.println(" mDisplayedClockSize: " + mDisplayedClockSize); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index ad06e05c2d6e9..dd78f1cef78ca 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -22,8 +22,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static com.android.keyguard.KeyguardClockSwitch.LARGE; import static com.android.keyguard.KeyguardClockSwitch.SMALL; -import android.app.WallpaperManager; -import android.content.res.Resources; import android.database.ContentObserver; import android.os.UserHandle; import android.provider.Settings; @@ -32,36 +30,30 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.LinearLayout; -import android.widget.RelativeLayout; import androidx.annotation.NonNull; -import com.android.internal.colorextraction.ColorExtractor; -import com.android.keyguard.clock.ClockManager; import com.android.systemui.Dumpable; import com.android.systemui.R; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; -import com.android.systemui.plugins.ClockPlugin; +import com.android.systemui.plugins.Clock; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shared.clocks.ClockRegistry; import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; import com.android.systemui.statusbar.notification.AnimatableProperty; import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.stack.AnimationProperties; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationIconContainer; -import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.util.ViewController; import com.android.systemui.util.settings.SecureSettings; import java.io.PrintWriter; import java.util.Locale; -import java.util.TimeZone; import java.util.concurrent.Executor; import javax.inject.Inject; @@ -71,48 +63,24 @@ import javax.inject.Inject; */ public class KeyguardClockSwitchController extends ViewController implements Dumpable { - private static final boolean CUSTOM_CLOCKS_ENABLED = true; - private final StatusBarStateController mStatusBarStateController; - private final SysuiColorExtractor mColorExtractor; - private final ClockManager mClockManager; + private final ClockRegistry mClockRegistry; private final KeyguardSliceViewController mKeyguardSliceViewController; private final NotificationIconAreaController mNotificationIconAreaController; - private final BroadcastDispatcher mBroadcastDispatcher; - private final BatteryController mBatteryController; private final LockscreenSmartspaceController mSmartspaceController; - private final Resources mResources; private final SecureSettings mSecureSettings; private final DumpManager mDumpManager; + private final ClockEventController mClockEventController; - /** - * Clock for both small and large sizes - */ - private AnimatableClockController mClockViewController; - private FrameLayout mClockFrame; // top aligned clock - private AnimatableClockController mLargeClockViewController; + /** Clock frames for both small and large sizes */ + private FrameLayout mSmallClockFrame; // top aligned clock private FrameLayout mLargeClockFrame; // centered clock @KeyguardClockSwitch.ClockSize private int mCurrentClockSize = SMALL; - private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private int mKeyguardClockTopMargin = 0; - - /** - * Listener for changes to the color palette. - * - * The color palette changes when the wallpaper is changed. - */ - private final ColorExtractor.OnColorsChangedListener mColorsListener = - (extractor, which) -> { - if ((which & WallpaperManager.FLAG_LOCK) != 0) { - mView.updateColors(getGradientColors()); - } - }; - - private final ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin; + private final ClockRegistry.ClockChangeListener mClockChangedListener; private ViewGroup mStatusArea; // If set will replace keyguard_slice_view @@ -121,9 +89,9 @@ public class KeyguardClockSwitchController extends ViewController { + setClock(mClockRegistry.createCurrentClock()); + }; } /** @@ -188,40 +154,18 @@ public class KeyguardClockSwitchController extends ViewController { + mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction()); }).start(); - - mKeyguardStatusViewController.animateFoldToAod(); } /** @@ -5814,7 +5802,6 @@ public final class NotificationPanelViewController { public void onDozeAmountChanged(float linearAmount, float amount) { mInterpolatedDarkAmount = amount; mLinearDarkAmount = linearAmount; - mKeyguardStatusViewController.setDarkAmount(mInterpolatedDarkAmount); mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount); positionClockAndNotifications(); } @@ -5930,11 +5917,8 @@ public final class NotificationPanelViewController { updateMaxDisplayedNotifications(!shouldAvoidChangingNotificationsCount()); setIsFullWidth(mNotificationStackScrollLayoutController.getWidth() == mView.getWidth()); - // Update Clock Pivot - mKeyguardStatusViewController.setPivotX(((float) mView.getWidth()) / 2f); - mKeyguardStatusViewController.setPivotY( - (FONT_HEIGHT - CAP_HEIGHT) / 2048f - * mKeyguardStatusViewController.getClockTextSize()); + // Update Clock Pivot (used by anti-burnin transformations) + mKeyguardStatusViewController.updatePivot(mView.getWidth(), mView.getHeight()); // Calculate quick setting heights. int oldMaxHeight = mQsMaxExpansionHeight; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 84bb82beee1cc..ce04fb5999635 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -442,7 +442,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue state |= DISABLE_CLOCK; } - if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) { if (mNetworkController.hasEmergencyCryptKeeperText()) { state |= DISABLE_NOTIFICATION_ICONS; @@ -452,13 +451,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } } - // The shelf will be hidden when dozing with a custom clock, we must show notification - // icons in this occasion. - if (mStatusBarStateController.isDozing() - && mNotificationPanelViewController.hasCustomClock()) { - state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO; - } - if (mOngoingCallController.hasOngoingCall()) { state &= ~DISABLE_ONGOING_CALL_CHIP; } else { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt new file mode 100644 index 0000000000000..4f3995252b544 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -0,0 +1,259 @@ +/* + * 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.keyguard + +import android.content.BroadcastReceiver +import android.testing.AndroidTestingRunner +import android.widget.TextView +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.plugins.Clock +import com.android.systemui.plugins.ClockAnimations +import com.android.systemui.plugins.ClockEvents +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.policy.BatteryController +import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.capture +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.mock +import java.util.TimeZone +import org.junit.Assert.assertEquals +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.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever +import org.mockito.junit.MockitoJUnit + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class ClockEventControllerTest : SysuiTestCase() { + + @JvmField @Rule val mockito = MockitoJUnit.rule() + @Mock private lateinit var statusBarStateController: StatusBarStateController + @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher + @Mock private lateinit var batteryController: BatteryController + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + @Mock private lateinit var configurationController: ConfigurationController + @Mock private lateinit var animations: ClockAnimations + @Mock private lateinit var events: ClockEvents + @Mock private lateinit var clock: Clock + + private lateinit var clockEventController: ClockEventController + + @Before + fun setUp() { + whenever(clock.smallClock).thenReturn(TextView(context)) + whenever(clock.largeClock).thenReturn(TextView(context)) + whenever(clock.events).thenReturn(events) + whenever(clock.animations).thenReturn(animations) + + clockEventController = ClockEventController( + statusBarStateController, + broadcastDispatcher, + batteryController, + keyguardUpdateMonitor, + configurationController, + context.resources, + context + ) + } + + @Test + fun clockSet_validateInitialization() { + clockEventController.clock = clock + + verify(clock).initialize(any(), anyFloat(), anyFloat()) + } + + @Test + fun clockUnset_validateState() { + clockEventController.clock = clock + clockEventController.clock = null + + assertEquals(clockEventController.clock, null) + } + + @Test + fun themeChanged_verifyClockPaletteUpdated() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val captor = argumentCaptor() + verify(configurationController).addCallback(capture(captor)) + captor.value.onThemeChanged() + + verify(events).onColorPaletteChanged(any()) + } + + @Test + fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val batteryCaptor = argumentCaptor() + verify(batteryController).addCallback(capture(batteryCaptor)) + val keyguardCaptor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor)) + keyguardCaptor.value.onKeyguardVisibilityChanged(true) + batteryCaptor.value.onBatteryLevelChanged(10, false, true) + + verify(animations).charge() + } + + @Test + fun batteryCallback_keyguardShowingCharging_Duplicate_verifyChargeAnimation() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val batteryCaptor = argumentCaptor() + verify(batteryController).addCallback(capture(batteryCaptor)) + val keyguardCaptor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor)) + keyguardCaptor.value.onKeyguardVisibilityChanged(true) + batteryCaptor.value.onBatteryLevelChanged(10, false, true) + batteryCaptor.value.onBatteryLevelChanged(10, false, true) + + verify(animations, times(1)).charge() + } + + @Test + fun batteryCallback_keyguardHiddenCharging_verifyChargeAnimation() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val batteryCaptor = argumentCaptor() + verify(batteryController).addCallback(capture(batteryCaptor)) + val keyguardCaptor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor)) + keyguardCaptor.value.onKeyguardVisibilityChanged(false) + batteryCaptor.value.onBatteryLevelChanged(10, false, true) + + verify(animations, never()).charge() + } + + @Test + fun batteryCallback_keyguardShowingNotCharging_verifyChargeAnimation() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val batteryCaptor = argumentCaptor() + verify(batteryController).addCallback(capture(batteryCaptor)) + val keyguardCaptor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor)) + keyguardCaptor.value.onKeyguardVisibilityChanged(true) + batteryCaptor.value.onBatteryLevelChanged(10, false, false) + + verify(animations, never()).charge() + } + + @Test + fun localeCallback_verifyClockNotified() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val captor = argumentCaptor() + verify(broadcastDispatcher).registerReceiver( + capture(captor), any(), eq(null), eq(null), anyInt(), eq(null) + ) + captor.value.onReceive(context, mock()) + + verify(events).onLocaleChanged(any()) + } + + @Test + fun keyguardCallback_visibilityChanged_clockDozeCalled() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val captor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(captor)) + + captor.value.onKeyguardVisibilityChanged(true) + verify(animations, never()).doze(0f) + + captor.value.onKeyguardVisibilityChanged(false) + verify(animations, times(1)).doze(0f) + } + + @Test + fun keyguardCallback_timeFormat_clockNotified() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val captor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(captor)) + captor.value.onTimeFormatChanged("12h") + + verify(events).onTimeFormatChanged(false) + } + + @Test + fun keyguardCallback_timezoneChanged_clockNotified() { + val mockTimeZone = mock() + clockEventController.clock = clock + clockEventController.registerListeners() + + val captor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(captor)) + captor.value.onTimeZoneChanged(mockTimeZone) + + verify(events).onTimeZoneChanged(mockTimeZone) + } + + @Test + fun keyguardCallback_userSwitched_clockNotified() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val captor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(capture(captor)) + captor.value.onUserSwitchComplete(10) + + verify(events).onTimeFormatChanged(false) + } + + @Test + fun keyguardCallback_verifyKeyguardChanged() { + clockEventController.clock = clock + clockEventController.registerListeners() + + val captor = argumentCaptor() + verify(statusBarStateController).addCallback(capture(captor)) + captor.value.onDozeAmountChanged(0.4f, 0.6f) + + verify(animations).doze(0.4f) + } + + @Test + fun unregisterListeners_validate() { + clockEventController.unregisterListeners() + verify(broadcastDispatcher).unregisterReceiver(any()) + verify(configurationController).removeCallback(any()) + verify(batteryController).removeCallback(any()) + verify(keyguardUpdateMonitor).removeCallback(any()) + verify(statusBarStateController).removeCallback(any()) + } +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index b2d9219d44e8e..635ee9ea1a2f5 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -19,7 +19,6 @@ package com.android.keyguard; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -41,24 +40,19 @@ import android.widget.RelativeLayout; import androidx.test.filters.SmallTest; -import com.android.internal.colorextraction.ColorExtractor; -import com.android.keyguard.clock.ClockManager; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; -import com.android.systemui.plugins.ClockPlugin; +import com.android.systemui.plugins.Clock; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.clocks.AnimatableClockView; +import com.android.systemui.shared.clocks.ClockRegistry; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; -import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationIconContainer; -import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.time.FakeSystemClock; @@ -80,22 +74,12 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { @Mock private StatusBarStateController mStatusBarStateController; @Mock - private SysuiColorExtractor mColorExtractor; - @Mock - private ClockManager mClockManager; + private ClockRegistry mClockRegistry; @Mock KeyguardSliceViewController mKeyguardSliceViewController; @Mock NotificationIconAreaController mNotificationIconAreaController; @Mock - BroadcastDispatcher mBroadcastDispatcher; - @Mock - BatteryController mBatteryController; - @Mock - KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @Mock - KeyguardBypassController mBypassController; - @Mock LockscreenSmartspaceController mSmartspaceController; @Mock @@ -103,11 +87,11 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { @Mock KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; @Mock - private ClockPlugin mClockPlugin; - @Mock - ColorExtractor.GradientColors mGradientColors; + private Clock mClock; @Mock DumpManager mDumpManager; + @Mock + ClockEventController mClockEventController; @Mock private NotificationIconContainer mNotificationIcons; @@ -139,8 +123,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { when(mView.getContext()).thenReturn(getContext()); when(mView.getResources()).thenReturn(mResources); - when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView); - when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView); when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame); when(mClockView.getContext()).thenReturn(getContext()); when(mLargeClockView.getContext()).thenReturn(getContext()); @@ -151,23 +133,20 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { mController = new KeyguardClockSwitchController( mView, mStatusBarStateController, - mColorExtractor, - mClockManager, + mClockRegistry, mKeyguardSliceViewController, mNotificationIconAreaController, - mBroadcastDispatcher, - mBatteryController, - mKeyguardUpdateMonitor, mSmartspaceController, mKeyguardUnlockAnimationController, mSecureSettings, mExecutor, - mResources, - mDumpManager + mDumpManager, + mClockEventController, + mFeatureFlags ); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); - when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors); + when(mClockRegistry.createCurrentClock()).thenReturn(mClock); mSliceView = new View(getContext()); when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView); @@ -214,20 +193,20 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { verifyAttachment(times(1)); listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView); - verify(mColorExtractor).removeOnColorsChangedListener( - any(ColorExtractor.OnColorsChangedListener.class)); + verify(mClockEventController).unregisterListeners(); } @Test public void testPluginPassesStatusBarState() { - ArgumentCaptor listenerArgumentCaptor = - ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class); + ArgumentCaptor listenerArgumentCaptor = + ArgumentCaptor.forClass(ClockRegistry.ClockChangeListener.class); mController.init(); - verify(mClockManager).addOnClockChangedListener(listenerArgumentCaptor.capture()); + verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture()); - listenerArgumentCaptor.getValue().onClockChanged(mClockPlugin); - verify(mView).setClockPlugin(mClockPlugin, StatusBarState.SHADE); + listenerArgumentCaptor.getValue().onClockChanged(); + verify(mView, times(2)).setClock(mClock, StatusBarState.SHADE); + verify(mClockEventController, times(2)).setClock(mClock); } @Test @@ -284,10 +263,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { } private void verifyAttachment(VerificationMode times) { - verify(mClockManager, times).addOnClockChangedListener( - any(ClockManager.ClockChangedListener.class)); - verify(mColorExtractor, times).addOnColorsChangedListener( - any(ColorExtractor.OnColorsChangedListener.class)); - verify(mView, times).updateColors(mGradientColors); + verify(mClockRegistry, times).registerClockChangeListener( + any(ClockRegistry.ClockChangeListener.class)); + verify(mClockEventController, times).registerListeners(); } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java index 6c6f0acd70859..a0295d09826f0 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java @@ -16,7 +16,6 @@ package com.android.keyguard; -import static android.view.View.GONE; import static android.view.View.VISIBLE; import static com.android.keyguard.KeyguardClockSwitch.LARGE; @@ -24,56 +23,61 @@ import static com.android.keyguard.KeyguardClockSwitch.SMALL; import static com.google.common.truth.Truth.assertThat; +import static junit.framework.TestCase.assertEquals; + import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; -import android.graphics.Color; -import android.graphics.Paint.Style; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.TextClock; +import android.widget.TextView; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; -import com.android.systemui.plugins.ClockPlugin; -import com.android.systemui.shared.clocks.AnimatableClockView; +import com.android.systemui.plugins.Clock; import com.android.systemui.statusbar.StatusBarState; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) // Need to run on the main thread because KeyguardSliceView$Row init checks for // the main thread before acquiring a wake lock. This class is constructed when -// the keyguard_clcok_switch layout is inflated. +// the keyguard_clock_switch layout is inflated. @RunWithLooper(setAsMainLooper = true) public class KeyguardClockSwitchTest extends SysuiTestCase { - private FrameLayout mClockFrame; - private FrameLayout mLargeClockFrame; - private TextClock mBigClock; + @Mock + ViewGroup mMockKeyguardSliceView; + + @Mock + Clock mClock; + + private FrameLayout mSmallClockFrame; + private FrameLayout mLargeClockFrame; - private AnimatableClockView mClockView; - private AnimatableClockView mLargeClockView; - View mMockKeyguardSliceView; KeyguardClockSwitch mKeyguardClockSwitch; @Before public void setUp() { - mMockKeyguardSliceView = mock(KeyguardSliceView.class); + MockitoAnnotations.initMocks(this); when(mMockKeyguardSliceView.getContext()).thenReturn(mContext); when(mMockKeyguardSliceView.findViewById(R.id.keyguard_status_area)) .thenReturn(mMockKeyguardSliceView); + when(mClock.getSmallClock()).thenReturn(new TextView(getContext())); + when(mClock.getLargeClock()).thenReturn(new TextView(getContext())); + LayoutInflater layoutInflater = LayoutInflater.from(getContext()); layoutInflater.setPrivateFactory(new LayoutInflater.Factory2() { @@ -93,164 +97,68 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { }); mKeyguardClockSwitch = (KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null); - mClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view); - mClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view); + mSmallClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view); mLargeClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view_large); - mLargeClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view_large); - mBigClock = new TextClock(getContext()); mKeyguardClockSwitch.mChildrenAreLaidOut = true; - MockitoAnnotations.initMocks(this); } @Test - public void onPluginConnected_showPluginClock() { - ClockPlugin plugin = mock(ClockPlugin.class); - TextClock pluginView = new TextClock(getContext()); - when(plugin.getView()).thenReturn(pluginView); - - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - - assertThat(mClockView.getVisibility()).isEqualTo(GONE); - assertThat(plugin.getView().getParent()).isEqualTo(mClockFrame); + public void noPluginConnected_showNothing() { + mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD); + assertEquals(mLargeClockFrame.getChildCount(), 0); + assertEquals(mSmallClockFrame.getChildCount(), 0); } @Test - public void onPluginConnected_showPluginBigClock() { - // GIVEN the plugin returns a view for the big clock - ClockPlugin plugin = mock(ClockPlugin.class); - when(plugin.getBigClockView()).thenReturn(mBigClock); - // WHEN the plugin is connected - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - // THEN the big clock container is visible and it is the parent of the - // big clock view. - assertThat(mLargeClockView.getVisibility()).isEqualTo(View.GONE); - assertThat(mBigClock.getParent()).isEqualTo(mLargeClockFrame); + public void pluginConnectedThenDisconnected_showNothing() { + mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD); + assertEquals(mLargeClockFrame.getChildCount(), 1); + assertEquals(mSmallClockFrame.getChildCount(), 1); + + mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD); + assertEquals(mLargeClockFrame.getChildCount(), 0); + assertEquals(mSmallClockFrame.getChildCount(), 0); } @Test - public void onPluginConnected_nullView() { - ClockPlugin plugin = mock(ClockPlugin.class); - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE); + public void onPluginConnected_showClock() { + mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD); + + assertEquals(mClock.getSmallClock().getParent(), mSmallClockFrame); + assertEquals(mClock.getLargeClock().getParent(), mLargeClockFrame); } @Test public void onPluginConnected_showSecondPluginClock() { // GIVEN a plugin has already connected - ClockPlugin plugin1 = mock(ClockPlugin.class); - when(plugin1.getView()).thenReturn(new TextClock(getContext())); - mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD); - // WHEN a second plugin is connected - ClockPlugin plugin2 = mock(ClockPlugin.class); - when(plugin2.getView()).thenReturn(new TextClock(getContext())); - mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD); + Clock otherClock = mock(Clock.class); + when(otherClock.getSmallClock()).thenReturn(new TextView(getContext())); + when(otherClock.getLargeClock()).thenReturn(new TextView(getContext())); + mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD); + mKeyguardClockSwitch.setClock(otherClock, StatusBarState.KEYGUARD); + // THEN only the view from the second plugin should be a child of KeyguardClockSwitch. - assertThat(plugin2.getView().getParent()).isEqualTo(mClockFrame); - assertThat(plugin1.getView().getParent()).isNull(); - } - - @Test - public void onPluginConnected_darkAmountInitialized() { - // GIVEN that the dark amount has already been set - mKeyguardClockSwitch.setDarkAmount(0.5f); - // WHEN a plugin is connected - ClockPlugin plugin = mock(ClockPlugin.class); - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - // THEN dark amount should be initalized on the plugin. - verify(plugin).setDarkAmount(0.5f); - } - - @Test - public void onPluginDisconnected_showDefaultClock() { - ClockPlugin plugin = mock(ClockPlugin.class); - TextClock pluginView = new TextClock(getContext()); - when(plugin.getView()).thenReturn(pluginView); - - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - assertThat(mClockView.getVisibility()).isEqualTo(GONE); - - mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD); - assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE); - - assertThat(plugin.getView().getParent()).isNull(); - } - - @Test - public void onPluginDisconnected_hidePluginBigClock() { - // GIVEN the plugin returns a view for the big clock - ClockPlugin plugin = mock(ClockPlugin.class); - TextClock pluginView = new TextClock(getContext()); - when(plugin.getBigClockView()).thenReturn(pluginView); - // WHEN the plugin is connected and then disconnected - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD); - // THEN the big lock container is GONE and the big clock view doesn't have - // a parent. - assertThat(mLargeClockView.getVisibility()).isEqualTo(VISIBLE); - assertThat(pluginView.getParent()).isNull(); - } - - @Test - public void onPluginDisconnected_nullView() { - ClockPlugin plugin = mock(ClockPlugin.class); - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD); - assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE); + assertThat(otherClock.getSmallClock().getParent()).isEqualTo(mSmallClockFrame); + assertThat(otherClock.getLargeClock().getParent()).isEqualTo(mLargeClockFrame); + assertThat(mClock.getSmallClock().getParent()).isNull(); + assertThat(mClock.getLargeClock().getParent()).isNull(); } @Test public void onPluginDisconnected_secondOfTwoDisconnected() { // GIVEN two plugins are connected - ClockPlugin plugin1 = mock(ClockPlugin.class); - when(plugin1.getView()).thenReturn(new TextClock(getContext())); - mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD); - ClockPlugin plugin2 = mock(ClockPlugin.class); - when(plugin2.getView()).thenReturn(new TextClock(getContext())); - mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD); + Clock otherClock = mock(Clock.class); + when(otherClock.getSmallClock()).thenReturn(new TextView(getContext())); + when(otherClock.getLargeClock()).thenReturn(new TextView(getContext())); + mKeyguardClockSwitch.setClock(otherClock, StatusBarState.KEYGUARD); + mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD); // WHEN the second plugin is disconnected - mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD); - // THEN the default clock should be shown. - assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE); - assertThat(plugin1.getView().getParent()).isNull(); - assertThat(plugin2.getView().getParent()).isNull(); - } - - @Test - public void onPluginDisconnected_onDestroyView() { - // GIVEN a plugin is connected - ClockPlugin clockPlugin = mock(ClockPlugin.class); - when(clockPlugin.getView()).thenReturn(new TextClock(getContext())); - mKeyguardClockSwitch.setClockPlugin(clockPlugin, StatusBarState.KEYGUARD); - // WHEN the plugin is disconnected - mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD); - // THEN onDestroyView is called on the plugin - verify(clockPlugin).onDestroyView(); - } - - @Test - public void setTextColor_pluginClockSetTextColor() { - ClockPlugin plugin = mock(ClockPlugin.class); - TextClock pluginView = new TextClock(getContext()); - when(plugin.getView()).thenReturn(pluginView); - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - - mKeyguardClockSwitch.setTextColor(Color.WHITE); - - verify(plugin).setTextColor(Color.WHITE); - } - - - @Test - public void setStyle_pluginClockSetStyle() { - ClockPlugin plugin = mock(ClockPlugin.class); - TextClock pluginView = new TextClock(getContext()); - when(plugin.getView()).thenReturn(pluginView); - Style style = mock(Style.class); - mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD); - - mKeyguardClockSwitch.setStyle(style); - - verify(plugin).setStyle(style); + mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD); + // THEN nothing should be shown + assertThat(otherClock.getSmallClock().getParent()).isNull(); + assertThat(otherClock.getLargeClock().getParent()).isNull(); + assertThat(mClock.getSmallClock().getParent()).isNull(); + assertThat(mClock.getLargeClock().getParent()).isNull(); } @Test @@ -262,7 +170,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1); assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE); - assertThat(mClockFrame.getAlpha()).isEqualTo(0); + assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0); } @Test @@ -271,7 +179,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1); assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE); - assertThat(mClockFrame.getAlpha()).isEqualTo(0); + assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0); } @Test @@ -281,8 +189,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { mKeyguardClockSwitch.mClockInAnim.end(); mKeyguardClockSwitch.mClockOutAnim.end(); - assertThat(mClockFrame.getAlpha()).isEqualTo(1); - assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE); + assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1); + assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE); // only big clock is removed at switch assertThat(mLargeClockFrame.getParent()).isNull(); assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0); @@ -292,8 +200,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { public void switchingToSmallClockNoAnimation_makesBigClockDisappear() { mKeyguardClockSwitch.switchToClock(SMALL, false); - assertThat(mClockFrame.getAlpha()).isEqualTo(1); - assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE); + assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1); + assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE); // only big clock is removed at switch assertThat(mLargeClockFrame.getParent()).isNull(); assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt index 1cbb8d00cb21e..131eac668af3b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt @@ -130,13 +130,16 @@ class ClockRegistryTest : SysuiTestCase() { pluginListener.onPluginConnected(plugin1, mockContext) pluginListener.onPluginConnected(plugin2, mockContext) val list = registry.getClocks() - assertEquals(list, listOf( - ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME), - ClockMetadata("clock_1", "clock 1"), - ClockMetadata("clock_2", "clock 2"), - ClockMetadata("clock_3", "clock 3"), - ClockMetadata("clock_4", "clock 4") - )) + assertEquals( + list, + listOf( + ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME), + ClockMetadata("clock_1", "clock 1"), + ClockMetadata("clock_2", "clock 2"), + ClockMetadata("clock_3", "clock 3"), + ClockMetadata("clock_4", "clock 4") + ) + ) } @Test @@ -158,11 +161,14 @@ class ClockRegistryTest : SysuiTestCase() { pluginListener.onPluginConnected(plugin1, mockContext) pluginListener.onPluginConnected(plugin2, mockContext) val list = registry.getClocks() - assertEquals(list, listOf( - ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME), - ClockMetadata("clock_1", "clock 1"), - ClockMetadata("clock_2", "clock 2") - )) + assertEquals( + list, + listOf( + ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME), + ClockMetadata("clock_1", "clock 1"), + ClockMetadata("clock_2", "clock 2") + ) + ) assertEquals(registry.createExampleClock("clock_1"), mockClock) assertEquals(registry.createExampleClock("clock_2"), mockClock) @@ -222,7 +228,7 @@ class ClockRegistryTest : SysuiTestCase() { pluginListener.onPluginConnected(plugin2, mockContext) var changeCallCount = 0 - registry.registerClockChangeListener({ changeCallCount++ }) + registry.registerClockChangeListener { changeCallCount++ } pluginListener.onPluginDisconnected(plugin1) assertEquals(0, changeCallCount) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 20bf50e41f49d..37c8f6285970c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -333,10 +333,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { } @Test - public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() { + public void disable_isDozing_clockAndSystemInfoVisible() { CollapsedStatusBarFragment fragment = resumeAndGetFragment(); when(mStatusBarStateController.isDozing()).thenReturn(true); - when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false); fragment.disable(DEFAULT_DISPLAY, 0, 0, false); @@ -345,10 +344,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { } @Test - public void disable_customClockButNotDozing_clockAndSystemInfoVisible() { + public void disable_NotDozing_clockAndSystemInfoVisible() { CollapsedStatusBarFragment fragment = resumeAndGetFragment(); when(mStatusBarStateController.isDozing()).thenReturn(false); - when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true); fragment.disable(DEFAULT_DISPLAY, 0, 0, false); @@ -356,40 +354,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { assertEquals(View.VISIBLE, getClockView().getVisibility()); } - @Test - public void disable_dozingAndCustomClock_clockAndSystemInfoHidden() { - CollapsedStatusBarFragment fragment = resumeAndGetFragment(); - when(mStatusBarStateController.isDozing()).thenReturn(true); - when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true); - - // Make sure they start out as visible - assertEquals(View.VISIBLE, getEndSideContentView().getVisibility()); - assertEquals(View.VISIBLE, getClockView().getVisibility()); - - fragment.disable(DEFAULT_DISPLAY, 0, 0, false); - - assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility()); - assertEquals(View.GONE, getClockView().getVisibility()); - } - - @Test - public void onDozingChanged_clockAndSystemInfoVisibilitiesUpdated() { - CollapsedStatusBarFragment fragment = resumeAndGetFragment(); - when(mStatusBarStateController.isDozing()).thenReturn(true); - when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true); - - // Make sure they start out as visible - assertEquals(View.VISIBLE, getEndSideContentView().getVisibility()); - assertEquals(View.VISIBLE, getClockView().getVisibility()); - - fragment.onDozingChanged(true); - - // When this callback is triggered, we want to make sure the clock and system info - // visibilities are recalculated. Since dozing=true, they shouldn't be visible. - assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility()); - assertEquals(View.GONE, getClockView().getVisibility()); - } - @Test public void disable_headsUpShouldBeVisibleTrue_clockDisabled() { CollapsedStatusBarFragment fragment = resumeAndGetFragment(); From 13c1e7eff3b468176400ccfa17be8842f3143566 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 21 Jun 2022 20:04:17 +0000 Subject: [PATCH 2/7] [DO NOT MERGE] Adding Region Sampler to Animatable Clocks A RegionSamplingHelper is used to extract the color of the wallpaper behind an AnimatableClockController. This is used to set the color of the clock to a contrasting hue so that the text is legible. These changes fixes the problem of the clock text blending into the wallpaper. Bug: 202758428 Test: atest AnimatableClockControllerTest Change-Id: I645c2a0b4e68d5ec9165a2eb354f6d814acbf596 Merged-In: I645c2a0b4e68d5ec9165a2eb354f6d814acbf596 --- .../keyguard/AnimatableClockController.java | 69 ++++++++++++++++++- .../AnimatableClockControllerTest.java | 14 +++- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java index dd69f334c783e..6064be94bc0a2 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java @@ -22,7 +22,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.graphics.Color; +import android.graphics.Rect; import android.icu.text.NumberFormat; +import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -30,16 +32,24 @@ import androidx.annotation.VisibleForTesting; import com.android.settingslib.Utils; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.clocks.AnimatableClockView; +import com.android.systemui.shared.navigationbar.RegionSamplingHelper; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.util.ViewController; import java.io.PrintWriter; import java.util.Locale; import java.util.Objects; +import java.util.Optional; import java.util.TimeZone; +import java.util.concurrent.Executor; + +import javax.inject.Inject; /** * Controller for an AnimatableClockView on the keyguard. Instantiated by @@ -54,7 +64,10 @@ public class AnimatableClockController extends ViewController mRegionSamplingHelper = Optional.empty(); + private Rect mSamplingBounds = new Rect(); private int mLockScreenColor; + private final boolean mRegionSamplingEnabled; private boolean mIsDozing; private boolean mIsCharging; @@ -67,13 +80,17 @@ public class AnimatableClockController extends ViewController { + regionSamplingHelper.setWindowVisible(true); + }); } private void reset() { @@ -169,6 +220,10 @@ public class AnimatableClockController extends ViewController { + regionSamplingHelper.start(mSamplingBounds); + }); + mView.onTimeZoneChanged(TimeZone.getDefault()); initColors(); mView.animateDoze(mIsDozing, false); @@ -180,6 +235,9 @@ public class AnimatableClockController extends ViewController { + regionSamplingHelper.stop(); + }); } /** Animate the clock appearance */ @@ -223,8 +281,10 @@ public class AnimatableClockController extends ViewController { + regionSamplingHelper.dump(pw); + }); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java index df506b479b88a..b5e9e8decb4c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java @@ -38,6 +38,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.Utils; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.clocks.AnimatableClockView; import com.android.systemui.statusbar.policy.BatteryController; @@ -53,6 +54,8 @@ import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; +import java.util.concurrent.Executor; + @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @@ -69,6 +72,12 @@ public class AnimatableClockControllerTest extends SysuiTestCase { private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock private Resources mResources; + @Mock + private Executor mMainExecutor; + @Mock + private Executor mBgExecutor; + @Mock + private FeatureFlags mFeatureFlags; private MockitoSession mStaticMockSession; private AnimatableClockController mAnimatableClockController; @@ -96,7 +105,10 @@ public class AnimatableClockControllerTest extends SysuiTestCase { mBroadcastDispatcher, mBatteryController, mKeyguardUpdateMonitor, - mResources + mResources, + mMainExecutor, + mBgExecutor, + mFeatureFlags ); mAnimatableClockController.init(); captureAttachListener(); From 417feefd5f163d3c35fa1ae5a21959bfe3220318 Mon Sep 17 00:00:00 2001 From: Grace Date: Wed, 29 Jun 2022 22:58:01 +0000 Subject: [PATCH 3/7] [DO NOT MERGE] Moving Text Protection to Clock Event Controller This change moves text protection from the Animatable Clock Controller to the Clock Event Controller. Bug: 202758428 Fixes: 241260493 Test: atest ClockEventControllerTest Change-Id: I33b8f69c1a5b7b915bb020be16593ef68c46281d Merged-In: I33b8f69c1a5b7b915bb020be16593ef68c46281d --- .../systemui/plugins/ClockProviderPlugin.kt | 21 ++- .../shared/clocks/DefaultClockProvider.kt | 31 ++++- .../android/keyguard/ClockEventController.kt | 120 ++++++++++++++++-- .../keyguard/ClockEventControllerTest.kt | 12 +- 4 files changed, 166 insertions(+), 18 deletions(-) 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 cafdc86761733..4889dbd239133 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt @@ -61,7 +61,11 @@ interface Clock { /** Initializes various rendering parameters. If never called, provides reasonable defaults. */ fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) { - events.onColorPaletteChanged(resources) + events.onColorPaletteChanged( + resources, + ClockDarkness.DEFAULT, + ClockDarkness.DEFAULT + ) animations.doze(dozeFraction) animations.fold(foldFraction) events.onTimeTick() @@ -89,7 +93,11 @@ interface ClockEvents { fun onFontSettingChanged() { } /** Call whenever the color palette should update */ - fun onColorPaletteChanged(resources: Resources) { } + fun onColorPaletteChanged( + resources: Resources, + smallClockIsDark: ClockDarkness, + largeClockIsDark: ClockDarkness + ) { } } /** Methods which trigger various clock animations */ @@ -112,3 +120,12 @@ data class ClockMetadata( val clockId: ClockId, val name: String ) + +/** + * Enum for whether clock region is dark or light. + */ +enum class ClockDarkness(val isDark: Boolean) { + DEFAULT(true), + DARK(true), + LIGHT(false) +} 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 1d8abe3fdf420..b95e52dce2087 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 @@ -22,6 +22,7 @@ import android.view.LayoutInflater import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.Clock import com.android.systemui.plugins.ClockAnimations +import com.android.systemui.plugins.ClockDarkness import com.android.systemui.plugins.ClockEvents import com.android.systemui.plugins.ClockId import com.android.systemui.plugins.ClockMetadata @@ -68,8 +69,8 @@ class DefaultClockProvider @Inject constructor( * AnimatableClockView used by the existing lockscreen clock. */ class DefaultClock( - private val layoutInflater: LayoutInflater, - private val resources: Resources + private val layoutInflater: LayoutInflater, + private val resources: Resources ) : Clock { override val smallClock = layoutInflater.inflate(R.layout.clock_default_small, null) as AnimatableClockView @@ -83,6 +84,16 @@ 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 fun updateClockColor(clock: AnimatableClockView, darkValue: ClockDarkness) { + val color = if (darkValue.isDark) { + resources.getColor(android.R.color.system_accent2_600) + } else { + resources.getColor(android.R.color.system_accent1_100) + } + clock.setColors(DOZE_COLOR, color) + clock.animateAppearOnLockscreen() + } + override val events = object : ClockEvents { override fun onTimeTick() = clocks.forEach { it.refreshTime() } @@ -104,9 +115,13 @@ class DefaultClock( recomputePadding() } - override fun onColorPaletteChanged(resources: Resources) { - val color = resources.getColor(android.R.color.system_accent1_100) - clocks.forEach { it.setColors(DOZE_COLOR, color) } + override fun onColorPaletteChanged( + resources: Resources, + smallClockIsDark: ClockDarkness, + largeClockIsDark: ClockDarkness + ) { + updateClockColor(smallClock, smallClockIsDark) + updateClockColor(largeClock, largeClockIsDark) } override fun onLocaleChanged(locale: Locale) { @@ -187,7 +202,11 @@ class DefaultClock( override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) { recomputePadding() animations = DefaultClockAnimations(dozeFraction, foldFraction) - events.onColorPaletteChanged(resources) + events.onColorPaletteChanged( + resources, + ClockDarkness.DEFAULT, + ClockDarkness.DEFAULT + ) events.onTimeTick() } diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index efd7bcf10cd21..1e62b9c3abb39 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -20,17 +20,24 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.res.Resources +import android.graphics.Rect import android.text.format.DateFormat +import android.view.View import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.flags.FeatureFlags import com.android.systemui.plugins.Clock +import com.android.systemui.plugins.ClockDarkness import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.shared.navigationbar.RegionSamplingHelper import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback import com.android.systemui.statusbar.policy.ConfigurationController import java.io.PrintWriter import java.util.Locale import java.util.TimeZone +import java.util.concurrent.Executor import javax.inject.Inject /** @@ -38,13 +45,16 @@ import javax.inject.Inject * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController]. */ class ClockEventController @Inject constructor( - private val statusBarStateController: StatusBarStateController, - private val broadcastDispatcher: BroadcastDispatcher, - private val batteryController: BatteryController, - private val keyguardUpdateMonitor: KeyguardUpdateMonitor, - private val configurationController: ConfigurationController, - @Main private val resources: Resources, - private val context: Context + private val statusBarStateController: StatusBarStateController, + private val broadcastDispatcher: BroadcastDispatcher, + private val batteryController: BatteryController, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val configurationController: ConfigurationController, + @Main private val resources: Resources, + private val context: Context, + @Main private val mainExecutor: Executor, + @Background private val bgExecutor: Executor, + private val featureFlags: FeatureFlags ) { var clock: Clock? = null set(value) { @@ -61,9 +71,94 @@ class ClockEventController @Inject constructor( private var dozeAmount = 0f private var isKeyguardShowing = false + private var smallClockIsDark = ClockDarkness.DEFAULT + private var largeClockIsDark = ClockDarkness.DEFAULT + private var smallSamplingBounds = Rect() + private var largeSamplingBounds = Rect() + + private val regionSamplingEnabled = + featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING) + + private fun setClockDarkness(isRegionDark: Boolean): ClockDarkness { + return if (isRegionDark) { + ClockDarkness.DARK + } else { + ClockDarkness.LIGHT + } + } + + // TODO: Abstract out the creation of RegionSampler and its fields + var smallRegionSampling: RegionSamplingHelper? = + if (!regionSamplingEnabled || clock == null) { + null + } else { + RegionSamplingHelper(clock?.smallClock, + object : RegionSamplingHelper.SamplingCallback { + override fun onRegionDarknessChanged(isRegionDark: Boolean) { + smallClockIsDark = setClockDarkness(isRegionDark) + clock?.events?.onColorPaletteChanged( + resources, + smallClockIsDark, + largeClockIsDark + ) + } + + override fun getSampledRegion(sampledView: View): Rect { + smallSamplingBounds = Rect( + sampledView.left, + sampledView.top, + sampledView.right, + sampledView.bottom + ) + return smallSamplingBounds + } + + override fun isSamplingEnabled(): Boolean { + return regionSamplingEnabled + } + }, + mainExecutor, bgExecutor) + } + + var largeRegionSampling: RegionSamplingHelper? = + if (!regionSamplingEnabled || clock == null) { + null + } else { + RegionSamplingHelper(clock?.largeClock, + object : RegionSamplingHelper.SamplingCallback { + override fun onRegionDarknessChanged(isRegionDark: Boolean) { + largeClockIsDark = setClockDarkness(isRegionDark) + clock?.events?.onColorPaletteChanged( + resources, + smallClockIsDark, + largeClockIsDark + ) + } + + override fun getSampledRegion(sampledView: View): Rect { + largeSamplingBounds = Rect( + sampledView.left, + sampledView.top, + sampledView.right, + sampledView.bottom + ) + return largeSamplingBounds + } + + override fun isSamplingEnabled(): Boolean { + return regionSamplingEnabled + } + }, + mainExecutor, bgExecutor) + } + private val configListener = object : ConfigurationController.ConfigurationListener { override fun onThemeChanged() { - clock?.events?.onColorPaletteChanged(resources) + clock?.events?.onColorPaletteChanged( + resources, + smallClockIsDark, + largeClockIsDark + ) } } @@ -114,6 +209,9 @@ class ClockEventController @Inject constructor( init { isDozing = statusBarStateController.isDozing + smallRegionSampling?.setWindowVisible(true) + largeRegionSampling?.setWindowVisible(true) + clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark) } fun registerListeners() { @@ -128,6 +226,8 @@ class ClockEventController @Inject constructor( batteryController.addCallback(batteryCallback) keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) statusBarStateController.addCallback(statusBarStateListener) + smallRegionSampling?.start(smallSamplingBounds) + largeRegionSampling?.start(largeSamplingBounds) } fun unregisterListeners() { @@ -136,6 +236,8 @@ class ClockEventController @Inject constructor( batteryController.removeCallback(batteryCallback) keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback) statusBarStateController.removeCallback(statusBarStateListener) + smallRegionSampling?.stop() + largeRegionSampling?.stop() } /** @@ -144,6 +246,8 @@ class ClockEventController @Inject constructor( fun dump(pw: PrintWriter) { pw.println(this) clock?.dump(pw) + smallRegionSampling?.dump(pw) + largeRegionSampling?.dump(pw) } companion object { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index 4f3995252b544..802194464b62c 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -21,6 +21,7 @@ import android.widget.TextView import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.flags.FeatureFlags import com.android.systemui.plugins.Clock import com.android.systemui.plugins.ClockAnimations import com.android.systemui.plugins.ClockEvents @@ -33,6 +34,7 @@ import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import java.util.TimeZone +import java.util.concurrent.Executor import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Rule @@ -60,6 +62,9 @@ class ClockEventControllerTest : SysuiTestCase() { @Mock private lateinit var animations: ClockAnimations @Mock private lateinit var events: ClockEvents @Mock private lateinit var clock: Clock + @Mock private lateinit var mainExecutor: Executor + @Mock private lateinit var bgExecutor: Executor + @Mock private lateinit var featureFlags: FeatureFlags private lateinit var clockEventController: ClockEventController @@ -77,7 +82,10 @@ class ClockEventControllerTest : SysuiTestCase() { keyguardUpdateMonitor, configurationController, context.resources, - context + context, + mainExecutor, + bgExecutor, + featureFlags ) } @@ -105,7 +113,7 @@ class ClockEventControllerTest : SysuiTestCase() { verify(configurationController).addCallback(capture(captor)) captor.value.onThemeChanged() - verify(events).onColorPaletteChanged(any()) + verify(events).onColorPaletteChanged(any(), any(), any()) } @Test From a724e0b753f710aef22c786bb089d3c8f7d7970a Mon Sep 17 00:00:00 2001 From: Grace Date: Mon, 11 Jul 2022 21:03:24 +0000 Subject: [PATCH 4/7] [DO NOT MERGE] 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 --- .../systemui/plugins/ClockProviderPlugin.kt | 19 +-- .../shared/clocks/DefaultClockProvider.kt | 23 +-- .../android/keyguard/ClockEventController.kt | 148 ++++++++---------- .../keyguard/ClockEventControllerTest.kt | 5 +- 4 files changed, 81 insertions(+), 114 deletions(-) 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 4889dbd239133..01e5d86549ebd 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt @@ -61,11 +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, - ClockDarkness.DEFAULT, - ClockDarkness.DEFAULT - ) + events.onColorPaletteChanged(resources, true, true) animations.doze(dozeFraction) animations.fold(foldFraction) events.onTimeTick() @@ -95,8 +91,8 @@ interface ClockEvents { /** Call whenever the color palette should update */ fun onColorPaletteChanged( resources: Resources, - smallClockIsDark: ClockDarkness, - largeClockIsDark: ClockDarkness + smallClockIsDark: Boolean, + largeClockIsDark: Boolean ) { } } @@ -120,12 +116,3 @@ data class ClockMetadata( val clockId: ClockId, val name: String ) - -/** - * Enum for whether clock region is dark or light. - */ -enum class ClockDarkness(val isDark: Boolean) { - DEFAULT(true), - DARK(true), - LIGHT(false) -} 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 b95e52dce2087..d881cd1e24154 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 @@ -22,7 +22,6 @@ import android.view.LayoutInflater import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.Clock import com.android.systemui.plugins.ClockAnimations -import com.android.systemui.plugins.ClockDarkness import com.android.systemui.plugins.ClockEvents import com.android.systemui.plugins.ClockId import com.android.systemui.plugins.ClockMetadata @@ -84,11 +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 fun updateClockColor(clock: AnimatableClockView, darkValue: ClockDarkness) { - val color = if (darkValue.isDark) { - resources.getColor(android.R.color.system_accent2_600) - } else { + 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_accent2_600) } clock.setColors(DOZE_COLOR, color) clock.animateAppearOnLockscreen() @@ -117,8 +116,8 @@ class DefaultClock( override fun onColorPaletteChanged( resources: Resources, - smallClockIsDark: ClockDarkness, - largeClockIsDark: ClockDarkness + smallClockIsDark: Boolean, + largeClockIsDark: Boolean ) { updateClockColor(smallClock, smallClockIsDark) updateClockColor(largeClock, largeClockIsDark) @@ -199,13 +198,17 @@ class DefaultClock( clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) } } - override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) { + override fun initialize( + resources: Resources, + dozeFraction: Float, + foldFraction: Float + ) { recomputePadding() animations = DefaultClockAnimations(dozeFraction, foldFraction) events.onColorPaletteChanged( resources, - ClockDarkness.DEFAULT, - ClockDarkness.DEFAULT + true, + true ) events.onTimeTick() } diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 1e62b9c3abb39..0e1e0cb2adcf0 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -20,17 +20,16 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.res.Resources -import android.graphics.Rect 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 import com.android.systemui.flags.FeatureFlags import com.android.systemui.plugins.Clock -import com.android.systemui.plugins.ClockDarkness import com.android.systemui.plugins.statusbar.StatusBarStateController -import com.android.systemui.shared.navigationbar.RegionSamplingHelper +import com.android.systemui.shared.regionsampling.RegionSamplingInstance import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback import com.android.systemui.statusbar.policy.ConfigurationController @@ -44,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, @@ -61,6 +60,7 @@ class ClockEventController @Inject constructor( field = value if (value != null) { value.initialize(resources, dozeAmount, 0f) + updateRegionSamplers(value) } } @@ -71,94 +71,71 @@ class ClockEventController @Inject constructor( private var dozeAmount = 0f private var isKeyguardShowing = false - private var smallClockIsDark = ClockDarkness.DEFAULT - private var largeClockIsDark = ClockDarkness.DEFAULT - private var smallSamplingBounds = Rect() - private var largeSamplingBounds = Rect() - private val regionSamplingEnabled = featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING) - private fun setClockDarkness(isRegionDark: Boolean): ClockDarkness { - return if (isRegionDark) { - ClockDarkness.DARK - } else { - ClockDarkness.LIGHT + private val updateFun = object : RegionSamplingInstance.UpdateColorCallback { + override fun updateColors() { + 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) } } - // TODO: Abstract out the creation of RegionSampler and its fields - var smallRegionSampling: RegionSamplingHelper? = - if (!regionSamplingEnabled || clock == null) { - null - } else { - RegionSamplingHelper(clock?.smallClock, - object : RegionSamplingHelper.SamplingCallback { - override fun onRegionDarknessChanged(isRegionDark: Boolean) { - smallClockIsDark = setClockDarkness(isRegionDark) - clock?.events?.onColorPaletteChanged( - resources, - smallClockIsDark, - largeClockIsDark - ) - } + fun updateRegionSamplers(currentClock: Clock?) { + smallRegionSamplingInstance = createRegionSampler( + currentClock?.smallClock, + mainExecutor, + bgExecutor, + regionSamplingEnabled, + updateFun + ) - override fun getSampledRegion(sampledView: View): Rect { - smallSamplingBounds = Rect( - sampledView.left, - sampledView.top, - sampledView.right, - sampledView.bottom - ) - return smallSamplingBounds - } + largeRegionSamplingInstance = createRegionSampler( + currentClock?.largeClock, + mainExecutor, + bgExecutor, + regionSamplingEnabled, + updateFun + ) - override fun isSamplingEnabled(): Boolean { - return regionSamplingEnabled - } - }, - mainExecutor, bgExecutor) - } + smallRegionSamplingInstance.startRegionSampler() + largeRegionSamplingInstance.startRegionSampler() - var largeRegionSampling: RegionSamplingHelper? = - if (!regionSamplingEnabled || clock == null) { - null - } else { - RegionSamplingHelper(clock?.largeClock, - object : RegionSamplingHelper.SamplingCallback { - override fun onRegionDarknessChanged(isRegionDark: Boolean) { - largeClockIsDark = setClockDarkness(isRegionDark) - clock?.events?.onColorPaletteChanged( - resources, - smallClockIsDark, - largeClockIsDark - ) - } + updateFun.updateColors() + } - override fun getSampledRegion(sampledView: View): Rect { - largeSamplingBounds = Rect( - sampledView.left, - sampledView.top, - sampledView.right, - sampledView.bottom - ) - return largeSamplingBounds - } + protected open fun createRegionSampler( + sampledView: View?, + mainExecutor: Executor?, + bgExecutor: Executor?, + regionSamplingEnabled: Boolean, + updateFun: RegionSamplingInstance.UpdateColorCallback + ): RegionSamplingInstance { + return RegionSamplingInstance( + sampledView, + mainExecutor, + bgExecutor, + regionSamplingEnabled, + updateFun) + } - override fun isSamplingEnabled(): Boolean { - return regionSamplingEnabled - } - }, - mainExecutor, bgExecutor) - } + lateinit var smallRegionSamplingInstance: RegionSamplingInstance + lateinit var largeRegionSamplingInstance: RegionSamplingInstance + + private var smallClockIsDark = true + private var largeClockIsDark = true private val configListener = object : ConfigurationController.ConfigurationListener { override fun onThemeChanged() { - clock?.events?.onColorPaletteChanged( - resources, - smallClockIsDark, - largeClockIsDark - ) + updateFun.updateColors() } } @@ -209,9 +186,6 @@ class ClockEventController @Inject constructor( init { isDozing = statusBarStateController.isDozing - smallRegionSampling?.setWindowVisible(true) - largeRegionSampling?.setWindowVisible(true) - clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark) } fun registerListeners() { @@ -226,8 +200,8 @@ class ClockEventController @Inject constructor( batteryController.addCallback(batteryCallback) keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) statusBarStateController.addCallback(statusBarStateListener) - smallRegionSampling?.start(smallSamplingBounds) - largeRegionSampling?.start(largeSamplingBounds) + smallRegionSamplingInstance.startRegionSampler() + largeRegionSamplingInstance.startRegionSampler() } fun unregisterListeners() { @@ -236,8 +210,8 @@ class ClockEventController @Inject constructor( batteryController.removeCallback(batteryCallback) keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback) statusBarStateController.removeCallback(statusBarStateListener) - smallRegionSampling?.stop() - largeRegionSampling?.stop() + smallRegionSamplingInstance.stopRegionSampler() + largeRegionSamplingInstance.stopRegionSampler() } /** @@ -246,8 +220,8 @@ class ClockEventController @Inject constructor( fun dump(pw: PrintWriter) { pw.println(this) clock?.dump(pw) - smallRegionSampling?.dump(pw) - largeRegionSampling?.dump(pw) + smallRegionSamplingInstance.dump(pw) + largeRegionSamplingInstance.dump(pw) } companion object { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index 802194464b62c..914d94522e83f 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -107,13 +107,15 @@ class ClockEventControllerTest : SysuiTestCase() { @Test fun themeChanged_verifyClockPaletteUpdated() { clockEventController.clock = clock + verify(events).onColorPaletteChanged(any(), any(), any()) + clockEventController.registerListeners() val captor = argumentCaptor() verify(configurationController).addCallback(capture(captor)) captor.value.onThemeChanged() - verify(events).onColorPaletteChanged(any(), any(), any()) + verify(events, times(2)).onColorPaletteChanged(any(), any(), any()) } @Test @@ -257,6 +259,7 @@ class ClockEventControllerTest : SysuiTestCase() { @Test fun unregisterListeners_validate() { + clockEventController.clock = clock clockEventController.unregisterListeners() verify(broadcastDispatcher).unregisterReceiver(any()) verify(configurationController).removeCallback(any()) From a823b466cc4f69446eb070303a1ee735d40c0c73 Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Wed, 24 Aug 2022 16:24:18 +0000 Subject: [PATCH 5/7] [DO NOT MERGE] 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 --- .../shared/clocks/AnimatableClockView.kt | 22 ++--- .../shared/clocks/DefaultClockProvider.kt | 3 +- .../shared/clocks/DefaultClockProviderTest.kt | 90 +++++++++++++++++-- 3 files changed, 99 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 580d45375afb2..b3b75f68e71e8 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 @@ -218,7 +220,7 @@ class AnimatableClockView @JvmOverloads constructor( } fun animateAppearOnLockscreen() { - if (textAnimator == null) { + if (isAnimationEnabled && textAnimator == null) { return } setTextStyle( @@ -234,7 +236,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = lockScreenWeight, textSize = -1f, color = lockScreenColor, - animate = true, + animate = isAnimationEnabled, duration = APPEAR_ANIM_DURATION, delay = 0, onAnimationEnd = null @@ -242,7 +244,7 @@ class AnimatableClockView @JvmOverloads constructor( } fun animateFoldAppear(animate: Boolean = true) { - if (textAnimator == null) { + if (isAnimationEnabled && textAnimator == null) { return } setTextStyle( @@ -258,7 +260,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, @@ -276,7 +278,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 @@ -286,7 +288,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 @@ -298,7 +300,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 @@ -332,7 +334,7 @@ class AnimatableClockView @JvmOverloads constructor( weight = weight, textSize = textSize, color = color, - animate = animate, + animate = animate && isAnimationEnabled, duration = duration, interpolator = interpolator, delay = delay, @@ -370,7 +372,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 d881cd1e24154..2099f165b0792 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 @@ -221,7 +222,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 6a62f99b50598bc0c4d3383cd1ec0982489b73ba Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Tue, 2 Aug 2022 16:49:33 +0000 Subject: [PATCH 6/7] [DO NOT MERGE] 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 --- .../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 a77575418e5f2..e3be36503c873 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 7/7] [DO NOT MERGE] 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 --- .../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 5c20b691b9910..b5e57667fbb83 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 @@ -118,6 +118,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())