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

Commit c3251c62 authored by Michael Mikhail's avatar Michael Mikhail
Browse files

Add two states for ringer view model.

This CL adds a control over the availability of ringer drawer in volume
dialog. It handles the unsupported current ringer mode and the single
volume mode cases.

Flag: com.android.systemui.volume_redesign
Bug: 369993851
Test: atest SystemUiRoboTests:VolumeDialogRingerDrawerViewModelTest
Change-Id: I02dff77b7d3c98ede32cdc3af25d0443f0381dd6
parent b95e6688
Loading
Loading
Loading
Loading
+44 −26
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.systemui.haptics.fakeVibratorHelper
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.fakeVolumeDialogController
import com.android.systemui.testKosmos
import com.android.systemui.volume.data.repository.audioSystemRepository
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -65,8 +66,8 @@ class VolumeDialogRingerDrawerViewModelTest : SysuiTestCase() {

            setUpRingerModeAndOpenDrawer(normalRingerMode)

            assertThat(ringerViewModel).isNotNull()
            assertThat(ringerViewModel?.drawerState)
            assertThat(ringerViewModel).isInstanceOf(RingerViewModelState.Available::class.java)
            assertThat((ringerViewModel as RingerViewModelState.Available).uiModel.drawerState)
                .isEqualTo(RingerDrawerState.Open(normalRingerMode))
        }

@@ -80,8 +81,8 @@ class VolumeDialogRingerDrawerViewModelTest : SysuiTestCase() {
            underTest.onRingerButtonClicked(normalRingerMode)
            controller.getState()

            assertThat(ringerViewModel).isNotNull()
            assertThat(ringerViewModel?.drawerState)
            assertThat(ringerViewModel).isInstanceOf(RingerViewModelState.Available::class.java)
            assertThat((ringerViewModel as RingerViewModelState.Available).uiModel.drawerState)
                .isEqualTo(RingerDrawerState.Closed(normalRingerMode))
        }

