Legacy setting syncer.

We need to respect the user's settings when we update quick affordance
selections and vice versa. See the documentation of the class for more
details.

Fix: 256662760
Test: added unit tests. Manually verified that updating settings and
selections updates the other side as expected.

Change-Id: Icd8ff1558fe887ca765ce325b97e7815f124b0db
This commit is contained in:
Alejandro Nijamkin
2022-11-07 12:17:52 -08:00
parent 694e0ab10f
commit 5a574a1db4
8 changed files with 548 additions and 81 deletions

View File

@@ -0,0 +1,214 @@
/*
* Copyright (C) 2022 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.keyguard.data.quickaffordance
import android.os.UserHandle
import android.provider.Settings
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer.Companion.BINDINGS
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* Keeps quick affordance selections and legacy user settings in sync.
*
* "Legacy user settings" are user settings like: Settings > Display > Lock screen > "Show device
* controls" Settings > Display > Lock screen > "Show wallet"
*
* Quick affordance selections are the ones available through the new custom lock screen experience
* from Settings > Wallpaper & Style.
*
* This class keeps these in sync, mostly for backwards compatibility purposes and in order to not
* "forget" an existing legacy user setting when the device gets updated with a version of System UI
* that has the new customizable lock screen feature.
*
* The way it works is that, when [startSyncing] is called, the syncer starts coroutines to listen
* for changes in both legacy user settings and their respective affordance selections. Whenever one
* of each pair is changed, the other member of that pair is also updated to match. For example, if
* the user turns on "Show device controls", we automatically select the home controls affordance
* for the preferred slot. Conversely, when the home controls affordance is unselected by the user,
* we set the "Show device controls" setting to "off".
*
* The class can be configured by updating its list of triplets in the code under [BINDINGS].
*/
@SysUISingleton
class KeyguardQuickAffordanceLegacySettingSyncer
@Inject
constructor(
@Application private val scope: CoroutineScope,
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val secureSettings: SecureSettings,
private val selectionsManager: KeyguardQuickAffordanceSelectionManager,
) {
companion object {
private val BINDINGS =
listOf(
Binding(
settingsKey = Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
affordanceId = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
),
Binding(
settingsKey = Settings.Secure.LOCKSCREEN_SHOW_WALLET,
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
affordanceId = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET,
),
Binding(
settingsKey = Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER,
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
affordanceId = BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER,
),
)
}
fun startSyncing(
bindings: List<Binding> = BINDINGS,
): Job {
return scope.launch { bindings.forEach { binding -> startSyncing(this, binding) } }
}
private fun startSyncing(
scope: CoroutineScope,
binding: Binding,
) {
secureSettings
.observerFlow(
names = arrayOf(binding.settingsKey),
userId = UserHandle.USER_ALL,
)
.map {
isSet(
settingsKey = binding.settingsKey,
)
}
.distinctUntilChanged()
.onEach { isSet ->
if (isSelected(binding.affordanceId) != isSet) {
if (isSet) {
select(
slotId = binding.slotId,
affordanceId = binding.affordanceId,
)
} else {
unselect(
affordanceId = binding.affordanceId,
)
}
}
}
.flowOn(backgroundDispatcher)
.launchIn(scope)
selectionsManager.selections
.map { it.values.flatten().toSet() }
.map { it.contains(binding.affordanceId) }
.distinctUntilChanged()
.onEach { isSelected ->
if (isSet(binding.settingsKey) != isSelected) {
set(binding.settingsKey, isSelected)
}
}
.flowOn(backgroundDispatcher)
.launchIn(scope)
}
private fun isSelected(
affordanceId: String,
): Boolean {
return selectionsManager
.getSelections() // Map<String, List<String>>
.values // Collection<List<String>>
.flatten() // List<String>
.toSet() // Set<String>
.contains(affordanceId)
}
private fun select(
slotId: String,
affordanceId: String,
) {
val affordanceIdsAtSlotId = selectionsManager.getSelections()[slotId] ?: emptyList()
selectionsManager.setSelections(
slotId = slotId,
affordanceIds = affordanceIdsAtSlotId + listOf(affordanceId),
)
}
private fun unselect(
affordanceId: String,
) {
val currentSelections = selectionsManager.getSelections()
val slotIdsContainingAffordanceId =
currentSelections
.filter { (_, affordanceIds) -> affordanceIds.contains(affordanceId) }
.map { (slotId, _) -> slotId }
slotIdsContainingAffordanceId.forEach { slotId ->
val currentAffordanceIds = currentSelections[slotId] ?: emptyList()
val affordanceIdsAfterUnselecting =
currentAffordanceIds.toMutableList().apply { remove(affordanceId) }
selectionsManager.setSelections(
slotId = slotId,
affordanceIds = affordanceIdsAfterUnselecting,
)
}
}
private fun isSet(
settingsKey: String,
): Boolean {
return secureSettings.getIntForUser(
settingsKey,
0,
UserHandle.USER_CURRENT,
) != 0
}
private suspend fun set(
settingsKey: String,
isSet: Boolean,
) {
withContext(backgroundDispatcher) {
secureSettings.putInt(
settingsKey,
if (isSet) 1 else 0,
)
}
}
data class Binding(
val settingsKey: String,
val slotId: String,
val affordanceId: String,
)
}

