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