Migrate KeyguardClockSwitch to new shared Clock library
This change modifies the KeyguardClockSwitch and Controller
to get clocks from the ClockRegistry. Since the only clock
available from the registry is the default one, this should
have no user-facing changes, and is intended only to update
the relevant codepaths.
Bug: 229771520
Test: Manual and Automated
Change-Id: Ia053aaec6987e00de980388a6c024d8bcf5203a2
(cherry picked from commit c8b33ca43f)
Merged-In: Ia053aaec6987e00de980388a6c024d8bcf5203a2
This commit is contained in:
@@ -485,7 +485,13 @@ class TextInterpolator(
|
||||
val out = mutableListOf<List<PositionedGlyphs>>()
|
||||
for (lineNo in 0 until layout.lineCount) { // Shape all lines.
|
||||
val lineStart = layout.getLineStart(lineNo)
|
||||
val count = layout.getLineEnd(lineNo) - lineStart
|
||||
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 runs = mutableListOf<PositionedGlyphs>()
|
||||
TextShaper.shapeText(layout.text, lineStart, count, layout.textDirectionHeuristic,
|
||||
paint) { _, _, glyphs, _ ->
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
*/
|
||||
package com.android.systemui.plugins
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import com.android.internal.colorextraction.ColorExtractor
|
||||
import com.android.systemui.plugins.annotations.ProvidesInterface
|
||||
import java.io.PrintWriter
|
||||
import java.util.Locale
|
||||
@@ -57,7 +57,15 @@ interface Clock {
|
||||
val events: ClockEvents
|
||||
|
||||
/** Triggers for various animations */
|
||||
val animation: ClockAnimation
|
||||
val animations: ClockAnimations
|
||||
|
||||
/** Initializes various rendering parameters. If never called, provides reasonable defaults. */
|
||||
fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
|
||||
events.onColorPaletteChanged(resources)
|
||||
animations.doze(dozeFraction)
|
||||
animations.fold(foldFraction)
|
||||
events.onTimeTick()
|
||||
}
|
||||
|
||||
/** Optional method for dumping debug information */
|
||||
fun dump(pw: PrintWriter) { }
|
||||
@@ -80,15 +88,12 @@ interface ClockEvents {
|
||||
/** Call whenever font settings change */
|
||||
fun onFontSettingChanged() { }
|
||||
|
||||
/** Call whenever the color pallete should update */
|
||||
fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) { }
|
||||
/** Call whenever the color palette should update */
|
||||
fun onColorPaletteChanged(resources: Resources) { }
|
||||
}
|
||||
|
||||
/** Methods which trigger various clock animations */
|
||||
interface ClockAnimation {
|
||||
/** Initializes the doze & fold animation positions. Defaults to neither folded nor dozing. */
|
||||
fun initialize(dozeFraction: Float, foldFraction: Float) { }
|
||||
|
||||
interface ClockAnimations {
|
||||
/** Runs an enter animation (if any) */
|
||||
fun enter() { }
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -31,42 +31,14 @@
|
||||
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="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
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
|
||||
|
||||
@@ -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:includeFontPadding="false"
|
||||
android:textColor="@android:color/white"
|
||||
android:format12Hour="@string/dream_time_complication_12_hr_time_format"
|
||||
|
||||
@@ -664,13 +664,7 @@
|
||||
<!-- 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_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="keyguard_large_clock_top_padding">100dp</dimen>
|
||||
|
||||
<dimen name="notification_scrim_corner_radius">32dp</dimen>
|
||||
|
||||
@@ -890,11 +884,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>
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
@@ -26,6 +25,7 @@
|
||||
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"
|
||||
|
||||
@@ -20,12 +20,15 @@ import android.annotation.ColorInt
|
||||
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
|
||||
@@ -75,6 +78,12 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
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
|
||||
@@ -133,6 +142,15 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@ import javax.inject.Inject
|
||||
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,12 +49,17 @@ open class ClockRegistry(
|
||||
defaultClockProvider: DefaultClockProvider
|
||||
) : this(context, pluginManager, handler, defaultClockProvider as ClockProvider) { }
|
||||
|
||||
// Usually this would be a typealias, but a SAM provides better java interop
|
||||
fun interface ClockChangeListener {
|
||||
fun onClockChanged()
|
||||
}
|
||||
|
||||
private val gson = Gson()
|
||||
private val availableClocks = mutableMapOf<ClockId, ClockInfo>()
|
||||
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> {
|
||||
@@ -73,7 +76,7 @@ open class ClockRegistry(
|
||||
context.contentResolver,
|
||||
Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE
|
||||
)
|
||||
return gson.fromJson(json, ClockSetting::class.java).clockId
|
||||
return gson.fromJson(json, ClockSetting::class.java)?.clockId ?: DEFAULT_CLOCK_ID
|
||||
}
|
||||
set(value) {
|
||||
val json = gson.toJson(ClockSetting(value, System.currentTimeMillis()))
|
||||
@@ -100,8 +103,11 @@ open class ClockRegistry(
|
||||
val id = clock.clockId
|
||||
val current = availableClocks[id]
|
||||
if (current != null) {
|
||||
Log.e(TAG, "Clock Id conflict: $id is registered by both " +
|
||||
"${provider::class.simpleName} and ${current.provider::class.simpleName}")
|
||||
Log.e(
|
||||
TAG,
|
||||
"Clock Id conflict: $id is registered by both " +
|
||||
"${provider::class.simpleName} and ${current.provider::class.simpleName}"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -110,7 +116,7 @@ open class ClockRegistry(
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Current clock ($currentId) was connected")
|
||||
}
|
||||
clockChangeListeners.forEach { it() }
|
||||
clockChangeListeners.forEach { it.onClockChanged() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +128,7 @@ open class ClockRegistry(
|
||||
|
||||
if (currentId == clock.clockId) {
|
||||
Log.w(TAG, "Current clock ($currentId) was disconnected")
|
||||
clockChangeListeners.forEach { it() }
|
||||
clockChangeListeners.forEach { it.onClockChanged() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,9 @@ import android.graphics.drawable.Drawable
|
||||
import android.icu.text.NumberFormat
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import com.android.internal.colorextraction.ColorExtractor
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.plugins.ClockAnimation
|
||||
import com.android.systemui.plugins.ClockAnimations
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
import com.android.systemui.plugins.ClockId
|
||||
import com.android.systemui.plugins.ClockMetadata
|
||||
@@ -102,10 +101,13 @@ class DefaultClock(
|
||||
TypedValue.COMPLEX_UNIT_PX,
|
||||
resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
|
||||
)
|
||||
recomputePadding()
|
||||
}
|
||||
|
||||
override fun onColorPaletteChanged(palette: ColorExtractor.GradientColors) =
|
||||
clocks.forEach { it.setColors(DOZE_COLOR, palette.mainColor) }
|
||||
override fun onColorPaletteChanged(resources: Resources) {
|
||||
val color = resources.getColor(android.R.color.system_accent1_100)
|
||||
clocks.forEach { it.setColors(DOZE_COLOR, color) }
|
||||
}
|
||||
|
||||
override fun onLocaleChanged(locale: Locale) {
|
||||
val nf = NumberFormat.getInstance(locale)
|
||||
@@ -119,8 +121,17 @@ class DefaultClock(
|
||||
}
|
||||
}
|
||||
|
||||
override val animation = object : ClockAnimation {
|
||||
override fun initialize(dozeFraction: Float, foldFraction: Float) {
|
||||
override var animations = DefaultClockAnimations(0f, 0f)
|
||||
private set
|
||||
|
||||
inner class DefaultClockAnimations(
|
||||
dozeFraction: Float,
|
||||
foldFraction: Float
|
||||
) : ClockAnimations {
|
||||
private var foldState = AnimationState(0f)
|
||||
private var dozeState = AnimationState(0f)
|
||||
|
||||
init {
|
||||
dozeState = AnimationState(dozeFraction)
|
||||
foldState = AnimationState(foldFraction)
|
||||
|
||||
@@ -132,14 +143,13 @@ class DefaultClock(
|
||||
}
|
||||
|
||||
override fun enter() {
|
||||
if (dozeState.isActive) {
|
||||
if (!dozeState.isActive) {
|
||||
clocks.forEach { it.animateAppearOnLockscreen() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun charge() = clocks.forEach { it.animateCharge { dozeState.isActive } }
|
||||
|
||||
private var foldState = AnimationState(0f)
|
||||
override fun fold(fraction: Float) {
|
||||
val (hasChanged, hasJumped) = foldState.update(fraction)
|
||||
if (hasChanged) {
|
||||
@@ -147,7 +157,6 @@ class DefaultClock(
|
||||
}
|
||||
}
|
||||
|
||||
private var dozeState = AnimationState(0f)
|
||||
override fun doze(fraction: Float) {
|
||||
val (hasChanged, hasJumped) = dozeState.update(fraction)
|
||||
if (hasChanged) {
|
||||
@@ -172,6 +181,19 @@ class DefaultClock(
|
||||
|
||||
init {
|
||||
events.onLocaleChanged(Locale.getDefault())
|
||||
clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) }
|
||||
}
|
||||
|
||||
override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
|
||||
recomputePadding()
|
||||
animations = DefaultClockAnimations(dozeFraction, foldFraction)
|
||||
events.onColorPaletteChanged(resources)
|
||||
events.onTimeTick()
|
||||
}
|
||||
|
||||
private fun recomputePadding() {
|
||||
val topPadding = -1 * (largeClock.bottom.toInt() - 180)
|
||||
largeClock.setPadding(0, topPadding, 0, 0)
|
||||
}
|
||||
|
||||
override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) }
|
||||
|
||||
@@ -182,18 +182,6 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
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();
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,8 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -17,19 +15,14 @@ import android.widget.RelativeLayout;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewScope;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.plugins.ClockPlugin;
|
||||
import com.android.systemui.shared.clocks.AnimatableClockView;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
|
||||
*/
|
||||
@@ -49,18 +42,11 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
public static final int LARGE = 0;
|
||||
public static final int SMALL = 1;
|
||||
|
||||
/**
|
||||
* Optional/alternative clock injected via plugin.
|
||||
*/
|
||||
private ClockPlugin mClockPlugin;
|
||||
|
||||
/**
|
||||
* Frame for small/large clocks
|
||||
*/
|
||||
private FrameLayout mClockFrame;
|
||||
private FrameLayout mSmallClockFrame;
|
||||
private FrameLayout mLargeClockFrame;
|
||||
private AnimatableClockView mClockView;
|
||||
private AnimatableClockView mLargeClockView;
|
||||
|
||||
private View mStatusArea;
|
||||
private int mSmartspaceTopOffset;
|
||||
@@ -80,12 +66,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
@VisibleForTesting AnimatorSet mClockOutAnim = null;
|
||||
private ObjectAnimator mStatusAreaAnim = null;
|
||||
|
||||
/**
|
||||
* If the Keyguard Slice has a header (big center-aligned text.)
|
||||
*/
|
||||
private boolean mSupportsDarkText;
|
||||
private int[] mColorPalette;
|
||||
|
||||
private int mClockSwitchYAmount;
|
||||
@VisibleForTesting boolean mChildrenAreLaidOut = false;
|
||||
|
||||
@@ -97,97 +77,38 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
* Apply dp changes on font/scale change
|
||||
*/
|
||||
public void onDensityOrFontScaleChanged() {
|
||||
mLargeClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
|
||||
.getDimensionPixelSize(R.dimen.large_clock_text_size));
|
||||
mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
|
||||
.getDimensionPixelSize(R.dimen.clock_text_size));
|
||||
|
||||
mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.keyguard_clock_switch_y_shift);
|
||||
|
||||
mSmartspaceTopOffset = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.keyguard_smartspace_top_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this view is presenting a custom clock, or the default implementation.
|
||||
*/
|
||||
public boolean hasCustomClock() {
|
||||
return mClockPlugin != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mClockFrame = findViewById(R.id.lockscreen_clock_view);
|
||||
mClockView = findViewById(R.id.animatable_clock_view);
|
||||
mSmallClockFrame = findViewById(R.id.lockscreen_clock_view);
|
||||
mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large);
|
||||
mLargeClockView = findViewById(R.id.animatable_clock_view_large);
|
||||
mStatusArea = findViewById(R.id.keyguard_status_area);
|
||||
|
||||
onDensityOrFontScaleChanged();
|
||||
}
|
||||
|
||||
void setClockPlugin(ClockPlugin plugin, int statusBarState) {
|
||||
void setClock(Clock clock, int statusBarState) {
|
||||
// Disconnect from existing plugin.
|
||||
if (mClockPlugin != null) {
|
||||
View smallClockView = mClockPlugin.getView();
|
||||
if (smallClockView != null && smallClockView.getParent() == mClockFrame) {
|
||||
mClockFrame.removeView(smallClockView);
|
||||
}
|
||||
View bigClockView = mClockPlugin.getBigClockView();
|
||||
if (bigClockView != null && bigClockView.getParent() == mLargeClockFrame) {
|
||||
mLargeClockFrame.removeView(bigClockView);
|
||||
}
|
||||
mClockPlugin.onDestroyView();
|
||||
mClockPlugin = null;
|
||||
}
|
||||
if (plugin == null) {
|
||||
mClockView.setVisibility(View.VISIBLE);
|
||||
mLargeClockView.setVisibility(View.VISIBLE);
|
||||
mSmallClockFrame.removeAllViews();
|
||||
mLargeClockFrame.removeAllViews();
|
||||
|
||||
if (clock == null) {
|
||||
Log.e(TAG, "No clock being shown");
|
||||
return;
|
||||
}
|
||||
|
||||
// Attach small and big clock views to hierarchy.
|
||||
View smallClockView = plugin.getView();
|
||||
if (smallClockView != null) {
|
||||
mClockFrame.addView(smallClockView, -1,
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
mClockView.setVisibility(View.GONE);
|
||||
}
|
||||
View bigClockView = plugin.getBigClockView();
|
||||
if (bigClockView != null) {
|
||||
mLargeClockFrame.addView(bigClockView);
|
||||
mLargeClockView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Initialize plugin parameters.
|
||||
mClockPlugin = plugin;
|
||||
mClockPlugin.setStyle(getPaint().getStyle());
|
||||
mClockPlugin.setTextColor(getCurrentTextColor());
|
||||
mClockPlugin.setDarkAmount(mDarkAmount);
|
||||
if (mColorPalette != null) {
|
||||
mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It will also update plugin setStyle if plugin is connected.
|
||||
*/
|
||||
public void setStyle(Style style) {
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setStyle(style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It will also update plugin setTextColor if plugin is connected.
|
||||
*/
|
||||
public void setTextColor(int color) {
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setTextColor(color);
|
||||
}
|
||||
mSmallClockFrame.addView(clock.getSmallClock(), -1,
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
mLargeClockFrame.addView(clock.getLargeClock());
|
||||
}
|
||||
|
||||
private void updateClockViews(boolean useLargeClock, boolean animate) {
|
||||
@@ -203,14 +124,14 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
int direction = 1;
|
||||
float statusAreaYTranslation;
|
||||
if (useLargeClock) {
|
||||
out = mClockFrame;
|
||||
out = mSmallClockFrame;
|
||||
in = mLargeClockFrame;
|
||||
if (indexOfChild(in) == -1) addView(in);
|
||||
direction = -1;
|
||||
statusAreaYTranslation = mClockFrame.getTop() - mStatusArea.getTop()
|
||||
statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop()
|
||||
+ mSmartspaceTopOffset;
|
||||
} else {
|
||||
in = mClockFrame;
|
||||
in = mSmallClockFrame;
|
||||
out = mLargeClockFrame;
|
||||
statusAreaYTranslation = 0f;
|
||||
|
||||
@@ -268,18 +189,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
mStatusAreaAnim.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount (ratio) that the device has transitioned to doze.
|
||||
*
|
||||
* @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
|
||||
*/
|
||||
public void setDarkAmount(float darkAmount) {
|
||||
mDarkAmount = darkAmount;
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setDarkAmount(darkAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the desired clock and hide the other one
|
||||
*
|
||||
@@ -311,64 +220,11 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
mChildrenAreLaidOut = true;
|
||||
}
|
||||
|
||||
public Paint getPaint() {
|
||||
return mClockView.getPaint();
|
||||
}
|
||||
|
||||
public int getCurrentTextColor() {
|
||||
return mClockView.getCurrentTextColor();
|
||||
}
|
||||
|
||||
public float getTextSize() {
|
||||
return mClockView.getTextSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm.
|
||||
*/
|
||||
public void refresh() {
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.onTimeTick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies that the time zone has changed.
|
||||
*/
|
||||
public void onTimeZoneChanged(TimeZone timeZone) {
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.onTimeZoneChanged(timeZone);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies that the time format has changed.
|
||||
*
|
||||
* @param timeFormat "12" for 12-hour format, "24" for 24-hour format
|
||||
*/
|
||||
public void onTimeFormatChanged(String timeFormat) {
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.onTimeFormatChanged(timeFormat);
|
||||
}
|
||||
}
|
||||
|
||||
void updateColors(ColorExtractor.GradientColors colors) {
|
||||
mSupportsDarkText = colors.supportsDarkText();
|
||||
mColorPalette = colors.getColorPalette();
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setColorPalette(mSupportsDarkText, mColorPalette);
|
||||
}
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw, String[] args) {
|
||||
pw.println("KeyguardClockSwitch:");
|
||||
pw.println(" mClockPlugin: " + mClockPlugin);
|
||||
pw.println(" mClockFrame: " + mClockFrame);
|
||||
pw.println(" mClockFrame: " + mSmallClockFrame);
|
||||
pw.println(" mLargeClockFrame: " + mLargeClockFrame);
|
||||
pw.println(" mStatusArea: " + mStatusArea);
|
||||
pw.println(" mDarkAmount: " + mDarkAmount);
|
||||
pw.println(" mSupportsDarkText: " + mSupportsDarkText);
|
||||
pw.println(" mColorPalette: " + Arrays.toString(mColorPalette));
|
||||
pw.println(" mDisplayedClockSize: " + mDisplayedClockSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
|
||||
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
@@ -32,34 +30,28 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.keyguard.clock.ClockManager;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.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;
|
||||
@@ -69,48 +61,24 @@ import javax.inject.Inject;
|
||||
*/
|
||||
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;
|
||||
/** Clock frames for both small and large sizes */
|
||||
private FrameLayout mSmallClockFrame; // top aligned clock
|
||||
private FrameLayout mLargeClockFrame; // centered clock
|
||||
|
||||
@KeyguardClockSwitch.ClockSize
|
||||
private int mCurrentClockSize = SMALL;
|
||||
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
|
||||
private int mKeyguardClockTopMargin = 0;
|
||||
|
||||
/**
|
||||
* Listener for changes to the color palette.
|
||||
*
|
||||
* The color palette changes when the wallpaper is changed.
|
||||
*/
|
||||
private final ColorExtractor.OnColorsChangedListener mColorsListener =
|
||||
(extractor, which) -> {
|
||||
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
|
||||
mView.updateColors(getGradientColors());
|
||||
}
|
||||
};
|
||||
|
||||
private final ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
|
||||
private final ClockRegistry.ClockChangeListener mClockChangedListener;
|
||||
|
||||
private ViewGroup mStatusArea;
|
||||
// If set will replace keyguard_slice_view
|
||||
@@ -119,9 +87,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
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();
|
||||
@@ -142,34 +110,30 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
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) {
|
||||
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;
|
||||
|
||||
mClockChangedListener = () -> {
|
||||
setClock(mClockRegistry.createCurrentClock());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,40 +150,18 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
public 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);
|
||||
|
||||
@@ -242,7 +184,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
ksv.setVisibility(View.GONE);
|
||||
|
||||
addSmartspaceView(ksvIndex);
|
||||
updateClockLayout();
|
||||
}
|
||||
|
||||
mSecureSettings.registerContentObserverForUser(
|
||||
@@ -264,11 +205,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
|
||||
@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);
|
||||
|
||||
@@ -307,18 +246,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
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,44 +261,31 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
|
||||
boolean appeared = mView.switchToClock(clockSize, animate);
|
||||
if (animate && appeared && clockSize == LARGE) {
|
||||
mLargeClockViewController.animateAppear();
|
||||
}
|
||||
}
|
||||
|
||||
public void animateFoldToAod() {
|
||||
if (mClockViewController != null) {
|
||||
mClockViewController.animateFoldAppear();
|
||||
mLargeClockViewController.animateFoldAppear();
|
||||
getClock().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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,7 +297,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
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);
|
||||
@@ -396,25 +310,39 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,12 +357,13 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
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() {
|
||||
@@ -467,8 +396,10 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@ public class KeyguardStatusView extends GridLayout {
|
||||
private View mMediaHostContainer;
|
||||
|
||||
private float mDarkAmount = 0;
|
||||
private int mTextColor;
|
||||
|
||||
public KeyguardStatusView(Context context) {
|
||||
this(context, null, 0);
|
||||
@@ -71,7 +67,6 @@ public class KeyguardStatusView extends GridLayout {
|
||||
}
|
||||
|
||||
mKeyguardSlice = findViewById(R.id.keyguard_slice_view);
|
||||
mTextColor = mClockView.getCurrentTextColor();
|
||||
|
||||
mMediaHostContainer = findViewById(R.id.status_view_media_container);
|
||||
|
||||
@@ -83,15 +78,12 @@ public class KeyguardStatusView extends GridLayout {
|
||||
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 class KeyguardStatusView extends GridLayout {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
@@ -95,13 +93,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
mKeyguardSliceViewController.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
* 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 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,11 +211,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
refreshTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeZoneChanged(TimeZone timeZone) {
|
||||
mKeyguardClockSwitchController.updateTimeZone(timeZone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyguardVisibilityChanged(boolean showing) {
|
||||
if (showing) {
|
||||
|
||||
@@ -290,11 +290,6 @@ public final class NotificationPanelViewController extends PanelViewController {
|
||||
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.
|
||||
@@ -1107,13 +1102,6 @@ public final class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
@@ -3881,9 +3869,10 @@ public final class NotificationPanelViewController extends PanelViewController {
|
||||
endAction.run();
|
||||
}
|
||||
})
|
||||
.setUpdateListener(anim -> {
|
||||
mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction());
|
||||
})
|
||||
.start();
|
||||
|
||||
mKeyguardStatusViewController.animateFoldToAod();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4596,7 +4585,6 @@ public final class NotificationPanelViewController extends PanelViewController {
|
||||
public void onDozeAmountChanged(float linearAmount, float amount) {
|
||||
mInterpolatedDarkAmount = amount;
|
||||
mLinearDarkAmount = linearAmount;
|
||||
mKeyguardStatusViewController.setDarkAmount(mInterpolatedDarkAmount);
|
||||
mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
|
||||
positionClockAndNotifications();
|
||||
}
|
||||
@@ -4706,11 +4694,8 @@ public final class NotificationPanelViewController extends PanelViewController {
|
||||
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;
|
||||
|
||||
@@ -439,7 +439,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
state |= DISABLE_CLOCK;
|
||||
}
|
||||
|
||||
|
||||
if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
|
||||
if (mNetworkController.hasEmergencyCryptKeeperText()) {
|
||||
state |= DISABLE_NOTIFICATION_ICONS;
|
||||
@@ -449,13 +448,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
}
|
||||
}
|
||||
|
||||
// The shelf will be hidden when dozing with a custom clock, we must show notification
|
||||
// icons in this occasion.
|
||||
if (mStatusBarStateController.isDozing()
|
||||
&& mNotificationPanelViewController.hasCustomClock()) {
|
||||
state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
|
||||
}
|
||||
|
||||
if (mOngoingCallController.hasOngoingCall()) {
|
||||
state &= ~DISABLE_ONGOING_CALL_CHIP;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
package com.android.keyguard
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.plugins.ClockAnimations
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.statusbar.policy.BatteryController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import java.util.TimeZone
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.anyFloat
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
class ClockEventControllerTest : SysuiTestCase() {
|
||||
|
||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||
@Mock private lateinit var statusBarStateController: StatusBarStateController
|
||||
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
|
||||
@Mock private lateinit var batteryController: BatteryController
|
||||
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||
@Mock private lateinit var configurationController: ConfigurationController
|
||||
@Mock private lateinit var animations: ClockAnimations
|
||||
@Mock private lateinit var events: ClockEvents
|
||||
@Mock private lateinit var clock: Clock
|
||||
|
||||
private lateinit var clockEventController: ClockEventController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
whenever(clock.smallClock).thenReturn(TextView(context))
|
||||
whenever(clock.largeClock).thenReturn(TextView(context))
|
||||
whenever(clock.events).thenReturn(events)
|
||||
whenever(clock.animations).thenReturn(animations)
|
||||
|
||||
clockEventController = ClockEventController(
|
||||
statusBarStateController,
|
||||
broadcastDispatcher,
|
||||
batteryController,
|
||||
keyguardUpdateMonitor,
|
||||
configurationController,
|
||||
context.resources,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clockSet_validateInitialization() {
|
||||
clockEventController.clock = clock
|
||||
|
||||
verify(clock).initialize(any(), anyFloat(), anyFloat())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clockUnset_validateState() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.clock = null
|
||||
|
||||
assertEquals(clockEventController.clock, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun themeChanged_verifyClockPaletteUpdated() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<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())
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package com.android.keyguard;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -41,23 +40,18 @@ import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.keyguard.clock.ClockManager;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.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;
|
||||
@@ -79,22 +73,12 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private StatusBarStateController mStatusBarStateController;
|
||||
@Mock
|
||||
private SysuiColorExtractor mColorExtractor;
|
||||
@Mock
|
||||
private ClockManager mClockManager;
|
||||
private ClockRegistry mClockRegistry;
|
||||
@Mock
|
||||
KeyguardSliceViewController mKeyguardSliceViewController;
|
||||
@Mock
|
||||
NotificationIconAreaController mNotificationIconAreaController;
|
||||
@Mock
|
||||
BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Mock
|
||||
BatteryController mBatteryController;
|
||||
@Mock
|
||||
KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Mock
|
||||
KeyguardBypassController mBypassController;
|
||||
@Mock
|
||||
LockscreenSmartspaceController mSmartspaceController;
|
||||
|
||||
@Mock
|
||||
@@ -102,11 +86,11 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||
@Mock
|
||||
private ClockPlugin mClockPlugin;
|
||||
@Mock
|
||||
ColorExtractor.GradientColors mGradientColors;
|
||||
private Clock mClock;
|
||||
@Mock
|
||||
DumpManager mDumpManager;
|
||||
@Mock
|
||||
ClockEventController mClockEventController;
|
||||
|
||||
@Mock
|
||||
private NotificationIconContainer mNotificationIcons;
|
||||
@@ -136,8 +120,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
when(mView.getContext()).thenReturn(getContext());
|
||||
when(mView.getResources()).thenReturn(mResources);
|
||||
|
||||
when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView);
|
||||
when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView);
|
||||
when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame);
|
||||
when(mClockView.getContext()).thenReturn(getContext());
|
||||
when(mLargeClockView.getContext()).thenReturn(getContext());
|
||||
@@ -148,23 +130,19 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
mController = new KeyguardClockSwitchController(
|
||||
mView,
|
||||
mStatusBarStateController,
|
||||
mColorExtractor,
|
||||
mClockManager,
|
||||
mClockRegistry,
|
||||
mKeyguardSliceViewController,
|
||||
mNotificationIconAreaController,
|
||||
mBroadcastDispatcher,
|
||||
mBatteryController,
|
||||
mKeyguardUpdateMonitor,
|
||||
mSmartspaceController,
|
||||
mKeyguardUnlockAnimationController,
|
||||
mSecureSettings,
|
||||
mExecutor,
|
||||
mResources,
|
||||
mDumpManager
|
||||
mDumpManager,
|
||||
mClockEventController
|
||||
);
|
||||
|
||||
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);
|
||||
@@ -211,20 +189,20 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
verifyAttachment(times(1));
|
||||
|
||||
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
|
||||
verify(mColorExtractor).removeOnColorsChangedListener(
|
||||
any(ColorExtractor.OnColorsChangedListener.class));
|
||||
verify(mClockEventController).unregisterListeners();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPluginPassesStatusBarState() {
|
||||
ArgumentCaptor<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
|
||||
@@ -281,10 +259,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
private void verifyAttachment(VerificationMode times) {
|
||||
verify(mClockManager, times).addOnClockChangedListener(
|
||||
any(ClockManager.ClockChangedListener.class));
|
||||
verify(mColorExtractor, times).addOnColorsChangedListener(
|
||||
any(ColorExtractor.OnColorsChangedListener.class));
|
||||
verify(mView, times).updateColors(mGradientColors);
|
||||
verify(mClockRegistry, times).registerClockChangeListener(
|
||||
any(ClockRegistry.ClockChangeListener.class));
|
||||
verify(mClockEventController, times).registerListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
|
||||
@@ -24,56 +23,61 @@ import static com.android.keyguard.KeyguardClockSwitch.SMALL;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextClock;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.ClockPlugin;
|
||||
import com.android.systemui.shared.clocks.AnimatableClockView;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
// Need to run on the main thread because KeyguardSliceView$Row init checks for
|
||||
// the main thread before acquiring a wake lock. This class is constructed when
|
||||
// the keyguard_clcok_switch layout is inflated.
|
||||
// the keyguard_clock_switch layout is inflated.
|
||||
@RunWithLooper(setAsMainLooper = true)
|
||||
public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
private FrameLayout mClockFrame;
|
||||
private FrameLayout mLargeClockFrame;
|
||||
private TextClock mBigClock;
|
||||
@Mock
|
||||
ViewGroup mMockKeyguardSliceView;
|
||||
|
||||
@Mock
|
||||
Clock mClock;
|
||||
|
||||
private FrameLayout mSmallClockFrame;
|
||||
private FrameLayout mLargeClockFrame;
|
||||
|
||||
private AnimatableClockView mClockView;
|
||||
private AnimatableClockView mLargeClockView;
|
||||
View mMockKeyguardSliceView;
|
||||
KeyguardClockSwitch mKeyguardClockSwitch;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mMockKeyguardSliceView = mock(KeyguardSliceView.class);
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mMockKeyguardSliceView.getContext()).thenReturn(mContext);
|
||||
when(mMockKeyguardSliceView.findViewById(R.id.keyguard_status_area))
|
||||
.thenReturn(mMockKeyguardSliceView);
|
||||
|
||||
when(mClock.getSmallClock()).thenReturn(new TextView(getContext()));
|
||||
when(mClock.getLargeClock()).thenReturn(new TextView(getContext()));
|
||||
|
||||
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
|
||||
layoutInflater.setPrivateFactory(new LayoutInflater.Factory2() {
|
||||
|
||||
@@ -93,164 +97,68 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
});
|
||||
mKeyguardClockSwitch =
|
||||
(KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
|
||||
mClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
|
||||
mClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view);
|
||||
mSmallClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
|
||||
mLargeClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view_large);
|
||||
mLargeClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view_large);
|
||||
mBigClock = new TextClock(getContext());
|
||||
mKeyguardClockSwitch.mChildrenAreLaidOut = true;
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginConnected_showPluginClock() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
|
||||
assertThat(mClockView.getVisibility()).isEqualTo(GONE);
|
||||
assertThat(plugin.getView().getParent()).isEqualTo(mClockFrame);
|
||||
public void noPluginConnected_showNothing() {
|
||||
mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
|
||||
assertEquals(mLargeClockFrame.getChildCount(), 0);
|
||||
assertEquals(mSmallClockFrame.getChildCount(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginConnected_showPluginBigClock() {
|
||||
// GIVEN the plugin returns a view for the big clock
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
when(plugin.getBigClockView()).thenReturn(mBigClock);
|
||||
// WHEN the plugin is connected
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
// THEN the big clock container is visible and it is the parent of the
|
||||
// big clock view.
|
||||
assertThat(mLargeClockView.getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(mBigClock.getParent()).isEqualTo(mLargeClockFrame);
|
||||
public void pluginConnectedThenDisconnected_showNothing() {
|
||||
mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
|
||||
assertEquals(mLargeClockFrame.getChildCount(), 1);
|
||||
assertEquals(mSmallClockFrame.getChildCount(), 1);
|
||||
|
||||
mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
|
||||
assertEquals(mLargeClockFrame.getChildCount(), 0);
|
||||
assertEquals(mSmallClockFrame.getChildCount(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginConnected_nullView() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
|
||||
public void onPluginConnected_showClock() {
|
||||
mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
|
||||
|
||||
assertEquals(mClock.getSmallClock().getParent(), mSmallClockFrame);
|
||||
assertEquals(mClock.getLargeClock().getParent(), mLargeClockFrame);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginConnected_showSecondPluginClock() {
|
||||
// GIVEN a plugin has already connected
|
||||
ClockPlugin plugin1 = mock(ClockPlugin.class);
|
||||
when(plugin1.getView()).thenReturn(new TextClock(getContext()));
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
|
||||
// WHEN a second plugin is connected
|
||||
ClockPlugin plugin2 = mock(ClockPlugin.class);
|
||||
when(plugin2.getView()).thenReturn(new TextClock(getContext()));
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
|
||||
Clock otherClock = mock(Clock.class);
|
||||
when(otherClock.getSmallClock()).thenReturn(new TextView(getContext()));
|
||||
when(otherClock.getLargeClock()).thenReturn(new TextView(getContext()));
|
||||
mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
|
||||
mKeyguardClockSwitch.setClock(otherClock, StatusBarState.KEYGUARD);
|
||||
|
||||
// THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
|
||||
assertThat(plugin2.getView().getParent()).isEqualTo(mClockFrame);
|
||||
assertThat(plugin1.getView().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginConnected_darkAmountInitialized() {
|
||||
// GIVEN that the dark amount has already been set
|
||||
mKeyguardClockSwitch.setDarkAmount(0.5f);
|
||||
// WHEN a plugin is connected
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
// THEN dark amount should be initalized on the plugin.
|
||||
verify(plugin).setDarkAmount(0.5f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginDisconnected_showDefaultClock() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
assertThat(mClockView.getVisibility()).isEqualTo(GONE);
|
||||
|
||||
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
|
||||
assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
|
||||
|
||||
assertThat(plugin.getView().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginDisconnected_hidePluginBigClock() {
|
||||
// GIVEN the plugin returns a view for the big clock
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getBigClockView()).thenReturn(pluginView);
|
||||
// WHEN the plugin is connected and then disconnected
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
|
||||
// THEN the big lock container is GONE and the big clock view doesn't have
|
||||
// a parent.
|
||||
assertThat(mLargeClockView.getVisibility()).isEqualTo(VISIBLE);
|
||||
assertThat(pluginView.getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginDisconnected_nullView() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
|
||||
assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
|
||||
assertThat(otherClock.getSmallClock().getParent()).isEqualTo(mSmallClockFrame);
|
||||
assertThat(otherClock.getLargeClock().getParent()).isEqualTo(mLargeClockFrame);
|
||||
assertThat(mClock.getSmallClock().getParent()).isNull();
|
||||
assertThat(mClock.getLargeClock().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginDisconnected_secondOfTwoDisconnected() {
|
||||
// GIVEN two plugins are connected
|
||||
ClockPlugin plugin1 = mock(ClockPlugin.class);
|
||||
when(plugin1.getView()).thenReturn(new TextClock(getContext()));
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
|
||||
ClockPlugin plugin2 = mock(ClockPlugin.class);
|
||||
when(plugin2.getView()).thenReturn(new TextClock(getContext()));
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
|
||||
Clock otherClock = mock(Clock.class);
|
||||
when(otherClock.getSmallClock()).thenReturn(new TextView(getContext()));
|
||||
when(otherClock.getLargeClock()).thenReturn(new TextView(getContext()));
|
||||
mKeyguardClockSwitch.setClock(otherClock, StatusBarState.KEYGUARD);
|
||||
mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
|
||||
// WHEN the second plugin is disconnected
|
||||
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
|
||||
// THEN the default clock should be shown.
|
||||
assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
|
||||
assertThat(plugin1.getView().getParent()).isNull();
|
||||
assertThat(plugin2.getView().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginDisconnected_onDestroyView() {
|
||||
// GIVEN a plugin is connected
|
||||
ClockPlugin clockPlugin = mock(ClockPlugin.class);
|
||||
when(clockPlugin.getView()).thenReturn(new TextClock(getContext()));
|
||||
mKeyguardClockSwitch.setClockPlugin(clockPlugin, StatusBarState.KEYGUARD);
|
||||
// WHEN the plugin is disconnected
|
||||
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
|
||||
// THEN onDestroyView is called on the plugin
|
||||
verify(clockPlugin).onDestroyView();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTextColor_pluginClockSetTextColor() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
|
||||
mKeyguardClockSwitch.setTextColor(Color.WHITE);
|
||||
|
||||
verify(plugin).setTextColor(Color.WHITE);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void setStyle_pluginClockSetStyle() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
Style style = mock(Style.class);
|
||||
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
|
||||
|
||||
mKeyguardClockSwitch.setStyle(style);
|
||||
|
||||
verify(plugin).setStyle(style);
|
||||
mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
|
||||
// THEN nothing should be shown
|
||||
assertThat(otherClock.getSmallClock().getParent()).isNull();
|
||||
assertThat(otherClock.getLargeClock().getParent()).isNull();
|
||||
assertThat(mClock.getSmallClock().getParent()).isNull();
|
||||
assertThat(mClock.getLargeClock().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -262,7 +170,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
|
||||
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
|
||||
assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
|
||||
assertThat(mClockFrame.getAlpha()).isEqualTo(0);
|
||||
assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -271,7 +179,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
|
||||
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
|
||||
assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
|
||||
assertThat(mClockFrame.getAlpha()).isEqualTo(0);
|
||||
assertThat(mSmallClockFrame.getAlpha()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -281,8 +189,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
mKeyguardClockSwitch.mClockInAnim.end();
|
||||
mKeyguardClockSwitch.mClockOutAnim.end();
|
||||
|
||||
assertThat(mClockFrame.getAlpha()).isEqualTo(1);
|
||||
assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE);
|
||||
assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1);
|
||||
assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE);
|
||||
// only big clock is removed at switch
|
||||
assertThat(mLargeClockFrame.getParent()).isNull();
|
||||
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
|
||||
@@ -292,8 +200,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
public void switchingToSmallClockNoAnimation_makesBigClockDisappear() {
|
||||
mKeyguardClockSwitch.switchToClock(SMALL, false);
|
||||
|
||||
assertThat(mClockFrame.getAlpha()).isEqualTo(1);
|
||||
assertThat(mClockFrame.getVisibility()).isEqualTo(VISIBLE);
|
||||
assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1);
|
||||
assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE);
|
||||
// only big clock is removed at switch
|
||||
assertThat(mLargeClockFrame.getParent()).isNull();
|
||||
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0);
|
||||
|
||||
@@ -129,13 +129,16 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
pluginListener.onPluginConnected(plugin1, mockContext)
|
||||
pluginListener.onPluginConnected(plugin2, mockContext)
|
||||
val list = registry.getClocks()
|
||||
assertEquals(list, listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2"),
|
||||
ClockMetadata("clock_3", "clock 3"),
|
||||
ClockMetadata("clock_4", "clock 4")
|
||||
))
|
||||
assertEquals(
|
||||
list,
|
||||
listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2"),
|
||||
ClockMetadata("clock_3", "clock 3"),
|
||||
ClockMetadata("clock_4", "clock 4")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -157,11 +160,14 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
pluginListener.onPluginConnected(plugin1, mockContext)
|
||||
pluginListener.onPluginConnected(plugin2, mockContext)
|
||||
val list = registry.getClocks()
|
||||
assertEquals(list, listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2")
|
||||
))
|
||||
assertEquals(
|
||||
list,
|
||||
listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2")
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(registry.createExampleClock("clock_1"), mockClock)
|
||||
assertEquals(registry.createExampleClock("clock_2"), mockClock)
|
||||
@@ -221,7 +227,7 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
pluginListener.onPluginConnected(plugin2, mockContext)
|
||||
|
||||
var changeCallCount = 0
|
||||
registry.registerClockChangeListener({ changeCallCount++ })
|
||||
registry.registerClockChangeListener { changeCallCount++ }
|
||||
|
||||
pluginListener.onPluginDisconnected(plugin1)
|
||||
assertEquals(0, changeCallCount)
|
||||
|
||||
@@ -230,10 +230,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() {
|
||||
public void disable_isDozing_clockAndSystemInfoVisible() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(true);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false);
|
||||
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
@@ -242,10 +241,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_customClockButNotDozing_clockAndSystemInfoVisible() {
|
||||
public void disable_NotDozing_clockAndSystemInfoVisible() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
|
||||
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
@@ -253,40 +251,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_dozingAndCustomClock_clockAndSystemInfoHidden() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(true);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
|
||||
|
||||
// Make sure they start out as visible
|
||||
assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.GONE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDozingChanged_clockAndSystemInfoVisibilitiesUpdated() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(true);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
|
||||
|
||||
// Make sure they start out as visible
|
||||
assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
|
||||
fragment.onDozingChanged(true);
|
||||
|
||||
// When this callback is triggered, we want to make sure the clock and system info
|
||||
// visibilities are recalculated. Since dozing=true, they shouldn't be visible.
|
||||
assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.GONE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_headsUpShouldBeVisibleTrue_clockDisabled() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
|
||||
Reference in New Issue
Block a user