1 /* 2 * Copyright (C) 2021 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.statusbar.policy 18 19 import android.content.ComponentName 20 import android.content.Context 21 import android.content.pm.ServiceInfo 22 import android.provider.Settings 23 24 import androidx.test.ext.junit.runners.AndroidJUnit4 25 import androidx.test.filters.SmallTest 26 27 import com.android.systemui.res.R 28 import com.android.systemui.SysuiTestCase 29 import com.android.systemui.controls.ControlsServiceInfo 30 import com.android.systemui.controls.dagger.ControlsComponent 31 import com.android.systemui.controls.controller.ControlsController 32 import com.android.systemui.controls.controller.SeedResponse 33 import com.android.systemui.controls.controller.StructureInfo 34 import com.android.systemui.controls.management.ControlsListingController 35 import com.android.systemui.controls.management.ControlsListingController.ControlsListingCallback 36 import com.android.systemui.settings.UserContextProvider 37 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.PREFS_CONTROLS_FILE 38 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.PREFS_CONTROLS_SEEDING_COMPLETED 39 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.QS_DEFAULT_POSITION 40 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.QS_PRIORITY_POSITION 41 import com.android.systemui.util.mockito.mock 42 import com.android.systemui.util.settings.SecureSettings 43 44 import java.util.Optional 45 import java.util.function.Consumer 46 47 import org.junit.Before 48 import org.junit.Test 49 import org.junit.runner.RunWith 50 51 import org.mockito.ArgumentCaptor 52 import org.mockito.Captor 53 import org.mockito.Mock 54 import org.mockito.Mockito 55 import org.mockito.MockitoAnnotations 56 import org.mockito.Mockito.never 57 import org.mockito.Mockito.verify 58 import org.mockito.Mockito.`when` 59 import org.mockito.ArgumentMatchers.anyInt 60 import org.mockito.ArgumentMatchers.anyObject 61 62 @SmallTest 63 @RunWith(AndroidJUnit4::class) 64 class DeviceControlsControllerImplTest : SysuiTestCase() { 65 66 @Mock 67 private lateinit var controlsComponent: ControlsComponent 68 @Mock 69 private lateinit var controlsController: ControlsController 70 @Mock 71 private lateinit var controlsListingController: ControlsListingController 72 @Mock 73 private lateinit var callback: DeviceControlsController.Callback 74 @Captor 75 private lateinit var listingCallbackCaptor: ArgumentCaptor<ControlsListingCallback> 76 @Mock 77 private lateinit var structureInfo: StructureInfo 78 @Mock 79 private lateinit var serviceInfo: ServiceInfo 80 @Mock 81 private lateinit var userContextProvider: UserContextProvider 82 @Mock 83 private lateinit var secureSettings: SecureSettings 84 @Captor 85 private lateinit var seedCallback: ArgumentCaptor<Consumer<SeedResponse>> 86 87 private lateinit var controlsServiceInfo: ControlsServiceInfo 88 private lateinit var controller: DeviceControlsControllerImpl 89 90 companion object { capturenull91 fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() 92 fun <T> eq(value: T): T = Mockito.eq(value) ?: value 93 private val TEST_PKG = "test.pkg" 94 private val TEST_COMPONENT = ComponentName(TEST_PKG, "test.class") 95 } 96 97 @Before 98 fun setUp() { 99 MockitoAnnotations.initMocks(this) 100 101 `when`(controlsComponent.getControlsController()) 102 .thenReturn(Optional.of(controlsController)) 103 `when`(controlsComponent.getControlsListingController()) 104 .thenReturn(Optional.of(controlsListingController)) 105 106 `when`(controlsComponent.isEnabled()).thenReturn(true) 107 108 controller = DeviceControlsControllerImpl( 109 mContext, 110 controlsComponent, 111 userContextProvider, 112 secureSettings 113 ) 114 115 `when`(secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1)).thenReturn(1) 116 117 `when`(serviceInfo.componentName).thenReturn(TEST_COMPONENT) 118 controlsServiceInfo = ControlsServiceInfo(mContext, serviceInfo) 119 120 `when`(userContextProvider.userContext).thenReturn(mContext) 121 mContext.getSharedPreferences(PREFS_CONTROLS_FILE, Context.MODE_PRIVATE).edit() 122 .putStringSet(PREFS_CONTROLS_SEEDING_COMPLETED, emptySet()) 123 .apply() 124 } 125 126 @Test testNoCallbackWhenNoServicesAvailablenull127 fun testNoCallbackWhenNoServicesAvailable() { 128 `when`(controlsController.getFavorites()).thenReturn(emptyList()) 129 controller.setCallback(callback) 130 131 verify(controlsListingController).addCallback(capture(listingCallbackCaptor)) 132 listingCallbackCaptor.value.onServicesUpdated(emptyList()) 133 verify(callback, never()).onControlsUpdate(anyInt()) 134 } 135 136 @Test testCallbackWithNullValueWhenSettingIsDisablednull137 fun testCallbackWithNullValueWhenSettingIsDisabled() { 138 `when`(secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1)).thenReturn(0) 139 controller.setCallback(callback) 140 141 verify(controlsListingController, never()).addCallback(anyObject()) 142 verify(callback).onControlsUpdate(null) 143 } 144 145 @Test testSetPriorityPositionIsSetWhenFavoritesAreAvailablenull146 fun testSetPriorityPositionIsSetWhenFavoritesAreAvailable() { 147 `when`(controlsController.getFavorites()).thenReturn(listOf(structureInfo)) 148 controller.setCallback(callback) 149 150 verify(controlsListingController).addCallback(capture(listingCallbackCaptor)) 151 listingCallbackCaptor.value.onServicesUpdated(listOf(controlsServiceInfo)) 152 verify(callback).onControlsUpdate(QS_PRIORITY_POSITION) 153 } 154 155 @Test testSetDefaultPositionIsSetWhenNoFavoritesAreAvailablenull156 fun testSetDefaultPositionIsSetWhenNoFavoritesAreAvailable() { 157 `when`(controlsController.getFavorites()).thenReturn(emptyList()) 158 controller.setCallback(callback) 159 160 mContext.getOrCreateTestableResources().addOverride( 161 R.array.config_controlsPreferredPackages, 162 arrayOf(TEST_PKG)) 163 164 verify(controlsListingController).addCallback(capture(listingCallbackCaptor)) 165 listingCallbackCaptor.value.onServicesUpdated(listOf(controlsServiceInfo)) 166 167 verify(controlsController).seedFavoritesForComponents( 168 eq(listOf(TEST_COMPONENT)), 169 capture(seedCallback) 170 ) 171 seedCallback.value.accept(SeedResponse(TEST_PKG, true)) 172 verify(callback).onControlsUpdate(QS_DEFAULT_POSITION) 173 } 174 175 @Test testControlsDisabledRemoveFromAutoTrackernull176 fun testControlsDisabledRemoveFromAutoTracker() { 177 `when`(controlsComponent.isEnabled()).thenReturn(false) 178 val callback: DeviceControlsController.Callback = mock() 179 180 controller.setCallback(callback) 181 182 verify(callback).removeControlsAutoTracker() 183 verify(callback, never()).onControlsUpdate(anyInt()) 184 } 185 } 186