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

Commit e09eefdb authored by Brad Hinegardner's avatar Brad Hinegardner Committed by Automerger Merge Worker
Browse files

Merge "Adjust Mute Quick Affordance to not make binder calls on main thread"...

Merge "Adjust Mute Quick Affordance to not make binder calls on main thread" into tm-qpr-dev am: d56308bc

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21159008



Change-Id: I2ac73a4848d52541c7f9678b76a4f984f61279e9
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents f6da96cb d56308bc
Loading
Loading
Loading
Loading
+48 −31
Original line number Diff line number Diff line
@@ -27,16 +27,24 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.RingerModeTracker
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

@SysUISingleton
@@ -46,6 +54,9 @@ class MuteQuickAffordanceConfig @Inject constructor(
        private val userFileManager: UserFileManager,
        private val ringerModeTracker: RingerModeTracker,
        private val audioManager: AudioManager,
        @Application private val coroutineScope: CoroutineScope,
        @Main private val mainDispatcher: CoroutineDispatcher,
        @Background private val backgroundDispatcher: CoroutineDispatcher,
) : KeyguardQuickAffordanceConfig {

    private var previousNonSilentMode: Int = DEFAULT_LAST_NON_SILENT_VALUE
@@ -58,7 +69,7 @@ class MuteQuickAffordanceConfig @Inject constructor(

    override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> =
        ringerModeTracker.ringerModeInternal.asFlow()
            .onStart { emit(getLastNonSilentRingerMode()) }
            .onStart { getLastNonSilentRingerMode() }
            .distinctUntilChanged()
            .onEach { mode ->
                // only remember last non-SILENT ringer mode
@@ -87,13 +98,14 @@ class MuteQuickAffordanceConfig @Inject constructor(
                    activationState,
                )
            }
            .flowOn(backgroundDispatcher)

    override fun onTriggered(
        expandable: Expandable?
    ): KeyguardQuickAffordanceConfig.OnTriggeredResult {
        coroutineScope.launch(backgroundDispatcher) {
            val newRingerMode: Int
        val currentRingerMode =
                ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE
            val currentRingerMode = audioManager.ringerModeInternal
            if (currentRingerMode == AudioManager.RINGER_MODE_SILENT) {
                newRingerMode = previousNonSilentMode
            } else {
@@ -104,21 +116,25 @@ class MuteQuickAffordanceConfig @Inject constructor(
            if (currentRingerMode != newRingerMode) {
                audioManager.ringerModeInternal = newRingerMode
            }
        }
        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
    }

    override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState =
        withContext(backgroundDispatcher) {
            if (audioManager.isVolumeFixed) {
                KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
            } else {
                KeyguardQuickAffordanceConfig.PickerScreenState.Default()
            }
        }

    /**
     * Gets the last non-silent ringer mode from shared-preferences if it exists. This is
     *  cached by [MuteQuickAffordanceCoreStartable] while this affordance is selected
     */
    private fun getLastNonSilentRingerMode(): Int =
    private suspend fun getLastNonSilentRingerMode(): Int =
        withContext(backgroundDispatcher) {
            userFileManager.getSharedPreferences(
                    MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME,
                    Context.MODE_PRIVATE,
@@ -127,6 +143,7 @@ class MuteQuickAffordanceConfig @Inject constructor(
                    LAST_NON_SILENT_RINGER_MODE_KEY,
                    ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE
            )
        }

    private fun <T> LiveData<T>.asFlow(): Flow<T?> =
        conflatedCallbackFlow {
@@ -134,7 +151,7 @@ class MuteQuickAffordanceConfig @Inject constructor(
            observeForever(observer)
            send(value)
            awaitClose { removeObserver(observer) }
            }
        }.flowOn(mainDispatcher)

    companion object {
        const val LAST_NON_SILENT_RINGER_MODE_KEY = "key_last_non_silent_ringer_mode"
+15 −9
Original line number Diff line number Diff line
@@ -23,15 +23,18 @@ import androidx.lifecycle.Observer
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.RingerModeTracker
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
@@ -45,6 +48,7 @@ class MuteQuickAffordanceCoreStartable @Inject constructor(
    private val userFileManager: UserFileManager,
    private val keyguardQuickAffordanceRepository: KeyguardQuickAffordanceRepository,
    @Application private val coroutineScope: CoroutineScope,
    @Background private val backgroundDispatcher: CoroutineDispatcher,
) : CoreStartable {

    private val observer = Observer(this::updateLastNonSilentRingerMode)
@@ -72,6 +76,7 @@ class MuteQuickAffordanceCoreStartable @Inject constructor(
    }

    private fun updateLastNonSilentRingerMode(lastRingerMode: Int) {
        coroutineScope.launch(backgroundDispatcher) {
            if (AudioManager.RINGER_MODE_SILENT != lastRingerMode) {
                userFileManager.getSharedPreferences(
                        MuteQuickAffordanceConfig.MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME,
@@ -84,3 +89,4 @@ class MuteQuickAffordanceCoreStartable @Inject constructor(
            }
        }
    }
}
 No newline at end of file
+17 −13
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.systemui.keyguard.data.quickaffordance

import android.content.Context
import android.media.AudioManager
import androidx.lifecycle.LiveData
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.UserFileManager
@@ -27,10 +26,12 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.util.RingerModeTracker
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
@@ -57,13 +58,15 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
    @Mock
    private lateinit var userFileManager: UserFileManager

    private lateinit var testDispatcher: TestDispatcher
    private lateinit var testScope: TestScope

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)

        testScope = TestScope()
        testDispatcher = StandardTestDispatcher()
        testScope = TestScope(testDispatcher)

        whenever(userTracker.userContext).thenReturn(context)
        whenever(userFileManager.getSharedPreferences(any(), any(), any()))
@@ -74,7 +77,10 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
                userTracker,
                userFileManager,
                ringerModeTracker,
                audioManager
                audioManager,
                testScope.backgroundScope,
                testDispatcher,
                testDispatcher,
        )
    }

@@ -103,17 +109,16 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
    }

    @Test
    fun `triggered - state was previously NORMAL - currently SILENT - move to previous state`() {
    fun `triggered - state was previously NORMAL - currently SILENT - move to previous state`() = testScope.runTest {
        //given
        val ringerModeCapture = argumentCaptor<Int>()
        val ringerModeInternal = mock<LiveData<Int>>()
        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
        whenever(ringerModeInternal.value).thenReturn(AudioManager.RINGER_MODE_NORMAL)
        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
        underTest.onTriggered(null)
        whenever(ringerModeInternal.value).thenReturn(AudioManager.RINGER_MODE_SILENT)
        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_SILENT)

        //when
        val result = underTest.onTriggered(null)
        runCurrent()
        verify(audioManager, times(2)).ringerModeInternal = ringerModeCapture.capture()

        //then
@@ -122,15 +127,14 @@ class MuteQuickAffordanceConfigTest : SysuiTestCase() {
    }

    @Test
    fun `triggered - state is not SILENT - move to SILENT ringer`() {
    fun `triggered - state is not SILENT - move to SILENT ringer`() = testScope.runTest {
        //given
        val ringerModeCapture = argumentCaptor<Int>()
        val ringerModeInternal = mock<LiveData<Int>>()
        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
        whenever(ringerModeInternal.value).thenReturn(AudioManager.RINGER_MODE_NORMAL)
        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)

        //when
        val result = underTest.onTriggered(null)
        runCurrent()
        verify(audioManager).ringerModeInternal = ringerModeCapture.capture()

        //then
+8 −2
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -67,6 +69,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
    @Mock
    private lateinit var keyguardQuickAffordanceRepository: KeyguardQuickAffordanceRepository

    private lateinit var testDispatcher: TestDispatcher
    private lateinit var testScope: TestScope

    private lateinit var underTest: MuteQuickAffordanceCoreStartable
@@ -83,7 +86,8 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
        val emission = MutableStateFlow(mapOf("testQuickAffordanceKey" to listOf(config)))
        whenever(keyguardQuickAffordanceRepository.selections).thenReturn(emission)

        testScope = TestScope()
        testDispatcher = StandardTestDispatcher()
        testScope = TestScope(testDispatcher)

        underTest = MuteQuickAffordanceCoreStartable(
            featureFlags,
@@ -91,7 +95,8 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
            ringerModeTracker,
            userFileManager,
            keyguardQuickAffordanceRepository,
            testScope,
            testScope.backgroundScope,
            testDispatcher,
        )
    }

@@ -158,6 +163,7 @@ class MuteQuickAffordanceCoreStartableTest : SysuiTestCase() {
        runCurrent()
        verify(ringerModeInternal).observeForever(observerCaptor.capture())
        observerCaptor.value.onChanged(newRingerMode)
        runCurrent()
        val result = sharedPrefs.getInt("key_last_non_silent_ringer_mode", -1)

        //then