diff options
9 files changed, 388 insertions, 119 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepository.kt new file mode 100644 index 000000000000..3d10ab906f2f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepository.kt @@ -0,0 +1,29 @@ +/* + * 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.controls + +import kotlinx.coroutines.flow.StateFlow + +/** Repository for Device controls related settings. */ +interface ControlsSettingsRepository { + /** Whether device controls activity can be shown above lockscreen for this user. */ + val canShowControlsInLockscreen: StateFlow<Boolean> + + /** Whether trivial controls can be actioned from the lockscreen for this user. */ + val allowActionOnTrivialControlsInLockscreen: StateFlow<Boolean> +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepositoryImpl.kt new file mode 100644 index 000000000000..9dc422a09674 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/ControlsSettingsRepositoryImpl.kt @@ -0,0 +1,90 @@ +/* + * 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.controls + +import android.provider.Settings +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.qs.SettingObserver +import com.android.systemui.user.data.repository.UserRepository +import com.android.systemui.util.settings.SecureSettings +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.stateIn + +/** + * This implementation uses an `@Application` [CoroutineScope] to provide hot flows for the values + * of the tracked settings. + */ +@SysUISingleton +class ControlsSettingsRepositoryImpl +@Inject +constructor( + @Application private val scope: CoroutineScope, + @Background private val backgroundDispatcher: CoroutineDispatcher, + private val userRepository: UserRepository, + private val secureSettings: SecureSettings +) : ControlsSettingsRepository { + + override val canShowControlsInLockscreen = + makeFlowForSetting(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS) + + override val allowActionOnTrivialControlsInLockscreen = + makeFlowForSetting(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS) + + @OptIn(ExperimentalCoroutinesApi::class) + private fun makeFlowForSetting(setting: String): StateFlow<Boolean> { + return userRepository.selectedUserInfo + .distinctUntilChanged() + .flatMapLatest { userInfo -> + conflatedCallbackFlow { + val observer = + object : SettingObserver(secureSettings, null, setting, userInfo.id) { + override fun handleValueChanged( + value: Int, + observedChange: Boolean + ) { + trySend(value == 1) + } + } + observer.isListening = true + trySend(observer.value == 1) + awaitClose { observer.isListening = false } + } + .flowOn(backgroundDispatcher) + .distinctUntilChanged() + } + .stateIn( + scope, + started = SharingStarted.Eagerly, + // When the observer starts listening, the flow will emit the current value + // so the initialValue here is irrelevant. + initialValue = false, + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt index 9e4a364562e5..77d0496e43db 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt @@ -16,13 +16,10 @@ package com.android.systemui.controls.dagger -import android.content.ContentResolver import android.content.Context -import android.database.ContentObserver -import android.os.UserHandle -import android.provider.Settings import com.android.internal.widget.LockPatternUtils import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT +import com.android.systemui.controls.ControlsSettingsRepository import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.controller.ControlsTileResourceConfiguration import com.android.systemui.controls.controller.ControlsTileResourceConfigurationImpl @@ -31,12 +28,10 @@ import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.dagger.SysUISingleton import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.KeyguardStateController -import com.android.systemui.util.settings.SecureSettings import dagger.Lazy +import kotlinx.coroutines.flow.StateFlow import java.util.Optional import javax.inject.Inject -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow /** * Pseudo-component to inject into classes outside `com.android.systemui.controls`. @@ -46,47 +41,26 @@ import kotlinx.coroutines.flow.asStateFlow */ @SysUISingleton class ControlsComponent @Inject constructor( - @ControlsFeatureEnabled private val featureEnabled: Boolean, - private val context: Context, - private val lazyControlsController: Lazy<ControlsController>, - private val lazyControlsUiController: Lazy<ControlsUiController>, - private val lazyControlsListingController: Lazy<ControlsListingController>, - private val lockPatternUtils: LockPatternUtils, - private val keyguardStateController: KeyguardStateController, - private val userTracker: UserTracker, - private val secureSettings: SecureSettings, - private val optionalControlsTileResourceConfiguration: - Optional<ControlsTileResourceConfiguration> + @ControlsFeatureEnabled private val featureEnabled: Boolean, + private val context: Context, + private val lazyControlsController: Lazy<ControlsController>, + private val lazyControlsUiController: Lazy<ControlsUiController>, + private val lazyControlsListingController: Lazy<ControlsListingController>, + private val lockPatternUtils: LockPatternUtils, + private val keyguardStateController: KeyguardStateController, + private val userTracker: UserTracker, + controlsSettingsRepository: ControlsSettingsRepository, + optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration> ) { - private val contentResolver: ContentResolver - get() = context.contentResolver - private val _canShowWhileLockedSetting = MutableStateFlow(false) - val canShowWhileLockedSetting = _canShowWhileLockedSetting.asStateFlow() + val canShowWhileLockedSetting: StateFlow<Boolean> = + controlsSettingsRepository.canShowControlsInLockscreen private val controlsTileResourceConfiguration: ControlsTileResourceConfiguration = optionalControlsTileResourceConfiguration.orElse( ControlsTileResourceConfigurationImpl() ) - val showWhileLockedObserver = object : ContentObserver(null) { - override fun onChange(selfChange: Boolean) { - updateShowWhileLocked() - } - } - - init { - if (featureEnabled) { - secureSettings.registerContentObserverForUser( - Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), - false, /* notifyForDescendants */ - showWhileLockedObserver, - UserHandle.USER_ALL - ) - updateShowWhileLocked() - } - } - fun getControlsController(): Optional<ControlsController> { return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty() } @@ -127,11 +101,6 @@ class ControlsComponent @Inject constructor( return Visibility.AVAILABLE } - private fun updateShowWhileLocked() { - _canShowWhileLockedSetting.value = secureSettings.getIntForUser( - Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 0, UserHandle.USER_CURRENT) != 0 - } - enum class Visibility { AVAILABLE, AVAILABLE_AFTER_UNLOCK, UNAVAILABLE } diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt index 6f58abdeed56..9ae605e30a83 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt @@ -20,6 +20,8 @@ import android.app.Activity import android.content.pm.PackageManager import com.android.systemui.controls.ControlsMetricsLogger import com.android.systemui.controls.ControlsMetricsLoggerImpl +import com.android.systemui.controls.ControlsSettingsRepository +import com.android.systemui.controls.ControlsSettingsRepositoryImpl import com.android.systemui.controls.controller.ControlsBindingController import com.android.systemui.controls.controller.ControlsBindingControllerImpl import com.android.systemui.controls.controller.ControlsController @@ -83,6 +85,11 @@ abstract class ControlsModule { abstract fun provideUiController(controller: ControlsUiControllerImpl): ControlsUiController @Binds + abstract fun provideSettingsManager( + manager: ControlsSettingsRepositoryImpl + ): ControlsSettingsRepository + + @Binds abstract fun provideMetricsLogger(logger: ControlsMetricsLoggerImpl): ControlsMetricsLogger @Binds diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index b8a00133c728..8472ca0731d7 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -24,9 +24,6 @@ import android.app.PendingIntent import android.content.Context import android.content.pm.PackageManager import android.content.pm.ResolveInfo -import android.database.ContentObserver -import android.net.Uri -import android.os.Handler import android.os.UserHandle import android.os.VibrationEffect import android.provider.Settings.Secure @@ -40,6 +37,7 @@ import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.controls.ControlsMetricsLogger +import com.android.systemui.controls.ControlsSettingsRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter @@ -68,17 +66,17 @@ class ControlActionCoordinatorImpl @Inject constructor( private val vibrator: VibratorHelper, private val secureSettings: SecureSettings, private val userContextProvider: UserContextProvider, - @Main mainHandler: Handler + private val controlsSettingsRepository: ControlsSettingsRepository, ) : ControlActionCoordinator { private var dialog: Dialog? = null private var pendingAction: Action? = null private var actionsInProgress = mutableSetOf<String>() private val isLocked: Boolean get() = !keyguardStateController.isUnlocked() - private var mAllowTrivialControls: Boolean = secureSettings.getIntForUser( - Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS, 0, UserHandle.USER_CURRENT) != 0 - private var mShowDeviceControlsInLockscreen: Boolean = secureSettings.getIntForUser( - Secure.LOCKSCREEN_SHOW_CONTROLS, 0, UserHandle.USER_CURRENT) != 0 + private val allowTrivialControls: Boolean + get() = controlsSettingsRepository.allowActionOnTrivialControlsInLockscreen.value + private val showDeviceControlsInLockscreen: Boolean + get() = controlsSettingsRepository.canShowControlsInLockscreen.value override lateinit var activityContext: Context companion object { @@ -86,38 +84,6 @@ class ControlActionCoordinatorImpl @Inject constructor( private const val MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG = 2 } - init { - val lockScreenShowControlsUri = - secureSettings.getUriFor(Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS) - val showControlsUri = - secureSettings.getUriFor(Secure.LOCKSCREEN_SHOW_CONTROLS) - val controlsContentObserver = object : ContentObserver(mainHandler) { - override fun onChange(selfChange: Boolean, uri: Uri?) { - super.onChange(selfChange, uri) - when (uri) { - lockScreenShowControlsUri -> { - mAllowTrivialControls = secureSettings.getIntForUser( - Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS, - 0, UserHandle.USER_CURRENT) != 0 - } - showControlsUri -> { - mShowDeviceControlsInLockscreen = secureSettings - .getIntForUser(Secure.LOCKSCREEN_SHOW_CONTROLS, - 0, UserHandle.USER_CURRENT) != 0 - } - } - } - } - secureSettings.registerContentObserverForUser( - lockScreenShowControlsUri, - false /* notifyForDescendants */, controlsContentObserver, UserHandle.USER_ALL - ) - secureSettings.registerContentObserverForUser( - showControlsUri, - false /* notifyForDescendants */, controlsContentObserver, UserHandle.USER_ALL - ) - } - override fun closeDialogs() { dialog?.dismiss() dialog = null @@ -224,7 +190,7 @@ class ControlActionCoordinatorImpl @Inject constructor( @AnyThread @VisibleForTesting fun bouncerOrRun(action: Action) { - val authRequired = action.authIsRequired || !mAllowTrivialControls + val authRequired = action.authIsRequired || !allowTrivialControls if (keyguardStateController.isShowing() && authRequired) { if (isLocked) { @@ -282,7 +248,7 @@ class ControlActionCoordinatorImpl @Inject constructor( PREFS_CONTROLS_FILE, Context.MODE_PRIVATE) val attempts = prefs.getInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, 0) if (attempts >= MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG || - (mShowDeviceControlsInLockscreen && mAllowTrivialControls)) { + (showDeviceControlsInLockscreen && allowTrivialControls)) { return } val builder = AlertDialog @@ -304,7 +270,7 @@ class ControlActionCoordinatorImpl @Inject constructor( true } - if (mShowDeviceControlsInLockscreen) { + if (showDeviceControlsInLockscreen) { dialog = builder .setTitle(R.string.controls_settings_trivial_controls_dialog_title) .setMessage(R.string.controls_settings_trivial_controls_dialog_message) diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ControlsSettingsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ControlsSettingsRepositoryImplTest.kt new file mode 100644 index 000000000000..4b88b44c3f03 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ControlsSettingsRepositoryImplTest.kt @@ -0,0 +1,187 @@ +/* + * 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.controls + +import android.content.pm.UserInfo +import android.provider.Settings +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.util.settings.FakeSettings +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@SmallTest +@RunWith(JUnit4::class) +@OptIn(ExperimentalCoroutinesApi::class) +class ControlsSettingsRepositoryImplTest : SysuiTestCase() { + + companion object { + private const val LOCKSCREEN_SHOW = Settings.Secure.LOCKSCREEN_SHOW_CONTROLS + private const val LOCKSCREEN_ACTION = Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS + + private fun createUser(id: Int): UserInfo { + return UserInfo(id, "user_$id", 0) + } + + private val ALL_USERS = (0..1).map { it to createUser(it) }.toMap() + } + + private lateinit var underTest: ControlsSettingsRepository + + private lateinit var testScope: TestScope + private lateinit var secureSettings: FakeSettings + private lateinit var userRepository: FakeUserRepository + + @Before + fun setUp() { + secureSettings = FakeSettings() + userRepository = FakeUserRepository() + userRepository.setUserInfos(ALL_USERS.values.toList()) + + val coroutineDispatcher = UnconfinedTestDispatcher() + testScope = TestScope(coroutineDispatcher) + + underTest = + ControlsSettingsRepositoryImpl( + scope = testScope.backgroundScope, + backgroundDispatcher = coroutineDispatcher, + userRepository = userRepository, + secureSettings = secureSettings, + ) + } + + @Test + fun showInLockScreen() = + testScope.runTest { + setUser(0) + val values = mutableListOf<Boolean>() + val job = + launch(UnconfinedTestDispatcher()) { + underTest.canShowControlsInLockscreen.toList(values) + } + assertThat(values.last()).isFalse() + + secureSettings.putBool(LOCKSCREEN_SHOW, true) + assertThat(values.last()).isTrue() + + secureSettings.putBool(LOCKSCREEN_SHOW, false) + assertThat(values.last()).isFalse() + + secureSettings.putBoolForUser(LOCKSCREEN_SHOW, true, 1) + assertThat(values.last()).isFalse() + + setUser(1) + assertThat(values.last()).isTrue() + + job.cancel() + } + + @Test + fun showInLockScreen_changesInOtherUsersAreNotQueued() = + testScope.runTest { + setUser(0) + + val values = mutableListOf<Boolean>() + val job = + launch(UnconfinedTestDispatcher()) { + underTest.canShowControlsInLockscreen.toList(values) + } + + secureSettings.putBoolForUser(LOCKSCREEN_SHOW, true, 1) + secureSettings.putBoolForUser(LOCKSCREEN_SHOW, false, 1) + + setUser(1) + assertThat(values.last()).isFalse() + assertThat(values).containsNoneIn(listOf(true)) + + job.cancel() + } + + @Test + fun actionInLockScreen() = + testScope.runTest { + setUser(0) + val values = mutableListOf<Boolean>() + val job = + launch(UnconfinedTestDispatcher()) { + underTest.allowActionOnTrivialControlsInLockscreen.toList(values) + } + assertThat(values.last()).isFalse() + + secureSettings.putBool(LOCKSCREEN_ACTION, true) + assertThat(values.last()).isTrue() + + secureSettings.putBool(LOCKSCREEN_ACTION, false) + assertThat(values.last()).isFalse() + + secureSettings.putBoolForUser(LOCKSCREEN_ACTION, true, 1) + assertThat(values.last()).isFalse() + + setUser(1) + assertThat(values.last()).isTrue() + + job.cancel() + } + + @Test + fun actionInLockScreen_changesInOtherUsersAreNotQueued() = + testScope.runTest { + setUser(0) + + val values = mutableListOf<Boolean>() + val job = + launch(UnconfinedTestDispatcher()) { + underTest.allowActionOnTrivialControlsInLockscreen.toList(values) + } + + secureSettings.putBoolForUser(LOCKSCREEN_ACTION, true, 1) + secureSettings.putBoolForUser(LOCKSCREEN_ACTION, false, 1) + + setUser(1) + assertThat(values.last()).isFalse() + assertThat(values).containsNoneIn(listOf(true)) + + job.cancel() + } + + @Test + fun valueIsUpdatedWhenNotSubscribed() = + testScope.runTest { + setUser(0) + assertThat(underTest.canShowControlsInLockscreen.value).isFalse() + + secureSettings.putBool(LOCKSCREEN_SHOW, true) + + assertThat(underTest.canShowControlsInLockscreen.value).isTrue() + } + + private suspend fun setUser(id: Int) { + secureSettings.userId = id + userRepository.setSelectedUserInfo(ALL_USERS[id]!!) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/FakeControlsSettingsRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/FakeControlsSettingsRepository.kt new file mode 100644 index 000000000000..8a1bed20e700 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/FakeControlsSettingsRepository.kt @@ -0,0 +1,37 @@ +/* + * 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.controls + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class FakeControlsSettingsRepository : ControlsSettingsRepository { + private val _canShowControlsInLockscreen = MutableStateFlow(false) + override val canShowControlsInLockscreen = _canShowControlsInLockscreen.asStateFlow() + private val _allowActionOnTrivialControlsInLockscreen = MutableStateFlow(false) + override val allowActionOnTrivialControlsInLockscreen = + _allowActionOnTrivialControlsInLockscreen.asStateFlow() + + fun setCanShowControlsInLockscreen(value: Boolean) { + _canShowControlsInLockscreen.value = value + } + + fun setAllowActionOnTrivialControlsInLockscreen(value: Boolean) { + _allowActionOnTrivialControlsInLockscreen.value = value + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt index 4ed5649c9c50..1d00d6b05568 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt @@ -18,30 +18,24 @@ package com.android.systemui.controls.ui import android.content.Context import android.content.SharedPreferences -import android.database.ContentObserver -import android.net.Uri -import android.os.Handler -import android.os.UserHandle -import android.provider.Settings import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.controls.ControlsMetricsLogger +import com.android.systemui.controls.FakeControlsSettingsRepository import com.android.systemui.plugins.ActivityStarter import com.android.systemui.settings.UserContextProvider import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.mockito.any import com.android.systemui.util.settings.SecureSettings import com.android.wm.shell.TaskViewFactory import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Answers -import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.`when` @@ -79,8 +73,6 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { @Mock private lateinit var secureSettings: SecureSettings @Mock - private lateinit var mainHandler: Handler - @Mock private lateinit var userContextProvider: UserContextProvider companion object { @@ -91,17 +83,15 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { private lateinit var coordinator: ControlActionCoordinatorImpl private lateinit var action: ControlActionCoordinatorImpl.Action + private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository @Before fun setUp() { MockitoAnnotations.initMocks(this) - `when`(secureSettings.getUriFor(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS)) - .thenReturn(Settings.Secure - .getUriFor(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS)) - `when`(secureSettings.getIntForUser(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS, - 0, UserHandle.USER_CURRENT)) - .thenReturn(1) + controlsSettingsRepository = FakeControlsSettingsRepository() + controlsSettingsRepository.setAllowActionOnTrivialControlsInLockscreen(true) + controlsSettingsRepository.setCanShowControlsInLockscreen(true) coordinator = spy(ControlActionCoordinatorImpl( mContext, @@ -115,7 +105,7 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { vibratorHelper, secureSettings, userContextProvider, - mainHandler + controlsSettingsRepository )) val userContext = mock(Context::class.java) @@ -128,9 +118,6 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { `when`(pref.getInt(DeviceControlsControllerImpl.PREFS_SETTINGS_DIALOG_ATTEMPTS, 0)) .thenReturn(2) - verify(secureSettings).registerContentObserverForUser(any(Uri::class.java), - anyBoolean(), any(ContentObserver::class.java), anyInt()) - `when`(cvh.cws.ci.controlId).thenReturn(ID) `when`(cvh.cws.control?.isAuthRequired()).thenReturn(true) action = spy(coordinator.Action(ID, {}, false, true)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt index 77f451f61c3c..48fc46b7e730 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt @@ -17,19 +17,18 @@ package com.android.systemui.controls.dagger import android.testing.AndroidTestingRunner -import android.provider.Settings import androidx.test.filters.SmallTest import com.android.internal.widget.LockPatternUtils import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT import com.android.systemui.SysuiTestCase +import com.android.systemui.controls.FakeControlsSettingsRepository import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.controller.ControlsTileResourceConfiguration import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.KeyguardStateController -import com.android.systemui.util.settings.SecureSettings import dagger.Lazy import java.util.Optional import org.junit.Assert.assertEquals @@ -63,13 +62,13 @@ class ControlsComponentTest : SysuiTestCase() { @Mock private lateinit var lockPatternUtils: LockPatternUtils @Mock - private lateinit var secureSettings: SecureSettings - @Mock private lateinit var optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration> @Mock private lateinit var controlsTileResourceConfiguration: ControlsTileResourceConfiguration + private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository + companion object { fun <T> eq(value: T): T = Mockito.eq(value) ?: value } @@ -78,6 +77,8 @@ class ControlsComponentTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) + controlsSettingsRepository = FakeControlsSettingsRepository() + `when`(userTracker.userHandle.identifier).thenReturn(0) `when`(optionalControlsTileResourceConfiguration.orElse(any())) .thenReturn(controlsTileResourceConfiguration) @@ -125,8 +126,7 @@ class ControlsComponentTest : SysuiTestCase() { `when`(lockPatternUtils.getStrongAuthForUser(anyInt())) .thenReturn(STRONG_AUTH_NOT_REQUIRED) `when`(keyguardStateController.isUnlocked()).thenReturn(false) - `when`(secureSettings.getInt(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), anyInt())) - .thenReturn(0) + controlsSettingsRepository.setCanShowControlsInLockscreen(false) val component = setupComponent(true) assertEquals(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK, component.getVisibility()) @@ -137,9 +137,7 @@ class ControlsComponentTest : SysuiTestCase() { `when`(lockPatternUtils.getStrongAuthForUser(anyInt())) .thenReturn(STRONG_AUTH_NOT_REQUIRED) `when`(keyguardStateController.isUnlocked()).thenReturn(false) - `when`(secureSettings.getIntForUser(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), - anyInt(), anyInt())) - .thenReturn(1) + controlsSettingsRepository.setCanShowControlsInLockscreen(true) val component = setupComponent(true) assertEquals(ControlsComponent.Visibility.AVAILABLE, component.getVisibility()) @@ -147,8 +145,7 @@ class ControlsComponentTest : SysuiTestCase() { @Test fun testFeatureEnabledAndCanShowWhileUnlockedVisibility() { - `when`(secureSettings.getInt(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), anyInt())) - .thenReturn(0) + controlsSettingsRepository.setCanShowControlsInLockscreen(false) `when`(lockPatternUtils.getStrongAuthForUser(anyInt())) .thenReturn(STRONG_AUTH_NOT_REQUIRED) `when`(keyguardStateController.isUnlocked()).thenReturn(true) @@ -187,7 +184,7 @@ class ControlsComponentTest : SysuiTestCase() { lockPatternUtils, keyguardStateController, userTracker, - secureSettings, + controlsSettingsRepository, optionalControlsTileResourceConfiguration ) } |