View File

@@ -22,6 +22,7 @@ import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
@@ -40,6 +41,7 @@ constructor(
@Application private val appContext: Context,
@Application private val scope: CoroutineScope,
private val selectionManager: KeyguardQuickAffordanceSelectionManager,
legacySettingSyncer: KeyguardQuickAffordanceLegacySettingSyncer,
private val configs: Set<@JvmSuppressWildcards KeyguardQuickAffordanceConfig>,
) {
/**
@@ -83,6 +85,10 @@ constructor(
}
}
init {
legacySettingSyncer.startSyncing()
}
/**
* Returns a snapshot of the [KeyguardQuickAffordanceConfig] instances of the affordances at the
* slot with the given ID. The configs are sorted in descending priority order.

View File

@@ -27,6 +27,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -41,6 +42,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -71,26 +73,28 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
underTest = KeyguardQuickAffordanceProvider()
val scope = CoroutineScope(IMMEDIATE)
val selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
)
val quickAffordanceRepository =
KeyguardQuickAffordanceRepository(
appContext = context,
scope = CoroutineScope(IMMEDIATE),
selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
),
scope = scope,
selectionManager = selectionManager,
configs =
setOf(
FakeKeyguardQuickAffordanceConfig(
@@ -102,6 +106,13 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
pickerIconResourceId = 2,
),
),
legacySettingSyncer =
KeyguardQuickAffordanceLegacySettingSyncer(
scope = scope,
backgroundDispatcher = IMMEDIATE,
secureSettings = FakeSettings(),
selectionsManager = selectionManager,
),
)
underTest.interactor =
KeyguardQuickAffordanceInteractor(

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2022 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.keyguard.data.quickaffordance
import android.content.Context
import android.content.res.Resources
import android.provider.Settings
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(JUnit4::class)
class KeyguardQuickAffordanceLegacySettingSyncerTest : SysuiTestCase() {
@Mock private lateinit var sharedPrefs: FakeSharedPreferences
private lateinit var underTest: KeyguardQuickAffordanceLegacySettingSyncer
private lateinit var testScope: TestScope
private lateinit var testDispatcher: TestDispatcher
private lateinit var selectionManager: KeyguardQuickAffordanceSelectionManager
private lateinit var settings: FakeSettings
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
val context: Context = mock()
sharedPrefs = FakeSharedPreferences()
whenever(context.getSharedPreferences(anyString(), any())).thenReturn(sharedPrefs)
val resources: Resources = mock()
whenever(resources.getStringArray(R.array.config_keyguardQuickAffordanceDefaults))
.thenReturn(emptyArray())
whenever(context.resources).thenReturn(resources)
testDispatcher = UnconfinedTestDispatcher()
testScope = TestScope(testDispatcher)
selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = FakeUserTracker(),
)
settings = FakeSettings()
settings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 0)
settings.putInt(Settings.Secure.LOCKSCREEN_SHOW_WALLET, 0)
settings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER, 0)
underTest =
KeyguardQuickAffordanceLegacySettingSyncer(
scope = testScope,
backgroundDispatcher = testDispatcher,
secureSettings = settings,
selectionsManager = selectionManager,
)
}
@Test
fun `Setting a setting selects the affordance`() =
testScope.runTest {
val job = underTest.startSyncing()
settings.putInt(
Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
1,
)
assertThat(
selectionManager
.getSelections()
.getOrDefault(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
emptyList()
)
)
.contains(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
job.cancel()
}
@Test
fun `Clearing a setting selects the affordance`() =
testScope.runTest {
val job = underTest.startSyncing()
settings.putInt(
Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
1,
)
settings.putInt(
Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
0,
)
assertThat(
selectionManager
.getSelections()
.getOrDefault(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
emptyList()
)
)
.doesNotContain(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
job.cancel()
}
@Test
fun `Selecting an affordance sets its setting`() =
testScope.runTest {
val job = underTest.startSyncing()
selectionManager.setSelections(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
listOf(BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET)
)
advanceUntilIdle()
assertThat(settings.getInt(Settings.Secure.LOCKSCREEN_SHOW_WALLET)).isEqualTo(1)
job.cancel()
}
@Test
fun `Unselecting an affordance clears its setting`() =
testScope.runTest {
val job = underTest.startSyncing()
selectionManager.setSelections(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
listOf(BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET)
)
selectionManager.setSelections(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
emptyList()
)
assertThat(settings.getInt(Settings.Secure.LOCKSCREEN_SHOW_WALLET)).isEqualTo(0)
job.cancel()
}
}

View File

@@ -22,6 +22,7 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
@@ -30,6 +31,7 @@ import com.android.systemui.settings.UserFileManager
import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -58,25 +60,35 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
fun setUp() {
config1 = FakeKeyguardQuickAffordanceConfig("built_in:1")
config2 = FakeKeyguardQuickAffordanceConfig("built_in:2")
val scope = CoroutineScope(IMMEDIATE)
val selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = FakeUserTracker(),
)
underTest =
KeyguardQuickAffordanceRepository(
appContext = context,
scope = CoroutineScope(IMMEDIATE),
selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = FakeUserTracker(),
scope = scope,
selectionManager = selectionManager,
legacySettingSyncer =
KeyguardQuickAffordanceLegacySettingSyncer(
scope = scope,
backgroundDispatcher = IMMEDIATE,
secureSettings = FakeSettings(),
selectionsManager = selectionManager,
),
configs = setOf(config1, config2),
)

View File

@@ -30,6 +30,7 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -44,6 +45,7 @@ import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.runBlockingTest
@@ -234,25 +236,34 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
)
val qrCodeScanner =
FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
val scope = CoroutineScope(IMMEDIATE)
val selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
)
val quickAffordanceRepository =
KeyguardQuickAffordanceRepository(
appContext = context,
scope = CoroutineScope(IMMEDIATE),
selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
scope = scope,
selectionManager = selectionManager,
legacySettingSyncer =
KeyguardQuickAffordanceLegacySettingSyncer(
scope = scope,
backgroundDispatcher = IMMEDIATE,
secureSettings = FakeSettings(),
selectionsManager = selectionManager,
),
configs = setOf(homeControls, quickAccessWallet, qrCodeScanner),
)

View File

@@ -27,6 +27,7 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -42,6 +43,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -93,26 +95,35 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
)
qrCodeScanner =
FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
val scope = CoroutineScope(IMMEDIATE)
val selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
)
val quickAffordanceRepository =
KeyguardQuickAffordanceRepository(
appContext = context,
scope = CoroutineScope(IMMEDIATE),
selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
scope = scope,
selectionManager = selectionManager,
legacySettingSyncer =
KeyguardQuickAffordanceLegacySettingSyncer(
scope = scope,
backgroundDispatcher = IMMEDIATE,
secureSettings = FakeSettings(),
selectionsManager = selectionManager,
),
configs = setOf(homeControls, quickAccessWallet, qrCodeScanner),
)

View File

@@ -28,6 +28,7 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -44,6 +45,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlin.math.max
import kotlin.math.min
@@ -118,25 +120,34 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
whenever(userTracker.userHandle).thenReturn(mock())
whenever(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED)
val scope = CoroutineScope(IMMEDIATE)
val selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
)
val quickAffordanceRepository =
KeyguardQuickAffordanceRepository(
appContext = context,
scope = CoroutineScope(IMMEDIATE),
selectionManager =
KeyguardQuickAffordanceSelectionManager(
context = context,
userFileManager =
mock<UserFileManager>().apply {
whenever(
getSharedPreferences(
anyString(),
anyInt(),
anyInt(),
)
)
.thenReturn(FakeSharedPreferences())
},
userTracker = userTracker,
scope = scope,
selectionManager = selectionManager,
legacySettingSyncer =
KeyguardQuickAffordanceLegacySettingSyncer(
scope = scope,
backgroundDispatcher = IMMEDIATE,
secureSettings = FakeSettings(),
selectionsManager = selectionManager,
),
configs =
setOf(