diff options
| author | 2024-11-07 11:59:25 -0500 | |
|---|---|---|
| committer | 2024-11-20 09:33:12 -0500 | |
| commit | edf622121243ee83c6088d4ca7ab23b654eb44ff (patch) | |
| tree | 0a9e23249bb3869105efae0a96f05450a1d2f34b | |
| parent | feb3f74a74a6f0ec87511682e14addab00909ee5 (diff) | |
Add a TableLog for hydrator
This adds an optional TableLog for hydrator to allow logging of changing
states.
As a first use, add it to QSFragmentComposeViewModel.
Flag: EXEMPT logging
Fixes: 379669380
Test: manual, dump QSFragmentComposeViewModel
Change-Id: Ie103fa01d36d54a9f02ad2f25dd521ab25183ae2
5 files changed, 75 insertions, 21 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt index 881228d597b0..93ecae32ac17 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt @@ -21,11 +21,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.snapshots.StateFactoryMarker import com.android.app.tracing.coroutines.launchTraced as launch import com.android.app.tracing.coroutines.traceCoroutine +import com.android.systemui.log.table.TableLogBuffer import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -import com.android.app.tracing.coroutines.launchTraced as launch /** * Keeps snapshot/Compose [State]s up-to-date. @@ -47,6 +47,12 @@ class Hydrator( * concatenation or templating. */ private val traceName: String, + /** + * An optional [TableLogBuffer] to log emissions to the states. [traceName] will be used as the + * prefix for the columns logged by this [Hydrator], allowing to aggregate multiple hydrators in + * the same table. + */ + private val tableLogBuffer: TableLogBuffer? = null, ) : ExclusiveActivatable() { private val children = mutableListOf<NamedActivatable>() @@ -62,15 +68,8 @@ class Hydrator( * automatically set on the returned [State]. */ @StateFactoryMarker - fun <T> hydratedStateOf( - traceName: String, - source: StateFlow<T>, - ): State<T> { - return hydratedStateOf( - traceName = traceName, - initialValue = source.value, - source = source, - ) + fun <T> hydratedStateOf(traceName: String, source: StateFlow<T>): State<T> { + return hydratedStateOf(traceName = traceName, initialValue = source.value, source = source) } /** @@ -81,26 +80,44 @@ class Hydrator( * performance findings with actual code. One recommendation: prefer whole string literals * instead of some complex concatenation or templating scheme. Use `null` to disable * performance tracing for this state. + * + * If a [TableLogBuffer] was provided, every emission to the flow will be logged using the + * [traceName] as the column name. For this to work correctly, all the states in the same + * hydrator should have different [traceName]. Use `null` to disable logging for this state. + * * @param initialValue The first value to place on the [State] * @param source The upstream [Flow] to collect from; values emitted to it will be automatically * set on the returned [State]. */ @StateFactoryMarker - fun <T> hydratedStateOf( - traceName: String?, - initialValue: T, - source: Flow<T>, - ): State<T> { + fun <T> hydratedStateOf(traceName: String?, initialValue: T, source: Flow<T>): State<T> { check(!isActive) { "Cannot call hydratedStateOf after Hydrator is already active." } val mutableState = mutableStateOf(initialValue) + traceName?.let { name -> + tableLogBuffer?.logChange( + prefix = this.traceName, + columnName = name, + value = initialValue?.toString(), + isInitial = true, + ) + } children.add( NamedActivatable( traceName = traceName, activatable = object : ExclusiveActivatable() { override suspend fun onActivated(): Nothing { - source.collect { mutableState.value = it } + source.collect { + traceName?.let { name -> + tableLogBuffer?.logChange( + prefix = this@Hydrator.traceName, + columnName = name, + value = it?.toString(), + ) + } + mutableState.value = it + } awaitCancellation() } }, @@ -122,8 +139,5 @@ class Hydrator( } } - private data class NamedActivatable( - val traceName: String?, - val activatable: Activatable, - ) + private data class NamedActivatable(val traceName: String?, val activatable: Activatable) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeLog.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeLog.kt new file mode 100644 index 000000000000..5f151eba5c84 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeLog.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 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.qs.composefragment.dagger + +import javax.inject.Qualifier + +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) +annotation class QSFragmentComposeLog diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt index 2ec729223a8d..bea0d144fffb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt @@ -19,6 +19,8 @@ package com.android.systemui.qs.composefragment.dagger import android.content.Context import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.log.table.TableLogBufferFactory import com.android.systemui.qs.flags.QSComposeFragment import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.util.Utils @@ -38,5 +40,14 @@ interface QSFragmentComposeModule { fun providesUsingMedia(@ShadeDisplayAware context: Context): Boolean { return QSComposeFragment.isEnabled && Utils.useQsMediaPlayer(context) } + + @Provides + @SysUISingleton + @QSFragmentComposeLog + fun providesQSFragmentComposeViewModelTableLog( + factory: TableLogBufferFactory + ): TableLogBuffer { + return factory.create("QSFragmentComposeViewModel", 200) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt index e3de6d5152e4..5c582baefdac 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt @@ -39,6 +39,7 @@ import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.Hydrator +import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QQS import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QS @@ -48,6 +49,7 @@ import com.android.systemui.media.dagger.MediaModule.QS_PANEL import com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.FooterActionsController +import com.android.systemui.qs.composefragment.dagger.QSFragmentComposeLog import com.android.systemui.qs.composefragment.dagger.QSFragmentComposeModule import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.panels.domain.interactor.TileSquishinessInteractor @@ -101,6 +103,7 @@ constructor( private val largeScreenHeaderHelper: LargeScreenHeaderHelper, private val squishinessInteractor: TileSquishinessInteractor, private val inFirstPageViewModel: InFirstPageViewModel, + @QSFragmentComposeLog private val tableLogBuffer: TableLogBuffer, mediaInRowInLandscapeViewModelFactory: MediaInRowInLandscapeViewModel.Factory, @Named(QUICK_QS_PANEL) val qqsMediaHost: MediaHost, @Named(QS_PANEL) val qsMediaHost: MediaHost, @@ -112,7 +115,7 @@ constructor( private val qqsMediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QQS) private val qsMediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QS) - private val hydrator = Hydrator("QSFragmentComposeViewModel.hydrator") + private val hydrator = Hydrator("QSFragmentComposeViewModel.hydrator", tableLogBuffer) val footerActionsViewModel = footerActionsViewModelFactory.create(lifecycleScope).also { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt index 45d5b387fea0..80db0ae36b01 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt @@ -22,6 +22,7 @@ import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.kosmos.Kosmos +import com.android.systemui.log.table.logcatTableLogBuffer import com.android.systemui.media.controls.ui.view.qqsMediaHost import com.android.systemui.media.controls.ui.view.qsMediaHost import com.android.systemui.qs.composefragment.dagger.usingMediaInComposeFragment @@ -58,6 +59,7 @@ val Kosmos.qsFragmentComposeViewModelFactory by largeScreenHeaderHelper, tileSquishinessInteractor, inFirstPageViewModel, + logcatTableLogBuffer(this@Fixture), mediaInRowInLandscapeViewModelFactory, qqsMediaHost, qsMediaHost, |