1 /*
<lambda>null2  * Copyright (C) 2024 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 package com.android.systemui.keyguard.data.quickaffordance
18 
19 import android.app.Activity
20 import androidx.test.filters.SmallTest
21 import com.android.systemui.SysuiTestCase
22 import com.android.systemui.controls.ControlsServiceInfo
23 import com.android.systemui.controls.controller.ControlsController
24 import com.android.systemui.controls.dagger.ControlsComponent
25 import com.android.systemui.controls.management.ControlsListingController
26 import com.android.systemui.controls.ui.ControlsUiController
27 import com.android.systemui.res.R
28 import com.android.systemui.util.mockito.mock
29 import com.android.systemui.util.mockito.whenever
30 import com.google.common.truth.Truth.assertThat
31 import java.util.Optional
32 import kotlinx.coroutines.flow.MutableStateFlow
33 import kotlinx.coroutines.flow.launchIn
34 import kotlinx.coroutines.flow.onEach
35 import kotlinx.coroutines.test.runBlockingTest
36 import org.junit.Before
37 import org.junit.Test
38 import org.junit.runner.RunWith
39 import org.mockito.ArgumentCaptor
40 import org.mockito.Captor
41 import org.mockito.Mock
42 import org.mockito.Mockito.verify
43 import org.mockito.MockitoAnnotations
44 import platform.test.runner.parameterized.Parameter
45 import platform.test.runner.parameterized.ParameterizedAndroidJunit4
46 import platform.test.runner.parameterized.Parameters
47 
48 @SmallTest
49 @RunWith(ParameterizedAndroidJunit4::class)
50 class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTestCase() {
51 
52     companion object {
53         @Parameters(
54             name =
55                 "feature enabled = {0}, has favorites = {1}, has panels = {2}, " +
56                     "has service infos = {3}, can show while locked = {4}, " +
57                     "visibility is AVAILABLE {5} - expected visible = {6}"
58         )
59         @JvmStatic
60         fun data() =
61             (0 until 64)
62                 .map { combination ->
63                     arrayOf(
64                         /* isFeatureEnabled= */ combination and 0b100000 != 0,
65                         /* hasFavorites = */ combination and 0b010000 != 0,
66                         /* hasPanels = */ combination and 0b001000 != 0,
67                         /* hasServiceInfos= */ combination and 0b000100 != 0,
68                         /* canShowWhileLocked= */ combination and 0b000010 != 0,
69                         /* visibilityAvailable= */ combination and 0b000001 != 0,
70                         /* isVisible= */ combination in setOf(0b111111, 0b110111, 0b101111),
71                     )
72                 }
73                 .toList()
74     }
75 
76     @Mock private lateinit var component: ControlsComponent
77     @Mock private lateinit var controlsController: ControlsController
78     @Mock private lateinit var controlsListingController: ControlsListingController
79     @Mock private lateinit var controlsUiController: ControlsUiController
80     @Mock private lateinit var controlsServiceInfo: ControlsServiceInfo
81     @Captor
82     private lateinit var callbackCaptor:
83         ArgumentCaptor<ControlsListingController.ControlsListingCallback>
84 
85     private lateinit var underTest: HomeControlsKeyguardQuickAffordanceConfig
86 
87     @JvmField @Parameter(0) var isFeatureEnabled: Boolean = false
88     @JvmField @Parameter(1) var hasFavorites: Boolean = false
89     @JvmField @Parameter(2) var hasPanels: Boolean = false
90     @JvmField @Parameter(3) var hasServiceInfos: Boolean = false
91     @JvmField @Parameter(4) var canShowWhileLocked: Boolean = false
92     @JvmField @Parameter(5) var isVisibilityAvailable: Boolean = false
93     @JvmField @Parameter(6) var isVisibleExpected: Boolean = false
94 
95     @Before
96     fun setUp() {
97         MockitoAnnotations.initMocks(this)
98         whenever(component.getTileImageId()).thenReturn(R.drawable.controls_icon)
99         whenever(component.getTileTitleId()).thenReturn(R.string.quick_controls_title)
100         whenever(component.getControlsController()).thenReturn(Optional.of(controlsController))
101         whenever(component.getControlsListingController())
102             .thenReturn(Optional.of(controlsListingController))
103         whenever(controlsUiController.resolveActivity()).thenReturn(FakeActivity::class.java)
104         whenever(component.getControlsUiController()).thenReturn(Optional.of(controlsUiController))
105         if (hasPanels) {
106             whenever(controlsServiceInfo.panelActivity).thenReturn(mock())
107         }
108         whenever(controlsListingController.getCurrentServices())
109             .thenReturn(
110                 if (hasServiceInfos) {
111                     listOf(controlsServiceInfo, mock())
112                 } else {
113                     emptyList()
114                 }
115             )
116         whenever(component.canShowWhileLockedSetting)
117             .thenReturn(MutableStateFlow(canShowWhileLocked))
118         whenever(component.getVisibility())
119             .thenReturn(
120                 if (isVisibilityAvailable) {
121                     ControlsComponent.Visibility.AVAILABLE
122                 } else {
123                     ControlsComponent.Visibility.UNAVAILABLE
124                 }
125             )
126 
127         underTest =
128             HomeControlsKeyguardQuickAffordanceConfig(
129                 context = context,
130                 component = component,
131             )
132     }
133 
134     @Test
135     fun state() = runBlockingTest {
136         whenever(component.isEnabled()).thenReturn(isFeatureEnabled)
137         whenever(controlsController.getFavorites())
138             .thenReturn(
139                 if (hasFavorites) {
140                     listOf(mock())
141                 } else {
142                     emptyList()
143                 }
144             )
145         val values = mutableListOf<KeyguardQuickAffordanceConfig.LockScreenState>()
146         val job = underTest.lockScreenState.onEach(values::add).launchIn(this)
147 
148         if (canShowWhileLocked) {
149             val serviceInfoMock: ControlsServiceInfo = mock {
150                 if (hasPanels) {
151                     whenever(panelActivity).thenReturn(mock())
152                 }
153             }
154             verify(controlsListingController).addCallback(callbackCaptor.capture())
155             callbackCaptor.value.onServicesUpdated(
156                 if (hasServiceInfos) {
157                     listOf(serviceInfoMock)
158                 } else {
159                     emptyList()
160                 }
161             )
162         }
163 
164         assertThat(values.last())
165             .isInstanceOf(
166                 if (isVisibleExpected) {
167                     KeyguardQuickAffordanceConfig.LockScreenState.Visible::class.java
168                 } else {
169                     KeyguardQuickAffordanceConfig.LockScreenState.Hidden::class.java
170                 }
171             )
172         assertThat(underTest.getPickerScreenState())
173             .isInstanceOf(
174                 when {
175                     !isFeatureEnabled ->
176                         KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice::class
177                             .java
178                     hasServiceInfos && (hasFavorites || hasPanels) ->
179                         KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java
180                     else -> KeyguardQuickAffordanceConfig.PickerScreenState.Disabled::class.java
181                 }
182             )
183         job.cancel()
184     }
185 
186     private class FakeActivity : Activity()
187 }
188