@@ -97,16 +98,12 @@ class VolumeDialogRingerDrawerViewModelTest : SysuiTestCase() {
            controller.getState()
            runCurrent()

            assertThat(ringerViewModel).isNotNull()
            assertThat(
                    ringerViewModel
                        ?.availableButtons
                        ?.get(ringerViewModel!!.currentButtonIndex)
                        ?.ringerMode
                )
            assertThat(ringerViewModel).isInstanceOf(RingerViewModelState.Available::class.java)

            var uiModel = (ringerViewModel as RingerViewModelState.Available).uiModel
            assertThat(uiModel.availableButtons[uiModel.currentButtonIndex]?.ringerMode)
                .isEqualTo(vibrateRingerMode)
            assertThat(ringerViewModel?.drawerState)
                .isEqualTo(RingerDrawerState.Closed(vibrateRingerMode))
            assertThat(uiModel.drawerState).isEqualTo(RingerDrawerState.Closed(vibrateRingerMode))

            val silentRingerMode = RingerMode(RINGER_MODE_SILENT)
            // Open drawer
@@ -118,27 +115,48 @@ class VolumeDialogRingerDrawerViewModelTest : SysuiTestCase() {
            controller.getState()
            runCurrent()

            assertThat(ringerViewModel).isNotNull()
            assertThat(
                    ringerViewModel
                        ?.availableButtons
                        ?.get(ringerViewModel!!.currentButtonIndex)
                        ?.ringerMode
                )
            assertThat(ringerViewModel).isInstanceOf(RingerViewModelState.Available::class.java)

            uiModel = (ringerViewModel as RingerViewModelState.Available).uiModel
            assertThat(uiModel.availableButtons[uiModel.currentButtonIndex]?.ringerMode)
                .isEqualTo(silentRingerMode)
            assertThat(ringerViewModel?.drawerState)
                .isEqualTo(RingerDrawerState.Closed(silentRingerMode))
            assertThat(uiModel.drawerState).isEqualTo(RingerDrawerState.Closed(silentRingerMode))
            assertThat(controller.hasScheduledTouchFeedback).isFalse()
            assertThat(vibratorHelper.totalVibrations).isEqualTo(2)
        }

    private fun TestScope.setUpRingerModeAndOpenDrawer(selectedRingerMode: RingerMode) {
        controller.setStreamVolume(STREAM_RING, 50)
        controller.setRingerMode(selectedRingerMode.value, false)
        runCurrent()
    @Test
    fun onVolumeSingleMode_ringerIsUnavailable() =
        testScope.runTest {
            val ringerViewModel by collectLastValue(underTest.ringerViewModel)

            kosmos.audioSystemRepository.setIsSingleVolume(true)
            setUpRingerMode(RingerMode(RINGER_MODE_NORMAL))

            assertThat(ringerViewModel).isInstanceOf(RingerViewModelState.Unavailable::class.java)
        }

    @Test
    fun setUnsupportedRingerMode_ringerIsUnavailable() =
        testScope.runTest {
            val ringerViewModel by collectLastValue(underTest.ringerViewModel)

            controller.setHasVibrator(false)
            setUpRingerMode(RingerMode(RINGER_MODE_VIBRATE))

            assertThat(ringerViewModel).isInstanceOf(RingerViewModelState.Unavailable::class.java)
        }

    private fun TestScope.setUpRingerModeAndOpenDrawer(selectedRingerMode: RingerMode) {
        setUpRingerMode(selectedRingerMode)
        underTest.onRingerButtonClicked(RingerMode(selectedRingerMode.value))
        controller.getState()
        runCurrent()
    }

    private fun TestScope.setUpRingerMode(selectedRingerMode: RingerMode) {
        controller.setStreamVolume(STREAM_RING, 50)
        controller.setRingerMode(selectedRingerMode.value, false)
        runCurrent()
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.media.AudioManager.RINGER_MODE_NORMAL
import android.media.AudioManager.RINGER_MODE_SILENT
import android.media.AudioManager.RINGER_MODE_VIBRATE
import android.provider.Settings
import com.android.settingslib.volume.data.repository.AudioSystemRepository
import com.android.settingslib.volume.shared.model.RingerMode
import com.android.systemui.plugins.VolumeDialogController
import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
@@ -43,6 +44,7 @@ constructor(
    @VolumeDialog private val coroutineScope: CoroutineScope,
    volumeDialogStateInteractor: VolumeDialogStateInteractor,
    private val controller: VolumeDialogController,
    private val audioSystemRepository: AudioSystemRepository,
) {

    val ringerModel: Flow<VolumeDialogRingerModel> =
@@ -70,6 +72,7 @@ constructor(
                isMuted = it.level == 0 || it.muted,
                level = it.level,
                levelMax = it.levelMax,
                isSingleVolume = audioSystemRepository.isSingleVolume,
            )
        }
    }
+2 −0
Original line number Diff line number Diff line
@@ -31,4 +31,6 @@ data class VolumeDialogRingerModel(
    val level: Int,
    /** Ring stream maximum level */
    val levelMax: Int,
    /** in single volume mode */
    val isSingleVolume: Boolean,
)
+25 −0
Original line number Diff line number Diff line
/*
 * 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.volume.dialog.ringer.ui.viewmodel

/** Models ringer view model state. */
sealed class RingerViewModelState {

    data class Available(val uiModel: RingerViewModel) : RingerViewModelState()

    data object Unavailable : RingerViewModelState()
}
+15 −11
Original line number Diff line number Diff line
@@ -34,11 +34,10 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn

@@ -56,13 +55,12 @@ constructor(

    private val drawerState = MutableStateFlow<RingerDrawerState>(RingerDrawerState.Initial)

    val ringerViewModel: Flow<RingerViewModel> =
    val ringerViewModel: StateFlow<RingerViewModelState> =
        combine(interactor.ringerModel, drawerState) { ringerModel, state ->
                ringerModel.toViewModel(state)
            }
            .flowOn(backgroundDispatcher)
            .stateIn(coroutineScope, SharingStarted.Eagerly, null)
            .filterNotNull()
            .stateIn(coroutineScope, SharingStarted.Eagerly, RingerViewModelState.Unavailable)

    // Vibration attributes.
    private val sonificiationVibrationAttributes =
@@ -105,16 +103,22 @@ constructor(

    private fun VolumeDialogRingerModel.toViewModel(
        drawerState: RingerDrawerState
    ): RingerViewModel {
    ): RingerViewModelState {
        val currentIndex = availableModes.indexOf(currentRingerMode)
        if (currentIndex == -1) {
            volumeDialogLogger.onCurrentRingerModeIsUnsupported(currentRingerMode)
        }
        return RingerViewModel(
        return if (currentIndex == -1 || isSingleVolume) {
            RingerViewModelState.Unavailable
        } else {
            RingerViewModelState.Available(
                RingerViewModel(
                    availableButtons = availableModes.map { mode -> toButtonViewModel(mode) },
                    currentButtonIndex = currentIndex,
                    drawerState = drawerState,
                )
            )
        }
    }

    private fun VolumeDialogRingerModel.toButtonViewModel(
Loading