summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt59
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt230
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt21
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt8
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/core/LogcatOnlyMessageBuffer.kt76
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt24
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt207
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt4
12 files changed, 348 insertions, 314 deletions
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index b9d66432b5f2..2bfa7d9bbd7b 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -33,6 +33,8 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.GlyphCallback
import com.android.systemui.animation.TextAnimator
import com.android.systemui.customization.R
+import com.android.systemui.log.core.LogcatOnlyMessageBuffer
+import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.core.Logger
import com.android.systemui.log.core.MessageBuffer
import java.io.PrintWriter
@@ -51,12 +53,13 @@ class AnimatableClockView @JvmOverloads constructor(
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : TextView(context, attrs, defStyleAttr, defStyleRes) {
- var messageBuffer: MessageBuffer? = null
- set(value) {
- logger = if (value != null) Logger(value, TAG) else null
- }
-
- private var logger: Logger? = null
+ // To protect us from issues from this being null while the TextView constructor is running, we
+ // implement the get method and ensure a value is returned before initialization is complete.
+ private var logger = DEFAULT_LOGGER
+ get() = field ?: DEFAULT_LOGGER
+ var messageBuffer: MessageBuffer
+ get() = logger.buffer
+ set(value) { logger = Logger(value, TAG) }
private val time = Calendar.getInstance()
@@ -133,8 +136,8 @@ class AnimatableClockView @JvmOverloads constructor(
}
override fun onAttachedToWindow() {
+ logger.d("onAttachedToWindow")
super.onAttachedToWindow()
- logger?.d("onAttachedToWindow")
refreshFormat()
}
@@ -150,13 +153,13 @@ class AnimatableClockView @JvmOverloads constructor(
time.timeInMillis = timeOverrideInMillis ?: System.currentTimeMillis()
contentDescription = DateFormat.format(descFormat, time)
val formattedText = DateFormat.format(format, time)
- logger?.d({ "refreshTime: new formattedText=$str1" }) { str1 = formattedText?.toString() }
+ logger.d({ "refreshTime: new formattedText=$str1" }) { str1 = formattedText?.toString() }
// Setting text actually triggers a layout pass (because the text view is set to
// wrap_content width and TextView always relayouts for this). Avoid needless
// relayout if the text didn't actually change.
if (!TextUtils.equals(text, formattedText)) {
text = formattedText
- logger?.d({ "refreshTime: done setting new time text to: $str1" }) {
+ logger.d({ "refreshTime: done setting new time text to: $str1" }) {
str1 = formattedText?.toString()
}
// Because the TextLayout may mutate under the hood as a result of the new text, we
@@ -165,21 +168,22 @@ class AnimatableClockView @JvmOverloads constructor(
// without being notified TextInterpolator being notified.
if (layout != null) {
textAnimator?.updateLayout(layout)
- logger?.d("refreshTime: done updating textAnimator layout")
+ logger.d("refreshTime: done updating textAnimator layout")
}
requestLayout()
- logger?.d("refreshTime: after requestLayout")
+ logger.d("refreshTime: after requestLayout")
}
}
fun onTimeZoneChanged(timeZone: TimeZone?) {
+ logger.d({ "onTimeZoneChanged($str1)" }) { str1 = timeZone?.toString() }
time.timeZone = timeZone
refreshFormat()
- logger?.d({ "onTimeZoneChanged newTimeZone=$str1" }) { str1 = timeZone?.toString() }
}
@SuppressLint("DrawAllocation")
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ logger.d("onMeasure")
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val animator = textAnimator
if (animator == null) {
@@ -189,10 +193,10 @@ class AnimatableClockView @JvmOverloads constructor(
} else {
animator.updateLayout(layout)
}
- logger?.d("onMeasure")
}
override fun onDraw(canvas: Canvas) {
+ logger.d({ "onDraw($str1)"}) { str1 = text.toString() }
// Use textAnimator to render text if animation is enabled.
// Otherwise default to using standard draw functions.
if (isAnimationEnabled) {
@@ -201,22 +205,23 @@ class AnimatableClockView @JvmOverloads constructor(
} else {
super.onDraw(canvas)
}
- logger?.d("onDraw")
}
override fun invalidate() {
+ @Suppress("UNNECESSARY_SAFE_CALL")
+ // logger won't be initialized when called by TextView's constructor
+ logger.d("invalidate")
super.invalidate()
- logger?.d("invalidate")
}
override fun onTextChanged(
- text: CharSequence,
- start: Int,
- lengthBefore: Int,
- lengthAfter: Int
+ text: CharSequence,
+ start: Int,
+ lengthBefore: Int,
+ lengthAfter: Int
) {
+ logger.d({ "onTextChanged($str1)" }) { str1 = text.toString() }
super.onTextChanged(text, start, lengthBefore, lengthAfter)
- logger?.d({ "onTextChanged text=$str1" }) { str1 = text.toString() }
}
fun setLineSpacingScale(scale: Float) {
@@ -230,7 +235,7 @@ class AnimatableClockView @JvmOverloads constructor(
}
fun animateColorChange() {
- logger?.d("animateColorChange")
+ logger.d("animateColorChange")
setTextStyle(
weight = lockScreenWeight,
textSize = -1f,
@@ -252,7 +257,7 @@ class AnimatableClockView @JvmOverloads constructor(
}
fun animateAppearOnLockscreen() {
- logger?.d("animateAppearOnLockscreen")
+ logger.d("animateAppearOnLockscreen")
setTextStyle(
weight = dozingWeight,
textSize = -1f,
@@ -278,7 +283,7 @@ class AnimatableClockView @JvmOverloads constructor(
if (isAnimationEnabled && textAnimator == null) {
return
}
- logger?.d("animateFoldAppear")
+ logger.d("animateFoldAppear")
setTextStyle(
weight = lockScreenWeightInternal,
textSize = -1f,
@@ -305,7 +310,7 @@ class AnimatableClockView @JvmOverloads constructor(
// Skip charge animation if dozing animation is already playing.
return
}
- logger?.d("animateCharge")
+ logger.d("animateCharge")
val startAnimPhase2 = Runnable {
setTextStyle(
weight = if (isDozing()) dozingWeight else lockScreenWeight,
@@ -329,7 +334,7 @@ class AnimatableClockView @JvmOverloads constructor(
}
fun animateDoze(isDozing: Boolean, animate: Boolean) {
- logger?.d("animateDoze")
+ logger.d("animateDoze")
setTextStyle(
weight = if (isDozing) dozingWeight else lockScreenWeight,
textSize = -1f,
@@ -448,7 +453,7 @@ class AnimatableClockView @JvmOverloads constructor(
isSingleLineInternal && !use24HourFormat -> Patterns.sClockView12
else -> DOUBLE_LINE_FORMAT_12_HOUR
}
- logger?.d({ "refreshFormat format=$str1" }) { str1 = format?.toString() }
+ logger.d({ "refreshFormat($str1)" }) { str1 = format?.toString() }
descFormat = if (use24HourFormat) Patterns.sClockView24 else Patterns.sClockView12
refreshTime()
@@ -552,6 +557,8 @@ class AnimatableClockView @JvmOverloads constructor(
companion object {
private val TAG = AnimatableClockView::class.simpleName!!
+ private val DEFAULT_LOGGER = Logger(LogcatOnlyMessageBuffer(LogLevel.WARNING), TAG)
+
const val ANIMATION_DURATION_FOLD_TO_AOD: Int = 600
private const val DOUBLE_LINE_FORMAT_12_HOUR = "hh\nmm"
private const val DOUBLE_LINE_FORMAT_24_HOUR = "HH\nmm"
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index cdd074d872c0..41bde5298c66 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -21,20 +21,16 @@ import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.UserHandle
import android.provider.Settings
-import android.util.Log
import androidx.annotation.OpenForTesting
-import com.android.systemui.log.LogMessageImpl
import com.android.systemui.log.core.LogLevel
-import com.android.systemui.log.core.LogMessage
+import com.android.systemui.log.core.LogcatOnlyMessageBuffer
import com.android.systemui.log.core.Logger
-import com.android.systemui.log.core.MessageBuffer
-import com.android.systemui.log.core.MessageInitializer
-import com.android.systemui.log.core.MessagePrinter
import com.android.systemui.plugins.PluginLifecycleManager
import com.android.systemui.plugins.PluginListener
import com.android.systemui.plugins.PluginManager
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.plugins.clocks.ClockProvider
import com.android.systemui.plugins.clocks.ClockProviderPlugin
@@ -77,32 +73,6 @@ private fun <TKey : Any, TVal : Any> ConcurrentHashMap<TKey, TVal>.concurrentGet
return result ?: value
}
-private val TMP_MESSAGE: LogMessage by lazy { LogMessageImpl.Factory.create() }
-
-private inline fun Logger?.tryLog(
- tag: String,
- level: LogLevel,
- messageInitializer: MessageInitializer,
- noinline messagePrinter: MessagePrinter,
- ex: Throwable? = null,
-) {
- if (this != null) {
- // Wrap messagePrinter to convert it from crossinline to noinline
- this.log(level, messagePrinter, ex, messageInitializer)
- } else {
- messageInitializer(TMP_MESSAGE)
- val msg = messagePrinter(TMP_MESSAGE)
- when (level) {
- LogLevel.VERBOSE -> Log.v(tag, msg, ex)
- LogLevel.DEBUG -> Log.d(tag, msg, ex)
- LogLevel.INFO -> Log.i(tag, msg, ex)
- LogLevel.WARNING -> Log.w(tag, msg, ex)
- LogLevel.ERROR -> Log.e(tag, msg, ex)
- LogLevel.WTF -> Log.wtf(tag, msg, ex)
- }
- }
-}
-
/** ClockRegistry aggregates providers and plugins */
open class ClockRegistry(
val context: Context,
@@ -114,12 +84,15 @@ open class ClockRegistry(
val handleAllUsers: Boolean,
defaultClockProvider: ClockProvider,
val fallbackClockId: ClockId = DEFAULT_CLOCK_ID,
- messageBuffer: MessageBuffer? = null,
+ val clockBuffers: ClockMessageBuffers? = null,
val keepAllLoaded: Boolean,
subTag: String,
var isTransitClockEnabled: Boolean = false,
) {
private val TAG = "${ClockRegistry::class.simpleName} ($subTag)"
+ private val logger: Logger =
+ Logger(clockBuffers?.infraMessageBuffer ?: LogcatOnlyMessageBuffer(LogLevel.DEBUG), TAG)
+
interface ClockChangeListener {
// Called when the active clock changes
fun onCurrentClockChanged() {}
@@ -128,7 +101,6 @@ open class ClockRegistry(
fun onAvailableClocksChanged() {}
}
- private val logger: Logger? = if (messageBuffer != null) Logger(messageBuffer, TAG) else null
private val availableClocks = ConcurrentHashMap<ClockId, ClockInfo>()
private val clockChangeListeners = mutableListOf<ClockChangeListener>()
private val settingObserver =
@@ -157,21 +129,15 @@ open class ClockRegistry(
val knownClocks = KNOWN_PLUGINS.get(manager.getPackage())
if (knownClocks == null) {
- logger.tryLog(
- TAG,
- LogLevel.WARNING,
- { str1 = manager.getPackage() },
- { "Loading unrecognized clock package: $str1" }
- )
+ logger.w({ "Loading unrecognized clock package: $str1" }) {
+ str1 = manager.getPackage()
+ }
return true
}
- logger.tryLog(
- TAG,
- LogLevel.INFO,
- { str1 = manager.getPackage() },
- { "Skipping initial load of known clock package package: $str1" }
- )
+ logger.i({ "Skipping initial load of known clock package package: $str1" }) {
+ str1 = manager.getPackage()
+ }
var isCurrentClock = false
var isClockListChanged = false
@@ -185,19 +151,14 @@ open class ClockRegistry(
}
if (manager != info.manager) {
- logger.tryLog(
- TAG,
- LogLevel.ERROR,
- {
- str1 = id
- str2 = info.manager.toString()
- str3 = manager.toString()
- },
- {
- "Clock Id conflict on attach: " +
- "$str1 is double registered by $str2 and $str3"
- }
- )
+ logger.e({
+ "Clock Id conflict on attach: " +
+ "$str1 is double registered by $str2 and $str3"
+ }) {
+ str1 = id
+ str2 = info.manager.toString()
+ str3 = manager.toString()
+ }
continue
}
@@ -219,6 +180,8 @@ open class ClockRegistry(
pluginContext: Context,
manager: PluginLifecycleManager<ClockProviderPlugin>
) {
+ plugin.initialize(clockBuffers)
+
var isClockListChanged = false
for (clock in plugin.getClocks()) {
val id = clock.clockId
@@ -233,19 +196,14 @@ open class ClockRegistry(
}
if (manager != info.manager) {
- logger.tryLog(
- TAG,
- LogLevel.ERROR,
- {
- str1 = id
- str2 = info.manager.toString()
- str3 = manager.toString()
- },
- {
- "Clock Id conflict on load: " +
- "$str1 is double registered by $str2 and $str3"
- }
- )
+ logger.e({
+ "Clock Id conflict on load: " +
+ "$str1 is double registered by $str2 and $str3"
+ }) {
+ str1 = id
+ str2 = info.manager.toString()
+ str3 = manager.toString()
+ }
manager.unloadPlugin()
continue
}
@@ -268,19 +226,14 @@ open class ClockRegistry(
val id = clock.clockId
val info = availableClocks[id]
if (info?.manager != manager) {
- logger.tryLog(
- TAG,
- LogLevel.ERROR,
- {
- str1 = id
- str2 = info?.manager.toString()
- str3 = manager.toString()
- },
- {
- "Clock Id conflict on unload: " +
- "$str1 is double registered by $str2 and $str3"
- }
- )
+ logger.e({
+ "Clock Id conflict on unload: " +
+ "$str1 is double registered by $str2 and $str3"
+ }) {
+ str1 = id
+ str2 = info?.manager.toString()
+ str3 = manager.toString()
+ }
continue
}
info.provider = null
@@ -350,7 +303,7 @@ open class ClockRegistry(
ClockSettings.deserialize(json)
} catch (ex: Exception) {
- logger.tryLog(TAG, LogLevel.ERROR, {}, { "Failed to parse clock settings" }, ex)
+ logger.e("Failed to parse clock settings", ex)
null
}
settings = result
@@ -379,7 +332,7 @@ open class ClockRegistry(
)
}
} catch (ex: Exception) {
- logger.tryLog(TAG, LogLevel.ERROR, {}, { "Failed to set clock settings" }, ex)
+ logger.e("Failed to set clock settings", ex)
}
settings = value
}
@@ -451,7 +404,8 @@ open class ClockRegistry(
}
init {
- // Register default clock designs
+ // Initialize & register default clock designs
+ defaultClockProvider.initialize(clockBuffers)
for (clock in defaultClockProvider.getClocks()) {
availableClocks[clock.clockId] = ClockInfo(clock, defaultClockProvider, null)
}
@@ -514,12 +468,7 @@ open class ClockRegistry(
fun verifyLoadedProviders() {
val shouldSchedule = isQueued.compareAndSet(false, true)
if (!shouldSchedule) {
- logger.tryLog(
- TAG,
- LogLevel.VERBOSE,
- {},
- { "verifyLoadedProviders: shouldSchedule=false" }
- )
+ logger.v("verifyLoadedProviders: shouldSchedule=false")
return
}
@@ -528,12 +477,7 @@ open class ClockRegistry(
synchronized(availableClocks) {
isQueued.set(false)
if (keepAllLoaded) {
- logger.tryLog(
- TAG,
- LogLevel.INFO,
- {},
- { "verifyLoadedProviders: keepAllLoaded=true" }
- )
+ logger.i("verifyLoadedProviders: keepAllLoaded=true")
// Enforce that all plugins are loaded if requested
for ((_, info) in availableClocks) {
info.manager?.loadPlugin()
@@ -543,12 +487,7 @@ open class ClockRegistry(
val currentClock = availableClocks[currentClockId]
if (currentClock == null) {
- logger.tryLog(
- TAG,
- LogLevel.INFO,
- {},
- { "verifyLoadedProviders: currentClock=null" }
- )
+ logger.i("verifyLoadedProviders: currentClock=null")
// Current Clock missing, load no plugins and use default
for ((_, info) in availableClocks) {
info.manager?.unloadPlugin()
@@ -556,12 +495,7 @@ open class ClockRegistry(
return@launch
}
- logger.tryLog(
- TAG,
- LogLevel.INFO,
- {},
- { "verifyLoadedProviders: load currentClock" }
- )
+ logger.i("verifyLoadedProviders: load currentClock")
val currentManager = currentClock.manager
currentManager?.loadPlugin()
@@ -577,30 +511,26 @@ open class ClockRegistry(
private fun onConnected(info: ClockInfo) {
val isCurrent = currentClockId == info.metadata.clockId
- logger.tryLog(
- TAG,
+ logger.log(
if (isCurrent) LogLevel.INFO else LogLevel.DEBUG,
- {
- str1 = info.metadata.clockId
- str2 = info.manager.toString()
- bool1 = isCurrent
- },
{ "Connected $str1 @$str2" + if (bool1) " (Current Clock)" else "" }
- )
+ ) {
+ str1 = info.metadata.clockId
+ str2 = info.manager.toString()
+ bool1 = isCurrent
+ }
}
private fun onLoaded(info: ClockInfo) {
val isCurrent = currentClockId == info.metadata.clockId
- logger.tryLog(
- TAG,
+ logger.log(
if (isCurrent) LogLevel.INFO else LogLevel.DEBUG,
- {
- str1 = info.metadata.clockId
- str2 = info.manager.toString()
- bool1 = isCurrent
- },
{ "Loaded $str1 @$str2" + if (bool1) " (Current Clock)" else "" }
- )
+ ) {
+ str1 = info.metadata.clockId
+ str2 = info.manager.toString()
+ bool1 = isCurrent
+ }
if (isCurrent) {
triggerOnCurrentClockChanged()
@@ -609,16 +539,14 @@ open class ClockRegistry(
private fun onUnloaded(info: ClockInfo) {
val isCurrent = currentClockId == info.metadata.clockId
- logger.tryLog(
- TAG,
+ logger.log(
if (isCurrent) LogLevel.WARNING else LogLevel.DEBUG,
- {
- str1 = info.metadata.clockId
- str2 = info.manager.toString()
- bool1 = isCurrent
- },
{ "Unloaded $str1 @$str2" + if (bool1) " (Current Clock)" else "" }
- )
+ ) {
+ str1 = info.metadata.clockId
+ str2 = info.manager.toString()
+ bool1 = isCurrent
+ }
if (isCurrent) {
triggerOnCurrentClockChanged()
@@ -627,16 +555,14 @@ open class ClockRegistry(
private fun onDisconnected(info: ClockInfo) {
val isCurrent = currentClockId == info.metadata.clockId
- logger.tryLog(
- TAG,
+ logger.log(
if (isCurrent) LogLevel.INFO else LogLevel.DEBUG,
- {
- str1 = info.metadata.clockId
- str2 = info.manager.toString()
- bool1 = isCurrent
- },
{ "Disconnected $str1 @$str2" + if (bool1) " (Current Clock)" else "" }
- )
+ ) {
+ str1 = info.metadata.clockId
+ str2 = info.manager.toString()
+ bool1 = isCurrent
+ }
}
fun getClocks(): List<ClockMetadata> {
@@ -676,23 +602,13 @@ open class ClockRegistry(
if (isEnabled && clockId.isNotEmpty()) {
val clock = createClock(clockId)
if (clock != null) {
- logger.tryLog(TAG, LogLevel.INFO, { str1 = clockId }, { "Rendering clock $str1" })
+ logger.i({ "Rendering clock $str1" }) { str1 = clockId }
return clock
} else if (availableClocks.containsKey(clockId)) {
- logger.tryLog(
- TAG,
- LogLevel.WARNING,
- { str1 = clockId },
- { "Clock $str1 not loaded; using default" }
- )
+ logger.w({ "Clock $str1 not loaded; using default" }) { str1 = clockId }
verifyLoadedProviders()
} else {
- logger.tryLog(
- TAG,
- LogLevel.ERROR,
- { str1 = clockId },
- { "Clock $str1 not found; using default" }
- )
+ logger.e({ "Clock $str1 not found; using default" }) { str1 = clockId }
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 01c03b1f25f6..99d321695d04 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -33,6 +33,7 @@ import com.android.systemui.plugins.clocks.ClockEvents
import com.android.systemui.plugins.clocks.ClockFaceConfig
import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.plugins.clocks.ClockFaceEvents
+import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.plugins.clocks.DefaultClockFaceLayout
import com.android.systemui.plugins.clocks.WeatherData
@@ -41,8 +42,6 @@ import java.io.PrintWriter
import java.util.Locale
import java.util.TimeZone
-private val TAG = DefaultClockController::class.simpleName
-
/**
* Controls the default clock visuals.
*
@@ -56,6 +55,7 @@ class DefaultClockController(
private val settings: ClockSettings?,
private val hasStepClockAnimation: Boolean = false,
private val migratedClocks: Boolean = false,
+ messageBuffers: ClockMessageBuffers? = null,
) : ClockController {
override val smallClock: DefaultClockFaceController
override val largeClock: LargeClockFaceController
@@ -83,13 +83,15 @@ class DefaultClockController(
DefaultClockFaceController(
layoutInflater.inflate(R.layout.clock_default_small, parent, false)
as AnimatableClockView,
- settings?.seedColor
+ settings?.seedColor,
+ messageBuffers?.smallClockMessageBuffer
)
largeClock =
LargeClockFaceController(
layoutInflater.inflate(R.layout.clock_default_large, parent, false)
as AnimatableClockView,
- settings?.seedColor
+ settings?.seedColor,
+ messageBuffers?.largeClockMessageBuffer
)
clocks = listOf(smallClock.view, largeClock.view)
@@ -110,6 +112,7 @@ class DefaultClockController(
open inner class DefaultClockFaceController(
override val view: AnimatableClockView,
var seedColor: Int?,
+ messageBuffer: MessageBuffer?,
) : ClockFaceController {
// MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -120,12 +123,6 @@ class DefaultClockController(
override val config = ClockFaceConfig()
override val layout = DefaultClockFaceLayout(view)
- override var messageBuffer: MessageBuffer?
- get() = view.messageBuffer
- set(value) {
- view.messageBuffer = value
- }
-
override var animations: DefaultClockAnimations = DefaultClockAnimations(view, 0f, 0f)
internal set
@@ -134,6 +131,7 @@ class DefaultClockController(
currentColor = seedColor!!
}
view.setColors(DOZE_COLOR, currentColor)
+ messageBuffer?.let { view.messageBuffer = it }
}
override val events =
@@ -188,7 +186,8 @@ class DefaultClockController(
inner class LargeClockFaceController(
view: AnimatableClockView,
seedColor: Int?,
- ) : DefaultClockFaceController(view, seedColor) {
+ messageBuffer: MessageBuffer?,
+ ) : DefaultClockFaceController(view, seedColor, messageBuffer) {
override val layout = DefaultClockFaceLayout(view)
override val config =
ClockFaceConfig(hasCustomPositionUpdatedAnimation = hasStepClockAnimation)
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index a219be53bd1a..20f87a059656 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -20,6 +20,7 @@ import android.view.LayoutInflater
import com.android.systemui.customization.R
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.plugins.clocks.ClockProvider
import com.android.systemui.plugins.clocks.ClockSettings
@@ -35,6 +36,12 @@ class DefaultClockProvider(
val hasStepClockAnimation: Boolean = false,
val migratedClocks: Boolean = false
) : ClockProvider {
+ private var messageBuffers: ClockMessageBuffers? = null
+
+ override fun initialize(buffers: ClockMessageBuffers?) {
+ messageBuffers = buffers
+ }
+
override fun getClocks(): List<ClockMetadata> = listOf(ClockMetadata(DEFAULT_CLOCK_ID))
override fun createClock(settings: ClockSettings): ClockController {
@@ -49,6 +56,7 @@ class DefaultClockProvider(
settings,
hasStepClockAnimation,
migratedClocks,
+ messageBuffers,
)
}
diff --git a/packages/SystemUI/log/src/com/android/systemui/log/core/LogcatOnlyMessageBuffer.kt b/packages/SystemUI/log/src/com/android/systemui/log/core/LogcatOnlyMessageBuffer.kt
new file mode 100644
index 000000000000..006b521ad867
--- /dev/null
+++ b/packages/SystemUI/log/src/com/android/systemui/log/core/LogcatOnlyMessageBuffer.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 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.log.core
+
+import android.util.Log
+import com.android.systemui.log.LogMessageImpl
+
+/**
+ * A simple implementation of [MessageBuffer] that forwards messages to [android.util.Log]
+ * immediately. This defeats the intention behind [LogBuffer] and should only be used when
+ * [LogBuffer]s are unavailable in a certain context.
+ */
+class LogcatOnlyMessageBuffer(
+ val targetLogLevel: LogLevel,
+) : MessageBuffer {
+ private val singleMessage = LogMessageImpl.Factory.create()
+ private var isObtained: Boolean = false
+
+ @Synchronized
+ override fun obtain(
+ tag: String,
+ level: LogLevel,
+ messagePrinter: MessagePrinter,
+ exception: Throwable?,
+ ): LogMessage {
+ if (isObtained) {
+ throw UnsupportedOperationException(
+ "Message has already been obtained. Call order is incorrect."
+ )
+ }
+
+ singleMessage.reset(tag, level, System.currentTimeMillis(), messagePrinter, exception)
+ isObtained = true
+ return singleMessage
+ }
+
+ @Synchronized
+ override fun commit(message: LogMessage) {
+ if (singleMessage != message) {
+ throw IllegalArgumentException("Message argument is not the expected message.")
+ }
+ if (!isObtained) {
+ throw UnsupportedOperationException(
+ "Message has not been obtained. Call order is incorrect."
+ )
+ }
+
+ if (message.level >= targetLogLevel) {
+ val strMessage = message.messagePrinter(message)
+ when (message.level) {
+ LogLevel.VERBOSE -> Log.v(message.tag, strMessage, message.exception)
+ LogLevel.DEBUG -> Log.d(message.tag, strMessage, message.exception)
+ LogLevel.INFO -> Log.i(message.tag, strMessage, message.exception)
+ LogLevel.WARNING -> Log.w(message.tag, strMessage, message.exception)
+ LogLevel.ERROR -> Log.e(message.tag, strMessage, message.exception)
+ LogLevel.WTF -> Log.wtf(message.tag, strMessage, message.exception)
+ }
+ }
+
+ isObtained = false
+ }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
index 1c5f221f2efb..4436be7cd7d7 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
@@ -41,16 +41,13 @@ interface ClockProviderPlugin : Plugin, ClockProvider {
/** Interface for building clocks and providing information about those clocks */
interface ClockProvider {
+ /** Initializes the clock provider with debug log buffers */
+ fun initialize(buffers: ClockMessageBuffers?)
+
/** Returns metadata for all clocks this provider knows about */
fun getClocks(): List<ClockMetadata>
/** Initializes and returns the target clock design */
- @Deprecated("Use overload with ClockSettings")
- fun createClock(id: ClockId): ClockController {
- return createClock(ClockSettings(id, null))
- }
-
- /** Initializes and returns the target clock design */
fun createClock(settings: ClockSettings): ClockController
/** A static thumbnail for rendering in some examples */
@@ -98,11 +95,20 @@ interface ClockFaceController {
/** Triggers for various animations */
val animations: ClockAnimations
-
- /** Some clocks may log debug information */
- var messageBuffer: MessageBuffer?
}
+/** For clocks that want to report debug information */
+data class ClockMessageBuffers(
+ /** Message buffer for general infra */
+ val infraMessageBuffer: MessageBuffer,
+
+ /** Message buffer for small clock renering */
+ val smallClockMessageBuffer: MessageBuffer,
+
+ /** Message buffer for large clock rendering */
+ val largeClockMessageBuffer: MessageBuffer,
+)
+
/** Specifies layout information for the */
interface ClockFaceLayout {
/** All clock views to add to the root constraint layout before applying constraints. */
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 76abad8ae863..bcc20448297d 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -45,12 +45,11 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
import com.android.systemui.log.core.LogLevel.DEBUG
-import com.android.systemui.log.dagger.KeyguardLargeClockLog
-import com.android.systemui.log.dagger.KeyguardSmallClockLog
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockFaceController
+import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockTickRate
import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.WeatherData
@@ -91,117 +90,120 @@ constructor(
private val context: Context,
@Main private val mainExecutor: DelayableExecutor,
@Background private val bgExecutor: Executor,
- @KeyguardSmallClockLog private val smallLogBuffer: LogBuffer?,
- @KeyguardLargeClockLog private val largeLogBuffer: LogBuffer?,
+ private val clockBuffers: ClockMessageBuffers,
private val featureFlags: FeatureFlags,
private val zenModeController: ZenModeController,
) {
+ var loggers = listOf(
+ clockBuffers.infraMessageBuffer,
+ clockBuffers.smallClockMessageBuffer,
+ clockBuffers.largeClockMessageBuffer
+ ).map { Logger(it, TAG) }
+
var clock: ClockController? = null
+ get() = field
set(value) {
- smallClockOnAttachStateChangeListener?.let {
- field?.smallClock?.view?.removeOnAttachStateChangeListener(it)
- smallClockFrame?.viewTreeObserver
- ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
- }
- largeClockOnAttachStateChangeListener?.let {
- field?.largeClock?.view?.removeOnAttachStateChangeListener(it)
- }
-
+ disconnectClock(field)
field = value
- if (value != null) {
- smallLogBuffer?.log(TAG, DEBUG, {}, { "New Clock" })
- value.smallClock.messageBuffer = smallLogBuffer
- largeLogBuffer?.log(TAG, DEBUG, {}, { "New Clock" })
- value.largeClock.messageBuffer = largeLogBuffer
-
- value.initialize(resources, dozeAmount, 0f)
-
- if (!regionSamplingEnabled) {
- updateColors()
- } else {
- clock?.let {
- smallRegionSampler = createRegionSampler(
- it.smallClock.view,
- mainExecutor,
- bgExecutor,
- regionSamplingEnabled,
- isLockscreen = true,
- ::updateColors
- )?.apply { startRegionSampler() }
-
- largeRegionSampler = createRegionSampler(
- it.largeClock.view,
- mainExecutor,
- bgExecutor,
- regionSamplingEnabled,
- isLockscreen = true,
- ::updateColors
- )?.apply { startRegionSampler() }
-
- updateColors()
- }
- }
- updateFontSizes()
- updateTimeListeners()
- weatherData?.let {
- if (WeatherData.DEBUG) {
- Log.i(TAG, "Pushing cached weather data to new clock: $it")
- }
- value.events.onWeatherDataChanged(it)
- }
- zenData?.let {
- value.events.onZenDataChanged(it)
- }
- alarmData?.let {
- value.events.onAlarmDataChanged(it)
- }
+ connectClock(value)
+ }
- smallClockOnAttachStateChangeListener =
- object : OnAttachStateChangeListener {
- var pastVisibility: Int? = null
- override fun onViewAttachedToWindow(view: View) {
- value.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
- // Match the asing for view.parent's layout classes.
- smallClockFrame = view.parent as ViewGroup
- smallClockFrame?.let { frame ->
- pastVisibility = frame.visibility
- onGlobalLayoutListener = OnGlobalLayoutListener {
- val currentVisibility = frame.visibility
- if (pastVisibility != currentVisibility) {
- pastVisibility = currentVisibility
- // when small clock is visible,
- // recalculate bounds and sample
- if (currentVisibility == View.VISIBLE) {
- smallRegionSampler?.stopRegionSampler()
- smallRegionSampler?.startRegionSampler()
- }
- }
- }
- frame.viewTreeObserver
- .addOnGlobalLayoutListener(onGlobalLayoutListener)
- }
- }
+ private fun disconnectClock(clock: ClockController?) {
+ if (clock == null) { return; }
+ smallClockOnAttachStateChangeListener?.let {
+ clock.smallClock.view.removeOnAttachStateChangeListener(it)
+ smallClockFrame?.viewTreeObserver
+ ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
+ }
+ largeClockOnAttachStateChangeListener?.let {
+ clock.largeClock.view.removeOnAttachStateChangeListener(it)
+ }
+ }
- override fun onViewDetachedFromWindow(p0: View) {
- smallClockFrame?.viewTreeObserver
- ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
- }
- }
- value.smallClock.view
- .addOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
+ private fun connectClock(clock: ClockController?) {
+ if (clock == null) { return; }
+ val clockStr = clock.toString()
+ loggers.forEach { it.d({ "New Clock: $str1" }) { str1 = clockStr } }
- largeClockOnAttachStateChangeListener =
- object : OnAttachStateChangeListener {
- override fun onViewAttachedToWindow(p0: View) {
- value.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
- }
- override fun onViewDetachedFromWindow(p0: View) {
+ clock.initialize(resources, dozeAmount, 0f)
+
+ if (!regionSamplingEnabled) {
+ updateColors()
+ } else {
+ smallRegionSampler = createRegionSampler(
+ clock.smallClock.view,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ isLockscreen = true,
+ ::updateColors
+ ).apply { startRegionSampler() }
+
+ largeRegionSampler = createRegionSampler(
+ clock.largeClock.view,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ isLockscreen = true,
+ ::updateColors
+ ).apply { startRegionSampler() }
+
+ updateColors()
+ }
+ updateFontSizes()
+ updateTimeListeners()
+
+ weatherData?.let {
+ if (WeatherData.DEBUG) {
+ Log.i(TAG, "Pushing cached weather data to new clock: $it")
+ }
+ clock.events.onWeatherDataChanged(it)
+ }
+ zenData?.let {
+ clock.events.onZenDataChanged(it)
+ }
+ alarmData?.let {
+ clock.events.onAlarmDataChanged(it)
+ }
+
+ smallClockOnAttachStateChangeListener = object : OnAttachStateChangeListener {
+ var pastVisibility: Int? = null
+ override fun onViewAttachedToWindow(view: View) {
+ clock.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ // Match the asing for view.parent's layout classes.
+ smallClockFrame = (view.parent as ViewGroup)?.also { frame ->
+ pastVisibility = frame.visibility
+ onGlobalLayoutListener = OnGlobalLayoutListener {
+ val currentVisibility = frame.visibility
+ if (pastVisibility != currentVisibility) {
+ pastVisibility = currentVisibility
+ // when small clock is visible,
+ // recalculate bounds and sample
+ if (currentVisibility == View.VISIBLE) {
+ smallRegionSampler?.stopRegionSampler()
+ smallRegionSampler?.startRegionSampler()
+ }
}
+ }
+ frame.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
- value.largeClock.view
- .addOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
+ }
+
+ override fun onViewDetachedFromWindow(p0: View) {
+ smallClockFrame?.viewTreeObserver
+ ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
}
+ clock.smallClock.view.addOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
+
+ largeClockOnAttachStateChangeListener = object : OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(p0: View) {
+ clock.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ }
+ override fun onViewDetachedFromWindow(p0: View) {}
+ }
+ clock.largeClock.view.addOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
+ }
@VisibleForTesting
var smallClockOnAttachStateChangeListener: OnAttachStateChangeListener? = null
@@ -247,6 +249,7 @@ constructor(
largeClock.events.onRegionDarknessChanged(isRegionDark)
}
}
+
protected open fun createRegionSampler(
sampledView: View,
mainExecutor: Executor?,
@@ -254,7 +257,7 @@ constructor(
regionSamplingEnabled: Boolean,
isLockscreen: Boolean,
updateColors: () -> Unit
- ): RegionSampler? {
+ ): RegionSampler {
return RegionSampler(
sampledView,
mainExecutor,
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
index 661ce2ce60ba..878a5d88f164 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
@@ -28,9 +28,8 @@ 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.log.LogBuffer;
-import com.android.systemui.log.dagger.KeyguardClockLog;
import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.clocks.ClockMessageBuffers;
import com.android.systemui.res.R;
import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.shared.clocks.DefaultClockProvider;
@@ -56,7 +55,7 @@ public abstract class ClockRegistryModule {
FeatureFlags featureFlags,
@Main Resources resources,
LayoutInflater layoutInflater,
- @KeyguardClockLog LogBuffer logBuffer) {
+ ClockMessageBuffers clockBuffers) {
ClockRegistry registry = new ClockRegistry(
context,
pluginManager,
@@ -72,7 +71,7 @@ public abstract class ClockRegistryModule {
featureFlags.isEnabled(Flags.STEP_CLOCK_ANIMATION),
migrateClocksToBlueprint()),
context.getString(R.string.lockscreen_clock_id_fallback),
- logBuffer,
+ clockBuffers,
/* keepAllLoaded = */ false,
/* subTag = */ "System",
/* isTransitClockEnabled = */ featureFlags.isEnabled(Flags.TRANSIT_CLOCK));
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index d8bb3e65392f..0d5ba641b599 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -26,6 +26,7 @@ import com.android.systemui.log.echo.LogcatEchoTrackerDebug;
import com.android.systemui.log.echo.LogcatEchoTrackerProd;
import com.android.systemui.log.table.TableLogBuffer;
import com.android.systemui.log.table.TableLogBufferFactory;
+import com.android.systemui.plugins.clocks.ClockMessageBuffers;
import com.android.systemui.qs.QSFragmentLegacy;
import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository;
import com.android.systemui.qs.pipeline.shared.TileSpec;
@@ -417,6 +418,18 @@ public class LogModule {
}
/**
+ * Provides a {@link ClockMessageBuffers} which contains the keyguard clock message buffers.
+ */
+ @Provides
+ public static ClockMessageBuffers provideKeyguardClockMessageBuffers(
+ @KeyguardClockLog LogBuffer infraClockLog,
+ @KeyguardSmallClockLog LogBuffer smallClockLog,
+ @KeyguardLargeClockLog LogBuffer largeClockLog
+ ) {
+ return new ClockMessageBuffers(infraClockLog, smallClockLog, largeClockLog);
+ }
+
+ /**
* Provides a {@link LogBuffer} for use by {@link com.android.keyguard.KeyguardUpdateMonitor}.
*/
@Provides
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 6f58bc2fcc9f..e6637e60b146 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -30,13 +30,15 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.core.LogcatOnlyMessageBuffer
import com.android.systemui.plugins.clocks.ClockAnimations
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockEvents
import com.android.systemui.plugins.clocks.ClockFaceConfig
import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.plugins.clocks.ClockFaceEvents
+import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockTickRate
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -94,9 +96,9 @@ class ClockEventControllerTest : SysuiTestCase() {
@Mock private lateinit var largeClockEvents: ClockFaceEvents
@Mock private lateinit var parentView: View
private lateinit var repository: FakeKeyguardRepository
- @Mock private lateinit var smallLogBuffer: LogBuffer
- @Mock private lateinit var largeLogBuffer: LogBuffer
@Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+ private val messageBuffer = LogcatOnlyMessageBuffer(LogLevel.DEBUG)
+ private val clockBuffers = ClockMessageBuffers(messageBuffer, messageBuffer, messageBuffer)
private lateinit var underTest: ClockEventController
@Mock private lateinit var zenModeController: ZenModeController
@@ -140,8 +142,7 @@ class ClockEventControllerTest : SysuiTestCase() {
context,
mainExecutor,
bgExecutor,
- smallLogBuffer,
- largeLogBuffer,
+ clockBuffers,
withDeps.featureFlags,
zenModeController
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index ee94cbbcfd79..ee27c5c9ba0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -26,6 +26,7 @@ import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.TRANSIT_CLOCK
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockId
+import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.plugins.clocks.ClockProviderPlugin
import com.android.systemui.plugins.clocks.ClockSettings
@@ -128,6 +129,7 @@ class ClockRegistryTest : SysuiTestCase() {
override fun createClock(settings: ClockSettings): ClockController =
createCallbacks[settings.clockId!!]!!(settings.clockId!!)
override fun getClockThumbnail(id: ClockId): Drawable? = thumbnailCallbacks[id]!!(id)
+ override fun initialize(buffers: ClockMessageBuffers?) { }
fun addClock(
id: ClockId,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index fef262f50306..e0e8d1f51884 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -26,6 +26,7 @@ import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.customization.R
+import com.android.systemui.plugins.clocks.ClockId
import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
import com.android.systemui.util.mockito.any
@@ -49,6 +50,9 @@ import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+private fun DefaultClockProvider.createClock(id: ClockId): DefaultClockController =
+ createClock(ClockSettings(id, null)) as DefaultClockController
+
@RunWith(AndroidTestingRunner::class)
@SmallTest
class DefaultClockProviderTest : SysuiTestCase() {