Merge changes from topic "clock_cherrypick_fixes" into tm-qpr-dev
* changes: [DO NOT MERGE] Initialize TimeZone during DefaultClockProvider init [DO NOT MERGE] Correct large clock position [DO NOT MERGE] Additional Tests for DefaultClock [DO NOT MERGE] Update DefaultClockProvider colors [DO NOT MERGE] Moving Text Protection to Clock Event Controller [DO NOT MERGE] Adding Region Sampler to Animatable Clocks [DO NOT MERGE] Revert "[DO NOT MERGE]Revert "Migrate KeyguardClockSwitch to new..."
This commit is contained in:
committed by
Android (Google) Code Review
commit
6e98d9838d
@@ -39,6 +39,7 @@
|
||||
-packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
|
||||
-packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
|
||||
-packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
|
||||
-packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
|
||||
-packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
|
||||
-packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
|
||||
-packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
|
||||
@@ -156,6 +157,8 @@
|
||||
-packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
|
||||
-packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt
|
||||
-packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
|
||||
-packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
|
||||
-packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
|
||||
-packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
|
||||
-packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt
|
||||
-packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
|
||||
@@ -246,6 +249,7 @@
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
|
||||
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
|
||||
@@ -575,6 +579,7 @@
|
||||
-packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt
|
||||
-packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
|
||||
@@ -633,6 +638,7 @@
|
||||
-packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
|
||||
@@ -720,6 +726,7 @@
|
||||
-packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
|
||||
|
||||
@@ -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, true, true)
|
||||
animations.doze(dozeFraction)
|
||||
animations.fold(foldFraction)
|
||||
events.onTimeTick()
|
||||
}
|
||||
|
||||
/** Optional method for dumping debug information */
|
||||
fun dump(pw: PrintWriter) { }
|
||||
@@ -80,15 +88,16 @@ 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,
|
||||
smallClockIsDark: Boolean,
|
||||
largeClockIsDark: Boolean
|
||||
) { }
|
||||
}
|
||||
|
||||
/** Methods which trigger various clock animations */
|
||||
interface ClockAnimation {
|
||||
/** Initializes the doze & fold animation positions. Defaults to neither folded nor dozing. */
|
||||
fun initialize(dozeFraction: Float, foldFraction: Float) { }
|
||||
|
||||
interface ClockAnimations {
|
||||
/** Runs an enter animation (if any) */
|
||||
fun enter() { }
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -23,6 +23,7 @@
|
||||
android:id="@+id/keyguard_clock_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:layout_gravity="center_horizontal|top">
|
||||
<FrameLayout
|
||||
android:id="@+id/lockscreen_clock_view"
|
||||
@@ -30,44 +31,13 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:paddingStart="@dimen/clock_padding_start">
|
||||
<com.android.systemui.shared.clocks.AnimatableClockView
|
||||
android:id="@+id/animatable_clock_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:gravity="start"
|
||||
android:textSize="@dimen/clock_text_size"
|
||||
android:fontFamily="@font/clock"
|
||||
android:elegantTextHeight="false"
|
||||
android:singleLine="true"
|
||||
android:fontFeatureSettings="pnum"
|
||||
chargeAnimationDelay="350"
|
||||
dozeWeight="200"
|
||||
lockScreenWeight="400"
|
||||
/>
|
||||
</FrameLayout>
|
||||
android:paddingStart="@dimen/clock_padding_start" />
|
||||
<FrameLayout
|
||||
android:id="@+id/lockscreen_clock_view_large"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/keyguard_slice_view"
|
||||
android:visibility="gone">
|
||||
<com.android.systemui.shared.clocks.AnimatableClockView
|
||||
android:id="@+id/animatable_clock_view_large"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center_horizontal"
|
||||
android:textSize="@dimen/large_clock_text_size"
|
||||
android:fontFamily="@font/clock"
|
||||
android:typeface="monospace"
|
||||
android:elegantTextHeight="false"
|
||||
chargeAnimationDelay="200"
|
||||
dozeWeight="200"
|
||||
lockScreenWeight="400"
|
||||
/>
|
||||
</FrameLayout>
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/keyguard_large_clock_top_margin"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- Not quite optimal but needed to translate these items as a group. The
|
||||
NotificationIconContainer has its own logic for translation. -->
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
android:id="@+id/time_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/clock"
|
||||
android:fontFamily="@*android:string/config_clockFontFamily"
|
||||
android:textColor="@android:color/white"
|
||||
android:format12Hour="@string/dream_time_complication_12_hr_time_format"
|
||||
android:format24Hour="@string/dream_time_complication_24_hr_time_format"
|
||||
|
||||
@@ -671,12 +671,6 @@
|
||||
<!-- With the large clock, move up slightly from the center -->
|
||||
<dimen name="keyguard_large_clock_top_margin">-60dp</dimen>
|
||||
|
||||
<!-- TODO: Remove during migration -->
|
||||
<!-- Default line spacing multiplier between hours and minutes of the keyguard clock -->
|
||||
<item name="keyguard_clock_line_spacing_scale" type="dimen" format="float">.7</item>
|
||||
<!-- Burmese line spacing multiplier between hours and minutes of the keyguard clock -->
|
||||
<item name="keyguard_clock_line_spacing_scale_burmese" type="dimen" format="float">1</item>
|
||||
|
||||
<dimen name="notification_scrim_corner_radius">32dp</dimen>
|
||||
|
||||
<!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
|
||||
@@ -895,11 +889,6 @@
|
||||
burn-in on AOD. -->
|
||||
<dimen name="burn_in_prevention_offset_y_clock">42dp</dimen>
|
||||
|
||||
<!-- Clock maximum font size (dp is intentional, to prevent any further scaling) -->
|
||||
<!-- TODO: Remove when clock migration complete -->
|
||||
<dimen name="large_clock_text_size">150dp</dimen>
|
||||
<dimen name="clock_text_size">86dp</dimen>
|
||||
|
||||
<!-- The maximum offset in either direction that icons move to prevent burn-in on AOD. -->
|
||||
<dimen name="default_burn_in_prevention_offset">15dp</dimen>
|
||||
|
||||
|
||||
@@ -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,14 +18,14 @@
|
||||
-->
|
||||
<com.android.systemui.shared.clocks.AnimatableClockView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/animatable_clock_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:gravity="start"
|
||||
android:textSize="@dimen/small_clock_text_size"
|
||||
android:fontFamily="@*android:string/config_clockFontFamily"
|
||||
android:elegantTextHeight="false"
|
||||
android:ellipsize="none"
|
||||
android:singleLine="true"
|
||||
android:fontFeatureSettings="pnum"
|
||||
chargeAnimationDelay="350"
|
||||
|
||||
@@ -20,12 +20,16 @@ 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.internal.annotations.VisibleForTesting
|
||||
import com.android.systemui.animation.GlyphCallback
|
||||
import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.animation.TextAnimator
|
||||
@@ -74,7 +78,8 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
private var textAnimator: TextAnimator? = null
|
||||
private var onTextAnimatorInitialized: Runnable? = null
|
||||
|
||||
var timeOverrideInMillis: Long? = null
|
||||
@VisibleForTesting var isAnimationEnabled: Boolean = true
|
||||
@VisibleForTesting var timeOverrideInMillis: Long? = null
|
||||
|
||||
val dozingWeight: Int
|
||||
get() = if (useBoldedVersion()) dozingWeightInternal + 100 else dozingWeightInternal
|
||||
@@ -82,6 +87,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
|
||||
@@ -141,6 +152,15 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
if (!TextUtils.equals(text, formattedText)) {
|
||||
text = formattedText
|
||||
lastTextUpdate = getTimestamp()
|
||||
|
||||
// Because the TextLayout may mutate under the hood as a result of the new text, we
|
||||
// notify the TextAnimator that it may have changed and request a measure/layout. A
|
||||
// crash will occur on the next invocation of setTextStyle if the layout is mutated
|
||||
// without being notified TextInterpolator being notified.
|
||||
if (layout != null) {
|
||||
textAnimator?.updateLayout(layout)
|
||||
}
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +220,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
fun animateAppearOnLockscreen() {
|
||||
if (textAnimator == null) {
|
||||
if (isAnimationEnabled && textAnimator == null) {
|
||||
return
|
||||
}
|
||||
setTextStyle(
|
||||
@@ -216,7 +236,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
weight = lockScreenWeight,
|
||||
textSize = -1f,
|
||||
color = lockScreenColor,
|
||||
animate = true,
|
||||
animate = isAnimationEnabled,
|
||||
duration = APPEAR_ANIM_DURATION,
|
||||
delay = 0,
|
||||
onAnimationEnd = null
|
||||
@@ -224,7 +244,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
fun animateFoldAppear(animate: Boolean = true) {
|
||||
if (textAnimator == null) {
|
||||
if (isAnimationEnabled && textAnimator == null) {
|
||||
return
|
||||
}
|
||||
setTextStyle(
|
||||
@@ -240,7 +260,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
weight = dozingWeightInternal,
|
||||
textSize = -1f,
|
||||
color = dozingColor,
|
||||
animate = animate,
|
||||
animate = animate && isAnimationEnabled,
|
||||
interpolator = Interpolators.EMPHASIZED_DECELERATE,
|
||||
duration = ANIMATION_DURATION_FOLD_TO_AOD.toLong(),
|
||||
delay = 0,
|
||||
@@ -258,7 +278,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
weight = if (isDozing()) dozingWeight else lockScreenWeight,
|
||||
textSize = -1f,
|
||||
color = null,
|
||||
animate = true,
|
||||
animate = isAnimationEnabled,
|
||||
duration = CHARGE_ANIM_DURATION_PHASE_1,
|
||||
delay = 0,
|
||||
onAnimationEnd = null
|
||||
@@ -268,7 +288,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
weight = if (isDozing()) lockScreenWeight else dozingWeight,
|
||||
textSize = -1f,
|
||||
color = null,
|
||||
animate = true,
|
||||
animate = isAnimationEnabled,
|
||||
duration = CHARGE_ANIM_DURATION_PHASE_0,
|
||||
delay = chargeAnimationDelay.toLong(),
|
||||
onAnimationEnd = startAnimPhase2
|
||||
@@ -280,7 +300,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
weight = if (isDozing) dozingWeight else lockScreenWeight,
|
||||
textSize = -1f,
|
||||
color = if (isDozing) dozingColor else lockScreenColor,
|
||||
animate = animate,
|
||||
animate = animate && isAnimationEnabled,
|
||||
duration = DOZE_ANIM_DURATION,
|
||||
delay = 0,
|
||||
onAnimationEnd = null
|
||||
@@ -314,7 +334,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
weight = weight,
|
||||
textSize = textSize,
|
||||
color = color,
|
||||
animate = animate,
|
||||
animate = animate && isAnimationEnabled,
|
||||
duration = duration,
|
||||
interpolator = interpolator,
|
||||
delay = delay,
|
||||
@@ -352,7 +372,7 @@ class AnimatableClockView @JvmOverloads constructor(
|
||||
weight = weight,
|
||||
textSize = textSize,
|
||||
color = color,
|
||||
animate = animate,
|
||||
animate = animate && isAnimationEnabled,
|
||||
interpolator = null,
|
||||
duration = duration,
|
||||
delay = delay,
|
||||
|
||||
@@ -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,6 +49,11 @@ open class ClockRegistry(
|
||||
defaultClockProvider: DefaultClockProvider
|
||||
) : this(context, pluginManager, handler, defaultClockProvider as ClockProvider) { }
|
||||
|
||||
// Usually this would be a typealias, but a SAM provides better java interop
|
||||
fun interface ClockChangeListener {
|
||||
fun onClockChanged()
|
||||
}
|
||||
|
||||
var isEnabled: Boolean = false
|
||||
|
||||
private val gson = Gson()
|
||||
@@ -58,7 +61,7 @@ open class ClockRegistry(
|
||||
private val clockChangeListeners = mutableListOf<ClockChangeListener>()
|
||||
private val settingObserver = object : ContentObserver(handler) {
|
||||
override fun onChange(selfChange: Boolean, uris: Collection<Uri>, flags: Int, userId: Int) =
|
||||
clockChangeListeners.forEach { it() }
|
||||
clockChangeListeners.forEach { it.onClockChanged() }
|
||||
}
|
||||
|
||||
private val pluginListener = object : PluginListener<ClockProviderPlugin> {
|
||||
@@ -117,8 +120,11 @@ open class ClockRegistry(
|
||||
val id = clock.clockId
|
||||
val current = availableClocks[id]
|
||||
if (current != null) {
|
||||
Log.e(TAG, "Clock Id conflict: $id is registered by both " +
|
||||
"${provider::class.simpleName} and ${current.provider::class.simpleName}")
|
||||
Log.e(
|
||||
TAG,
|
||||
"Clock Id conflict: $id is registered by both " +
|
||||
"${provider::class.simpleName} and ${current.provider::class.simpleName}"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -127,7 +133,7 @@ open class ClockRegistry(
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Current clock ($currentId) was connected")
|
||||
}
|
||||
clockChangeListeners.forEach { it() }
|
||||
clockChangeListeners.forEach { it.onClockChanged() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,7 +145,7 @@ open class ClockRegistry(
|
||||
|
||||
if (currentId == clock.clockId) {
|
||||
Log.w(TAG, "Current clock ($currentId) was disconnected")
|
||||
clockChangeListeners.forEach { it() }
|
||||
clockChangeListeners.forEach { it.onClockChanged() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,16 +13,18 @@
|
||||
*/
|
||||
package com.android.systemui.shared.clocks
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.icu.text.NumberFormat
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import com.android.internal.colorextraction.ColorExtractor
|
||||
import android.widget.FrameLayout
|
||||
import com.android.internal.annotations.VisibleForTesting
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.plugins.ClockAnimation
|
||||
import com.android.systemui.plugins.ClockAnimations
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
import com.android.systemui.plugins.ClockId
|
||||
import com.android.systemui.plugins.ClockMetadata
|
||||
@@ -39,6 +41,7 @@ const val DEFAULT_CLOCK_ID = "DEFAULT"
|
||||
|
||||
/** Provides the default system clock */
|
||||
class DefaultClockProvider @Inject constructor(
|
||||
val ctx: Context,
|
||||
val layoutInflater: LayoutInflater,
|
||||
@Main val resources: Resources
|
||||
) : ClockProvider {
|
||||
@@ -49,7 +52,7 @@ class DefaultClockProvider @Inject constructor(
|
||||
if (id != DEFAULT_CLOCK_ID) {
|
||||
throw IllegalArgumentException("$id is unsupported by $TAG")
|
||||
}
|
||||
return DefaultClock(layoutInflater, resources)
|
||||
return DefaultClock(ctx, layoutInflater, resources)
|
||||
}
|
||||
|
||||
override fun getClockThumbnail(id: ClockId): Drawable? {
|
||||
@@ -69,14 +72,13 @@ class DefaultClockProvider @Inject constructor(
|
||||
* AnimatableClockView used by the existing lockscreen clock.
|
||||
*/
|
||||
class DefaultClock(
|
||||
private val layoutInflater: LayoutInflater,
|
||||
private val resources: Resources
|
||||
ctx: Context,
|
||||
private val layoutInflater: LayoutInflater,
|
||||
private val resources: Resources
|
||||
) : Clock {
|
||||
override val smallClock =
|
||||
layoutInflater.inflate(R.layout.clock_default_small, null) as AnimatableClockView
|
||||
override val largeClock =
|
||||
layoutInflater.inflate(R.layout.clock_default_large, null) as AnimatableClockView
|
||||
private val clocks = listOf(smallClock, largeClock)
|
||||
override val smallClock: AnimatableClockView
|
||||
override val largeClock: AnimatableClockView
|
||||
private val clocks get() = listOf(smallClock, largeClock)
|
||||
|
||||
private val burmeseNf = NumberFormat.getInstance(Locale.forLanguageTag("my"))
|
||||
private val burmeseNumerals = burmeseNf.format(FORMAT_NUMBER.toLong())
|
||||
@@ -84,7 +86,43 @@ class DefaultClock(
|
||||
resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese)
|
||||
private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)
|
||||
|
||||
override val events = object : ClockEvents {
|
||||
override val events: ClockEvents
|
||||
override lateinit var animations: ClockAnimations
|
||||
private set
|
||||
|
||||
init {
|
||||
val parent = FrameLayout(ctx)
|
||||
|
||||
smallClock = layoutInflater.inflate(
|
||||
R.layout.clock_default_small,
|
||||
parent,
|
||||
false
|
||||
) as AnimatableClockView
|
||||
|
||||
largeClock = layoutInflater.inflate(
|
||||
R.layout.clock_default_large,
|
||||
parent,
|
||||
false
|
||||
) as AnimatableClockView
|
||||
|
||||
events = DefaultClockEvents()
|
||||
animations = DefaultClockAnimations(0f, 0f)
|
||||
|
||||
events.onLocaleChanged(Locale.getDefault())
|
||||
|
||||
// DOZE_COLOR is a placeholder, and will be assigned correctly in initialize
|
||||
clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) }
|
||||
}
|
||||
|
||||
override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
|
||||
recomputePadding()
|
||||
animations = DefaultClockAnimations(dozeFraction, foldFraction)
|
||||
events.onColorPaletteChanged(resources, true, true)
|
||||
events.onTimeZoneChanged(TimeZone.getDefault())
|
||||
events.onTimeTick()
|
||||
}
|
||||
|
||||
inner class DefaultClockEvents() : ClockEvents {
|
||||
override fun onTimeTick() = clocks.forEach { it.refreshTime() }
|
||||
|
||||
override fun onTimeFormatChanged(is24Hr: Boolean) =
|
||||
@@ -102,10 +140,17 @@ 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,
|
||||
smallClockIsDark: Boolean,
|
||||
largeClockIsDark: Boolean
|
||||
) {
|
||||
updateClockColor(smallClock, smallClockIsDark)
|
||||
updateClockColor(largeClock, largeClockIsDark)
|
||||
}
|
||||
|
||||
override fun onLocaleChanged(locale: Locale) {
|
||||
val nf = NumberFormat.getInstance(locale)
|
||||
@@ -119,8 +164,14 @@ class DefaultClock(
|
||||
}
|
||||
}
|
||||
|
||||
override val animation = object : ClockAnimation {
|
||||
override fun initialize(dozeFraction: Float, foldFraction: Float) {
|
||||
inner class DefaultClockAnimations(
|
||||
dozeFraction: Float,
|
||||
foldFraction: Float
|
||||
) : ClockAnimations {
|
||||
private var foldState = AnimationState(0f)
|
||||
private var dozeState = AnimationState(0f)
|
||||
|
||||
init {
|
||||
dozeState = AnimationState(dozeFraction)
|
||||
foldState = AnimationState(foldFraction)
|
||||
|
||||
@@ -132,14 +183,13 @@ 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 +197,6 @@ class DefaultClock(
|
||||
}
|
||||
}
|
||||
|
||||
private var dozeState = AnimationState(0f)
|
||||
override fun doze(fraction: Float) {
|
||||
val (hasChanged, hasJumped) = dozeState.update(fraction)
|
||||
if (hasChanged) {
|
||||
@@ -170,14 +219,26 @@ class DefaultClock(
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
events.onLocaleChanged(Locale.getDefault())
|
||||
private fun updateClockColor(clock: AnimatableClockView, isRegionDark: Boolean) {
|
||||
val color = if (isRegionDark) {
|
||||
resources.getColor(android.R.color.system_accent1_100)
|
||||
} else {
|
||||
resources.getColor(android.R.color.system_accent2_600)
|
||||
}
|
||||
clock.setColors(DOZE_COLOR, color)
|
||||
clock.animateAppearOnLockscreen()
|
||||
}
|
||||
|
||||
private fun recomputePadding() {
|
||||
val lp = largeClock.getLayoutParams() as FrameLayout.LayoutParams
|
||||
lp.topMargin = (-0.5f * largeClock.bottom).toInt()
|
||||
largeClock.setLayoutParams(lp)
|
||||
}
|
||||
|
||||
override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) }
|
||||
|
||||
companion object {
|
||||
private const val DOZE_COLOR = Color.WHITE
|
||||
@VisibleForTesting const val DOZE_COLOR = Color.WHITE
|
||||
private const val FORMAT_NUMBER = 1234567890
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.icu.text.NumberFormat;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -30,16 +32,24 @@ import androidx.annotation.VisibleForTesting;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.clocks.AnimatableClockView;
|
||||
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Controller for an AnimatableClockView on the keyguard. Instantiated by
|
||||
@@ -54,7 +64,10 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final BatteryController mBatteryController;
|
||||
private final int mDozingColor = Color.WHITE;
|
||||
private Optional<RegionSamplingHelper> mRegionSamplingHelper = Optional.empty();
|
||||
private Rect mSamplingBounds = new Rect();
|
||||
private int mLockScreenColor;
|
||||
private final boolean mRegionSamplingEnabled;
|
||||
|
||||
private boolean mIsDozing;
|
||||
private boolean mIsCharging;
|
||||
@@ -67,13 +80,17 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
private final float mBurmeseLineSpacing;
|
||||
private final float mDefaultLineSpacing;
|
||||
|
||||
@Inject
|
||||
public AnimatableClockController(
|
||||
AnimatableClockView view,
|
||||
StatusBarStateController statusBarStateController,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
BatteryController batteryController,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
@Main Resources resources
|
||||
@Main Resources resources,
|
||||
@Main Executor mainExecutor,
|
||||
@Background Executor bgExecutor,
|
||||
FeatureFlags featureFlags
|
||||
) {
|
||||
super(view);
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
@@ -86,6 +103,40 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
R.dimen.keyguard_clock_line_spacing_scale_burmese);
|
||||
mDefaultLineSpacing = resources.getFloat(
|
||||
R.dimen.keyguard_clock_line_spacing_scale);
|
||||
|
||||
mRegionSamplingEnabled = featureFlags.isEnabled(Flags.REGION_SAMPLING);
|
||||
if (!mRegionSamplingEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mRegionSamplingHelper = Optional.of(new RegionSamplingHelper(mView,
|
||||
new RegionSamplingHelper.SamplingCallback() {
|
||||
@Override
|
||||
public void onRegionDarknessChanged(boolean isRegionDark) {
|
||||
if (isRegionDark) {
|
||||
mLockScreenColor = Color.WHITE;
|
||||
} else {
|
||||
mLockScreenColor = Color.BLACK;
|
||||
}
|
||||
initColors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect getSampledRegion(View sampledView) {
|
||||
mSamplingBounds = new Rect(sampledView.getLeft(), sampledView.getTop(),
|
||||
sampledView.getRight(), sampledView.getBottom());
|
||||
return mSamplingBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSamplingEnabled() {
|
||||
return mRegionSamplingEnabled;
|
||||
}
|
||||
}, mainExecutor, bgExecutor)
|
||||
);
|
||||
mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
|
||||
regionSamplingHelper.setWindowVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
@@ -169,6 +220,10 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
|
||||
mStatusBarStateController.addCallback(mStatusBarStateListener);
|
||||
|
||||
mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
|
||||
regionSamplingHelper.start(mSamplingBounds);
|
||||
});
|
||||
|
||||
mView.onTimeZoneChanged(TimeZone.getDefault());
|
||||
initColors();
|
||||
mView.animateDoze(mIsDozing, false);
|
||||
@@ -180,18 +235,9 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
|
||||
mBatteryController.removeCallback(mBatteryCallback);
|
||||
mStatusBarStateController.removeCallback(mStatusBarStateListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of pixels below the baseline. For fonts that support languages such as
|
||||
* Burmese, this space can be significant.
|
||||
*/
|
||||
public float getBottom() {
|
||||
if (mView.getPaint() != null && mView.getPaint().getFontMetrics() != null) {
|
||||
return mView.getPaint().getFontMetrics().bottom;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
|
||||
regionSamplingHelper.stop();
|
||||
});
|
||||
}
|
||||
|
||||
/** Animate the clock appearance */
|
||||
@@ -235,8 +281,10 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
}
|
||||
|
||||
private void initColors() {
|
||||
mLockScreenColor = Utils.getColorAttrDefaultColor(getContext(),
|
||||
com.android.systemui.R.attr.wallpaperTextColorAccent);
|
||||
if (!mRegionSamplingEnabled) {
|
||||
mLockScreenColor = Utils.getColorAttrDefaultColor(getContext(),
|
||||
com.android.systemui.R.attr.wallpaperTextColorAccent);
|
||||
}
|
||||
mView.setColors(mDozingColor, mLockScreenColor);
|
||||
mView.animateDoze(mIsDozing, false);
|
||||
}
|
||||
@@ -247,5 +295,8 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
|
||||
public void dump(@NonNull PrintWriter pw) {
|
||||
pw.println(this);
|
||||
mView.dump(pw);
|
||||
mRegionSamplingHelper.ifPresent((regionSamplingHelper) -> {
|
||||
regionSamplingHelper.dump(pw);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.keyguard
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.res.Resources
|
||||
import android.text.format.DateFormat
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.shared.regionsampling.RegionSamplingInstance
|
||||
import com.android.systemui.statusbar.policy.BatteryController
|
||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import java.io.PrintWriter
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
|
||||
* [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
|
||||
*/
|
||||
open class ClockEventController @Inject constructor(
|
||||
private val statusBarStateController: StatusBarStateController,
|
||||
private val broadcastDispatcher: BroadcastDispatcher,
|
||||
private val batteryController: BatteryController,
|
||||
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||
private val configurationController: ConfigurationController,
|
||||
@Main private val resources: Resources,
|
||||
private val context: Context,
|
||||
@Main private val mainExecutor: Executor,
|
||||
@Background private val bgExecutor: Executor,
|
||||
private val featureFlags: FeatureFlags
|
||||
) {
|
||||
var clock: Clock? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (value != null) {
|
||||
value.initialize(resources, dozeAmount, 0f)
|
||||
updateRegionSamplers(value)
|
||||
}
|
||||
}
|
||||
|
||||
private var isDozing = false
|
||||
private set
|
||||
|
||||
private var isCharging = false
|
||||
private var dozeAmount = 0f
|
||||
private var isKeyguardShowing = false
|
||||
|
||||
private val regionSamplingEnabled =
|
||||
featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING)
|
||||
|
||||
private val updateFun = object : RegionSamplingInstance.UpdateColorCallback {
|
||||
override fun updateColors() {
|
||||
if (regionSamplingEnabled) {
|
||||
smallClockIsDark = smallRegionSamplingInstance.currentRegionDarkness().isDark
|
||||
largeClockIsDark = largeRegionSamplingInstance.currentRegionDarkness().isDark
|
||||
} else {
|
||||
val isLightTheme = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
|
||||
smallClockIsDark = isLightTheme.data == 0
|
||||
largeClockIsDark = isLightTheme.data == 0
|
||||
}
|
||||
clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateRegionSamplers(currentClock: Clock?) {
|
||||
smallRegionSamplingInstance = createRegionSampler(
|
||||
currentClock?.smallClock,
|
||||
mainExecutor,
|
||||
bgExecutor,
|
||||
regionSamplingEnabled,
|
||||
updateFun
|
||||
)
|
||||
|
||||
largeRegionSamplingInstance = createRegionSampler(
|
||||
currentClock?.largeClock,
|
||||
mainExecutor,
|
||||
bgExecutor,
|
||||
regionSamplingEnabled,
|
||||
updateFun
|
||||
)
|
||||
|
||||
smallRegionSamplingInstance.startRegionSampler()
|
||||
largeRegionSamplingInstance.startRegionSampler()
|
||||
|
||||
updateFun.updateColors()
|
||||
}
|
||||
|
||||
protected open fun createRegionSampler(
|
||||
sampledView: View?,
|
||||
mainExecutor: Executor?,
|
||||
bgExecutor: Executor?,
|
||||
regionSamplingEnabled: Boolean,
|
||||
updateFun: RegionSamplingInstance.UpdateColorCallback
|
||||
): RegionSamplingInstance {
|
||||
return RegionSamplingInstance(
|
||||
sampledView,
|
||||
mainExecutor,
|
||||
bgExecutor,
|
||||
regionSamplingEnabled,
|
||||
updateFun)
|
||||
}
|
||||
|
||||
lateinit var smallRegionSamplingInstance: RegionSamplingInstance
|
||||
lateinit var largeRegionSamplingInstance: RegionSamplingInstance
|
||||
|
||||
private var smallClockIsDark = true
|
||||
private var largeClockIsDark = true
|
||||
|
||||
private val configListener = object : ConfigurationController.ConfigurationListener {
|
||||
override fun onThemeChanged() {
|
||||
updateFun.updateColors()
|
||||
}
|
||||
}
|
||||
|
||||
private val batteryCallback = object : BatteryStateChangeCallback {
|
||||
override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
|
||||
if (isKeyguardShowing && !isCharging && charging) {
|
||||
clock?.animations?.charge()
|
||||
}
|
||||
isCharging = charging
|
||||
}
|
||||
}
|
||||
|
||||
private val localeBroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
clock?.events?.onLocaleChanged(Locale.getDefault())
|
||||
}
|
||||
}
|
||||
|
||||
private val statusBarStateListener = object : StatusBarStateController.StateListener {
|
||||
override fun onDozeAmountChanged(linear: Float, eased: Float) {
|
||||
clock?.animations?.doze(linear)
|
||||
|
||||
isDozing = linear > dozeAmount
|
||||
dozeAmount = linear
|
||||
}
|
||||
}
|
||||
|
||||
private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
|
||||
override fun onKeyguardVisibilityChanged(showing: Boolean) {
|
||||
isKeyguardShowing = showing
|
||||
if (!isKeyguardShowing) {
|
||||
clock?.animations?.doze(if (isDozing) 1f else 0f)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTimeFormatChanged(timeFormat: String) {
|
||||
clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
|
||||
}
|
||||
|
||||
override fun onTimeZoneChanged(timeZone: TimeZone) {
|
||||
clock?.events?.onTimeZoneChanged(timeZone)
|
||||
}
|
||||
|
||||
override fun onUserSwitchComplete(userId: Int) {
|
||||
clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
isDozing = statusBarStateController.isDozing
|
||||
}
|
||||
|
||||
fun registerListeners() {
|
||||
dozeAmount = statusBarStateController.dozeAmount
|
||||
isDozing = statusBarStateController.isDozing || dozeAmount != 0f
|
||||
|
||||
broadcastDispatcher.registerReceiver(
|
||||
localeBroadcastReceiver,
|
||||
IntentFilter(Intent.ACTION_LOCALE_CHANGED)
|
||||
)
|
||||
configurationController.addCallback(configListener)
|
||||
batteryController.addCallback(batteryCallback)
|
||||
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
|
||||
statusBarStateController.addCallback(statusBarStateListener)
|
||||
smallRegionSamplingInstance.startRegionSampler()
|
||||
largeRegionSamplingInstance.startRegionSampler()
|
||||
}
|
||||
|
||||
fun unregisterListeners() {
|
||||
broadcastDispatcher.unregisterReceiver(localeBroadcastReceiver)
|
||||
configurationController.removeCallback(configListener)
|
||||
batteryController.removeCallback(batteryCallback)
|
||||
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
|
||||
statusBarStateController.removeCallback(statusBarStateListener)
|
||||
smallRegionSamplingInstance.stopRegionSampler()
|
||||
largeRegionSamplingInstance.stopRegionSampler()
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump information for debugging
|
||||
*/
|
||||
fun dump(pw: PrintWriter) {
|
||||
pw.println(this)
|
||||
clock?.dump(pw)
|
||||
smallRegionSamplingInstance.dump(pw)
|
||||
largeRegionSamplingInstance.dump(pw)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = ClockEventController::class.simpleName
|
||||
private const val FORMAT_NUMBER = 1234567890
|
||||
}
|
||||
}
|
||||
@@ -5,31 +5,23 @@ 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;
|
||||
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 +41,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 +65,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
@VisibleForTesting AnimatorSet mClockOutAnim = null;
|
||||
private ObjectAnimator mStatusAreaAnim = null;
|
||||
|
||||
/**
|
||||
* If the Keyguard Slice has a header (big center-aligned text.)
|
||||
*/
|
||||
private boolean mSupportsDarkText;
|
||||
private int[] mColorPalette;
|
||||
|
||||
private int mClockSwitchYAmount;
|
||||
@VisibleForTesting boolean mChildrenAreLaidOut = false;
|
||||
@VisibleForTesting boolean mAnimateOnLayout = true;
|
||||
@@ -98,97 +77,36 @@ 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());
|
||||
mLargeClockFrame.addView(clock.getLargeClock());
|
||||
}
|
||||
|
||||
private void updateClockViews(boolean useLargeClock, boolean animate) {
|
||||
@@ -204,14 +122,14 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
int direction = 1;
|
||||
float statusAreaYTranslation;
|
||||
if (useLargeClock) {
|
||||
out = mClockFrame;
|
||||
out = mSmallClockFrame;
|
||||
in = mLargeClockFrame;
|
||||
if (indexOfChild(in) == -1) addView(in);
|
||||
direction = -1;
|
||||
statusAreaYTranslation = mClockFrame.getTop() - mStatusArea.getTop()
|
||||
statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop()
|
||||
+ mSmartspaceTopOffset;
|
||||
} else {
|
||||
in = mClockFrame;
|
||||
in = mSmallClockFrame;
|
||||
out = mLargeClockFrame;
|
||||
statusAreaYTranslation = 0f;
|
||||
|
||||
@@ -269,18 +187,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
mStatusAreaAnim.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount (ratio) that the device has transitioned to doze.
|
||||
*
|
||||
* @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
|
||||
*/
|
||||
public void setDarkAmount(float darkAmount) {
|
||||
mDarkAmount = darkAmount;
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setDarkAmount(darkAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the desired clock and hide the other one
|
||||
*
|
||||
@@ -312,64 +218,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(" mSmallClockFrame: " + mSmallClockFrame);
|
||||
pw.println(" mLargeClockFrame: " + mLargeClockFrame);
|
||||
pw.println(" mStatusArea: " + mStatusArea);
|
||||
pw.println(" mDarkAmount: " + mDarkAmount);
|
||||
pw.println(" mSupportsDarkText: " + mSupportsDarkText);
|
||||
pw.println(" mColorPalette: " + Arrays.toString(mColorPalette));
|
||||
pw.println(" mDisplayedClockSize: " + mDisplayedClockSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
|
||||
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
@@ -32,36 +30,30 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.keyguard.clock.ClockManager;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.plugins.ClockPlugin;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.clocks.ClockRegistry;
|
||||
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
|
||||
import com.android.systemui.statusbar.notification.AnimatableProperty;
|
||||
import com.android.systemui.statusbar.notification.PropertyAnimator;
|
||||
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
||||
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
|
||||
import com.android.systemui.statusbar.phone.NotificationIconContainer;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
import com.android.systemui.util.settings.SecureSettings;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -71,48 +63,23 @@ 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;
|
||||
private FrameLayout mSmallClockFrame; // top aligned clock
|
||||
private FrameLayout mLargeClockFrame; // centered clock
|
||||
|
||||
@KeyguardClockSwitch.ClockSize
|
||||
private int mCurrentClockSize = SMALL;
|
||||
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
|
||||
private int mKeyguardClockTopMargin = 0;
|
||||
|
||||
/**
|
||||
* Listener for changes to the color palette.
|
||||
*
|
||||
* The color palette changes when the wallpaper is changed.
|
||||
*/
|
||||
private final ColorExtractor.OnColorsChangedListener mColorsListener =
|
||||
(extractor, which) -> {
|
||||
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
|
||||
mView.updateColors(getGradientColors());
|
||||
}
|
||||
};
|
||||
|
||||
private final ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
|
||||
private final ClockRegistry.ClockChangeListener mClockChangedListener;
|
||||
|
||||
private ViewGroup mStatusArea;
|
||||
// If set will replace keyguard_slice_view
|
||||
@@ -121,9 +88,9 @@ 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();
|
||||
@@ -144,34 +111,32 @@ 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,
|
||||
FeatureFlags featureFlags) {
|
||||
super(keyguardClockSwitch);
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mColorExtractor = colorExtractor;
|
||||
mClockManager = clockManager;
|
||||
mClockRegistry = clockRegistry;
|
||||
mKeyguardSliceViewController = keyguardSliceViewController;
|
||||
mNotificationIconAreaController = notificationIconAreaController;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mBatteryController = batteryController;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mSmartspaceController = smartspaceController;
|
||||
mResources = resources;
|
||||
mSecureSettings = secureSettings;
|
||||
mUiExecutor = uiExecutor;
|
||||
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
|
||||
mDumpManager = dumpManager;
|
||||
mClockEventController = clockEventController;
|
||||
|
||||
mClockRegistry.setEnabled(featureFlags.isEnabled(Flags.LOCKSCREEN_CUSTOM_CLOCKS));
|
||||
mClockChangedListener = () -> {
|
||||
setClock(mClockRegistry.createCurrentClock());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,43 +150,21 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
* Attach the controller to the view it relates to.
|
||||
*/
|
||||
@Override
|
||||
public void onInit() {
|
||||
protected void onInit() {
|
||||
mKeyguardSliceViewController.init();
|
||||
|
||||
mClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
|
||||
mSmallClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
|
||||
mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large);
|
||||
|
||||
mClockViewController =
|
||||
new AnimatableClockController(
|
||||
mView.findViewById(R.id.animatable_clock_view),
|
||||
mStatusBarStateController,
|
||||
mBroadcastDispatcher,
|
||||
mBatteryController,
|
||||
mKeyguardUpdateMonitor,
|
||||
mResources);
|
||||
mClockViewController.init();
|
||||
|
||||
mLargeClockViewController =
|
||||
new AnimatableClockController(
|
||||
mView.findViewById(R.id.animatable_clock_view_large),
|
||||
mStatusBarStateController,
|
||||
mBroadcastDispatcher,
|
||||
mBatteryController,
|
||||
mKeyguardUpdateMonitor,
|
||||
mResources);
|
||||
mLargeClockViewController.init();
|
||||
|
||||
mDumpManager.unregisterDumpable(getClass().toString()); // unregister previous clocks
|
||||
mDumpManager.registerDumpable(getClass().toString(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
if (CUSTOM_CLOCKS_ENABLED) {
|
||||
mClockManager.addOnClockChangedListener(mClockChangedListener);
|
||||
}
|
||||
mColorExtractor.addOnColorsChangedListener(mColorsListener);
|
||||
mView.updateColors(getGradientColors());
|
||||
mClockRegistry.registerClockChangeListener(mClockChangedListener);
|
||||
setClock(mClockRegistry.createCurrentClock());
|
||||
mClockEventController.registerListeners();
|
||||
mKeyguardClockTopMargin =
|
||||
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
|
||||
|
||||
@@ -244,7 +187,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
ksv.setVisibility(View.GONE);
|
||||
|
||||
addSmartspaceView(ksvIndex);
|
||||
updateClockLayout();
|
||||
}
|
||||
|
||||
mSecureSettings.registerContentObserverForUser(
|
||||
@@ -266,11 +208,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);
|
||||
|
||||
@@ -309,18 +249,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,46 +262,34 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
|
||||
mCurrentClockSize = clockSize;
|
||||
|
||||
Clock clock = getClock();
|
||||
boolean appeared = mView.switchToClock(clockSize, animate);
|
||||
if (animate && appeared && clockSize == LARGE) {
|
||||
mLargeClockViewController.animateAppear();
|
||||
}
|
||||
}
|
||||
|
||||
public void animateFoldToAod() {
|
||||
if (mClockViewController != null) {
|
||||
mClockViewController.animateFoldAppear();
|
||||
mLargeClockViewController.animateFoldAppear();
|
||||
if (clock != null && animate && appeared && clockSize == LARGE) {
|
||||
clock.getAnimations().enter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're presenting a custom clock of just the default one.
|
||||
* Animates the clock view between folded and unfolded states
|
||||
*/
|
||||
public boolean hasCustomClock() {
|
||||
return mView.hasCustomClock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the clock text size.
|
||||
*/
|
||||
public float getClockTextSize() {
|
||||
return mView.getTextSize();
|
||||
public void animateFoldToAod(float foldFraction) {
|
||||
Clock clock = getClock();
|
||||
if (clock != null) {
|
||||
clock.getAnimations().fold(foldFraction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh clock. Called in response to TIME_TICK broadcasts.
|
||||
*/
|
||||
void refresh() {
|
||||
if (mClockViewController != null) {
|
||||
mClockViewController.refreshTime();
|
||||
mLargeClockViewController.refreshTime();
|
||||
}
|
||||
if (mSmartspaceController != null) {
|
||||
mSmartspaceController.requestSmartspaceUpdate();
|
||||
}
|
||||
|
||||
mView.refresh();
|
||||
Clock clock = getClock();
|
||||
if (clock != null) {
|
||||
clock.getEvents().onTimeTick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,7 +301,7 @@ 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);
|
||||
@@ -398,25 +314,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,12 +361,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() {
|
||||
@@ -458,8 +389,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
* bounds during the unlock transition.
|
||||
*/
|
||||
private void setClipChildrenForUnlock(boolean clip) {
|
||||
mView.setClipChildren(clip);
|
||||
|
||||
if (mStatusArea != null) {
|
||||
mStatusArea.setClipChildren(clip);
|
||||
}
|
||||
@@ -469,8 +398,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.
|
||||
@@ -1112,13 +1107,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;
|
||||
@@ -3974,9 +3962,9 @@ public final class NotificationPanelViewController extends PanelViewController {
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
endAction.run();
|
||||
}
|
||||
}).setUpdateListener(anim -> {
|
||||
mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction());
|
||||
}).start();
|
||||
|
||||
mKeyguardStatusViewController.animateFoldToAod();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4686,7 +4674,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();
|
||||
}
|
||||
@@ -4796,11 +4783,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;
|
||||
|
||||
@@ -442,7 +442,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
state |= DISABLE_CLOCK;
|
||||
}
|
||||
|
||||
|
||||
if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
|
||||
if (mNetworkController.hasEmergencyCryptKeeperText()) {
|
||||
state |= DISABLE_NOTIFICATION_ICONS;
|
||||
@@ -452,13 +451,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
}
|
||||
}
|
||||
|
||||
// The shelf will be hidden when dozing with a custom clock, we must show notification
|
||||
// icons in this occasion.
|
||||
if (mStatusBarStateController.isDozing()
|
||||
&& mNotificationPanelViewController.hasCustomClock()) {
|
||||
state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
|
||||
}
|
||||
|
||||
if (mOngoingCallController.hasOngoingCall()) {
|
||||
state &= ~DISABLE_ONGOING_CALL_CHIP;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
package com.android.keyguard
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.plugins.ClockAnimations
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.statusbar.policy.BatteryController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import java.util.TimeZone
|
||||
import java.util.concurrent.Executor
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.anyFloat
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
class ClockEventControllerTest : SysuiTestCase() {
|
||||
|
||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||
@Mock private lateinit var statusBarStateController: StatusBarStateController
|
||||
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
|
||||
@Mock private lateinit var batteryController: BatteryController
|
||||
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||
@Mock private lateinit var configurationController: ConfigurationController
|
||||
@Mock private lateinit var animations: ClockAnimations
|
||||
@Mock private lateinit var events: ClockEvents
|
||||
@Mock private lateinit var clock: Clock
|
||||
@Mock private lateinit var mainExecutor: Executor
|
||||
@Mock private lateinit var bgExecutor: Executor
|
||||
@Mock private lateinit var featureFlags: FeatureFlags
|
||||
|
||||
private lateinit var clockEventController: ClockEventController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
whenever(clock.smallClock).thenReturn(TextView(context))
|
||||
whenever(clock.largeClock).thenReturn(TextView(context))
|
||||
whenever(clock.events).thenReturn(events)
|
||||
whenever(clock.animations).thenReturn(animations)
|
||||
|
||||
clockEventController = ClockEventController(
|
||||
statusBarStateController,
|
||||
broadcastDispatcher,
|
||||
batteryController,
|
||||
keyguardUpdateMonitor,
|
||||
configurationController,
|
||||
context.resources,
|
||||
context,
|
||||
mainExecutor,
|
||||
bgExecutor,
|
||||
featureFlags
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clockSet_validateInitialization() {
|
||||
clockEventController.clock = clock
|
||||
|
||||
verify(clock).initialize(any(), anyFloat(), anyFloat())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clockUnset_validateState() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.clock = null
|
||||
|
||||
assertEquals(clockEventController.clock, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun themeChanged_verifyClockPaletteUpdated() {
|
||||
clockEventController.clock = clock
|
||||
verify(events).onColorPaletteChanged(any(), any(), any())
|
||||
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
|
||||
verify(configurationController).addCallback(capture(captor))
|
||||
captor.value.onThemeChanged()
|
||||
|
||||
verify(events, times(2)).onColorPaletteChanged(any(), any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardShowingCharging_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
|
||||
verify(animations).charge()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardShowingCharging_Duplicate_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
|
||||
verify(animations, times(1)).charge()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardHiddenCharging_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(false)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, true)
|
||||
|
||||
verify(animations, never()).charge()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryCallback_keyguardShowingNotCharging_verifyChargeAnimation() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val batteryCaptor = argumentCaptor<BatteryController.BatteryStateChangeCallback>()
|
||||
verify(batteryController).addCallback(capture(batteryCaptor))
|
||||
val keyguardCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCaptor))
|
||||
keyguardCaptor.value.onKeyguardVisibilityChanged(true)
|
||||
batteryCaptor.value.onBatteryLevelChanged(10, false, false)
|
||||
|
||||
verify(animations, never()).charge()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun localeCallback_verifyClockNotified() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<BroadcastReceiver>()
|
||||
verify(broadcastDispatcher).registerReceiver(
|
||||
capture(captor), any(), eq(null), eq(null), anyInt(), eq(null)
|
||||
)
|
||||
captor.value.onReceive(context, mock())
|
||||
|
||||
verify(events).onLocaleChanged(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_visibilityChanged_clockDozeCalled() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
|
||||
captor.value.onKeyguardVisibilityChanged(true)
|
||||
verify(animations, never()).doze(0f)
|
||||
|
||||
captor.value.onKeyguardVisibilityChanged(false)
|
||||
verify(animations, times(1)).doze(0f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_timeFormat_clockNotified() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
captor.value.onTimeFormatChanged("12h")
|
||||
|
||||
verify(events).onTimeFormatChanged(false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_timezoneChanged_clockNotified() {
|
||||
val mockTimeZone = mock<TimeZone>()
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
captor.value.onTimeZoneChanged(mockTimeZone)
|
||||
|
||||
verify(events).onTimeZoneChanged(mockTimeZone)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_userSwitched_clockNotified() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
|
||||
verify(keyguardUpdateMonitor).registerCallback(capture(captor))
|
||||
captor.value.onUserSwitchComplete(10)
|
||||
|
||||
verify(events).onTimeFormatChanged(false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keyguardCallback_verifyKeyguardChanged() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.registerListeners()
|
||||
|
||||
val captor = argumentCaptor<StatusBarStateController.StateListener>()
|
||||
verify(statusBarStateController).addCallback(capture(captor))
|
||||
captor.value.onDozeAmountChanged(0.4f, 0.6f)
|
||||
|
||||
verify(animations).doze(0.4f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unregisterListeners_validate() {
|
||||
clockEventController.clock = clock
|
||||
clockEventController.unregisterListeners()
|
||||
verify(broadcastDispatcher).unregisterReceiver(any())
|
||||
verify(configurationController).removeCallback(any())
|
||||
verify(batteryController).removeCallback(any())
|
||||
verify(keyguardUpdateMonitor).removeCallback(any())
|
||||
verify(statusBarStateController).removeCallback(any())
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package com.android.keyguard;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -41,24 +40,19 @@ import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.keyguard.clock.ClockManager;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.plugins.ClockPlugin;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.clocks.AnimatableClockView;
|
||||
import com.android.systemui.shared.clocks.ClockRegistry;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
|
||||
import com.android.systemui.statusbar.phone.NotificationIconContainer;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.settings.SecureSettings;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
@@ -80,22 +74,12 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private StatusBarStateController mStatusBarStateController;
|
||||
@Mock
|
||||
private SysuiColorExtractor mColorExtractor;
|
||||
@Mock
|
||||
private ClockManager mClockManager;
|
||||
private ClockRegistry mClockRegistry;
|
||||
@Mock
|
||||
KeyguardSliceViewController mKeyguardSliceViewController;
|
||||
@Mock
|
||||
NotificationIconAreaController mNotificationIconAreaController;
|
||||
@Mock
|
||||
BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Mock
|
||||
BatteryController mBatteryController;
|
||||
@Mock
|
||||
KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Mock
|
||||
KeyguardBypassController mBypassController;
|
||||
@Mock
|
||||
LockscreenSmartspaceController mSmartspaceController;
|
||||
|
||||
@Mock
|
||||
@@ -103,11 +87,11 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||
@Mock
|
||||
private ClockPlugin mClockPlugin;
|
||||
@Mock
|
||||
ColorExtractor.GradientColors mGradientColors;
|
||||
private Clock mClock;
|
||||
@Mock
|
||||
DumpManager mDumpManager;
|
||||
@Mock
|
||||
ClockEventController mClockEventController;
|
||||
|
||||
@Mock
|
||||
private NotificationIconContainer mNotificationIcons;
|
||||
@@ -139,8 +123,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
when(mView.getContext()).thenReturn(getContext());
|
||||
when(mView.getResources()).thenReturn(mResources);
|
||||
|
||||
when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView);
|
||||
when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView);
|
||||
when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame);
|
||||
when(mClockView.getContext()).thenReturn(getContext());
|
||||
when(mLargeClockView.getContext()).thenReturn(getContext());
|
||||
@@ -151,23 +133,20 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
mController = new KeyguardClockSwitchController(
|
||||
mView,
|
||||
mStatusBarStateController,
|
||||
mColorExtractor,
|
||||
mClockManager,
|
||||
mClockRegistry,
|
||||
mKeyguardSliceViewController,
|
||||
mNotificationIconAreaController,
|
||||
mBroadcastDispatcher,
|
||||
mBatteryController,
|
||||
mKeyguardUpdateMonitor,
|
||||
mSmartspaceController,
|
||||
mKeyguardUnlockAnimationController,
|
||||
mSecureSettings,
|
||||
mExecutor,
|
||||
mResources,
|
||||
mDumpManager
|
||||
mDumpManager,
|
||||
mClockEventController,
|
||||
mFeatureFlags
|
||||
);
|
||||
|
||||
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
|
||||
when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors);
|
||||
when(mClockRegistry.createCurrentClock()).thenReturn(mClock);
|
||||
|
||||
mSliceView = new View(getContext());
|
||||
when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
|
||||
@@ -214,20 +193,20 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
verifyAttachment(times(1));
|
||||
|
||||
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
|
||||
verify(mColorExtractor).removeOnColorsChangedListener(
|
||||
any(ColorExtractor.OnColorsChangedListener.class));
|
||||
verify(mClockEventController).unregisterListeners();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPluginPassesStatusBarState() {
|
||||
ArgumentCaptor<ClockManager.ClockChangedListener> listenerArgumentCaptor =
|
||||
ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class);
|
||||
ArgumentCaptor<ClockRegistry.ClockChangeListener> listenerArgumentCaptor =
|
||||
ArgumentCaptor.forClass(ClockRegistry.ClockChangeListener.class);
|
||||
|
||||
mController.init();
|
||||
verify(mClockManager).addOnClockChangedListener(listenerArgumentCaptor.capture());
|
||||
verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture());
|
||||
|
||||
listenerArgumentCaptor.getValue().onClockChanged(mClockPlugin);
|
||||
verify(mView).setClockPlugin(mClockPlugin, StatusBarState.SHADE);
|
||||
listenerArgumentCaptor.getValue().onClockChanged();
|
||||
verify(mView, times(2)).setClock(mClock, StatusBarState.SHADE);
|
||||
verify(mClockEventController, times(2)).setClock(mClock);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -284,10 +263,8 @@ 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);
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.clocks.AnimatableClockView;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
@@ -53,6 +54,8 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
@@ -69,6 +72,12 @@ public class AnimatableClockControllerTest extends SysuiTestCase {
|
||||
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
@Mock
|
||||
private Executor mMainExecutor;
|
||||
@Mock
|
||||
private Executor mBgExecutor;
|
||||
@Mock
|
||||
private FeatureFlags mFeatureFlags;
|
||||
|
||||
private MockitoSession mStaticMockSession;
|
||||
private AnimatableClockController mAnimatableClockController;
|
||||
@@ -96,7 +105,10 @@ public class AnimatableClockControllerTest extends SysuiTestCase {
|
||||
mBroadcastDispatcher,
|
||||
mBatteryController,
|
||||
mKeyguardUpdateMonitor,
|
||||
mResources
|
||||
mResources,
|
||||
mMainExecutor,
|
||||
mBgExecutor,
|
||||
mFeatureFlags
|
||||
);
|
||||
mAnimatableClockController.init();
|
||||
captureAttachListener();
|
||||
|
||||
@@ -130,13 +130,16 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
pluginListener.onPluginConnected(plugin1, mockContext)
|
||||
pluginListener.onPluginConnected(plugin2, mockContext)
|
||||
val list = registry.getClocks()
|
||||
assertEquals(list, listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2"),
|
||||
ClockMetadata("clock_3", "clock 3"),
|
||||
ClockMetadata("clock_4", "clock 4")
|
||||
))
|
||||
assertEquals(
|
||||
list,
|
||||
listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2"),
|
||||
ClockMetadata("clock_3", "clock 3"),
|
||||
ClockMetadata("clock_4", "clock 4")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -158,11 +161,14 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
pluginListener.onPluginConnected(plugin1, mockContext)
|
||||
pluginListener.onPluginConnected(plugin2, mockContext)
|
||||
val list = registry.getClocks()
|
||||
assertEquals(list, listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2")
|
||||
))
|
||||
assertEquals(
|
||||
list,
|
||||
listOf(
|
||||
ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
|
||||
ClockMetadata("clock_1", "clock 1"),
|
||||
ClockMetadata("clock_2", "clock 2")
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(registry.createExampleClock("clock_1"), mockClock)
|
||||
assertEquals(registry.createExampleClock("clock_2"), mockClock)
|
||||
@@ -222,7 +228,7 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
pluginListener.onPluginConnected(plugin2, mockContext)
|
||||
|
||||
var changeCallCount = 0
|
||||
registry.registerClockChangeListener({ changeCallCount++ })
|
||||
registry.registerClockChangeListener { changeCallCount++ }
|
||||
|
||||
pluginListener.onPluginDisconnected(plugin1)
|
||||
assertEquals(0, changeCallCount)
|
||||
|
||||
@@ -19,17 +19,31 @@ package com.android.systemui.shared.clocks
|
||||
import android.content.res.Resources
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.shared.clocks.DefaultClock.Companion.DOZE_COLOR
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import junit.framework.Assert.assertEquals
|
||||
import junit.framework.Assert.assertNotNull
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.anyBoolean
|
||||
import org.mockito.ArgumentMatchers.anyFloat
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.ArgumentMatchers.notNull
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
|
||||
@@ -39,7 +53,8 @@ class DefaultClockProviderTest : SysuiTestCase() {
|
||||
|
||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||
|
||||
@Mock private lateinit var mockClockView: AnimatableClockView
|
||||
@Mock private lateinit var mockSmallClockView: AnimatableClockView
|
||||
@Mock private lateinit var mockLargeClockView: AnimatableClockView
|
||||
@Mock private lateinit var layoutInflater: LayoutInflater
|
||||
@Mock private lateinit var mockClockThumbnail: Drawable
|
||||
@Mock private lateinit var resources: Resources
|
||||
@@ -47,14 +62,16 @@ class DefaultClockProviderTest : SysuiTestCase() {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
whenever(layoutInflater.inflate(R.layout.clock_default_small, null))
|
||||
.thenReturn(mockClockView)
|
||||
whenever(layoutInflater.inflate(R.layout.clock_default_large, null))
|
||||
.thenReturn(mockClockView)
|
||||
whenever(layoutInflater.inflate(eq(R.layout.clock_default_small), any(), anyBoolean()))
|
||||
.thenReturn(mockSmallClockView)
|
||||
whenever(layoutInflater.inflate(eq(R.layout.clock_default_large), any(), anyBoolean()))
|
||||
.thenReturn(mockLargeClockView)
|
||||
whenever(resources.getDrawable(R.drawable.clock_default_thumbnail, null))
|
||||
.thenReturn(mockClockThumbnail)
|
||||
whenever(mockSmallClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
|
||||
whenever(mockLargeClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
|
||||
|
||||
provider = DefaultClockProvider(layoutInflater, resources)
|
||||
provider = DefaultClockProvider(context, layoutInflater, resources)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,7 +88,79 @@ class DefaultClockProviderTest : SysuiTestCase() {
|
||||
// Default clock provider must always provide the default clock
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
assertNotNull(clock)
|
||||
assertEquals(clock.smallClock, mockClockView)
|
||||
assertEquals(clock.largeClock, mockClockView)
|
||||
assertEquals(clock.smallClock, mockSmallClockView)
|
||||
assertEquals(clock.largeClock, mockLargeClockView)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_initialize() {
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
clock.initialize(resources, 0f, 0f)
|
||||
|
||||
verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
|
||||
verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
|
||||
verify(mockSmallClockView).onTimeZoneChanged(notNull())
|
||||
verify(mockLargeClockView).onTimeZoneChanged(notNull())
|
||||
verify(mockSmallClockView).refreshTime()
|
||||
verify(mockLargeClockView).refreshTime()
|
||||
verify(mockLargeClockView).setLayoutParams(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_events_onTimeTick() {
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
clock.events.onTimeTick()
|
||||
|
||||
verify(mockSmallClockView).refreshTime()
|
||||
verify(mockLargeClockView).refreshTime()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_events_onTimeFormatChanged() {
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
clock.events.onTimeFormatChanged(true)
|
||||
|
||||
verify(mockSmallClockView).refreshFormat(true)
|
||||
verify(mockLargeClockView).refreshFormat(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_events_onTimeZoneChanged() {
|
||||
val timeZone = mock<TimeZone>()
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
clock.events.onTimeZoneChanged(timeZone)
|
||||
|
||||
verify(mockSmallClockView).onTimeZoneChanged(timeZone)
|
||||
verify(mockLargeClockView).onTimeZoneChanged(timeZone)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_events_onFontSettingChanged() {
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
clock.events.onFontSettingChanged()
|
||||
|
||||
verify(mockSmallClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
|
||||
verify(mockLargeClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
|
||||
verify(mockLargeClockView).setLayoutParams(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_events_onColorPaletteChanged() {
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
clock.events.onColorPaletteChanged(resources, true, true)
|
||||
|
||||
verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
|
||||
verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_events_onLocaleChanged() {
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
clock.events.onLocaleChanged(Locale.getDefault())
|
||||
|
||||
verify(mockSmallClockView, times(2)).setLineSpacingScale(anyFloat())
|
||||
verify(mockLargeClockView, times(2)).setLineSpacingScale(anyFloat())
|
||||
verify(mockSmallClockView, times(2)).refreshFormat()
|
||||
verify(mockLargeClockView, times(2)).refreshFormat()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,10 +333,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() {
|
||||
public void disable_isDozing_clockAndSystemInfoVisible() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(true);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false);
|
||||
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
@@ -345,10 +344,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_customClockButNotDozing_clockAndSystemInfoVisible() {
|
||||
public void disable_NotDozing_clockAndSystemInfoVisible() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
|
||||
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
@@ -356,40 +354,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_dozingAndCustomClock_clockAndSystemInfoHidden() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(true);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
|
||||
|
||||
// Make sure they start out as visible
|
||||
assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.GONE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDozingChanged_clockAndSystemInfoVisibilitiesUpdated() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(true);
|
||||
when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
|
||||
|
||||
// Make sure they start out as visible
|
||||
assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
|
||||
fragment.onDozingChanged(true);
|
||||
|
||||
// When this callback is triggered, we want to make sure the clock and system info
|
||||
// visibilities are recalculated. Since dozing=true, they shouldn't be visible.
|
||||
assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.GONE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disable_headsUpShouldBeVisibleTrue_clockDisabled() {
|
||||
CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
|
||||
Reference in New Issue
Block a user