Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83e6d2e0 authored by Anton Potapov's avatar Anton Potapov
Browse files

Add extra Volume Panel logging and dump info

This CL adds dumping and logging Volume Panel local and global states

Flag: com.android.systemui.new_volume_panel
Test: atest VolumePanelViewModelTest
Test: atest ComponentsInteractorImplTest
Test: manual on the foldable
Fixes: 35786763
Change-Id: Ia2d9dd6d47e7affc7de7ca6cce2abfd2b77c8632
parent 40e7272d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ fun VolumePanelRoot(
) {
    val accessibilityTitle = stringResource(R.string.accessibility_volume_settings)
    val state: VolumePanelState by viewModel.volumePanelState.collectAsStateWithLifecycle()
    val components by viewModel.componentsLayout.collectAsStateWithLifecycle(null)
    val components by viewModel.componentsLayout.collectAsStateWithLifecycle()

    with(VolumePanelComposeScope(state)) {
        components?.let { componentsState ->
+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.volume.panel.domain.model.ComponentModel
import com.android.systemui.volume.panel.domain.unavailableCriteria
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import com.android.systemui.volume.panel.ui.composable.enabledComponents
import com.android.systemui.volume.shared.volumePanelLogger
import com.google.common.truth.Truth.assertThat
import javax.inject.Provider
import kotlinx.coroutines.test.runTest
@@ -49,6 +50,7 @@ class ComponentsInteractorImplTest : SysuiTestCase() {
                    enabledComponents,
                    { defaultCriteria },
                    testScope.backgroundScope,
                    volumePanelLogger,
                    criteriaByKey,
                )
            }
+80 −1
Original line number Diff line number Diff line
@@ -24,21 +24,30 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.broadcastDispatcher
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.dump.DumpManager
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.policy.configurationController
import com.android.systemui.statusbar.policy.fakeConfigurationController
import com.android.systemui.testKosmos
import com.android.systemui.volume.panel.dagger.factory.volumePanelComponentFactory
import com.android.systemui.volume.panel.data.repository.volumePanelGlobalStateRepository
import com.android.systemui.volume.panel.domain.interactor.criteriaByKey
import com.android.systemui.volume.panel.domain.interactor.volumePanelGlobalStateInteractor
import com.android.systemui.volume.panel.domain.unavailableCriteria
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import com.android.systemui.volume.panel.shared.model.mockVolumePanelUiComponentProvider
import com.android.systemui.volume.panel.ui.composable.componentByKey
import com.android.systemui.volume.panel.ui.layout.DefaultComponentsLayoutManager
import com.android.systemui.volume.panel.ui.layout.componentsLayoutManager
import com.android.systemui.volume.shared.volumePanelLogger
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
import javax.inject.Provider
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
@@ -55,6 +64,7 @@ class VolumePanelViewModelTest : SysuiTestCase() {
            volumePanelGlobalStateRepository.updateVolumePanelState { it.copy(isVisible = true) }
        }

    private val realDumpManager = DumpManager()
    private val testableResources = context.orCreateTestableResources

    private lateinit var underTest: VolumePanelViewModel
@@ -123,6 +133,60 @@ class VolumePanelViewModelTest : SysuiTestCase() {
        }
    }

    @Test
    fun testDumpableRegister_unregister() =
        with(kosmos) {
            testScope.runTest {
                val job = launch {
                    applicationCoroutineScope = this
                    underTest = createViewModel()

                    runCurrent()

                    assertThat(realDumpManager.getDumpables().any { it.name == DUMPABLE_NAME })
                        .isTrue()
                }

                runCurrent()
                job.cancel()

                assertThat(realDumpManager.getDumpables().any { it.name == DUMPABLE_NAME }).isTrue()
            }
        }

    @Test
    fun testDumpingState() =
        test({
            componentByKey =
                mapOf(
                    COMPONENT_1 to mockVolumePanelUiComponentProvider,
                    COMPONENT_2 to mockVolumePanelUiComponentProvider,
                    BOTTOM_BAR to mockVolumePanelUiComponentProvider,
                )
            criteriaByKey = mapOf(COMPONENT_2 to Provider { unavailableCriteria })
        }) {
            testScope.runTest {
                runCurrent()

                StringWriter().use {
                    underTest.dump(PrintWriter(it), emptyArray())

                    assertThat(it.buffer.toString())
                        .isEqualTo(
                            "volumePanelState=" +
                                "VolumePanelState(orientation=1, isLargeScreen=false)\n" +
                                "componentsLayout=( " +
                                "headerComponents= " +
                                "contentComponents=" +
                                "test_component:1:visible=true, " +
                                "test_component:2:visible=false " +
                                "footerComponents= " +
                                "bottomBarComponent=test_bottom_bar:visible=true )\n"
                        )
                }
            }
        }

    @Test
    fun dismissBroadcast_dismissesPanel() = test {
        testScope.runTest {
@@ -140,11 +204,26 @@ class VolumePanelViewModelTest : SysuiTestCase() {
    private fun test(setup: Kosmos.() -> Unit = {}, test: Kosmos.() -> Unit) =
        with(kosmos) {
            setup()
            underTest = volumePanelViewModel
            underTest = createViewModel()

            test()
        }

    private fun Kosmos.createViewModel(): VolumePanelViewModel =
        VolumePanelViewModel(
            context.orCreateTestableResources.resources,
            applicationCoroutineScope,
            volumePanelComponentFactory,
            configurationController,
            broadcastDispatcher,
            realDumpManager,
            volumePanelLogger,
            volumePanelGlobalStateInteractor,
        )

    private companion object {
        const val DUMPABLE_NAME = "VolumePanelViewModel"

        const val BOTTOM_BAR: VolumePanelComponentKey = "test_bottom_bar"
        const val COMPONENT_1: VolumePanelComponentKey = "test_component:1"
        const val COMPONENT_2: VolumePanelComponentKey = "test_component:2"
+9 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.volume.panel.data.repository
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.volume.panel.shared.VolumePanelLogger
import com.android.systemui.volume.panel.shared.model.VolumePanelGlobalState
import java.io.PrintWriter
import javax.inject.Inject
@@ -27,10 +28,15 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update

private const val TAG = "VolumePanelGlobalState"
private const val TAG = "VolumePanelGlobalStateRepository"

@SysUISingleton
class VolumePanelGlobalStateRepository @Inject constructor(dumpManager: DumpManager) : Dumpable {
class VolumePanelGlobalStateRepository
@Inject
constructor(
    dumpManager: DumpManager,
    private val logger: VolumePanelLogger,
) : Dumpable {

    private val mutableGlobalState =
        MutableStateFlow(
@@ -48,6 +54,7 @@ class VolumePanelGlobalStateRepository @Inject constructor(dumpManager: DumpMana
        update: (currentState: VolumePanelGlobalState) -> VolumePanelGlobalState
    ) {
        mutableGlobalState.update(update)
        logger.onVolumePanelGlobalStateChanged(mutableGlobalState.value)
    }

    override fun dump(pw: PrintWriter, args: Array<out String>) {
+17 −5
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.volume.panel.domain.interactor
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
import com.android.systemui.volume.panel.domain.model.ComponentModel
import com.android.systemui.volume.panel.shared.VolumePanelLogger
import com.android.systemui.volume.panel.shared.model.VolumePanelComponentKey
import javax.inject.Inject
import javax.inject.Provider
@@ -26,8 +27,12 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn

interface ComponentsInteractor {

@@ -45,6 +50,7 @@ constructor(
    enabledComponents: Collection<VolumePanelComponentKey>,
    defaultCriteria: Provider<ComponentAvailabilityCriteria>,
    @VolumePanelScope coroutineScope: CoroutineScope,
    private val logger: VolumePanelLogger,
    private val criteriaByKey:
        Map<
            VolumePanelComponentKey,
@@ -57,12 +63,18 @@ constructor(
        combine(
                enabledComponents.map { componentKey ->
                    val componentCriteria = (criteriaByKey[componentKey] ?: defaultCriteria).get()
                    componentCriteria.isAvailable().map { isAvailable ->
                    componentCriteria
                        .isAvailable()
                        .distinctUntilChanged()
                        .conflate()
                        .onEach { logger.onComponentAvailabilityChanged(componentKey, it) }
                        .map { isAvailable ->
                            ComponentModel(componentKey, isAvailable = isAvailable)
                        }
                }
            ) {
                it.asList()
            }
            .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)
            .stateIn(coroutineScope, SharingStarted.Eagerly, null)
            .filterNotNull()
}
Loading