Merge "Seperate clockface specific callbacks" into tm-qpr-dev am: 883ecccdfc am: e4c4493903
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19930066 Change-Id: I64077bcebd98ed13c8d85a5b98a3d067a0200af3 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -39,19 +39,19 @@ interface ClockProvider {
|
||||
fun getClocks(): List<ClockMetadata>
|
||||
|
||||
/** Initializes and returns the target clock design */
|
||||
fun createClock(id: ClockId): Clock
|
||||
fun createClock(id: ClockId): ClockController
|
||||
|
||||
/** A static thumbnail for rendering in some examples */
|
||||
fun getClockThumbnail(id: ClockId): Drawable?
|
||||
}
|
||||
|
||||
/** Interface for controlling an active clock */
|
||||
interface Clock {
|
||||
interface ClockController {
|
||||
/** A small version of the clock, appropriate for smaller viewports */
|
||||
val smallClock: View
|
||||
val smallClock: ClockFaceController
|
||||
|
||||
/** A large version of the clock, appropriate when a bigger viewport is available */
|
||||
val largeClock: View
|
||||
val largeClock: ClockFaceController
|
||||
|
||||
/** Events that clocks may need to respond to */
|
||||
val events: ClockEvents
|
||||
@@ -61,7 +61,7 @@ interface Clock {
|
||||
|
||||
/** Initializes various rendering parameters. If never called, provides reasonable defaults. */
|
||||
fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
|
||||
events.onColorPaletteChanged(resources, true, true)
|
||||
events.onColorPaletteChanged(resources)
|
||||
animations.doze(dozeFraction)
|
||||
animations.fold(foldFraction)
|
||||
events.onTimeTick()
|
||||
@@ -71,10 +71,19 @@ interface Clock {
|
||||
fun dump(pw: PrintWriter) { }
|
||||
}
|
||||
|
||||
/** Interface for a specific clock face version rendered by the clock */
|
||||
interface ClockFaceController {
|
||||
/** View that renders the clock face */
|
||||
val view: View
|
||||
|
||||
/** Events specific to this clock face */
|
||||
val events: ClockFaceEvents
|
||||
}
|
||||
|
||||
/** Events that should call when various rendering parameters change */
|
||||
interface ClockEvents {
|
||||
/** Call every time tick */
|
||||
fun onTimeTick()
|
||||
fun onTimeTick() { }
|
||||
|
||||
/** Call whenever timezone changes */
|
||||
fun onTimeZoneChanged(timeZone: TimeZone) { }
|
||||
@@ -89,11 +98,7 @@ interface ClockEvents {
|
||||
fun onFontSettingChanged() { }
|
||||
|
||||
/** Call whenever the color palette should update */
|
||||
fun onColorPaletteChanged(
|
||||
resources: Resources,
|
||||
smallClockIsDark: Boolean,
|
||||
largeClockIsDark: Boolean
|
||||
) { }
|
||||
fun onColorPaletteChanged(resources: Resources) { }
|
||||
}
|
||||
|
||||
/** Methods which trigger various clock animations */
|
||||
@@ -111,6 +116,12 @@ interface ClockAnimations {
|
||||
fun charge() { }
|
||||
}
|
||||
|
||||
/** Events that have specific data about the related face */
|
||||
interface ClockFaceEvents {
|
||||
/** Region Darkness specific to the clock face */
|
||||
fun onRegionDarknessChanged(isDark: Boolean) { }
|
||||
}
|
||||
|
||||
/** Some data about a clock design */
|
||||
data class ClockMetadata(
|
||||
val clockId: ClockId,
|
||||
|
||||
@@ -22,7 +22,7 @@ import android.os.UserHandle
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.plugins.ClockController
|
||||
import com.android.systemui.plugins.ClockId
|
||||
import com.android.systemui.plugins.ClockMetadata
|
||||
import com.android.systemui.plugins.ClockProvider
|
||||
@@ -33,7 +33,7 @@ import com.google.gson.Gson
|
||||
import javax.inject.Inject
|
||||
|
||||
private val TAG = ClockRegistry::class.simpleName
|
||||
private val DEBUG = true
|
||||
private const val DEBUG = true
|
||||
|
||||
/** ClockRegistry aggregates providers and plugins */
|
||||
open class ClockRegistry(
|
||||
@@ -130,6 +130,10 @@ open class ClockRegistry(
|
||||
}
|
||||
|
||||
availableClocks[id] = ClockInfo(clock, provider)
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Added ${clock.clockId}")
|
||||
}
|
||||
|
||||
if (currentId == id) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Current clock ($currentId) was connected")
|
||||
@@ -143,6 +147,9 @@ open class ClockRegistry(
|
||||
val currentId = currentClockId
|
||||
for (clock in provider.getClocks()) {
|
||||
availableClocks.remove(clock.clockId)
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Removed ${clock.clockId}")
|
||||
}
|
||||
|
||||
if (currentId == clock.clockId) {
|
||||
Log.w(TAG, "Current clock ($currentId) was disconnected")
|
||||
@@ -161,7 +168,7 @@ open class ClockRegistry(
|
||||
fun getClockThumbnail(clockId: ClockId): Drawable? =
|
||||
availableClocks[clockId]?.provider?.getClockThumbnail(clockId)
|
||||
|
||||
fun createExampleClock(clockId: ClockId): Clock? = createClock(clockId)
|
||||
fun createExampleClock(clockId: ClockId): ClockController? = createClock(clockId)
|
||||
|
||||
fun registerClockChangeListener(listener: ClockChangeListener) =
|
||||
clockChangeListeners.add(listener)
|
||||
@@ -169,11 +176,14 @@ open class ClockRegistry(
|
||||
fun unregisterClockChangeListener(listener: ClockChangeListener) =
|
||||
clockChangeListeners.remove(listener)
|
||||
|
||||
fun createCurrentClock(): Clock {
|
||||
fun createCurrentClock(): ClockController {
|
||||
val clockId = currentClockId
|
||||
if (isEnabled && clockId.isNotEmpty()) {
|
||||
val clock = createClock(clockId)
|
||||
if (clock != null) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "Rendering clock $clockId")
|
||||
}
|
||||
return clock
|
||||
} else {
|
||||
Log.e(TAG, "Clock $clockId not found; using default")
|
||||
@@ -183,7 +193,7 @@ open class ClockRegistry(
|
||||
return createClock(DEFAULT_CLOCK_ID)!!
|
||||
}
|
||||
|
||||
private fun createClock(clockId: ClockId): Clock? =
|
||||
private fun createClock(clockId: ClockId): ClockController? =
|
||||
availableClocks[clockId]?.provider?.createClock(clockId)
|
||||
|
||||
private data class ClockInfo(
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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.systemui.shared.clocks
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.icu.text.NumberFormat
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.systemui.plugins.ClockAnimations
|
||||
import com.android.systemui.plugins.ClockController
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
import com.android.systemui.plugins.ClockFaceController
|
||||
import com.android.systemui.plugins.ClockFaceEvents
|
||||
import com.android.systemui.shared.R
|
||||
import java.io.PrintWriter
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
|
||||
private val TAG = DefaultClockController::class.simpleName
|
||||
|
||||
/**
|
||||
* Controls the default clock visuals.
|
||||
*
|
||||
* This serves as an adapter between the clock interface and the AnimatableClockView used by the
|
||||
* existing lockscreen clock.
|
||||
*/
|
||||
class DefaultClockController(
|
||||
ctx: Context,
|
||||
private val layoutInflater: LayoutInflater,
|
||||
private val resources: Resources,
|
||||
) : ClockController {
|
||||
override val smallClock: DefaultClockFaceController
|
||||
override val largeClock: LargeClockFaceController
|
||||
private val clocks: List<AnimatableClockView>
|
||||
|
||||
private val burmeseNf = NumberFormat.getInstance(Locale.forLanguageTag("my"))
|
||||
private val burmeseNumerals = burmeseNf.format(FORMAT_NUMBER.toLong())
|
||||
private val burmeseLineSpacing =
|
||||
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: DefaultClockEvents
|
||||
override lateinit var animations: DefaultClockAnimations
|
||||
private set
|
||||
|
||||
init {
|
||||
val parent = FrameLayout(ctx)
|
||||
smallClock =
|
||||
DefaultClockFaceController(
|
||||
layoutInflater.inflate(R.layout.clock_default_small, parent, false)
|
||||
as AnimatableClockView
|
||||
)
|
||||
largeClock =
|
||||
LargeClockFaceController(
|
||||
layoutInflater.inflate(R.layout.clock_default_large, parent, false)
|
||||
as AnimatableClockView
|
||||
)
|
||||
clocks = listOf(smallClock.view, largeClock.view)
|
||||
|
||||
events = DefaultClockEvents()
|
||||
animations = DefaultClockAnimations(0f, 0f)
|
||||
events.onLocaleChanged(Locale.getDefault())
|
||||
}
|
||||
|
||||
override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
|
||||
largeClock.recomputePadding()
|
||||
animations = DefaultClockAnimations(dozeFraction, foldFraction)
|
||||
events.onColorPaletteChanged(resources)
|
||||
events.onTimeZoneChanged(TimeZone.getDefault())
|
||||
events.onTimeTick()
|
||||
}
|
||||
|
||||
open inner class DefaultClockFaceController(
|
||||
override val view: AnimatableClockView,
|
||||
) : ClockFaceController {
|
||||
// MAGENTA is a placeholder, and will be assigned correctly in initialize
|
||||
private var currentColor = Color.MAGENTA
|
||||
private var isRegionDark = false
|
||||
|
||||
init {
|
||||
view.setColors(currentColor, currentColor)
|
||||
}
|
||||
|
||||
override val events =
|
||||
object : ClockFaceEvents {
|
||||
override fun onRegionDarknessChanged(isRegionDark: Boolean) {
|
||||
this@DefaultClockFaceController.isRegionDark = isRegionDark
|
||||
updateColor()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateColor() {
|
||||
val color =
|
||||
if (isRegionDark) {
|
||||
resources.getColor(android.R.color.system_accent1_100)
|
||||
} else {
|
||||
resources.getColor(android.R.color.system_accent2_600)
|
||||
}
|
||||
|
||||
if (currentColor == color) {
|
||||
return
|
||||
}
|
||||
|
||||
currentColor = color
|
||||
view.setColors(DOZE_COLOR, color)
|
||||
view.animateAppearOnLockscreen()
|
||||
}
|
||||
}
|
||||
|
||||
inner class LargeClockFaceController(
|
||||
view: AnimatableClockView,
|
||||
) : DefaultClockFaceController(view) {
|
||||
fun recomputePadding() {
|
||||
val lp = view.getLayoutParams() as FrameLayout.LayoutParams
|
||||
lp.topMargin = (-0.5f * view.bottom).toInt()
|
||||
view.setLayoutParams(lp)
|
||||
}
|
||||
}
|
||||
|
||||
inner class DefaultClockEvents : ClockEvents {
|
||||
override fun onTimeTick() = clocks.forEach { it.refreshTime() }
|
||||
|
||||
override fun onTimeFormatChanged(is24Hr: Boolean) =
|
||||
clocks.forEach { it.refreshFormat(is24Hr) }
|
||||
|
||||
override fun onTimeZoneChanged(timeZone: TimeZone) =
|
||||
clocks.forEach { it.onTimeZoneChanged(timeZone) }
|
||||
|
||||
override fun onFontSettingChanged() {
|
||||
smallClock.view.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_PX,
|
||||
resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()
|
||||
)
|
||||
largeClock.view.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_PX,
|
||||
resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
|
||||
)
|
||||
largeClock.recomputePadding()
|
||||
}
|
||||
|
||||
override fun onColorPaletteChanged(resources: Resources) {
|
||||
largeClock.updateColor()
|
||||
smallClock.updateColor()
|
||||
}
|
||||
|
||||
override fun onLocaleChanged(locale: Locale) {
|
||||
val nf = NumberFormat.getInstance(locale)
|
||||
if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
|
||||
clocks.forEach { it.setLineSpacingScale(burmeseLineSpacing) }
|
||||
} else {
|
||||
clocks.forEach { it.setLineSpacingScale(defaultLineSpacing) }
|
||||
}
|
||||
|
||||
clocks.forEach { it.refreshFormat() }
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if (foldState.isActive) {
|
||||
clocks.forEach { it.animateFoldAppear(false) }
|
||||
} else {
|
||||
clocks.forEach { it.animateDoze(dozeState.isActive, false) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun enter() {
|
||||
if (!dozeState.isActive) {
|
||||
clocks.forEach { it.animateAppearOnLockscreen() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun charge() = clocks.forEach { it.animateCharge { dozeState.isActive } }
|
||||
|
||||
override fun fold(fraction: Float) {
|
||||
val (hasChanged, hasJumped) = foldState.update(fraction)
|
||||
if (hasChanged) {
|
||||
clocks.forEach { it.animateFoldAppear(!hasJumped) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun doze(fraction: Float) {
|
||||
val (hasChanged, hasJumped) = dozeState.update(fraction)
|
||||
if (hasChanged) {
|
||||
clocks.forEach { it.animateDoze(dozeState.isActive, !hasJumped) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AnimationState(
|
||||
var fraction: Float,
|
||||
) {
|
||||
var isActive: Boolean = fraction < 0.5f
|
||||
fun update(newFraction: Float): Pair<Boolean, Boolean> {
|
||||
val wasActive = isActive
|
||||
val hasJumped =
|
||||
(fraction == 0f && newFraction == 1f) || (fraction == 1f && newFraction == 0f)
|
||||
isActive = newFraction > fraction
|
||||
fraction = newFraction
|
||||
return Pair(wasActive != isActive, hasJumped)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) }
|
||||
|
||||
companion object {
|
||||
@VisibleForTesting const val DOZE_COLOR = Color.WHITE
|
||||
private const val FORMAT_NUMBER = 1234567890
|
||||
}
|
||||
}
|
||||
@@ -15,24 +15,14 @@ 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 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.ClockAnimations
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
import com.android.systemui.plugins.ClockController
|
||||
import com.android.systemui.plugins.ClockId
|
||||
import com.android.systemui.plugins.ClockMetadata
|
||||
import com.android.systemui.plugins.ClockProvider
|
||||
import com.android.systemui.shared.R
|
||||
import java.io.PrintWriter
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import javax.inject.Inject
|
||||
|
||||
private val TAG = DefaultClockProvider::class.simpleName
|
||||
@@ -48,11 +38,12 @@ class DefaultClockProvider @Inject constructor(
|
||||
override fun getClocks(): List<ClockMetadata> =
|
||||
listOf(ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME))
|
||||
|
||||
override fun createClock(id: ClockId): Clock {
|
||||
override fun createClock(id: ClockId): ClockController {
|
||||
if (id != DEFAULT_CLOCK_ID) {
|
||||
throw IllegalArgumentException("$id is unsupported by $TAG")
|
||||
}
|
||||
return DefaultClock(ctx, layoutInflater, resources)
|
||||
|
||||
return DefaultClockController(ctx, layoutInflater, resources)
|
||||
}
|
||||
|
||||
override fun getClockThumbnail(id: ClockId): Drawable? {
|
||||
@@ -64,190 +55,3 @@ class DefaultClockProvider @Inject constructor(
|
||||
return resources.getDrawable(R.drawable.clock_default_thumbnail, null)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the default clock visuals.
|
||||
*
|
||||
* This serves as an adapter between the clock interface and the
|
||||
* AnimatableClockView used by the existing lockscreen clock.
|
||||
*/
|
||||
class DefaultClock(
|
||||
ctx: Context,
|
||||
private val layoutInflater: LayoutInflater,
|
||||
private val resources: Resources
|
||||
) : Clock {
|
||||
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())
|
||||
private val burmeseLineSpacing =
|
||||
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: ClockEvents
|
||||
override lateinit var animations: ClockAnimations
|
||||
private set
|
||||
|
||||
private var smallRegionDarkness = false
|
||||
private var largeRegionDarkness = false
|
||||
|
||||
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) =
|
||||
clocks.forEach { it.refreshFormat(is24Hr) }
|
||||
|
||||
override fun onTimeZoneChanged(timeZone: TimeZone) =
|
||||
clocks.forEach { it.onTimeZoneChanged(timeZone) }
|
||||
|
||||
override fun onFontSettingChanged() {
|
||||
smallClock.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_PX,
|
||||
resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()
|
||||
)
|
||||
largeClock.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_PX,
|
||||
resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
|
||||
)
|
||||
recomputePadding()
|
||||
}
|
||||
|
||||
override fun onColorPaletteChanged(
|
||||
resources: Resources,
|
||||
smallClockIsDark: Boolean,
|
||||
largeClockIsDark: Boolean
|
||||
) {
|
||||
if (smallRegionDarkness != smallClockIsDark) {
|
||||
smallRegionDarkness = smallClockIsDark
|
||||
updateClockColor(smallClock, smallClockIsDark)
|
||||
}
|
||||
if (largeRegionDarkness != largeClockIsDark) {
|
||||
largeRegionDarkness = largeClockIsDark
|
||||
updateClockColor(largeClock, largeClockIsDark)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLocaleChanged(locale: Locale) {
|
||||
val nf = NumberFormat.getInstance(locale)
|
||||
if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
|
||||
clocks.forEach { it.setLineSpacingScale(burmeseLineSpacing) }
|
||||
} else {
|
||||
clocks.forEach { it.setLineSpacingScale(defaultLineSpacing) }
|
||||
}
|
||||
|
||||
clocks.forEach { it.refreshFormat() }
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if (foldState.isActive) {
|
||||
clocks.forEach { it.animateFoldAppear(false) }
|
||||
} else {
|
||||
clocks.forEach { it.animateDoze(dozeState.isActive, false) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun enter() {
|
||||
if (!dozeState.isActive) {
|
||||
clocks.forEach { it.animateAppearOnLockscreen() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun charge() = clocks.forEach { it.animateCharge { dozeState.isActive } }
|
||||
|
||||
override fun fold(fraction: Float) {
|
||||
val (hasChanged, hasJumped) = foldState.update(fraction)
|
||||
if (hasChanged) {
|
||||
clocks.forEach { it.animateFoldAppear(!hasJumped) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun doze(fraction: Float) {
|
||||
val (hasChanged, hasJumped) = dozeState.update(fraction)
|
||||
if (hasChanged) {
|
||||
clocks.forEach { it.animateDoze(dozeState.isActive, !hasJumped) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AnimationState(
|
||||
var fraction: Float
|
||||
) {
|
||||
var isActive: Boolean = fraction < 0.5f
|
||||
fun update(newFraction: Float): Pair<Boolean, Boolean> {
|
||||
val wasActive = isActive
|
||||
val hasJumped = (fraction == 0f && newFraction == 1f) ||
|
||||
(fraction == 1f && newFraction == 0f)
|
||||
isActive = newFraction > fraction
|
||||
fraction = newFraction
|
||||
return Pair(wasActive != isActive, hasJumped)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@VisibleForTesting const val DOZE_COLOR = Color.WHITE
|
||||
private const val FORMAT_NUMBER = 1234567890
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ 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.ClockController
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.shared.regionsampling.RegionSamplingInstance
|
||||
import com.android.systemui.statusbar.policy.BatteryController
|
||||
@@ -44,18 +44,18 @@ import javax.inject.Inject
|
||||
* [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
|
||||
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
|
||||
var clock: ClockController? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (value != null) {
|
||||
@@ -74,42 +74,45 @@ open class ClockEventController @Inject constructor(
|
||||
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)
|
||||
private fun updateColors() {
|
||||
if (regionSamplingEnabled && smallRegionSampler != null && largeRegionSampler != null) {
|
||||
smallClockIsDark = smallRegionSampler!!.currentRegionDarkness().isDark
|
||||
largeClockIsDark = largeRegionSampler!!.currentRegionDarkness().isDark
|
||||
} else {
|
||||
val isLightTheme = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
|
||||
smallClockIsDark = isLightTheme.data == 0
|
||||
largeClockIsDark = isLightTheme.data == 0
|
||||
}
|
||||
|
||||
clock?.smallClock?.events?.onRegionDarknessChanged(smallClockIsDark)
|
||||
clock?.largeClock?.events?.onRegionDarknessChanged(largeClockIsDark)
|
||||
}
|
||||
|
||||
fun updateRegionSamplers(currentClock: Clock?) {
|
||||
smallRegionSamplingInstance = createRegionSampler(
|
||||
currentClock?.smallClock,
|
||||
private fun updateRegionSamplers(currentClock: ClockController?) {
|
||||
smallRegionSampler?.stopRegionSampler()
|
||||
largeRegionSampler?.stopRegionSampler()
|
||||
|
||||
smallRegionSampler = createRegionSampler(
|
||||
currentClock?.smallClock?.view,
|
||||
mainExecutor,
|
||||
bgExecutor,
|
||||
regionSamplingEnabled,
|
||||
updateFun
|
||||
::updateColors
|
||||
)
|
||||
|
||||
largeRegionSamplingInstance = createRegionSampler(
|
||||
currentClock?.largeClock,
|
||||
largeRegionSampler = createRegionSampler(
|
||||
currentClock?.largeClock?.view,
|
||||
mainExecutor,
|
||||
bgExecutor,
|
||||
regionSamplingEnabled,
|
||||
updateFun
|
||||
::updateColors
|
||||
)
|
||||
|
||||
smallRegionSamplingInstance.startRegionSampler()
|
||||
largeRegionSamplingInstance.startRegionSampler()
|
||||
smallRegionSampler!!.startRegionSampler()
|
||||
largeRegionSampler!!.startRegionSampler()
|
||||
|
||||
updateFun.updateColors()
|
||||
updateColors()
|
||||
}
|
||||
|
||||
protected open fun createRegionSampler(
|
||||
@@ -117,25 +120,29 @@ open class ClockEventController @Inject constructor(
|
||||
mainExecutor: Executor?,
|
||||
bgExecutor: Executor?,
|
||||
regionSamplingEnabled: Boolean,
|
||||
updateFun: RegionSamplingInstance.UpdateColorCallback
|
||||
updateColors: () -> Unit
|
||||
): RegionSamplingInstance {
|
||||
return RegionSamplingInstance(
|
||||
sampledView,
|
||||
mainExecutor,
|
||||
bgExecutor,
|
||||
regionSamplingEnabled,
|
||||
updateFun)
|
||||
object : RegionSamplingInstance.UpdateColorCallback {
|
||||
override fun updateColors() {
|
||||
updateColors()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
lateinit var smallRegionSamplingInstance: RegionSamplingInstance
|
||||
lateinit var largeRegionSamplingInstance: RegionSamplingInstance
|
||||
var smallRegionSampler: RegionSamplingInstance? = null
|
||||
var largeRegionSampler: RegionSamplingInstance? = null
|
||||
|
||||
private var smallClockIsDark = true
|
||||
private var largeClockIsDark = true
|
||||
|
||||
private val configListener = object : ConfigurationController.ConfigurationListener {
|
||||
override fun onThemeChanged() {
|
||||
updateFun.updateColors()
|
||||
clock?.events?.onColorPaletteChanged(resources)
|
||||
}
|
||||
|
||||
override fun onDensityOrFontScaleChanged() {
|
||||
@@ -204,8 +211,8 @@ open class ClockEventController @Inject constructor(
|
||||
batteryController.addCallback(batteryCallback)
|
||||
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
|
||||
statusBarStateController.addCallback(statusBarStateListener)
|
||||
smallRegionSamplingInstance.startRegionSampler()
|
||||
largeRegionSamplingInstance.startRegionSampler()
|
||||
smallRegionSampler?.startRegionSampler()
|
||||
largeRegionSampler?.startRegionSampler()
|
||||
}
|
||||
|
||||
fun unregisterListeners() {
|
||||
@@ -214,8 +221,8 @@ open class ClockEventController @Inject constructor(
|
||||
batteryController.removeCallback(batteryCallback)
|
||||
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
|
||||
statusBarStateController.removeCallback(statusBarStateListener)
|
||||
smallRegionSamplingInstance.stopRegionSampler()
|
||||
largeRegionSamplingInstance.stopRegionSampler()
|
||||
smallRegionSampler?.stopRegionSampler()
|
||||
largeRegionSampler?.stopRegionSampler()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,8 +231,8 @@ open class ClockEventController @Inject constructor(
|
||||
fun dump(pw: PrintWriter) {
|
||||
pw.println(this)
|
||||
clock?.dump(pw)
|
||||
smallRegionSamplingInstance.dump(pw)
|
||||
largeRegionSamplingInstance.dump(pw)
|
||||
smallRegionSampler?.dump(pw)
|
||||
largeRegionSampler?.dump(pw)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,7 +17,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import com.android.keyguard.dagger.KeyguardStatusViewScope;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
import com.android.systemui.plugins.ClockController;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -94,7 +94,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
onDensityOrFontScaleChanged();
|
||||
}
|
||||
|
||||
void setClock(Clock clock, int statusBarState) {
|
||||
void setClock(ClockController clock, int statusBarState) {
|
||||
// Disconnect from existing plugin.
|
||||
mSmallClockFrame.removeAllViews();
|
||||
mLargeClockFrame.removeAllViews();
|
||||
@@ -105,8 +105,8 @@ public class KeyguardClockSwitch extends RelativeLayout {
|
||||
}
|
||||
|
||||
// Attach small and big clock views to hierarchy.
|
||||
mSmallClockFrame.addView(clock.getSmallClock());
|
||||
mLargeClockFrame.addView(clock.getLargeClock());
|
||||
mSmallClockFrame.addView(clock.getSmallClock().getView());
|
||||
mLargeClockFrame.addView(clock.getLargeClock().getView());
|
||||
}
|
||||
|
||||
private void updateClockViews(boolean useLargeClock, boolean animate) {
|
||||
|
||||
@@ -40,7 +40,7 @@ import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
import com.android.systemui.plugins.ClockController;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.clocks.ClockRegistry;
|
||||
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
|
||||
@@ -262,7 +262,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
|
||||
mCurrentClockSize = clockSize;
|
||||
|
||||
Clock clock = getClock();
|
||||
ClockController clock = getClock();
|
||||
boolean appeared = mView.switchToClock(clockSize, animate);
|
||||
if (clock != null && animate && appeared && clockSize == LARGE) {
|
||||
clock.getAnimations().enter();
|
||||
@@ -273,7 +273,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
* Animates the clock view between folded and unfolded states
|
||||
*/
|
||||
public void animateFoldToAod(float foldFraction) {
|
||||
Clock clock = getClock();
|
||||
ClockController clock = getClock();
|
||||
if (clock != null) {
|
||||
clock.getAnimations().fold(foldFraction);
|
||||
}
|
||||
@@ -286,7 +286,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
if (mSmartspaceController != null) {
|
||||
mSmartspaceController.requestSmartspaceUpdate();
|
||||
}
|
||||
Clock clock = getClock();
|
||||
ClockController clock = getClock();
|
||||
if (clock != null) {
|
||||
clock.getEvents().onTimeTick();
|
||||
}
|
||||
@@ -319,17 +319,17 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
* We can't directly getBottom() because clock changes positions in AOD for burn-in
|
||||
*/
|
||||
int getClockBottom(int statusBarHeaderHeight) {
|
||||
Clock clock = getClock();
|
||||
ClockController clock = getClock();
|
||||
if (clock == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
|
||||
int frameHeight = mLargeClockFrame.getHeight();
|
||||
int clockHeight = clock.getLargeClock().getHeight();
|
||||
int clockHeight = clock.getLargeClock().getView().getHeight();
|
||||
return frameHeight / 2 + clockHeight / 2;
|
||||
} else {
|
||||
int clockHeight = clock.getSmallClock().getHeight();
|
||||
int clockHeight = clock.getSmallClock().getView().getHeight();
|
||||
return clockHeight + statusBarHeaderHeight + mKeyguardClockTopMargin;
|
||||
}
|
||||
}
|
||||
@@ -338,15 +338,15 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
* Get the height of the currently visible clock on the keyguard.
|
||||
*/
|
||||
int getClockHeight() {
|
||||
Clock clock = getClock();
|
||||
ClockController clock = getClock();
|
||||
if (clock == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
|
||||
return clock.getLargeClock().getHeight();
|
||||
return clock.getLargeClock().getView().getHeight();
|
||||
} else {
|
||||
return clock.getSmallClock().getHeight();
|
||||
return clock.getSmallClock().getView().getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,12 +361,12 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
mNotificationIconAreaController.setupAodIcons(nic);
|
||||
}
|
||||
|
||||
private void setClock(Clock clock) {
|
||||
private void setClock(ClockController clock) {
|
||||
mClockEventController.setClock(clock);
|
||||
mView.setClock(clock, mStatusBarStateController.getState());
|
||||
}
|
||||
|
||||
private Clock getClock() {
|
||||
private ClockController getClock() {
|
||||
return mClockEventController.getClock();
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
|
||||
pw.println("currentClockSizeLarge=" + (mCurrentClockSize == LARGE));
|
||||
pw.println("mCanShowDoubleLineClock=" + mCanShowDoubleLineClock);
|
||||
Clock clock = getClock();
|
||||
ClockController clock = getClock();
|
||||
if (clock != null) {
|
||||
clock.dump(pw);
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@ 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.ClockController
|
||||
import com.android.systemui.plugins.ClockEvents
|
||||
import com.android.systemui.plugins.ClockFaceController
|
||||
import com.android.systemui.plugins.ClockFaceEvents
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.statusbar.policy.BatteryController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
@@ -40,6 +42,7 @@ 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.Mock
|
||||
@@ -61,17 +64,25 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
@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 clock: ClockController
|
||||
@Mock private lateinit var mainExecutor: Executor
|
||||
@Mock private lateinit var bgExecutor: Executor
|
||||
@Mock private lateinit var featureFlags: FeatureFlags
|
||||
@Mock private lateinit var smallClockController: ClockFaceController
|
||||
@Mock private lateinit var largeClockController: ClockFaceController
|
||||
@Mock private lateinit var smallClockEvents: ClockFaceEvents
|
||||
@Mock private lateinit var largeClockEvents: ClockFaceEvents
|
||||
|
||||
private lateinit var clockEventController: ClockEventController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
whenever(clock.smallClock).thenReturn(TextView(context))
|
||||
whenever(clock.largeClock).thenReturn(TextView(context))
|
||||
whenever(clock.smallClock).thenReturn(smallClockController)
|
||||
whenever(clock.largeClock).thenReturn(largeClockController)
|
||||
whenever(smallClockController.view).thenReturn(TextView(context))
|
||||
whenever(largeClockController.view).thenReturn(TextView(context))
|
||||
whenever(smallClockController.events).thenReturn(smallClockEvents)
|
||||
whenever(largeClockController.events).thenReturn(largeClockEvents)
|
||||
whenever(clock.events).thenReturn(events)
|
||||
whenever(clock.animations).thenReturn(animations)
|
||||
|
||||
@@ -107,7 +118,8 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun themeChanged_verifyClockPaletteUpdated() {
|
||||
clockEventController.clock = clock
|
||||
verify(events).onColorPaletteChanged(any(), any(), any())
|
||||
verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
|
||||
clockEventController.registerListeners()
|
||||
|
||||
@@ -115,13 +127,14 @@ class ClockEventControllerTest : SysuiTestCase() {
|
||||
verify(configurationController).addCallback(capture(captor))
|
||||
captor.value.onThemeChanged()
|
||||
|
||||
verify(events, times(2)).onColorPaletteChanged(any(), any(), any())
|
||||
verify(events).onColorPaletteChanged(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fontChanged_verifyFontSizeUpdated() {
|
||||
clockEventController.clock = clock
|
||||
verify(events).onColorPaletteChanged(any(), any(), any())
|
||||
verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
|
||||
|
||||
clockEventController.registerListeners()
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
import com.android.systemui.plugins.ClockController;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.clocks.AnimatableClockView;
|
||||
import com.android.systemui.shared.clocks.ClockRegistry;
|
||||
@@ -87,7 +87,7 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||
@Mock
|
||||
private Clock mClock;
|
||||
private ClockController mClock;
|
||||
@Mock
|
||||
DumpManager mDumpManager;
|
||||
@Mock
|
||||
|
||||
@@ -41,7 +41,8 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.Clock;
|
||||
import com.android.systemui.plugins.ClockController;
|
||||
import com.android.systemui.plugins.ClockFaceController;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -61,7 +62,13 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
ViewGroup mMockKeyguardSliceView;
|
||||
|
||||
@Mock
|
||||
Clock mClock;
|
||||
ClockController mClock;
|
||||
|
||||
@Mock
|
||||
ClockFaceController mSmallClock;
|
||||
|
||||
@Mock
|
||||
ClockFaceController mLargeClock;
|
||||
|
||||
private FrameLayout mSmallClockFrame;
|
||||
private FrameLayout mLargeClockFrame;
|
||||
@@ -75,8 +82,11 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
when(mMockKeyguardSliceView.findViewById(R.id.keyguard_status_area))
|
||||
.thenReturn(mMockKeyguardSliceView);
|
||||
|
||||
when(mClock.getSmallClock()).thenReturn(new TextView(getContext()));
|
||||
when(mClock.getLargeClock()).thenReturn(new TextView(getContext()));
|
||||
when(mClock.getSmallClock()).thenReturn(mSmallClock);
|
||||
when(mClock.getLargeClock()).thenReturn(mLargeClock);
|
||||
|
||||
when(mSmallClock.getView()).thenReturn(new TextView(getContext()));
|
||||
when(mLargeClock.getView()).thenReturn(new TextView(getContext()));
|
||||
|
||||
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
|
||||
layoutInflater.setPrivateFactory(new LayoutInflater.Factory2() {
|
||||
@@ -124,41 +134,49 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
public void onPluginConnected_showClock() {
|
||||
mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
|
||||
|
||||
assertEquals(mClock.getSmallClock().getParent(), mSmallClockFrame);
|
||||
assertEquals(mClock.getLargeClock().getParent(), mLargeClockFrame);
|
||||
assertEquals(mClock.getSmallClock().getView().getParent(), mSmallClockFrame);
|
||||
assertEquals(mClock.getLargeClock().getView().getParent(), mLargeClockFrame);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginConnected_showSecondPluginClock() {
|
||||
// GIVEN a plugin has already connected
|
||||
Clock otherClock = mock(Clock.class);
|
||||
when(otherClock.getSmallClock()).thenReturn(new TextView(getContext()));
|
||||
when(otherClock.getLargeClock()).thenReturn(new TextView(getContext()));
|
||||
ClockController otherClock = mock(ClockController.class);
|
||||
ClockFaceController smallClock = mock(ClockFaceController.class);
|
||||
ClockFaceController largeClock = mock(ClockFaceController.class);
|
||||
when(otherClock.getSmallClock()).thenReturn(smallClock);
|
||||
when(otherClock.getLargeClock()).thenReturn(largeClock);
|
||||
when(smallClock.getView()).thenReturn(new TextView(getContext()));
|
||||
when(largeClock.getView()).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(otherClock.getSmallClock().getParent()).isEqualTo(mSmallClockFrame);
|
||||
assertThat(otherClock.getLargeClock().getParent()).isEqualTo(mLargeClockFrame);
|
||||
assertThat(mClock.getSmallClock().getParent()).isNull();
|
||||
assertThat(mClock.getLargeClock().getParent()).isNull();
|
||||
assertThat(otherClock.getSmallClock().getView().getParent()).isEqualTo(mSmallClockFrame);
|
||||
assertThat(otherClock.getLargeClock().getView().getParent()).isEqualTo(mLargeClockFrame);
|
||||
assertThat(mClock.getSmallClock().getView().getParent()).isNull();
|
||||
assertThat(mClock.getLargeClock().getView().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginDisconnected_secondOfTwoDisconnected() {
|
||||
// GIVEN two plugins are connected
|
||||
Clock otherClock = mock(Clock.class);
|
||||
when(otherClock.getSmallClock()).thenReturn(new TextView(getContext()));
|
||||
when(otherClock.getLargeClock()).thenReturn(new TextView(getContext()));
|
||||
ClockController otherClock = mock(ClockController.class);
|
||||
ClockFaceController smallClock = mock(ClockFaceController.class);
|
||||
ClockFaceController largeClock = mock(ClockFaceController.class);
|
||||
when(otherClock.getSmallClock()).thenReturn(smallClock);
|
||||
when(otherClock.getLargeClock()).thenReturn(largeClock);
|
||||
when(smallClock.getView()).thenReturn(new TextView(getContext()));
|
||||
when(largeClock.getView()).thenReturn(new TextView(getContext()));
|
||||
mKeyguardClockSwitch.setClock(otherClock, StatusBarState.KEYGUARD);
|
||||
mKeyguardClockSwitch.setClock(mClock, StatusBarState.KEYGUARD);
|
||||
// WHEN the second plugin is disconnected
|
||||
mKeyguardClockSwitch.setClock(null, StatusBarState.KEYGUARD);
|
||||
// THEN nothing should be shown
|
||||
assertThat(otherClock.getSmallClock().getParent()).isNull();
|
||||
assertThat(otherClock.getLargeClock().getParent()).isNull();
|
||||
assertThat(mClock.getSmallClock().getParent()).isNull();
|
||||
assertThat(mClock.getLargeClock().getParent()).isNull();
|
||||
assertThat(otherClock.getSmallClock().getView().getParent()).isNull();
|
||||
assertThat(otherClock.getLargeClock().getView().getParent()).isNull();
|
||||
assertThat(mClock.getSmallClock().getView().getParent()).isNull();
|
||||
assertThat(mClock.getLargeClock().getView().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,7 +22,7 @@ import android.os.Handler
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.plugins.Clock
|
||||
import com.android.systemui.plugins.ClockController
|
||||
import com.android.systemui.plugins.ClockId
|
||||
import com.android.systemui.plugins.ClockMetadata
|
||||
import com.android.systemui.plugins.ClockProviderPlugin
|
||||
@@ -48,8 +48,8 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||
@Mock private lateinit var mockContext: Context
|
||||
@Mock private lateinit var mockPluginManager: PluginManager
|
||||
@Mock private lateinit var mockClock: Clock
|
||||
@Mock private lateinit var mockDefaultClock: Clock
|
||||
@Mock private lateinit var mockClock: ClockController
|
||||
@Mock private lateinit var mockDefaultClock: ClockController
|
||||
@Mock private lateinit var mockThumbnail: Drawable
|
||||
@Mock private lateinit var mockHandler: Handler
|
||||
@Mock private lateinit var mockContentResolver: ContentResolver
|
||||
@@ -60,7 +60,7 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
private var settingValue: String = ""
|
||||
|
||||
companion object {
|
||||
private fun failFactory(): Clock {
|
||||
private fun failFactory(): ClockController {
|
||||
fail("Unexpected call to createClock")
|
||||
return null!!
|
||||
}
|
||||
@@ -73,17 +73,17 @@ class ClockRegistryTest : SysuiTestCase() {
|
||||
|
||||
private class FakeClockPlugin : ClockProviderPlugin {
|
||||
private val metadata = mutableListOf<ClockMetadata>()
|
||||
private val createCallbacks = mutableMapOf<ClockId, () -> Clock>()
|
||||
private val createCallbacks = mutableMapOf<ClockId, () -> ClockController>()
|
||||
private val thumbnailCallbacks = mutableMapOf<ClockId, () -> Drawable?>()
|
||||
|
||||
override fun getClocks() = metadata
|
||||
override fun createClock(id: ClockId): Clock = createCallbacks[id]!!()
|
||||
override fun createClock(id: ClockId): ClockController = createCallbacks[id]!!()
|
||||
override fun getClockThumbnail(id: ClockId): Drawable? = thumbnailCallbacks[id]!!()
|
||||
|
||||
fun addClock(
|
||||
id: ClockId,
|
||||
name: String,
|
||||
create: () -> Clock = ::failFactory,
|
||||
create: () -> ClockController = ::failFactory,
|
||||
getThumbnail: () -> Drawable? = ::failThumbnail
|
||||
): FakeClockPlugin {
|
||||
metadata.add(ClockMetadata(id, name))
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.shared.clocks
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.util.TypedValue
|
||||
@@ -25,7 +26,7 @@ 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.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
@@ -88,17 +89,20 @@ class DefaultClockProviderTest : SysuiTestCase() {
|
||||
// Default clock provider must always provide the default clock
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
assertNotNull(clock)
|
||||
assertEquals(clock.smallClock, mockSmallClockView)
|
||||
assertEquals(clock.largeClock, mockLargeClockView)
|
||||
assertEquals(mockSmallClockView, clock.smallClock.view)
|
||||
assertEquals(mockLargeClockView, clock.largeClock.view)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultClock_initialize() {
|
||||
val clock = provider.createClock(DEFAULT_CLOCK_ID)
|
||||
verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
|
||||
verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
|
||||
|
||||
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).setColors(eq(DOZE_COLOR), anyInt())
|
||||
verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
|
||||
verify(mockSmallClockView).onTimeZoneChanged(notNull())
|
||||
verify(mockLargeClockView).onTimeZoneChanged(notNull())
|
||||
verify(mockSmallClockView).refreshTime()
|
||||
@@ -147,10 +151,14 @@ class DefaultClockProviderTest : SysuiTestCase() {
|
||||
@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())
|
||||
verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
|
||||
verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
|
||||
|
||||
clock.events.onColorPaletteChanged(resources)
|
||||
|
||||
verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
|
||||
verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user