• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 package com.android.systemui.keyguard.domain.interactor
19 
20 import android.app.admin.DevicePolicyManager
21 import android.os.UserHandle
22 import androidx.test.ext.junit.runners.AndroidJUnit4
23 import androidx.test.filters.SmallTest
24 import com.android.internal.widget.LockPatternUtils
25 import com.android.systemui.R
26 import com.android.systemui.RoboPilotTest
27 import com.android.systemui.SysuiTestCase
28 import com.android.systemui.animation.DialogLaunchAnimator
29 import com.android.systemui.common.shared.model.ContentDescription
30 import com.android.systemui.common.shared.model.Icon
31 import com.android.systemui.coroutines.collectLastValue
32 import com.android.systemui.dock.DockManager
33 import com.android.systemui.dock.DockManagerFake
34 import com.android.systemui.flags.FakeFeatureFlags
35 import com.android.systemui.flags.Flags
36 import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
37 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
38 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceProviderClientFactory
39 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
40 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
41 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
42 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
43 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
44 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
45 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
46 import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel
47 import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
48 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
49 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
50 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
51 import com.android.systemui.plugins.ActivityStarter
52 import com.android.systemui.settings.UserFileManager
53 import com.android.systemui.settings.UserTracker
54 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
55 import com.android.systemui.statusbar.policy.KeyguardStateController
56 import com.android.systemui.util.FakeSharedPreferences
57 import com.android.systemui.util.mockito.mock
58 import com.android.systemui.util.mockito.whenever
59 import com.android.systemui.util.settings.FakeSettings
60 import com.google.common.truth.Truth.assertThat
61 import kotlinx.coroutines.ExperimentalCoroutinesApi
62 import kotlinx.coroutines.test.StandardTestDispatcher
63 import kotlinx.coroutines.test.TestScope
64 import kotlinx.coroutines.test.runCurrent
65 import kotlinx.coroutines.test.runTest
66 import org.junit.Before
67 import org.junit.Test
68 import org.junit.runner.RunWith
69 import org.mockito.ArgumentMatchers.anyInt
70 import org.mockito.ArgumentMatchers.anyString
71 import org.mockito.Mock
72 import org.mockito.MockitoAnnotations
73 
74 @OptIn(ExperimentalCoroutinesApi::class)
75 @SmallTest
76 @RoboPilotTest
77 @RunWith(AndroidJUnit4::class)
78 class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
79 
80     @Mock private lateinit var lockPatternUtils: LockPatternUtils
81     @Mock private lateinit var keyguardStateController: KeyguardStateController
82     @Mock private lateinit var userTracker: UserTracker
83     @Mock private lateinit var activityStarter: ActivityStarter
84     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
85     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
86     @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
87 
88     private lateinit var underTest: KeyguardQuickAffordanceInteractor
89 
90     private lateinit var testScope: TestScope
91     private lateinit var repository: FakeKeyguardRepository
92     private lateinit var homeControls: FakeKeyguardQuickAffordanceConfig
93     private lateinit var quickAccessWallet: FakeKeyguardQuickAffordanceConfig
94     private lateinit var qrCodeScanner: FakeKeyguardQuickAffordanceConfig
95     private lateinit var featureFlags: FakeFeatureFlags
96     private lateinit var dockManager: DockManagerFake
97     private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
98 
99     @Before
setUpnull100     fun setUp() {
101         MockitoAnnotations.initMocks(this)
102 
103         overrideResource(R.bool.custom_lockscreen_shortcuts_enabled, true)
104         overrideResource(
105             R.array.config_keyguardQuickAffordanceDefaults,
106             arrayOf(
107                 KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START + ":" +
108                     BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
109                 KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END + ":" +
110                     BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
111             )
112         )
113 
114         repository = FakeKeyguardRepository()
115         repository.setKeyguardShowing(true)
116 
117         homeControls =
118             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
119         quickAccessWallet =
120             FakeKeyguardQuickAffordanceConfig(
121                 BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
122             )
123         qrCodeScanner =
124             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
125         val testDispatcher = StandardTestDispatcher()
126         testScope = TestScope(testDispatcher)
127 
128         dockManager = DockManagerFake()
129         biometricSettingsRepository = FakeBiometricSettingsRepository()
130 
131         val localUserSelectionManager =
132             KeyguardQuickAffordanceLocalUserSelectionManager(
133                 context = context,
134                 userFileManager =
135                     mock<UserFileManager>().apply {
136                         whenever(
137                                 getSharedPreferences(
138                                     anyString(),
139                                     anyInt(),
140                                     anyInt(),
141                                 )
142                             )
143                             .thenReturn(FakeSharedPreferences())
144                     },
145                 userTracker = userTracker,
146                 broadcastDispatcher = fakeBroadcastDispatcher,
147             )
148         val remoteUserSelectionManager =
149             KeyguardQuickAffordanceRemoteUserSelectionManager(
150                 scope = testScope.backgroundScope,
151                 userTracker = userTracker,
152                 clientFactory = FakeKeyguardQuickAffordanceProviderClientFactory(userTracker),
153                 userHandle = UserHandle.SYSTEM,
154             )
155         val quickAffordanceRepository =
156             KeyguardQuickAffordanceRepository(
157                 appContext = context,
158                 scope = testScope.backgroundScope,
159                 localUserSelectionManager = localUserSelectionManager,
160                 remoteUserSelectionManager = remoteUserSelectionManager,
161                 userTracker = userTracker,
162                 legacySettingSyncer =
163                     KeyguardQuickAffordanceLegacySettingSyncer(
164                         scope = testScope.backgroundScope,
165                         backgroundDispatcher = testDispatcher,
166                         secureSettings = FakeSettings(),
167                         selectionsManager = localUserSelectionManager,
168                     ),
169                 configs = setOf(homeControls, quickAccessWallet, qrCodeScanner),
170                 dumpManager = mock(),
171                 userHandle = UserHandle.SYSTEM,
172             )
173         featureFlags =
174             FakeFeatureFlags().apply {
175                 set(Flags.FACE_AUTH_REFACTOR, true)
176             }
177 
178         val withDeps =
179             KeyguardInteractorFactory.create(
180                 featureFlags = featureFlags,
181                 repository = repository,
182             )
183         underTest =
184             KeyguardQuickAffordanceInteractor(
185                 keyguardInteractor = withDeps.keyguardInteractor,
186                 lockPatternUtils = lockPatternUtils,
187                 keyguardStateController = keyguardStateController,
188                 userTracker = userTracker,
189                 activityStarter = activityStarter,
190                 featureFlags = featureFlags,
191                 repository = { quickAffordanceRepository },
192                 launchAnimator = launchAnimator,
193                 logger = logger,
194                 devicePolicyManager = devicePolicyManager,
195                 dockManager = dockManager,
196                 biometricSettingsRepository = biometricSettingsRepository,
197                 backgroundDispatcher = testDispatcher,
198                 appContext = context,
199             )
200     }
201 
202     @Test
quickAffordance_bottomStartAffordanceIsVisiblenull203     fun quickAffordance_bottomStartAffordanceIsVisible() =
204         testScope.runTest {
205             val configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS
206             homeControls.setState(
207                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
208                     icon = ICON,
209                     activationState = ActivationState.Active,
210                 )
211             )
212 
213             val collectedValue =
214                 collectLastValue(
215                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START)
216                 )
217 
218             assertThat(collectedValue())
219                 .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
220             val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible
221             assertThat(visibleModel.configKey).isEqualTo(
222                 "${KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START}::${configKey}"
223             )
224             assertThat(visibleModel.icon).isEqualTo(ICON)
225             assertThat(visibleModel.icon.contentDescription)
226                 .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
227             assertThat(visibleModel.activationState).isEqualTo(ActivationState.Active)
228         }
229 
230     @Test
quickAffordance_bottomEndAffordanceIsVisiblenull231     fun quickAffordance_bottomEndAffordanceIsVisible() =
232         testScope.runTest {
233             val configKey = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
234             quickAccessWallet.setState(
235                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
236                     icon = ICON,
237                 )
238             )
239 
240             val collectedValue =
241                 collectLastValue(
242                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
243                 )
244 
245             assertThat(collectedValue())
246                 .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
247             val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible
248             assertThat(visibleModel.configKey).isEqualTo(
249                 "${KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END}::${configKey}"
250             )
251             assertThat(visibleModel.icon).isEqualTo(ICON)
252             assertThat(visibleModel.icon.contentDescription)
253                 .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
254             assertThat(visibleModel.activationState).isEqualTo(ActivationState.NotSupported)
255         }
256 
257     @Test
quickAffordance_hiddenWhenAllFeaturesAreDisabledByDevicePolicynull258     fun quickAffordance_hiddenWhenAllFeaturesAreDisabledByDevicePolicy() =
259         testScope.runTest {
260             whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
261                 .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
262             quickAccessWallet.setState(
263                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
264                     icon = ICON,
265                 )
266             )
267 
268             val collectedValue by
269                 collectLastValue(
270                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
271                 )
272 
273             assertThat(collectedValue).isInstanceOf(KeyguardQuickAffordanceModel.Hidden::class.java)
274         }
275 
276     @Test
quickAffordance_hiddenWhenShortcutsFeatureIsDisabledByDevicePolicynull277     fun quickAffordance_hiddenWhenShortcutsFeatureIsDisabledByDevicePolicy() =
278         testScope.runTest {
279             whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
280                 .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
281             quickAccessWallet.setState(
282                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
283                     icon = ICON,
284                 )
285             )
286 
287             val collectedValue by
288                 collectLastValue(
289                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
290                 )
291 
292             assertThat(collectedValue).isInstanceOf(KeyguardQuickAffordanceModel.Hidden::class.java)
293         }
294 
295     @Test
quickAffordance_hiddenWhenUserIsInLockdownModenull296     fun quickAffordance_hiddenWhenUserIsInLockdownMode() =
297         testScope.runTest {
298             biometricSettingsRepository.setIsUserInLockdown(true)
299             quickAccessWallet.setState(
300                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
301                     icon = ICON,
302                 )
303             )
304 
305             val collectedValue by
306                 collectLastValue(
307                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
308                 )
309 
310             assertThat(collectedValue).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
311         }
312 
313     @Test
quickAffordance_bottomStartAffordanceHiddenWhileDozingnull314     fun quickAffordance_bottomStartAffordanceHiddenWhileDozing() =
315         testScope.runTest {
316             repository.setIsDozing(true)
317             homeControls.setState(
318                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
319                     icon = ICON,
320                 )
321             )
322 
323             val collectedValue =
324                 collectLastValue(
325                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START)
326                 )
327             assertThat(collectedValue()).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
328         }
329 
330     @Test
quickAffordance_bottomStartAffordanceHiddenWhenLockscreenIsNotShowingnull331     fun quickAffordance_bottomStartAffordanceHiddenWhenLockscreenIsNotShowing() =
332         testScope.runTest {
333             repository.setKeyguardShowing(false)
334             homeControls.setState(
335                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
336                     icon = ICON,
337                 )
338             )
339 
340             val collectedValue =
341                 collectLastValue(
342                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START)
343                 )
344             assertThat(collectedValue()).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
345         }
346 
347     @Test
quickAffordanceAlwaysVisible_evenWhenLockScreenNotShowingAndDozingnull348     fun quickAffordanceAlwaysVisible_evenWhenLockScreenNotShowingAndDozing() =
349         testScope.runTest {
350             repository.setKeyguardShowing(false)
351             repository.setIsDozing(true)
352             val configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS
353             homeControls.setState(
354                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
355                     icon = ICON,
356                     activationState = ActivationState.Active,
357                 )
358             )
359 
360             val collectedValue =
361                 collectLastValue(
362                     underTest.quickAffordanceAlwaysVisible(
363                         KeyguardQuickAffordancePosition.BOTTOM_START
364                     )
365                 )
366             assertThat(collectedValue())
367                 .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
368             val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible
369             assertThat(visibleModel.configKey).isEqualTo(
370                 "${KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START}::${configKey}"
371             )
372             assertThat(visibleModel.icon).isEqualTo(ICON)
373             assertThat(visibleModel.icon.contentDescription)
374                 .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
375             assertThat(visibleModel.activationState).isEqualTo(ActivationState.Active)
376         }
377 
378     @Test
selectnull379     fun select() =
380         testScope.runTest {
381             overrideResource(
382                 R.array.config_keyguardQuickAffordanceDefaults,
383                 arrayOf<String>(),
384             )
385             homeControls.setState(
386                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
387             )
388             quickAccessWallet.setState(
389                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
390             )
391             qrCodeScanner.setState(
392                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
393             )
394 
395             assertThat(underTest.getSelections())
396                 .isEqualTo(
397                     mapOf<String, List<String>>(
398                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to emptyList(),
399                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to emptyList(),
400                     )
401                 )
402 
403             val startConfig =
404                 collectLastValue(
405                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START)
406                 )
407             val endConfig =
408                 collectLastValue(
409                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
410                 )
411 
412             underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key)
413 
414             assertThat(startConfig())
415                 .isEqualTo(
416                     KeyguardQuickAffordanceModel.Visible(
417                         configKey =
418                             KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START +
419                                 "::${homeControls.key}",
420                         icon = ICON,
421                         activationState = ActivationState.NotSupported,
422                     )
423                 )
424             assertThat(endConfig())
425                 .isEqualTo(
426                     KeyguardQuickAffordanceModel.Hidden,
427                 )
428             assertThat(underTest.getSelections())
429                 .isEqualTo(
430                     mapOf(
431                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
432                             listOf(
433                                 KeyguardQuickAffordancePickerRepresentation(
434                                     id = homeControls.key,
435                                     name = homeControls.pickerName(),
436                                     iconResourceId = homeControls.pickerIconResourceId,
437                                 ),
438                             ),
439                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to emptyList(),
440                     )
441                 )
442 
443             underTest.select(
444                 KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
445                 quickAccessWallet.key
446             )
447 
448             assertThat(startConfig())
449                 .isEqualTo(
450                     KeyguardQuickAffordanceModel.Visible(
451                         configKey =
452                             KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START +
453                                 "::${quickAccessWallet.key}",
454                         icon = ICON,
455                         activationState = ActivationState.NotSupported,
456                     )
457                 )
458             assertThat(endConfig())
459                 .isEqualTo(
460                     KeyguardQuickAffordanceModel.Hidden,
461                 )
462             assertThat(underTest.getSelections())
463                 .isEqualTo(
464                     mapOf(
465                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
466                             listOf(
467                                 KeyguardQuickAffordancePickerRepresentation(
468                                     id = quickAccessWallet.key,
469                                     name = quickAccessWallet.pickerName(),
470                                     iconResourceId = quickAccessWallet.pickerIconResourceId,
471                                 ),
472                             ),
473                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to emptyList(),
474                     )
475                 )
476 
477             underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, qrCodeScanner.key)
478 
479             assertThat(startConfig())
480                 .isEqualTo(
481                     KeyguardQuickAffordanceModel.Visible(
482                         configKey =
483                             KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START +
484                                 "::${quickAccessWallet.key}",
485                         icon = ICON,
486                         activationState = ActivationState.NotSupported,
487                     )
488                 )
489             assertThat(endConfig())
490                 .isEqualTo(
491                     KeyguardQuickAffordanceModel.Visible(
492                         configKey =
493                             KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END +
494                                 "::${qrCodeScanner.key}",
495                         icon = ICON,
496                         activationState = ActivationState.NotSupported,
497                     )
498                 )
499             assertThat(underTest.getSelections())
500                 .isEqualTo(
501                     mapOf(
502                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
503                             listOf(
504                                 KeyguardQuickAffordancePickerRepresentation(
505                                     id = quickAccessWallet.key,
506                                     name = quickAccessWallet.pickerName(),
507                                     iconResourceId = quickAccessWallet.pickerIconResourceId,
508                                 ),
509                             ),
510                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to
511                             listOf(
512                                 KeyguardQuickAffordancePickerRepresentation(
513                                     id = qrCodeScanner.key,
514                                     name = qrCodeScanner.pickerName(),
515                                     iconResourceId = qrCodeScanner.pickerIconResourceId,
516                                 ),
517                             ),
518                     )
519                 )
520         }
521 
522     @Test
unselect_onenull523     fun unselect_one() =
524         testScope.runTest {
525             homeControls.setState(
526                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
527             )
528             quickAccessWallet.setState(
529                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
530             )
531             qrCodeScanner.setState(
532                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
533             )
534 
535             val startConfig =
536                 collectLastValue(
537                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START)
538                 )
539             val endConfig =
540                 collectLastValue(
541                     underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
542                 )
543             underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key)
544             underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, quickAccessWallet.key)
545             underTest.unselect(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key)
546 
547             assertThat(startConfig())
548                 .isEqualTo(
549                     KeyguardQuickAffordanceModel.Hidden,
550                 )
551             assertThat(endConfig())
552                 .isEqualTo(
553                     KeyguardQuickAffordanceModel.Visible(
554                         configKey =
555                             KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END +
556                                 "::${quickAccessWallet.key}",
557                         icon = ICON,
558                         activationState = ActivationState.NotSupported,
559                     )
560                 )
561             assertThat(underTest.getSelections())
562                 .isEqualTo(
563                     mapOf(
564                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to emptyList(),
565                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to
566                             listOf(
567                                 KeyguardQuickAffordancePickerRepresentation(
568                                     id = quickAccessWallet.key,
569                                     name = quickAccessWallet.pickerName(),
570                                     iconResourceId = quickAccessWallet.pickerIconResourceId,
571                                 ),
572                             ),
573                     )
574                 )
575 
576             underTest.unselect(
577                 KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
578                 quickAccessWallet.key
579             )
580 
581             assertThat(startConfig())
582                 .isEqualTo(
583                     KeyguardQuickAffordanceModel.Hidden,
584                 )
585             assertThat(endConfig())
586                 .isEqualTo(
587                     KeyguardQuickAffordanceModel.Hidden,
588                 )
589             assertThat(underTest.getSelections())
590                 .isEqualTo(
591                     mapOf<String, List<String>>(
592                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to emptyList(),
593                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to emptyList(),
594                     )
595                 )
596         }
597 
598     @Test
useLongPress_whenDocked_isFalsenull599     fun useLongPress_whenDocked_isFalse() =
600         testScope.runTest {
601             dockManager.setIsDocked(true)
602 
603             val useLongPress by collectLastValue(underTest.useLongPress())
604 
605             assertThat(useLongPress).isFalse()
606         }
607 
608     @Test
useLongPress_whenNotDocked_isTruenull609     fun useLongPress_whenNotDocked_isTrue() =
610         testScope.runTest {
611             dockManager.setIsDocked(false)
612 
613             val useLongPress by collectLastValue(underTest.useLongPress())
614 
615             assertThat(useLongPress).isTrue()
616         }
617 
618     @Test
useLongPress_whenNotDocked_isTrue_changedTo_whenDocked_isFalsenull619     fun useLongPress_whenNotDocked_isTrue_changedTo_whenDocked_isFalse() =
620         testScope.runTest {
621             dockManager.setIsDocked(false)
622             val firstUseLongPress by collectLastValue(underTest.useLongPress())
623             runCurrent()
624 
625             assertThat(firstUseLongPress).isTrue()
626 
627             dockManager.setIsDocked(true)
628             dockManager.setDockEvent(DockManager.STATE_DOCKED)
629             val secondUseLongPress by collectLastValue(underTest.useLongPress())
630             runCurrent()
631 
632             assertThat(secondUseLongPress).isFalse()
633         }
634 
635     @Test
unselect_allnull636     fun unselect_all() =
637         testScope.runTest {
638             homeControls.setState(
639                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
640             )
641             quickAccessWallet.setState(
642                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
643             )
644             qrCodeScanner.setState(
645                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON)
646             )
647 
648             underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key)
649             underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, quickAccessWallet.key)
650             underTest.unselect(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, null)
651 
652             assertThat(underTest.getSelections())
653                 .isEqualTo(
654                     mapOf(
655                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to emptyList(),
656                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to
657                             listOf(
658                                 KeyguardQuickAffordancePickerRepresentation(
659                                     id = quickAccessWallet.key,
660                                     name = quickAccessWallet.pickerName(),
661                                     iconResourceId = quickAccessWallet.pickerIconResourceId,
662                                 ),
663                             ),
664                     )
665                 )
666 
667             underTest.unselect(
668                 KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
669                 null,
670             )
671 
672             assertThat(underTest.getSelections())
673                 .isEqualTo(
674                     mapOf<String, List<String>>(
675                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to emptyList(),
676                         KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to emptyList(),
677                     )
678                 )
679         }
680 
681     companion object {
682         private const val CONTENT_DESCRIPTION_RESOURCE_ID = 1337
683         private val ICON: Icon =
684             Icon.Resource(
685                 res = CONTENT_DESCRIPTION_RESOURCE_ID,
686                 contentDescription =
687                     ContentDescription.Resource(
688                         res = CONTENT_DESCRIPTION_RESOURCE_ID,
689                     ),
690             )
691     }
692 }
693