diff options
| author | 2023-02-01 23:42:21 +0000 | |
|---|---|---|
| committer | 2023-02-01 23:42:21 +0000 | |
| commit | ee68eee98c76b8f4aaecd8212d6564da7c67a924 (patch) | |
| tree | bdc90e61c4bc375a96e8884c5b5ef88eb774a02b | |
| parent | 001130e7a4478b84f82fc26a7608fa095f54f6ea (diff) | |
| parent | e09eefdb1dd5a503e24fb18ba21886c702b2af81 (diff) | |
Merge "Adjust Mute Quick Affordance to not make binder calls on main thread" into tm-qpr-dev am: d56308bc57 am: e09eefdb1d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21159008
Change-Id: Ie03859c3fd20b8c228f440f8f8e6c700fcda95ed
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
4 files changed, 88 insertions, 55 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt index d085db9a1eda..da91572894f3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt @@ -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,54 +98,60 @@ class MuteQuickAffordanceConfig @Inject constructor( activationState, ) } + .flowOn(backgroundDispatcher) override fun onTriggered( expandable: Expandable? ): KeyguardQuickAffordanceConfig.OnTriggeredResult { - val newRingerMode: Int - val currentRingerMode = - ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE - if (currentRingerMode == AudioManager.RINGER_MODE_SILENT) { - newRingerMode = previousNonSilentMode - } else { - previousNonSilentMode = currentRingerMode - newRingerMode = AudioManager.RINGER_MODE_SILENT - } + coroutineScope.launch(backgroundDispatcher) { + val newRingerMode: Int + val currentRingerMode = audioManager.ringerModeInternal + if (currentRingerMode == AudioManager.RINGER_MODE_SILENT) { + newRingerMode = previousNonSilentMode + } else { + previousNonSilentMode = currentRingerMode + newRingerMode = AudioManager.RINGER_MODE_SILENT + } - if (currentRingerMode != newRingerMode) { - audioManager.ringerModeInternal = newRingerMode + if (currentRingerMode != newRingerMode) { + audioManager.ringerModeInternal = newRingerMode + } } return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState = - if (audioManager.isVolumeFixed) { - KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice - } else { - KeyguardQuickAffordanceConfig.PickerScreenState.Default() + 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 = - userFileManager.getSharedPreferences( - MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME, - Context.MODE_PRIVATE, - userTracker.userId - ).getInt( - LAST_NON_SILENT_RINGER_MODE_KEY, - ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE - ) + private suspend fun getLastNonSilentRingerMode(): Int = + withContext(backgroundDispatcher) { + userFileManager.getSharedPreferences( + MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME, + Context.MODE_PRIVATE, + userTracker.userId + ).getInt( + LAST_NON_SILENT_RINGER_MODE_KEY, + ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE + ) + } private fun <T> LiveData<T>.asFlow(): Flow<T?> = - conflatedCallbackFlow { - val observer = Observer { value: T -> trySend(value) } - observeForever(observer) - send(value) - awaitClose { removeObserver(observer) } - } + conflatedCallbackFlow { + val observer = Observer { value: T -> trySend(value) } + 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" diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt index 12a6310ccc85..cd0805e663e4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt @@ -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,15 +76,17 @@ class MuteQuickAffordanceCoreStartable @Inject constructor( } private fun updateLastNonSilentRingerMode(lastRingerMode: Int) { - if (AudioManager.RINGER_MODE_SILENT != lastRingerMode) { - userFileManager.getSharedPreferences( - MuteQuickAffordanceConfig.MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME, - Context.MODE_PRIVATE, - userTracker.userId - ) - .edit() - .putInt(MuteQuickAffordanceConfig.LAST_NON_SILENT_RINGER_MODE_KEY, lastRingerMode) - .apply() + coroutineScope.launch(backgroundDispatcher) { + if (AudioManager.RINGER_MODE_SILENT != lastRingerMode) { + userFileManager.getSharedPreferences( + MuteQuickAffordanceConfig.MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME, + Context.MODE_PRIVATE, + userTracker.userId + ) + .edit() + .putInt(MuteQuickAffordanceConfig.LAST_NON_SILENT_RINGER_MODE_KEY, lastRingerMode) + .apply() + } } } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt index a3740d88e1a9..925c06fe8951 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt @@ -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 diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt index 26601b63e02d..34f3ed804bfa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt @@ -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 |