Merge changes from topic "clock_cherrypick_fixes" into tm-qpr-dev
* changes:
[DO NOT MERGE] Initialize TimeZone during DefaultClockProvider init
[DO NOT MERGE] Correct large clock position
[DO NOT MERGE] Additional Tests for DefaultClock
[DO NOT MERGE] Update DefaultClockProvider colors
[DO NOT MERGE] Moving Text Protection to Clock Event Controller
[DO NOT MERGE] Adding Region Sampler to Animatable Clocks
[DO NOT MERGE] Revert "[DO NOT MERGE]Revert "Migrate KeyguardClockSwitch to new..."
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index 3ca8dfe..51cc195 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 0c191607..01e5d86 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 @@
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, true, true)
+ animations.doze(dozeFraction)
+ animations.fold(foldFraction)
+ events.onTimeTick()
+ }
/** Optional method for dumping debug information */
fun dump(pw: PrintWriter) { }
@@ -80,15 +88,16 @@
/** 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,
+ smallClockIsDark: Boolean,
+ largeClockIsDark: Boolean
+ ) { }
}
/** 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 0137dc3..0000000
--- a/packages/SystemUI/res-keyguard/font/clock.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2020, 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.
-*/
--->
-
-<!--
-** AOD/LockScreen Clock font.
-** Should include all numeric glyphs in all supported locales.
-** Recommended: font with variable width to support AOD => LS animations
--->
-<!-- TODO: Remove when clock migration complete -->
-<font-family xmlns:android="http://schemas.android.com/apk/res/android">
- <font android:typeface="monospace"/>
-</font-family>
\ 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 6a38507..3ad7c8c 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">
<FrameLayout
android:id="@+id/lockscreen_clock_view"
@@ -30,44 +31,13 @@
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
- android:paddingStart="@dimen/clock_padding_start">
- <com.android.systemui.shared.clocks.AnimatableClockView
- android:id="@+id/animatable_clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start"
- android:gravity="start"
- android:textSize="@dimen/clock_text_size"
- android:fontFamily="@font/clock"
- android:elegantTextHeight="false"
- android:singleLine="true"
- android:fontFeatureSettings="pnum"
- chargeAnimationDelay="350"
- dozeWeight="200"
- lockScreenWeight="400"
- />
- </FrameLayout>
+ android:paddingStart="@dimen/clock_padding_start" />
<FrameLayout
android:id="@+id/lockscreen_clock_view_large"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/keyguard_slice_view"
- android:visibility="gone">
- <com.android.systemui.shared.clocks.AnimatableClockView
- android:id="@+id/animatable_clock_view_large"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center_horizontal"
- android:textSize="@dimen/large_clock_text_size"
- android:fontFamily="@font/clock"
- android:typeface="monospace"
- android:elegantTextHeight="false"
- chargeAnimationDelay="200"
- dozeWeight="200"
- lockScreenWeight="400"
- />
- </FrameLayout>
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/keyguard_large_clock_top_margin"
+ android:visibility="gone" />
<!-- Not quite optimal but needed to translate these items as a group. The
NotificationIconContainer has its own logic for translation. -->
diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml
index 6ba88a6..acb47f7 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml
@@ -19,7 +19,7 @@
android:id="@+id/time_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:fontFamily="@font/clock"
+ android:fontFamily="@*android:string/config_clockFontFamily"
android:textColor="@android:color/white"
android:format12Hour="@string/dream_time_complication_12_hr_time_format"
android:format24Hour="@string/dream_time_complication_24_hr_time_format"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9820237..e3be365 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -671,12 +671,6 @@
<!-- With the large clock, move up slightly from the center -->
<dimen name="keyguard_large_clock_top_margin">-60dp</dimen>
- <!-- TODO: Remove during migration -->
- <!-- Default line spacing multiplier between hours and minutes of the keyguard clock -->
- <item name="keyguard_clock_line_spacing_scale" type="dimen" format="float">.7</item>
- <!-- Burmese line spacing multiplier between hours and minutes of the keyguard clock -->
- <item name="keyguard_clock_line_spacing_scale_burmese" type="dimen" format="float">1</item>
-
<dimen name="notification_scrim_corner_radius">32dp</dimen>
<!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
@@ -895,11 +889,6 @@
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_y_clock">42dp</dimen>
- <!-- Clock maximum font size (dp is intentional, to prevent any further scaling) -->
- <!-- TODO: Remove when clock migration complete -->
- <dimen name="large_clock_text_size">150dp</dimen>
- <dimen name="clock_text_size">86dp</dimen>
-
<!-- The maximum offset in either direction that icons move to prevent burn-in on AOD. -->
<dimen name="default_burn_in_prevention_offset">15dp</dimen>
diff --git a/packages/SystemUI/shared/res/layout/clock_default_large.xml b/packages/SystemUI/shared/res/layout/clock_default_large.xml
index 8510a0a..0139d50 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 @@
-->
<com.android.systemui.shared.clocks.AnimatableClockView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/animatable_clock_view_large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
diff --git a/packages/SystemUI/shared/res/layout/clock_default_small.xml b/packages/SystemUI/shared/res/layout/clock_default_small.xml
index ec0e427..ff6d7f9 100644
--- a/packages/SystemUI/shared/res/layout/clock_default_small.xml
+++ b/packages/SystemUI/shared/res/layout/clock_default_small.xml
@@ -18,14 +18,14 @@
-->
<com.android.systemui.shared.clocks.AnimatableClockView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/animatable_clock_view"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:gravity="start"
android:textSize="@dimen/small_clock_text_size"
android:fontFamily="@*android:string/config_clockFontFamily"
android:elegantTextHeight="false"
+ android:ellipsize="none"
android:singleLine="true"
android:fontFeatureSettings="pnum"
chargeAnimationDelay="350"
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 c2fda82..b3b75f6 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
@@ -20,12 +20,16 @@
import android.annotation.FloatRange
import android.annotation.IntRange
import android.annotation.SuppressLint
+import android.app.compat.ChangeIdStateCache.invalidate
import android.content.Context
import android.graphics.Canvas
import android.text.TextUtils
import android.text.format.DateFormat
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
@@ -74,7 +78,8 @@
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
@@ -82,6 +87,12 @@
val lockScreenWeight: Int
get() = if (useBoldedVersion()) lockScreenWeightInternal + 100 else lockScreenWeightInternal
+ /**
+ * The number of pixels below the baseline. For fonts that support languages such as
+ * Burmese, this space can be significant and should be accounted for when computing layout.
+ */
+ val bottom get() = paint?.fontMetrics?.bottom ?: 0f
+
init {
val animatableClockViewAttributes = context.obtainStyledAttributes(
attrs, R.styleable.AnimatableClockView, defStyleAttr, defStyleRes
@@ -141,6 +152,15 @@
if (!TextUtils.equals(text, formattedText)) {
text = formattedText
lastTextUpdate = getTimestamp()
+
+ // Because the TextLayout may mutate under the hood as a result of the new text, we
+ // notify the TextAnimator that it may have changed and request a measure/layout. A
+ // crash will occur on the next invocation of setTextStyle if the layout is mutated
+ // without being notified TextInterpolator being notified.
+ if (layout != null) {
+ textAnimator?.updateLayout(layout)
+ }
+ requestLayout()
}
}
@@ -200,7 +220,7 @@
}
fun animateAppearOnLockscreen() {
- if (textAnimator == null) {
+ if (isAnimationEnabled && textAnimator == null) {
return
}
setTextStyle(
@@ -216,7 +236,7 @@
weight = lockScreenWeight,
textSize = -1f,
color = lockScreenColor,
- animate = true,
+ animate = isAnimationEnabled,
duration = APPEAR_ANIM_DURATION,
delay = 0,
onAnimationEnd = null
@@ -224,7 +244,7 @@
}
fun animateFoldAppear(animate: Boolean = true) {
- if (textAnimator == null) {
+ if (isAnimationEnabled && textAnimator == null) {
return
}
setTextStyle(
@@ -240,7 +260,7 @@
weight = dozingWeightInternal,
textSize = -1f,
color = dozingColor,
- animate = animate,
+ animate = animate && isAnimationEnabled,
interpolator = Interpolators.EMPHASIZED_DECELERATE,
duration = ANIMATION_DURATION_FOLD_TO_AOD.toLong(),
delay = 0,
@@ -258,7 +278,7 @@
weight = if (isDozing()) dozingWeight else lockScreenWeight,
textSize = -1f,
color = null,
- animate = true,
+ animate = isAnimationEnabled,
duration = CHARGE_ANIM_DURATION_PHASE_1,
delay = 0,
onAnimationEnd = null
@@ -268,7 +288,7 @@
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
@@ -280,7 +300,7 @@
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
@@ -314,7 +334,7 @@
weight = weight,
textSize = textSize,
color = color,
- animate = animate,
+ animate = animate && isAnimationEnabled,
duration = duration,
interpolator = interpolator,
delay = delay,
@@ -352,7 +372,7 @@
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/ClockRegistry.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index e707d4d..835d6e9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -35,8 +35,6 @@
private val TAG = ClockRegistry::class.simpleName
private val DEBUG = true
-typealias ClockChangeListener = () -> Unit
-
/** ClockRegistry aggregates providers and plugins */
open class ClockRegistry(
val context: Context,
@@ -51,6 +49,11 @@
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 @@
private val clockChangeListeners = mutableListOf<ClockChangeListener>()
private val settingObserver = object : ContentObserver(handler) {
override fun onChange(selfChange: Boolean, uris: Collection<Uri>, flags: Int, userId: Int) =
- clockChangeListeners.forEach { it() }
+ clockChangeListeners.forEach { it.onClockChanged() }
}
private val pluginListener = object : PluginListener<ClockProviderPlugin> {
@@ -117,8 +120,11 @@
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 @@
if (DEBUG) {
Log.i(TAG, "Current clock ($currentId) was connected")
}
- clockChangeListeners.forEach { it() }
+ clockChangeListeners.forEach { it.onClockChanged() }
}
}
}
@@ -139,7 +145,7 @@
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 5d8da59..b5e5766 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
@@ -13,16 +13,18 @@
*/
package com.android.systemui.shared.clocks
+import android.content.Context
import android.content.res.Resources
import android.graphics.Color
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 android.widget.FrameLayout
+import com.android.internal.annotations.VisibleForTesting
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
@@ -39,6 +41,7 @@
/** Provides the default system clock */
class DefaultClockProvider @Inject constructor(
+ val ctx: Context,
val layoutInflater: LayoutInflater,
@Main val resources: Resources
) : ClockProvider {
@@ -49,7 +52,7 @@
if (id != DEFAULT_CLOCK_ID) {
throw IllegalArgumentException("$id is unsupported by $TAG")
}
- return DefaultClock(layoutInflater, resources)
+ return DefaultClock(ctx, layoutInflater, resources)
}
override fun getClockThumbnail(id: ClockId): Drawable? {
@@ -69,14 +72,13 @@
* AnimatableClockView used by the existing lockscreen clock.
*/
class DefaultClock(
- private val layoutInflater: LayoutInflater,
- private val resources: Resources
+ ctx: Context,
+ private val layoutInflater: LayoutInflater,
+ private val resources: Resources
) : Clock {
- override val smallClock =
- layoutInflater.inflate(R.layout.clock_default_small, null) as AnimatableClockView
- override val largeClock =
- layoutInflater.inflate(R.layout.clock_default_large, null) as AnimatableClockView
- private val clocks = listOf(smallClock, largeClock)
+ override val smallClock: AnimatableClockView
+ override val largeClock: AnimatableClockView
+ private val clocks get() = listOf(smallClock, largeClock)
private val burmeseNf = NumberFormat.getInstance(Locale.forLanguageTag("my"))
private val burmeseNumerals = burmeseNf.format(FORMAT_NUMBER.toLong())
@@ -84,7 +86,43 @@
resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese)
private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)
- override val events = object : ClockEvents {
+ override val events: ClockEvents
+ override lateinit var animations: ClockAnimations
+ private set
+
+ init {
+ val parent = FrameLayout(ctx)
+
+ smallClock = layoutInflater.inflate(
+ R.layout.clock_default_small,
+ parent,
+ false
+ ) as AnimatableClockView
+
+ largeClock = layoutInflater.inflate(
+ R.layout.clock_default_large,
+ parent,
+ false
+ ) as AnimatableClockView
+
+ events = DefaultClockEvents()
+ animations = DefaultClockAnimations(0f, 0f)
+
+ events.onLocaleChanged(Locale.getDefault())
+
+ // DOZE_COLOR is a placeholder, and will be assigned correctly in initialize
+ 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, true, true)
+ events.onTimeZoneChanged(TimeZone.getDefault())
+ events.onTimeTick()
+ }
+
+ inner class DefaultClockEvents() : ClockEvents {
override fun onTimeTick() = clocks.forEach { it.refreshTime() }
override fun onTimeFormatChanged(is24Hr: Boolean) =
@@ -102,10 +140,17 @@
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,
+ smallClockIsDark: Boolean,
+ largeClockIsDark: Boolean
+ ) {
+ updateClockColor(smallClock, smallClockIsDark)
+ updateClockColor(largeClock, largeClockIsDark)
+ }
override fun onLocaleChanged(locale: Locale) {
val nf = NumberFormat.getInstance(locale)
@@ -119,8 +164,14 @@
}
}
- override val animation = object : ClockAnimation {
- override fun initialize(dozeFraction: Float, foldFraction: Float) {
+ 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 +183,13 @@
}
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 +197,6 @@
}
}
- private var dozeState = AnimationState(0f)
override fun doze(fraction: Float) {
val (hasChanged, hasJumped) = dozeState.update(fraction)
if (hasChanged) {
@@ -170,14 +219,26 @@
}
}
- init {
- events.onLocaleChanged(Locale.getDefault())
+ 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()
+ }
+
+ private fun recomputePadding() {
+ val lp = largeClock.getLayoutParams() as FrameLayout.LayoutParams
+ lp.topMargin = (-0.5f * largeClock.bottom).toInt()
+ largeClock.setLayoutParams(lp)
}
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/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 3c68c0d..6064be9 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.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 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 @@
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final BatteryController mBatteryController;
private final int mDozingColor = Color.WHITE;
+ private Optional<RegionSamplingHelper> 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 @@
private final float mBurmeseLineSpacing;
private final float mDefaultLineSpacing;
+ @Inject
public AnimatableClockController(
AnimatableClockView view,
StatusBarStateController statusBarStateController,
BroadcastDispatcher broadcastDispatcher,
BatteryController batteryController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- @Main Resources resources
+ @Main Resources resources,
+ @Main Executor mainExecutor,
+ @Background Executor bgExecutor,
+ FeatureFlags featureFlags
) {
super(view);
mStatusBarStateController = statusBarStateController;
@@ -86,6 +103,40 @@
R.dimen.keyguard_clock_line_spacing_scale_burmese);
mDefaultLineSpacing = resources.getFloat(
R.dimen.keyguard_clock_line_spacing_scale);
+
+ mRegionSamplingEnabled = featureFlags.isEnabled(Flags.REGION_SAMPLING);
+ if (!mRegionSamplingEnabled) {
+ return;
+ }
+
+ mRegionSamplingHelper = Optional.of(new RegionSamplingHelper(mView,
+ new RegionSamplingHelper.SamplingCallback() {
+ @Override
+ public void onRegionDarknessChanged(boolean isRegionDark) {
+ if (isRegionDark) {
+ mLockScreenColor = Color.WHITE;
+ } else {
+ mLockScreenColor = Color.BLACK;
+ }
+ initColors();
+ }
+
+ @Override
+ public Rect getSampledRegion(View sampledView) {
+ mSamplingBounds = new Rect(sampledView.getLeft(), sampledView.getTop(),
+ sampledView.getRight(), sampledView.getBottom());
+ return mSamplingBounds;
+ }
+
+ @Override
+ public boolean isSamplingEnabled() {
+ return mRegionSamplingEnabled;
+ }
+ }, mainExecutor, bgExecutor)
+ );
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.setWindowVisible(true);
+ });
}
private void reset() {
@@ -169,6 +220,10 @@
mStatusBarStateController.addCallback(mStatusBarStateListener);
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.start(mSamplingBounds);
+ });
+
mView.onTimeZoneChanged(TimeZone.getDefault());
initColors();
mView.animateDoze(mIsDozing, false);
@@ -180,18 +235,9 @@
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mBatteryController.removeCallback(mBatteryCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
- }
-
- /**
- * @return the number of pixels below the baseline. For fonts that support languages such as
- * Burmese, this space can be significant.
- */
- public float getBottom() {
- if (mView.getPaint() != null && mView.getPaint().getFontMetrics() != null) {
- return mView.getPaint().getFontMetrics().bottom;
- }
-
- return 0f;
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.stop();
+ });
}
/** Animate the clock appearance */
@@ -235,8 +281,10 @@
}
private void initColors() {
- mLockScreenColor = Utils.getColorAttrDefaultColor(getContext(),
- com.android.systemui.R.attr.wallpaperTextColorAccent);
+ if (!mRegionSamplingEnabled) {
+ mLockScreenColor = Utils.getColorAttrDefaultColor(getContext(),
+ com.android.systemui.R.attr.wallpaperTextColorAccent);
+ }
mView.setColors(mDozingColor, mLockScreenColor);
mView.animateDoze(mIsDozing, false);
}
@@ -247,5 +295,8 @@
public void dump(@NonNull PrintWriter pw) {
pw.println(this);
mView.dump(pw);
+ mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
+ regionSamplingHelper.dump(pw);
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
new file mode 100644
index 0000000..0e1e0cb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -0,0 +1,231 @@
+/*
+ * 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.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.res.Resources
+import android.text.format.DateFormat
+import android.util.TypedValue
+import android.view.View
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.plugins.Clock
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+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
+import java.io.PrintWriter
+import java.util.Locale
+import java.util.TimeZone
+import java.util.concurrent.Executor
+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].
+ */
+open 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,
+ @Main private val mainExecutor: Executor,
+ @Background private val bgExecutor: Executor,
+ private val featureFlags: FeatureFlags
+) {
+ var clock: Clock? = null
+ set(value) {
+ field = value
+ if (value != null) {
+ value.initialize(resources, dozeAmount, 0f)
+ updateRegionSamplers(value)
+ }
+ }
+
+ private var isDozing = false
+ private set
+
+ private var isCharging = false
+ private var dozeAmount = 0f
+ private var isKeyguardShowing = false
+
+ private val regionSamplingEnabled =
+ featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING)
+
+ 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)
+ }
+ }
+
+ fun updateRegionSamplers(currentClock: Clock?) {
+ smallRegionSamplingInstance = createRegionSampler(
+ currentClock?.smallClock,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ updateFun
+ )
+
+ largeRegionSamplingInstance = createRegionSampler(
+ currentClock?.largeClock,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ updateFun
+ )
+
+ smallRegionSamplingInstance.startRegionSampler()
+ largeRegionSamplingInstance.startRegionSampler()
+
+ updateFun.updateColors()
+ }
+
+ protected open fun createRegionSampler(
+ sampledView: View?,
+ mainExecutor: Executor?,
+ bgExecutor: Executor?,
+ regionSamplingEnabled: Boolean,
+ updateFun: RegionSamplingInstance.UpdateColorCallback
+ ): RegionSamplingInstance {
+ return RegionSamplingInstance(
+ sampledView,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ updateFun)
+ }
+
+ 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() {
+ updateFun.updateColors()
+ }
+ }
+
+ private val batteryCallback = object : BatteryStateChangeCallback {
+ override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
+ if (isKeyguardShowing && !isCharging && charging) {
+ clock?.animations?.charge()
+ }
+ isCharging = charging
+ }
+ }
+
+ private val localeBroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ clock?.events?.onLocaleChanged(Locale.getDefault())
+ }
+ }
+
+ private val statusBarStateListener = object : StatusBarStateController.StateListener {
+ override fun onDozeAmountChanged(linear: Float, eased: Float) {
+ clock?.animations?.doze(linear)
+
+ isDozing = linear > 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)
+ smallRegionSamplingInstance.startRegionSampler()
+ largeRegionSamplingInstance.startRegionSampler()
+ }
+
+ fun unregisterListeners() {
+ broadcastDispatcher.unregisterReceiver(localeBroadcastReceiver)
+ configurationController.removeCallback(configListener)
+ batteryController.removeCallback(batteryCallback)
+ keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
+ statusBarStateController.removeCallback(statusBarStateListener)
+ smallRegionSamplingInstance.stopRegionSampler()
+ largeRegionSamplingInstance.stopRegionSampler()
+ }
+
+ /**
+ * Dump information for debugging
+ */
+ fun dump(pw: PrintWriter) {
+ pw.println(this)
+ clock?.dump(pw)
+ smallRegionSamplingInstance.dump(pw)
+ largeRegionSamplingInstance.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 9164108..d7cd1d0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -5,31 +5,23 @@
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;
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.
*/
@@ -50,17 +42,10 @@
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 +65,6 @@
@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 +77,36 @@
* 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());
+ mLargeClockFrame.addView(clock.getLargeClock());
}
private void updateClockViews(boolean useLargeClock, boolean animate) {
@@ -204,14 +122,14 @@
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;
@@ -270,18 +188,6 @@
}
/**
- * 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
*
* @return true if desired clock appeared and false if it was already visible
@@ -312,64 +218,11 @@
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(" mSmallClockFrame: " + 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 ad06e05..2165099 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 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.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,23 @@
*/
public class KeyguardClockSwitchController extends ViewController<KeyguardClockSwitch>
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;
+ 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 +88,9 @@
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private boolean mOnlyClock = false;
- private Executor mUiExecutor;
+ private final Executor mUiExecutor;
private boolean mCanShowDoubleLineClock = true;
- private ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
+ private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
@Override
public void onChange(boolean change) {
updateDoubleLineClock();
@@ -144,34 +111,32 @@
public KeyguardClockSwitchController(
KeyguardClockSwitch keyguardClockSwitch,
StatusBarStateController statusBarStateController,
- SysuiColorExtractor colorExtractor,
- ClockManager clockManager,
+ ClockRegistry clockRegistry,
KeyguardSliceViewController keyguardSliceViewController,
NotificationIconAreaController notificationIconAreaController,
- BroadcastDispatcher broadcastDispatcher,
- BatteryController batteryController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
LockscreenSmartspaceController smartspaceController,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
SecureSettings secureSettings,
@Main Executor uiExecutor,
- @Main Resources resources,
- DumpManager dumpManager) {
+ DumpManager dumpManager,
+ ClockEventController clockEventController,
+ FeatureFlags featureFlags) {
super(keyguardClockSwitch);
mStatusBarStateController = statusBarStateController;
- mColorExtractor = colorExtractor;
- mClockManager = clockManager;
+ mClockRegistry = clockRegistry;
mKeyguardSliceViewController = keyguardSliceViewController;
mNotificationIconAreaController = notificationIconAreaController;
- mBroadcastDispatcher = broadcastDispatcher;
- mBatteryController = batteryController;
- mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mSmartspaceController = smartspaceController;
- mResources = resources;
mSecureSettings = secureSettings;
mUiExecutor = uiExecutor;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mDumpManager = dumpManager;
+ mClockEventController = clockEventController;
+
+ mClockRegistry.setEnabled(featureFlags.isEnabled(Flags.LOCKSCREEN_CUSTOM_CLOCKS));
+ mClockChangedListener = () -> {
+ setClock(mClockRegistry.createCurrentClock());
+ };
}
/**
@@ -185,43 +150,21 @@
* Attach the controller to the view it relates to.
*/
@Override
- public void onInit() {
+ protected void onInit() {
mKeyguardSliceViewController.init();
- mClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
+ mSmallClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large);
- mClockViewController =
- new AnimatableClockController(
- mView.findViewById(R.id.animatable_clock_view),
- mStatusBarStateController,
- mBroadcastDispatcher,
- mBatteryController,
- mKeyguardUpdateMonitor,
- mResources);
- mClockViewController.init();
-
- mLargeClockViewController =
- new AnimatableClockController(
- mView.findViewById(R.id.animatable_clock_view_large),
- mStatusBarStateController,
- mBroadcastDispatcher,
- mBatteryController,
- mKeyguardUpdateMonitor,
- mResources);
- mLargeClockViewController.init();
-
mDumpManager.unregisterDumpable(getClass().toString()); // unregister previous clocks
mDumpManager.registerDumpable(getClass().toString(), this);
}
@Override
protected void onViewAttached() {
- if (CUSTOM_CLOCKS_ENABLED) {
- mClockManager.addOnClockChangedListener(mClockChangedListener);
- }
- mColorExtractor.addOnColorsChangedListener(mColorsListener);
- mView.updateColors(getGradientColors());
+ mClockRegistry.registerClockChangeListener(mClockChangedListener);
+ setClock(mClockRegistry.createCurrentClock());
+ mClockEventController.registerListeners();
mKeyguardClockTopMargin =
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
@@ -244,7 +187,6 @@
ksv.setVisibility(View.GONE);
addSmartspaceView(ksvIndex);
- updateClockLayout();
}
mSecureSettings.registerContentObserverForUser(
@@ -266,11 +208,9 @@
@Override
protected void onViewDetached() {
- if (CUSTOM_CLOCKS_ENABLED) {
- mClockManager.removeOnClockChangedListener(mClockChangedListener);
- }
- mColorExtractor.removeOnColorsChangedListener(mColorsListener);
- mView.setClockPlugin(null, mStatusBarStateController.getState());
+ mClockRegistry.unregisterClockChangeListener(mClockChangedListener);
+ mClockEventController.unregisterListeners();
+ setClock(null);
mSecureSettings.unregisterContentObserver(mDoubleLineClockObserver);
@@ -309,18 +249,6 @@
mView.onDensityOrFontScaleChanged();
mKeyguardClockTopMargin =
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
-
- updateClockLayout();
- }
-
- private void updateClockLayout() {
- int largeClockTopMargin = getContext().getResources().getDimensionPixelSize(
- R.dimen.keyguard_large_clock_top_margin)
- - (int) mLargeClockViewController.getBottom();
- RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT,
- MATCH_PARENT);
- lp.topMargin = largeClockTopMargin;
- mLargeClockFrame.setLayoutParams(lp);
}
/**
@@ -334,46 +262,34 @@
mCurrentClockSize = clockSize;
+ Clock clock = getClock();
boolean appeared = mView.switchToClock(clockSize, animate);
- if (animate && appeared && clockSize == LARGE) {
- mLargeClockViewController.animateAppear();
- }
- }
-
- public void animateFoldToAod() {
- if (mClockViewController != null) {
- mClockViewController.animateFoldAppear();
- mLargeClockViewController.animateFoldAppear();
+ if (clock != null && animate && appeared && clockSize == LARGE) {
+ clock.getAnimations().enter();
}
}
/**
- * If we're presenting a custom clock of just the default one.
+ * Animates the clock view between folded and unfolded states
*/
- public boolean hasCustomClock() {
- return mView.hasCustomClock();
- }
-
- /**
- * Get the clock text size.
- */
- public float getClockTextSize() {
- return mView.getTextSize();
+ public void animateFoldToAod(float foldFraction) {
+ Clock clock = getClock();
+ if (clock != null) {
+ clock.getAnimations().fold(foldFraction);
+ }
}
/**
* Refresh clock. Called in response to TIME_TICK broadcasts.
*/
void refresh() {
- if (mClockViewController != null) {
- mClockViewController.refreshTime();
- mLargeClockViewController.refreshTime();
- }
if (mSmartspaceController != null) {
mSmartspaceController.requestSmartspaceUpdate();
}
-
- mView.refresh();
+ Clock clock = getClock();
+ if (clock != null) {
+ clock.getEvents().onTimeTick();
+ }
}
/**
@@ -385,7 +301,7 @@
void updatePosition(int x, float scale, AnimationProperties props, boolean animate) {
x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x;
- PropertyAnimator.setProperty(mClockFrame, AnimatableProperty.TRANSLATION_X,
+ PropertyAnimator.setProperty(mSmallClockFrame, AnimatableProperty.TRANSLATION_X,
x, props, animate);
PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_X,
scale, props, animate);
@@ -398,25 +314,39 @@
}
}
- void updateTimeZone(TimeZone timeZone) {
- mView.onTimeZoneChanged(timeZone);
- }
-
/**
* Get y-bottom position of the currently visible clock on the keyguard.
* We can't directly getBottom() because clock changes positions in AOD for burn-in
*/
int getClockBottom(int statusBarHeaderHeight) {
+ Clock clock = getClock();
+ if (clock == null) {
+ return 0;
+ }
+
if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
- View clock = mLargeClockFrame.findViewById(
- com.android.systemui.R.id.animatable_clock_view_large);
int frameHeight = mLargeClockFrame.getHeight();
- int clockHeight = clock.getHeight();
+ int clockHeight = clock.getLargeClock().getHeight();
return frameHeight / 2 + clockHeight / 2;
} else {
- return mClockFrame.findViewById(
- com.android.systemui.R.id.animatable_clock_view).getHeight()
- + statusBarHeaderHeight + mKeyguardClockTopMargin;
+ int clockHeight = clock.getSmallClock().getHeight();
+ return clockHeight + statusBarHeaderHeight + mKeyguardClockTopMargin;
+ }
+ }
+
+ /**
+ * Get the height of the currently visible clock on the keyguard.
+ */
+ int getClockHeight() {
+ Clock clock = getClock();
+ if (clock == null) {
+ return 0;
+ }
+
+ if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
+ return clock.getLargeClock().getHeight();
+ } else {
+ return clock.getSmallClock().getHeight();
}
}
@@ -431,12 +361,13 @@
mNotificationIconAreaController.setupAodIcons(nic);
}
- private void setClockPlugin(ClockPlugin plugin) {
- mView.setClockPlugin(plugin, mStatusBarStateController.getState());
+ private void setClock(Clock clock) {
+ mClockEventController.setClock(clock);
+ mView.setClock(clock, mStatusBarStateController.getState());
}
- private ColorExtractor.GradientColors getGradientColors() {
- return mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
+ private Clock getClock() {
+ return mClockEventController.getClock();
}
private int getCurrentLayoutDirection() {
@@ -458,8 +389,6 @@
* bounds during the unlock transition.
*/
private void setClipChildrenForUnlock(boolean clip) {
- mView.setClipChildren(clip);
-
if (mStatusArea != null) {
mStatusArea.setClipChildren(clip);
}
@@ -469,8 +398,10 @@
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("currentClockSizeLarge=" + (mCurrentClockSize == LARGE));
pw.println("mCanShowDoubleLineClock=" + mCanShowDoubleLineClock);
- mClockViewController.dump(pw);
- mLargeClockViewController.dump(pw);
+ Clock clock = getClock();
+ if (clock != null) {
+ clock.dump(pw);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index cb3172d..83e23bd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -17,14 +17,11 @@
package com.android.keyguard;
import android.content.Context;
-import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridLayout;
-import androidx.core.graphics.ColorUtils;
-
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
@@ -46,7 +43,6 @@
private View mMediaHostContainer;
private float mDarkAmount = 0;
- private int mTextColor;
public KeyguardStatusView(Context context) {
this(context, null, 0);
@@ -71,7 +67,6 @@
}
mKeyguardSlice = findViewById(R.id.keyguard_slice_view);
- mTextColor = mClockView.getCurrentTextColor();
mMediaHostContainer = findViewById(R.id.status_view_media_container);
@@ -83,15 +78,12 @@
return;
}
mDarkAmount = darkAmount;
- mClockView.setDarkAmount(darkAmount);
CrossFadeHelper.fadeOut(mMediaHostContainer, darkAmount);
updateDark();
}
void updateDark() {
- final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
mKeyguardSlice.setDarkAmount(mDarkAmount);
- mClockView.setTextColor(blendedTextColor);
}
/** Sets a translationY value on every child view except for the media view. */
@@ -113,7 +105,6 @@
public void dump(PrintWriter pw, String[] args) {
pw.println("KeyguardStatusView:");
pw.println(" mDarkAmount: " + mDarkAmount);
- pw.println(" mTextColor: " + Integer.toHexString(mTextColor));
if (mClockView != null) {
mClockView.dump(pw, args);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 014d082..c715a4e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -30,8 +30,6 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
-import java.util.TimeZone;
-
import javax.inject.Inject;
/**
@@ -96,13 +94,6 @@
}
/**
- * The amount we're in doze.
- */
- public void setDarkAmount(float darkAmount) {
- mView.setDarkAmount(darkAmount);
- }
-
- /**
* Set which clock should be displayed on the keyguard. The other one will be automatically
* hidden.
*/
@@ -114,16 +105,10 @@
* Performs fold to aod animation of the clocks (changes font weight from bold to thin).
* This animation is played when AOD is enabled and foldable device is fully folded, it is
* displayed on the outer screen
+ * @param foldFraction current fraction of fold animation complete
*/
- public void animateFoldToAod() {
- mKeyguardClockSwitchController.animateFoldToAod();
- }
-
- /**
- * If we're presenting a custom clock of just the default one.
- */
- public boolean hasCustomClock() {
- return mKeyguardClockSwitchController.hasCustomClock();
+ public void animateFoldToAod(float foldFraction) {
+ mKeyguardClockSwitchController.animateFoldToAod(foldFraction);
}
/**
@@ -143,24 +128,11 @@
}
/**
- * Set pivot x.
+ * Update the pivot position based on the parent view
*/
- public void setPivotX(float pivot) {
- mView.setPivotX(pivot);
- }
-
- /**
- * Set pivot y.
- */
- public void setPivotY(float pivot) {
- mView.setPivotY(pivot);
- }
-
- /**
- * Get the clock text size.
- */
- public float getClockTextSize() {
- return mKeyguardClockSwitchController.getClockTextSize();
+ public void updatePivot(float parentWidth, float parentHeight) {
+ mView.setPivotX(parentWidth / 2f);
+ mView.setPivotY(mKeyguardClockSwitchController.getClockHeight() / 2f);
}
/**
@@ -240,11 +212,6 @@
}
@Override
- public void onTimeZoneChanged(TimeZone timeZone) {
- mKeyguardClockSwitchController.updateTimeZone(timeZone);
- }
-
- @Override
public void onKeyguardVisibilityChanged(boolean showing) {
if (showing) {
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 67455d1..70c0cab 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -290,11 +290,6 @@
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
private final NotificationIconAreaController mNotificationIconAreaController;
- // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
- // changed.
- private static final int CAP_HEIGHT = 1456;
- private static final int FONT_HEIGHT = 2163;
-
/**
* Maximum time before which we will expand the panel even for slow motions when getting a
* touch passed over from launcher.
@@ -1112,13 +1107,6 @@
}
}
- /**
- * Returns if there's a custom clock being presented.
- */
- public boolean hasCustomClock() {
- return mKeyguardStatusViewController.hasCustomClock();
- }
-
private void setCentralSurfaces(CentralSurfaces centralSurfaces) {
// TODO: this can be injected.
mCentralSurfaces = centralSurfaces;
@@ -3974,9 +3962,9 @@
public void onAnimationEnd(Animator animation) {
endAction.run();
}
+ }).setUpdateListener(anim -> {
+ mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction());
}).start();
-
- mKeyguardStatusViewController.animateFoldToAod();
}
/**
@@ -4686,7 +4674,6 @@
public void onDozeAmountChanged(float linearAmount, float amount) {
mInterpolatedDarkAmount = amount;
mLinearDarkAmount = linearAmount;
- mKeyguardStatusViewController.setDarkAmount(mInterpolatedDarkAmount);
mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
positionClockAndNotifications();
}
@@ -4796,11 +4783,8 @@
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 84bb82b..ce04fb5 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 @@
state |= DISABLE_CLOCK;
}
-
if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
if (mNetworkController.hasEmergencyCryptKeeperText()) {
state |= DISABLE_NOTIFICATION_ICONS;
@@ -452,13 +451,6 @@
}
}
- // 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 0000000..914d945
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -0,0 +1,270 @@
+/*
+ * 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.flags.FeatureFlags
+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 java.util.concurrent.Executor
+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
+ @Mock private lateinit var mainExecutor: Executor
+ @Mock private lateinit var bgExecutor: Executor
+ @Mock private lateinit var featureFlags: FeatureFlags
+
+ 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,
+ mainExecutor,
+ bgExecutor,
+ featureFlags
+ )
+ }
+
+ @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
+ verify(events).onColorPaletteChanged(any(), any(), any())
+
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
+ verify(configurationController).addCallback(capture(captor))
+ captor.value.onThemeChanged()
+
+ verify(events, times(2)).onColorPaletteChanged(any(), any(), any())
+ }
+
+ @Test
+ fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() {
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ 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<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ 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<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ 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<BatteryController.BatteryStateChangeCallback>()
+ verify(batteryController).addCallback(capture(batteryCaptor))
+ val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ 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<BroadcastReceiver>()
+ 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<KeyguardUpdateMonitorCallback>()
+ 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<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(capture(captor))
+ captor.value.onTimeFormatChanged("12h")
+
+ verify(events).onTimeFormatChanged(false)
+ }
+
+ @Test
+ fun keyguardCallback_timezoneChanged_clockNotified() {
+ val mockTimeZone = mock<TimeZone>()
+ clockEventController.clock = clock
+ clockEventController.registerListeners()
+
+ val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ 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<KeyguardUpdateMonitorCallback>()
+ 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<StatusBarStateController.StateListener>()
+ verify(statusBarStateController).addCallback(capture(captor))
+ captor.value.onDozeAmountChanged(0.4f, 0.6f)
+
+ verify(animations).doze(0.4f)
+ }
+
+ @Test
+ fun unregisterListeners_validate() {
+ clockEventController.clock = clock
+ 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 b2d9219..635ee9e 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 @@
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 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 @@
@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 @@
@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 @@
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 @@
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 @@
verifyAttachment(times(1));
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
- verify(mColorExtractor).removeOnColorsChangedListener(
- any(ColorExtractor.OnColorsChangedListener.class));
+ verify(mClockEventController).unregisterListeners();
}
@Test
public void testPluginPassesStatusBarState() {
- ArgumentCaptor<ClockManager.ClockChangedListener> listenerArgumentCaptor =
- ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class);
+ ArgumentCaptor<ClockRegistry.ClockChangeListener> 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 @@
}
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 6c6f0ac..a0295d0 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.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;
- private AnimatableClockView mClockView;
- private AnimatableClockView mLargeClockView;
- View mMockKeyguardSliceView;
+ @Mock
+ Clock mClock;
+
+ private FrameLayout mSmallClockFrame;
+ private FrameLayout mLargeClockFrame;
+
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 @@
});
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 @@
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 @@
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 @@
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 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/keyguard/AnimatableClockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/AnimatableClockControllerTest.java
index df506b4..b5e9e8d 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.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.MockitoSession;
import org.mockito.quality.Strictness;
+import java.util.concurrent.Executor;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -69,6 +72,12 @@
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 @@
mBroadcastDispatcher,
mBatteryController,
mKeyguardUpdateMonitor,
- mResources
+ mResources,
+ mMainExecutor,
+ mBgExecutor,
+ mFeatureFlags
);
mAnimatableClockController.init();
captureAttachListener();
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 1cbb8d0..131eac6 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 @@
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 @@
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 @@
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/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index 7869448..2b4a109 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,31 @@
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.testing.AndroidTestingRunner
+import android.util.TypedValue
import android.view.LayoutInflater
+import android.widget.FrameLayout
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.any
+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.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
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
@@ -39,7 +53,8 @@
@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
@@ -47,14 +62,16 @@
@Before
fun setUp() {
- whenever(layoutInflater.inflate(R.layout.clock_default_small, null))
- .thenReturn(mockClockView)
- whenever(layoutInflater.inflate(R.layout.clock_default_large, null))
- .thenReturn(mockClockView)
+ whenever(layoutInflater.inflate(eq(R.layout.clock_default_small), any(), anyBoolean()))
+ .thenReturn(mockSmallClockView)
+ whenever(layoutInflater.inflate(eq(R.layout.clock_default_large), any(), anyBoolean()))
+ .thenReturn(mockLargeClockView)
whenever(resources.getDrawable(R.drawable.clock_default_thumbnail, null))
.thenReturn(mockClockThumbnail)
+ whenever(mockSmallClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
+ whenever(mockLargeClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
- provider = DefaultClockProvider(layoutInflater, resources)
+ provider = DefaultClockProvider(context, layoutInflater, resources)
}
@Test
@@ -71,7 +88,79 @@
// 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).onTimeZoneChanged(notNull())
+ verify(mockLargeClockView).onTimeZoneChanged(notNull())
+ verify(mockSmallClockView).refreshTime()
+ verify(mockLargeClockView).refreshTime()
+ verify(mockLargeClockView).setLayoutParams(any())
+ }
+
+ @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<TimeZone>()
+ 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).setLayoutParams(any())
+ }
+
+ @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()
}
}
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 20bf50e..37c8f62 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 @@
}
@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 @@
}
@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);
@@ -357,40 +355,6 @@
}
@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();
when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(true);