Merge "Add repository for controls related settings" into tm-qpr-dev
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 0000000..3d10ab9
--- /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 0000000..9dc422a
--- /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 9e4a364..77d0496e4 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.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 @@
  */
 @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 @@
         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 6f58abd..9ae605e 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.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 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 b8a0013..8472ca0 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.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.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 @@
     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 @@
         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 @@
     @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 @@
                 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 @@
                     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 0000000..4b88b44
--- /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 0000000..8a1bed2
--- /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 4ed5649c..1d00d6b 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 @@
 
 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 @@
     @Mock
     private lateinit var secureSettings: SecureSettings
     @Mock
-    private lateinit var mainHandler: Handler
-    @Mock
     private lateinit var userContextProvider: UserContextProvider
 
     companion object {
@@ -91,17 +83,15 @@
 
     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 @@
                 vibratorHelper,
                 secureSettings,
                 userContextProvider,
-                mainHandler
+                controlsSettingsRepository
         ))
 
         val userContext = mock(Context::class.java)
@@ -128,9 +118,6 @@
         `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 77f451f..48fc46b 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 @@
     @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 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        controlsSettingsRepository = FakeControlsSettingsRepository()
+
         `when`(userTracker.userHandle.identifier).thenReturn(0)
         `when`(optionalControlsTileResourceConfiguration.orElse(any()))
             .thenReturn(controlsTileResourceConfiguration)
@@ -125,8 +126,7 @@
         `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 @@
         `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 @@
 
     @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 @@
             lockPatternUtils,
             keyguardStateController,
             userTracker,
-            secureSettings,
+            controlsSettingsRepository,
             optionalControlsTileResourceConfiguration
         )
     }