[DO NOT MERGE]Revert "Migrate KeyguardClockSwitch to new shared Clock library"
Revert "Expose the clock version of google-sans"
Revert "Changes to SystemUIGoogle to support clock migration"
Revert submission 19451291-cherrypick-clock_migration-tvip0m638i
Reason for revert: b/241084042
Reverted Changes:
Ia053aaec6:Migrate KeyguardClockSwitch to new shared Clock li...
Ia3e067b93:Changes to SystemUIGoogle to support clock migrati...
I5dbf01a83:Add clock version of google-sans
Ia654d4f41:Expose the clock version of google-sans
Change-Id: I432d3d814c85b9ba20bbb7a88d2e52bd2337c10c
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index d427a57..ff64c78 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -485,13 +485,7 @@
val out = mutableListOf<List<PositionedGlyphs>>()
for (lineNo in 0 until layout.lineCount) { // Shape all lines.
val lineStart = layout.getLineStart(lineNo)
- var count = layout.getLineEnd(lineNo) - lineStart
- // Do not render the last character in the line if it's a newline and unprintable
- val last = lineStart + count - 1
- if (last > lineStart && last < layout.text.length && layout.text[last] == '\n') {
- count--
- }
-
+ val count = layout.getLineEnd(lineNo) - lineStart
val runs = mutableListOf<PositionedGlyphs>()
TextShaper.shapeText(layout.text, lineStart, count, layout.textDirectionHeuristic,
paint) { _, _, glyphs, _ ->
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 cafdc86..0c191607 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,15 +57,7 @@
val events: ClockEvents
/** Triggers for various animations */
- val animations: ClockAnimations
-
- /** Initializes various rendering parameters. If never called, provides reasonable defaults. */
- fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
- events.onColorPaletteChanged(resources)
- animations.doze(dozeFraction)
- animations.fold(foldFraction)
- events.onTimeTick()
- }
+ val animation: ClockAnimation
/** Optional method for dumping debug information */
fun dump(pw: PrintWriter) { }
@@ -88,12 +80,15 @@
/** Call whenever font settings change */
fun onFontSettingChanged() { }
- /** Call whenever the color palette should update */
- fun onColorPaletteChanged(resources: Resources) { }
+ /** Call whenever the color pallete should update */
+ fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) { }
}
/** Methods which trigger various clock animations */
-interface ClockAnimations {
+interface ClockAnimation {
+ /** Initializes the doze & fold animation positions. Defaults to neither folded nor dozing. */
+ fun initialize(dozeFraction: Float, foldFraction: Float) { }
+
/** 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
new file mode 100644
index 0000000..0137dc3
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/font/clock.xml
@@ -0,0 +1,28 @@
+<?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 8b8ebf0..6a38507 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -31,14 +31,42 @@
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>
<FrameLayout
android:id="@+id/lockscreen_clock_view_large"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_below="@id/keyguard_slice_view"
- android:paddingTop="@dimen/keyguard_large_clock_top_padding"
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>
<!-- Not quite optimal but needed to translate these items as a group. The
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 5f4e310..7a57293 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="@*android:string/config_clockFontFamily"
+ android:fontFamily="@font/clock"
android:includeFontPadding="false"
android:textColor="@android:color/white"
android:format12Hour="@string/dream_time_complication_12_hr_time_format"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 205b117..3fb00a3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -664,7 +664,13 @@
<!-- When large clock is showing, offset the smartspace by this amount -->
<dimen name="keyguard_smartspace_top_offset">12dp</dimen>
<!-- With the large clock, move up slightly from the center -->
- <dimen name="keyguard_large_clock_top_padding">100dp</dimen>
+ <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>
@@ -884,6 +890,11 @@
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 0139d50..8510a0a 100644
--- a/packages/SystemUI/shared/res/layout/clock_default_large.xml
+++ b/packages/SystemUI/shared/res/layout/clock_default_large.xml
@@ -18,6 +18,7 @@
-->
<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 390ff5e..ec0e427 100644
--- a/packages/SystemUI/shared/res/layout/clock_default_small.xml
+++ b/packages/SystemUI/shared/res/layout/clock_default_small.xml
@@ -18,6 +18,7 @@
-->
<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_height="wrap_content"
android:layout_gravity="start"
@@ -25,7 +26,6 @@
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 8f1959e..2739d59 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,15 +20,12 @@
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.systemui.animation.GlyphCallback
import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.TextAnimator
@@ -78,12 +75,6 @@
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
@@ -142,15 +133,6 @@
// relayout if the text didn't actually change.
if (!TextUtils.equals(text, formattedText)) {
text = formattedText
-
- // 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()
}
}
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 835d6e9..e707d4d 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,6 +35,8 @@
private val TAG = ClockRegistry::class.simpleName
private val DEBUG = true
+typealias ClockChangeListener = () -> Unit
+
/** ClockRegistry aggregates providers and plugins */
open class ClockRegistry(
val context: Context,
@@ -49,11 +51,6 @@
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()
@@ -61,7 +58,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.onClockChanged() }
+ clockChangeListeners.forEach { it() }
}
private val pluginListener = object : PluginListener<ClockProviderPlugin> {
@@ -120,11 +117,8 @@
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
}
@@ -133,7 +127,7 @@
if (DEBUG) {
Log.i(TAG, "Current clock ($currentId) was connected")
}
- clockChangeListeners.forEach { it.onClockChanged() }
+ clockChangeListeners.forEach { it() }
}
}
}
@@ -145,7 +139,7 @@
if (currentId == clock.clockId) {
Log.w(TAG, "Current clock ($currentId) was disconnected")
- clockChangeListeners.forEach { it.onClockChanged() }
+ clockChangeListeners.forEach { it() }
}
}
}
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 1d8abe3..5d8da59 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -19,9 +19,10 @@
import android.icu.text.NumberFormat
import android.util.TypedValue
import android.view.LayoutInflater
+import com.android.internal.colorextraction.ColorExtractor
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.Clock
-import com.android.systemui.plugins.ClockAnimations
+import com.android.systemui.plugins.ClockAnimation
import com.android.systemui.plugins.ClockEvents
import com.android.systemui.plugins.ClockId
import com.android.systemui.plugins.ClockMetadata
@@ -101,13 +102,10 @@
TypedValue.COMPLEX_UNIT_PX,
resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
)
- recomputePadding()
}
- override fun onColorPaletteChanged(resources: Resources) {
- val color = resources.getColor(android.R.color.system_accent1_100)
- clocks.forEach { it.setColors(DOZE_COLOR, color) }
- }
+ override fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) =
+ clocks.forEach { it.setColors(DOZE_COLOR, palette.mainColor) }
override fun onLocaleChanged(locale: Locale) {
val nf = NumberFormat.getInstance(locale)
@@ -121,17 +119,8 @@
}
}
- override var animations = DefaultClockAnimations(0f, 0f)
- private set
-
- inner class DefaultClockAnimations(
- dozeFraction: Float,
- foldFraction: Float
- ) : ClockAnimations {
- private var foldState = AnimationState(0f)
- private var dozeState = AnimationState(0f)
-
- init {
+ override val animation = object : ClockAnimation {
+ override fun initialize(dozeFraction: Float, foldFraction: Float) {
dozeState = AnimationState(dozeFraction)
foldState = AnimationState(foldFraction)
@@ -143,13 +132,14 @@
}
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) {
@@ -157,6 +147,7 @@
}
}
+ private var dozeState = AnimationState(0f)
override fun doze(fraction: Float) {
val (hasChanged, hasJumped) = dozeState.update(fraction)
if (hasChanged) {
@@ -181,19 +172,6 @@
init {
events.onLocaleChanged(Locale.getDefault())
- clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) }
- }
-
- override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
- recomputePadding()
- animations = DefaultClockAnimations(dozeFraction, foldFraction)
- events.onColorPaletteChanged(resources)
- events.onTimeTick()
- }
-
- private fun recomputePadding() {
- val topPadding = -1 * (largeClock.bottom.toInt() - 180)
- largeClock.setPadding(0, topPadding, 0, 0)
}
override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) }
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index e0b11d8..c69ff7e 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -182,6 +182,18 @@
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;
+ }
+
/** Animate the clock appearance */
public void animateAppear() {
if (!mIsDozing) mView.animateAppearOnLockscreen();
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
deleted file mode 100644
index efd7bcf..0000000
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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 com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.plugins.Clock
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-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 javax.inject.Inject
-
-/**
- * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
- * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
- */
-class ClockEventController @Inject constructor(
- 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
-) {
- var clock: Clock? = null
- set(value) {
- field = value
- if (value != null) {
- value.initialize(resources, dozeAmount, 0f)
- }
- }
-
- private var isDozing = false
- private set
-
- private var isCharging = false
- private var dozeAmount = 0f
- private var isKeyguardShowing = false
-
- private val configListener = object : ConfigurationController.ConfigurationListener {
- override fun onThemeChanged() {
- clock?.events?.onColorPaletteChanged(resources)
- }
- }
-
- 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)
- }
-
- fun unregisterListeners() {
- broadcastDispatcher.unregisterReceiver(localeBroadcastReceiver)
- configurationController.removeCallback(configListener)
- batteryController.removeCallback(batteryCallback)
- keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
- statusBarStateController.removeCallback(statusBarStateListener)
- }
-
- /**
- * Dump information for debugging
- */
- fun dump(pw: PrintWriter) {
- pw.println(this)
- clock?.dump(pw)
- }
-
- companion object {
- private val TAG = ClockEventController::class.simpleName
- private const val FORMAT_NUMBER = 1234567890
- }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index e1fabde..206b8be 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -5,8 +5,10 @@
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.Log;
+import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -15,14 +17,19 @@
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.Clock;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.shared.clocks.AnimatableClockView;
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.
*/
@@ -43,10 +50,17 @@
public static final int SMALL = 1;
/**
+ * Optional/alternative clock injected via plugin.
+ */
+ private ClockPlugin mClockPlugin;
+
+ /**
* Frame for small/large clocks
*/
- private FrameLayout mSmallClockFrame;
+ private FrameLayout mClockFrame;
private FrameLayout mLargeClockFrame;
+ private AnimatableClockView mClockView;
+ private AnimatableClockView mLargeClockView;
private View mStatusArea;
private int mSmartspaceTopOffset;
@@ -66,6 +80,12 @@
@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;
@@ -77,38 +97,97 @@
* 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();
- mSmallClockFrame = findViewById(R.id.lockscreen_clock_view);
+ mClockFrame = findViewById(R.id.lockscreen_clock_view);
+ mClockView = findViewById(R.id.animatable_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 setClock(Clock clock, int statusBarState) {
+ void setClockPlugin(ClockPlugin plugin, int statusBarState) {
// Disconnect from existing plugin.
- mSmallClockFrame.removeAllViews();
- mLargeClockFrame.removeAllViews();
-
- if (clock == null) {
- Log.e(TAG, "No clock being shown");
+ 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);
return;
}
-
// Attach small and big clock views to hierarchy.
- mSmallClockFrame.addView(clock.getSmallClock(), -1,
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- mLargeClockFrame.addView(clock.getLargeClock());
+ 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);
+ }
}
private void updateClockViews(boolean useLargeClock, boolean animate) {
@@ -124,14 +203,14 @@
int direction = 1;
float statusAreaYTranslation;
if (useLargeClock) {
- out = mSmallClockFrame;
+ out = mClockFrame;
in = mLargeClockFrame;
if (indexOfChild(in) == -1) addView(in);
direction = -1;
- statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop()
+ statusAreaYTranslation = mClockFrame.getTop() - mStatusArea.getTop()
+ mSmartspaceTopOffset;
} else {
- in = mSmallClockFrame;
+ in = mClockFrame;
out = mLargeClockFrame;
statusAreaYTranslation = 0f;
@@ -190,6 +269,18 @@
}
/**
+ * 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
@@ -220,11 +311,64 @@
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(" mClockFrame: " + mSmallClockFrame);
+ pw.println(" mClockPlugin: " + mClockPlugin);
+ pw.println(" mClockFrame: " + mClockFrame);
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 dd78f1c..ad06e05 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -22,6 +22,8 @@
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;
@@ -30,30 +32,36 @@
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.Clock;
+import com.android.systemui.plugins.ClockPlugin;
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;
@@ -63,24 +71,48 @@
*/
public class KeyguardClockSwitchController extends ViewController<KeyguardClockSwitch>
implements Dumpable {
+ private static final boolean CUSTOM_CLOCKS_ENABLED = true;
+
private final StatusBarStateController mStatusBarStateController;
- private final ClockRegistry mClockRegistry;
+ private final SysuiColorExtractor mColorExtractor;
+ private final ClockManager mClockManager;
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 frames for both small and large sizes */
- private FrameLayout mSmallClockFrame; // top aligned clock
+ /**
+ * Clock for both small and large sizes
+ */
+ private AnimatableClockController mClockViewController;
+ private FrameLayout mClockFrame; // top aligned clock
+ private AnimatableClockController mLargeClockViewController;
private FrameLayout mLargeClockFrame; // centered clock
@KeyguardClockSwitch.ClockSize
private int mCurrentClockSize = SMALL;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
private int mKeyguardClockTopMargin = 0;
- private final ClockRegistry.ClockChangeListener mClockChangedListener;
+
+ /**
+ * 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 ViewGroup mStatusArea;
// If set will replace keyguard_slice_view
@@ -89,9 +121,9 @@
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private boolean mOnlyClock = false;
- private final Executor mUiExecutor;
+ private Executor mUiExecutor;
private boolean mCanShowDoubleLineClock = true;
- private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
+ private ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
@Override
public void onChange(boolean change) {
updateDoubleLineClock();
@@ -112,32 +144,34 @@
public KeyguardClockSwitchController(
KeyguardClockSwitch keyguardClockSwitch,
StatusBarStateController statusBarStateController,
- ClockRegistry clockRegistry,
+ SysuiColorExtractor colorExtractor,
+ ClockManager clockManager,
KeyguardSliceViewController keyguardSliceViewController,
NotificationIconAreaController notificationIconAreaController,
+ BroadcastDispatcher broadcastDispatcher,
+ BatteryController batteryController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
LockscreenSmartspaceController smartspaceController,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
SecureSettings secureSettings,
@Main Executor uiExecutor,
- DumpManager dumpManager,
- ClockEventController clockEventController,
- FeatureFlags featureFlags) {
+ @Main Resources resources,
+ DumpManager dumpManager) {
super(keyguardClockSwitch);
mStatusBarStateController = statusBarStateController;
- mClockRegistry = clockRegistry;
+ mColorExtractor = colorExtractor;
+ mClockManager = clockManager;
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());
- };
}
/**
@@ -154,18 +188,40 @@
public void onInit() {
mKeyguardSliceViewController.init();
- mSmallClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
+ mClockFrame = 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() {
- mClockRegistry.registerClockChangeListener(mClockChangedListener);
- setClock(mClockRegistry.createCurrentClock());
- mClockEventController.registerListeners();
+ if (CUSTOM_CLOCKS_ENABLED) {
+ mClockManager.addOnClockChangedListener(mClockChangedListener);
+ }
+ mColorExtractor.addOnColorsChangedListener(mColorsListener);
+ mView.updateColors(getGradientColors());
mKeyguardClockTopMargin =
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
@@ -188,6 +244,7 @@
ksv.setVisibility(View.GONE);
addSmartspaceView(ksvIndex);
+ updateClockLayout();
}
mSecureSettings.registerContentObserverForUser(
@@ -209,9 +266,11 @@
@Override
protected void onViewDetached() {
- mClockRegistry.unregisterClockChangeListener(mClockChangedListener);
- mClockEventController.unregisterListeners();
- setClock(null);
+ if (CUSTOM_CLOCKS_ENABLED) {
+ mClockManager.removeOnClockChangedListener(mClockChangedListener);
+ }
+ mColorExtractor.removeOnColorsChangedListener(mColorsListener);
+ mView.setClockPlugin(null, mStatusBarStateController.getState());
mSecureSettings.unregisterContentObserver(mDoubleLineClockObserver);
@@ -250,6 +309,18 @@
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);
}
/**
@@ -263,34 +334,46 @@
mCurrentClockSize = clockSize;
- Clock clock = getClock();
boolean appeared = mView.switchToClock(clockSize, animate);
- if (clock != null && animate && appeared && clockSize == LARGE) {
- clock.getAnimations().enter();
+ if (animate && appeared && clockSize == LARGE) {
+ mLargeClockViewController.animateAppear();
+ }
+ }
+
+ public void animateFoldToAod() {
+ if (mClockViewController != null) {
+ mClockViewController.animateFoldAppear();
+ mLargeClockViewController.animateFoldAppear();
}
}
/**
- * Animates the clock view between folded and unfolded states
+ * If we're presenting a custom clock of just the default one.
*/
- public void animateFoldToAod(float foldFraction) {
- Clock clock = getClock();
- if (clock != null) {
- clock.getAnimations().fold(foldFraction);
- }
+ public boolean hasCustomClock() {
+ return mView.hasCustomClock();
+ }
+
+ /**
+ * Get the clock text size.
+ */
+ public float getClockTextSize() {
+ return mView.getTextSize();
}
/**
* Refresh clock. Called in response to TIME_TICK broadcasts.
*/
void refresh() {
+ if (mClockViewController != null) {
+ mClockViewController.refreshTime();
+ mLargeClockViewController.refreshTime();
+ }
if (mSmartspaceController != null) {
mSmartspaceController.requestSmartspaceUpdate();
}
- Clock clock = getClock();
- if (clock != null) {
- clock.getEvents().onTimeTick();
- }
+
+ mView.refresh();
}
/**
@@ -302,7 +385,7 @@
void updatePosition(int x, float scale, AnimationProperties props, boolean animate) {
x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x;
- PropertyAnimator.setProperty(mSmallClockFrame, AnimatableProperty.TRANSLATION_X,
+ PropertyAnimator.setProperty(mClockFrame, AnimatableProperty.TRANSLATION_X,
x, props, animate);
PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_X,
scale, props, animate);
@@ -315,39 +398,25 @@
}
}
+ 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.getLargeClock().getHeight();
+ int clockHeight = clock.getHeight();
return frameHeight / 2 + clockHeight / 2;
} else {
- 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();
+ return mClockFrame.findViewById(
+ com.android.systemui.R.id.animatable_clock_view).getHeight()
+ + statusBarHeaderHeight + mKeyguardClockTopMargin;
}
}
@@ -362,13 +431,12 @@
mNotificationIconAreaController.setupAodIcons(nic);
}
- private void setClock(Clock clock) {
- mClockEventController.setClock(clock);
- mView.setClock(clock, mStatusBarStateController.getState());
+ private void setClockPlugin(ClockPlugin plugin) {
+ mView.setClockPlugin(plugin, mStatusBarStateController.getState());
}
- private Clock getClock() {
- return mClockEventController.getClock();
+ private ColorExtractor.GradientColors getGradientColors() {
+ return mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
}
private int getCurrentLayoutDirection() {
@@ -401,10 +469,8 @@
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("currentClockSizeLarge=" + (mCurrentClockSize == LARGE));
pw.println("mCanShowDoubleLineClock=" + mCanShowDoubleLineClock);
- Clock clock = getClock();
- if (clock != null) {
- clock.dump(pw);
- }
+ mClockViewController.dump(pw);
+ mLargeClockViewController.dump(pw);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 83e23bd..cb3172d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -17,11 +17,14 @@
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;
@@ -43,6 +46,7 @@
private View mMediaHostContainer;
private float mDarkAmount = 0;
+ private int mTextColor;
public KeyguardStatusView(Context context) {
this(context, null, 0);
@@ -67,6 +71,7 @@
}
mKeyguardSlice = findViewById(R.id.keyguard_slice_view);
+ mTextColor = mClockView.getCurrentTextColor();
mMediaHostContainer = findViewById(R.id.status_view_media_container);
@@ -78,12 +83,15 @@
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. */
@@ -105,6 +113,7 @@
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 c715a4e..014d082 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -30,6 +30,8 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
+import java.util.TimeZone;
+
import javax.inject.Inject;
/**
@@ -94,6 +96,13 @@
}
/**
+ * 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.
*/
@@ -105,10 +114,16 @@
* 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(float foldFraction) {
- mKeyguardClockSwitchController.animateFoldToAod(foldFraction);
+ public void animateFoldToAod() {
+ mKeyguardClockSwitchController.animateFoldToAod();
+ }
+
+ /**
+ * If we're presenting a custom clock of just the default one.
+ */
+ public boolean hasCustomClock() {
+ return mKeyguardClockSwitchController.hasCustomClock();
}
/**
@@ -128,11 +143,24 @@
}
/**
- * Update the pivot position based on the parent view
+ * Set pivot x.
*/
- public void updatePivot(float parentWidth, float parentHeight) {
- mView.setPivotX(parentWidth / 2f);
- mView.setPivotY(mKeyguardClockSwitchController.getClockHeight() / 2f);
+ 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();
}
/**
@@ -212,6 +240,11 @@
}
@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 58e9bb8..88e4d90 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -294,6 +294,11 @@
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.
@@ -1122,6 +1127,13 @@
}
}
+ /**
+ * 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;
@@ -3909,9 +3921,9 @@
public void onAnimationEnd(Animator animation) {
endAction.run();
}
- }).setUpdateListener(anim -> {
- mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction());
}).start();
+
+ mKeyguardStatusViewController.animateFoldToAod();
}
/**
@@ -4624,6 +4636,7 @@
public void onDozeAmountChanged(float linearAmount, float amount) {
mInterpolatedDarkAmount = amount;
mLinearDarkAmount = linearAmount;
+ mKeyguardStatusViewController.setDarkAmount(mInterpolatedDarkAmount);
mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
positionClockAndNotifications();
}
@@ -4733,8 +4746,11 @@
updateMaxDisplayedNotifications(!shouldAvoidChangingNotificationsCount());
setIsFullWidth(mNotificationStackScrollLayoutController.getWidth() == mView.getWidth());
- // Update Clock Pivot (used by anti-burnin transformations)
- mKeyguardStatusViewController.updatePivot(mView.getWidth(), mView.getHeight());
+ // Update Clock Pivot
+ mKeyguardStatusViewController.setPivotX(((float) mView.getWidth()) / 2f);
+ mKeyguardStatusViewController.setPivotY(
+ (FONT_HEIGHT - CAP_HEIGHT) / 2048f
+ * mKeyguardStatusViewController.getClockTextSize());
// 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 fb26600..0848729 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
@@ -439,6 +439,7 @@
state |= DISABLE_CLOCK;
}
+
if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
if (mNetworkController.hasEmergencyCryptKeeperText()) {
state |= DISABLE_NOTIFICATION_ICONS;
@@ -448,6 +449,13 @@
}
}
+ // 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
deleted file mode 100644
index 4f39952..0000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.keyguard
-
-import android.content.BroadcastReceiver
-import android.testing.AndroidTestingRunner
-import android.widget.TextView
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.plugins.Clock
-import com.android.systemui.plugins.ClockAnimations
-import com.android.systemui.plugins.ClockEvents
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.statusbar.policy.BatteryController
-import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
-import java.util.TimeZone
-import org.junit.Assert.assertEquals
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.junit.MockitoJUnit
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-class ClockEventControllerTest : SysuiTestCase() {
-
- @JvmField @Rule val mockito = MockitoJUnit.rule()
- @Mock private lateinit var statusBarStateController: StatusBarStateController
- @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
- @Mock private lateinit var batteryController: BatteryController
- @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock private lateinit var configurationController: ConfigurationController
- @Mock private lateinit var animations: ClockAnimations
- @Mock private lateinit var events: ClockEvents
- @Mock private lateinit var clock: Clock
-
- private lateinit var clockEventController: ClockEventController
-
- @Before
- fun setUp() {
- whenever(clock.smallClock).thenReturn(TextView(context))
- whenever(clock.largeClock).thenReturn(TextView(context))
- whenever(clock.events).thenReturn(events)
- whenever(clock.animations).thenReturn(animations)
-
- clockEventController = ClockEventController(
- statusBarStateController,
- broadcastDispatcher,
- batteryController,
- keyguardUpdateMonitor,
- configurationController,
- context.resources,
- context
- )
- }
-
- @Test
- fun clockSet_validateInitialization() {
- clockEventController.clock = clock
-
- verify(clock).initialize(any(), anyFloat(), anyFloat())
- }
-
- @Test
- fun clockUnset_validateState() {
- clockEventController.clock = clock
- clockEventController.clock = null
-
- assertEquals(clockEventController.clock, null)
- }
-
- @Test
- fun themeChanged_verifyClockPaletteUpdated() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
- val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
- verify(configurationController).addCallback(capture(captor))
- captor.value.onThemeChanged()
-
- verify(events).onColorPaletteChanged(any())
- }
-
- @Test
- fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() {
- clockEventController.clock = clock
- clockEventController.registerListeners()
-
- val batteryCaptor = argumentCaptor<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.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 635ee9e..b2d9219 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -19,6 +19,7 @@
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;
@@ -40,19 +41,24 @@
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.Clock;
+import com.android.systemui.plugins.ClockPlugin;
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;
@@ -74,12 +80,22 @@
@Mock
private StatusBarStateController mStatusBarStateController;
@Mock
- private ClockRegistry mClockRegistry;
+ private SysuiColorExtractor mColorExtractor;
+ @Mock
+ private ClockManager mClockManager;
@Mock
KeyguardSliceViewController mKeyguardSliceViewController;
@Mock
NotificationIconAreaController mNotificationIconAreaController;
@Mock
+ BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ BatteryController mBatteryController;
+ @Mock
+ KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ KeyguardBypassController mBypassController;
+ @Mock
LockscreenSmartspaceController mSmartspaceController;
@Mock
@@ -87,11 +103,11 @@
@Mock
KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock
- private Clock mClock;
+ private ClockPlugin mClockPlugin;
+ @Mock
+ ColorExtractor.GradientColors mGradientColors;
@Mock
DumpManager mDumpManager;
- @Mock
- ClockEventController mClockEventController;
@Mock
private NotificationIconContainer mNotificationIcons;
@@ -123,6 +139,8 @@
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());
@@ -133,20 +151,23 @@
mController = new KeyguardClockSwitchController(
mView,
mStatusBarStateController,
- mClockRegistry,
+ mColorExtractor,
+ mClockManager,
mKeyguardSliceViewController,
mNotificationIconAreaController,
+ mBroadcastDispatcher,
+ mBatteryController,
+ mKeyguardUpdateMonitor,
mSmartspaceController,
mKeyguardUnlockAnimationController,
mSecureSettings,
mExecutor,
- mDumpManager,
- mClockEventController,
- mFeatureFlags
+ mResources,
+ mDumpManager
);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
- when(mClockRegistry.createCurrentClock()).thenReturn(mClock);
+ when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors);
mSliceView = new View(getContext());
when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
@@ -193,20 +214,20 @@
verifyAttachment(times(1));
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
- verify(mClockEventController).unregisterListeners();
+ verify(mColorExtractor).removeOnColorsChangedListener(
+ any(ColorExtractor.OnColorsChangedListener.class));
}
@Test
public void testPluginPassesStatusBarState() {
- ArgumentCaptor<ClockRegistry.ClockChangeListener> listenerArgumentCaptor =
- ArgumentCaptor.forClass(ClockRegistry.ClockChangeListener.class);
+ ArgumentCaptor<ClockManager.ClockChangedListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class);
mController.init();
- verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture());
+ verify(mClockManager).addOnClockChangedListener(listenerArgumentCaptor.capture());
- listenerArgumentCaptor.getValue().onClockChanged();
- verify(mView, times(2)).setClock(mClock, StatusBarState.SHADE);
- verify(mClockEventController, times(2)).setClock(mClock);
+ listenerArgumentCaptor.getValue().onClockChanged(mClockPlugin);
+ verify(mView).setClockPlugin(mClockPlugin, StatusBarState.SHADE);
}
@Test
@@ -263,8 +284,10 @@
}
private void verifyAttachment(VerificationMode times) {
- verify(mClockRegistry, times).registerClockChangeListener(
- any(ClockRegistry.ClockChangeListener.class));
- verify(mClockEventController, times).registerListeners();
+ verify(mClockManager, times).addOnClockChangedListener(
+ any(ClockManager.ClockChangedListener.class));
+ verify(mColorExtractor, times).addOnColorsChangedListener(
+ any(ColorExtractor.OnColorsChangedListener.class));
+ verify(mView, times).updateColors(mGradientColors);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index a0295d0..6c6f0ac 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
+import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
@@ -23,61 +24,56 @@
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.TextView;
+import android.widget.TextClock;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.Clock;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.shared.clocks.AnimatableClockView;
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_clock_switch layout is inflated.
+// the keyguard_clcok_switch layout is inflated.
@RunWithLooper(setAsMainLooper = true)
public class KeyguardClockSwitchTest extends SysuiTestCase {
- @Mock
- ViewGroup mMockKeyguardSliceView;
-
- @Mock
- Clock mClock;
-
- private FrameLayout mSmallClockFrame;
+ private FrameLayout mClockFrame;
private FrameLayout mLargeClockFrame;
+ private TextClock mBigClock;
+ private AnimatableClockView mClockView;
+ private AnimatableClockView mLargeClockView;
+ View mMockKeyguardSliceView;
KeyguardClockSwitch mKeyguardClockSwitch;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
+ mMockKeyguardSliceView = mock(KeyguardSliceView.class);
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() {
@@ -97,68 +93,164 @@
});
mKeyguardClockSwitch =
(KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
- mSmallClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
+ mClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
+ mClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_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 noPluginConnected_showNothing() {
- mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
- assertEquals(mLargeClockFrame.getChildCount(), 0);
- assertEquals(mSmallClockFrame.getChildCount(), 0);
+ 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);
}
@Test
- 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);
+ 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);
}
@Test
- public void onPluginConnected_showClock() {
- mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
-
- assertEquals(mClock.getSmallClock().getParent(), mSmallClockFrame);
- assertEquals(mClock.getLargeClock().getParent(), mLargeClockFrame);
+ public void onPluginConnected_nullView() {
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
+ assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
}
@Test
public void onPluginConnected_showSecondPluginClock() {
// GIVEN a plugin has already connected
- 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);
-
+ 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);
// THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
- assertThat(otherClock.getSmallClock().getParent()).isEqualTo(mSmallClockFrame);
- assertThat(otherClock.getLargeClock().getParent()).isEqualTo(mLargeClockFrame);
- assertThat(mClock.getSmallClock().getParent()).isNull();
- assertThat(mClock.getLargeClock().getParent()).isNull();
+ 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);
}
@Test
public void onPluginDisconnected_secondOfTwoDisconnected() {
// GIVEN two plugins are connected
- 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);
+ 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);
// WHEN the second plugin is disconnected
- 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();
+ 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);
}
@Test
@@ -170,7 +262,7 @@
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
- assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
+ assertThat(mClockFrame.getAlpha()).isEqualTo(0);
}
@Test
@@ -179,7 +271,7 @@
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
- assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
+ assertThat(mClockFrame.getAlpha()).isEqualTo(0);
}
@Test
@@ -189,8 +281,8 @@
mKeyguardClockSwitch.mClockInAnim.end();
mKeyguardClockSwitch.mClockOutAnim.end();
- assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1);
- assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE);
+ assertThat(mClockFrame.getAlpha()).isEqualTo(1);
+ assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE);
// only big clock is removed at switch
assertThat(mLargeClockFrame.getParent()).isNull();
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
@@ -200,8 +292,8 @@
public void switchingToSmallClockNoAnimation_makesBigClockDisappear() {
mKeyguardClockSwitch.switchToClock(SMALL, false);
- assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1);
- assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE);
+ assertThat(mClockFrame.getAlpha()).isEqualTo(1);
+ assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE);
// only big clock is removed at switch
assertThat(mLargeClockFrame.getParent()).isNull();
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 131eac6..1cbb8d0 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,16 +130,13 @@
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
@@ -161,14 +158,11 @@
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)
@@ -228,7 +222,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/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 25348f3..56804d5 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
@@ -230,9 +230,10 @@
}
@Test
- public void disable_isDozing_clockAndSystemInfoVisible() {
+ public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() {
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mStatusBarStateController.isDozing()).thenReturn(true);
+ when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
@@ -241,9 +242,10 @@
}
@Test
- public void disable_NotDozing_clockAndSystemInfoVisible() {
+ public void disable_customClockButNotDozing_clockAndSystemInfoVisible() {
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
@@ -252,6 +254,40 @@
}
@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);