From 0383dbd6063fd56ca635b1d5698a15cccb710762 Mon Sep 17 00:00:00 2001
From: nift4 <nift4@protonmail.com>
Date: Wed, 16 Mar 2022 19:14:47 +0100
Subject: [PATCH] Revert "Remove "Device Controls" from Settings"

This reverts commit 73702413f83353785ef109be1bd5c73befdcc148.

Change-Id: Idc55a0515983652fff1f68cd6503f46c607591cd
---
 core/java/android/provider/Settings.java      |  3 -
 .../controls/controller/ControlsController.kt |  5 ++
 .../controller/ControlsControllerImpl.kt      | 46 ++++++++++----
 .../controls/dagger/ControlsComponent.kt      |  4 +-
 .../management/ControlsRequestDialog.kt       |  5 +-
 .../controls/ui/ControlsUiController.kt       |  2 +
 .../controls/ui/ControlsUiControllerImpl.kt   |  3 +
 .../autoaddable/DeviceControlsAutoAddable.kt  |  2 +-
 .../statusbar/phone/AutoTileManager.java      |  5 +-
 .../policy/DeviceControlsController.kt        |  2 +-
 .../policy/DeviceControlsControllerImpl.kt    | 32 +++++-----
 .../controller/ControlsControllerImplTest.kt  | 60 ++++++++++++++++++-
 .../controls/dagger/ControlsComponentTest.kt  |  4 ++
 .../management/ControlsRequestDialogTest.kt   |  3 +-
 .../qs/tiles/DeviceControlsTileTest.kt        |  9 +++
 .../DeviceControlsControllerImplTest.kt       | 25 ++------
 16 files changed, 147 insertions(+), 63 deletions(-)

diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b82ddfa8b12e..c33cbcf08013 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11157,12 +11157,9 @@ public final class Settings {
          * 0 indicates disabled and 1 indicates enabled. A non existent value should be treated as
          * enabled.
          *
-         * @deprecated Controls are migrated to Quick Settings, rendering this unnecessary and will
-         *             be removed in a future release.
          * @hide
          */
         @Readable
-        @Deprecated
         public static final String CONTROLS_ENABLED = "controls_enabled";
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 2d37c292a6b8..d77a515d45a3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -41,6 +41,11 @@ import java.util.function.Consumer
  */
 interface ControlsController : UserAwareController {
 
+    /**
+     * Whether the controls system is available for the current user.
+     */
+    val available: Boolean
+
     // SERVICE COMMUNICATION
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 638da862018f..194e9d60a285 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -20,12 +20,14 @@ import android.app.PendingIntent
 import android.app.backup.BackupManager
 import android.content.BroadcastReceiver
 import android.content.ComponentName
+import android.content.ContentResolver
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
 import android.database.ContentObserver
 import android.net.Uri
 import android.os.UserHandle
+import android.provider.Settings
 import android.service.controls.Control
 import android.service.controls.actions.ControlAction
 import android.util.ArrayMap
@@ -71,10 +73,15 @@ class ControlsControllerImpl @Inject constructor (
 
     companion object {
         private const val TAG = "ControlsControllerImpl"
+        internal const val CONTROLS_AVAILABLE = Settings.Secure.CONTROLS_ENABLED
+        internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE)
         private const val USER_CHANGE_RETRY_DELAY = 500L // ms
         private const val DEFAULT_ENABLED = 1
         private const val PERMISSION_SELF = "com.android.systemui.permission.SELF"
         const val SUGGESTED_CONTROLS_PER_STRUCTURE = 6
+
+        private fun isAvailable(userId: Int, cr: ContentResolver) = Settings.Secure.getIntForUser(
+            cr, CONTROLS_AVAILABLE, DEFAULT_ENABLED, userId) != 0
     }
 
     private var userChanging: Boolean = true
@@ -87,6 +94,12 @@ class ControlsControllerImpl @Inject constructor (
     override val currentUserId
         get() = currentUser.identifier
 
+    private val contentResolver: ContentResolver
+        get() = context.contentResolver
+
+    override var available = isAvailable(currentUserId, contentResolver)
+        private set
+
     private val persistenceWrapper: ControlsFavoritePersistenceWrapper
     @VisibleForTesting
     internal var auxiliaryPersistenceWrapper: AuxiliaryPersistenceWrapper
@@ -117,7 +130,8 @@ class ControlsControllerImpl @Inject constructor (
                 BackupManager(userStructure.userContext)
         )
         auxiliaryPersistenceWrapper.changeFile(userStructure.auxiliaryFile)
-        resetFavorites()
+        available = isAvailable(newUser.identifier, contentResolver)
+        resetFavorites(available)
         bindingController.changeUser(newUser)
         listingController.changeUser(newUser)
         userChanging = false
@@ -141,7 +155,7 @@ class ControlsControllerImpl @Inject constructor (
                     Log.d(TAG, "Restore finished, storing auxiliary favorites")
                     auxiliaryPersistenceWrapper.initialize()
                     persistenceWrapper.storeFavorites(auxiliaryPersistenceWrapper.favorites)
-                    resetFavorites()
+                    resetFavorites(available)
                 }
             }
         }
@@ -160,7 +174,8 @@ class ControlsControllerImpl @Inject constructor (
             if (userChanging || userId != currentUserId) {
                 return
             }
-            resetFavorites()
+            available = isAvailable(currentUserId, contentResolver)
+            resetFavorites(available)
         }
     }
 
@@ -228,7 +243,7 @@ class ControlsControllerImpl @Inject constructor (
 
     init {
         dumpManager.registerDumpable(this)
-        resetFavorites()
+        resetFavorites(available)
         userChanging = false
         context.registerReceiver(
             restoreFinishedReceiver,
@@ -237,22 +252,26 @@ class ControlsControllerImpl @Inject constructor (
             null,
             Context.RECEIVER_NOT_EXPORTED
         )
+        contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL)
         listingController.addCallback(listingCallback)
     }
 
     fun destroy() {
         context.unregisterReceiver(restoreFinishedReceiver)
+        contentResolver.unregisterContentObserver(settingObserver)
         listingController.removeCallback(listingCallback)
     }
 
-    private fun resetFavorites() {
+    private fun resetFavorites(shouldLoad: Boolean) {
         Favorites.clear()
-        Favorites.load(persistenceWrapper.readFavorites())
-        // After loading favorites, add the package names of any apps with favorites to the list
-        // of authorized panels. That way, if the user has previously favorited controls for an app,
-        // that panel will be authorized.
-        authorizedPanelsRepository.addAuthorizedPanels(
-                Favorites.getAllStructures().map { it.componentName.packageName }.toSet())
+        if (shouldLoad) {
+            Favorites.load(persistenceWrapper.readFavorites())
+            // After loading favorites, add the package names of any apps with favorites to the list
+            // of authorized panels. That way, if the user has previously favorited controls for an app,
+            // that panel will be authorized.
+            authorizedPanelsRepository.addAuthorizedPanels(
+                    Favorites.getAllStructures().map { it.componentName.packageName }.toSet())
+        }
     }
 
     private fun confirmAvailability(): Boolean {
@@ -260,6 +279,10 @@ class ControlsControllerImpl @Inject constructor (
             Log.w(TAG, "Controls not available while user is changing")
             return false
         }
+        if (!available) {
+            Log.d(TAG, "Controls not available")
+            return false
+        }
         return true
     }
 
@@ -580,6 +603,7 @@ class ControlsControllerImpl @Inject constructor (
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
         pw.println("ControlsController state:")
+        pw.println("  Available: $available")
         pw.println("  Changing users: $userChanging")
         pw.println("  Current user: ${currentUser.identifier}")
         pw.println("  Favorites:")
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 88b9612e8efd..070dca56f844 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -43,7 +43,7 @@ class ControlsComponent
 @Inject
 constructor(
     @ControlsFeatureEnabled private val featureEnabled: Boolean,
-    lazyControlsController: Lazy<ControlsController>,
+    val lazyControlsController: Lazy<ControlsController>,
     lazyControlsUiController: Lazy<ControlsUiController>,
     lazyControlsListingController: Lazy<ControlsListingController>,
     private val lockPatternUtils: LockPatternUtils,
@@ -74,7 +74,7 @@ constructor(
         controlsListingController
 
     /** @return true if controls are feature-enabled and the user has the setting enabled */
-    fun isEnabled() = featureEnabled
+    fun isEnabled() = featureEnabled && lazyControlsController.get().available
 
     /**
      * Returns one of 3 states:
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
index d7a68b317a61..b1367d22768d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
@@ -74,7 +74,10 @@ open class ControlsRequestDialog @Inject constructor(
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-
+        if (!controller.available) {
+            Log.w(TAG, "Quick Controls not available for this user ")
+            finish()
+        }
         userTracker.addCallback(userTrackerCallback, mainExecutor)
         controlsListingController.addCallback(callback)
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index 0cc4683baef1..4c0453e1eaee 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -24,6 +24,8 @@ import android.view.ViewGroup
 import com.android.systemui.controls.controller.StructureInfo
 
 interface ControlsUiController {
+    val available: Boolean
+
     companion object {
         public const val TAG = "ControlsUiController"
         public const val EXTRA_ANIMATE = "extra_animate"
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index e71007ba55dd..01aa28941365 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -160,6 +160,9 @@ class ControlsUiControllerImpl @Inject constructor (
             reload(parent)
     }
 
+    override val available: Boolean
+        get() = controlsController.get().available
+
     private lateinit var activityContext: Context
     private lateinit var listingCallback: ControlsListingController.ControlsListingCallback
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddable.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddable.kt
index 76bfad936116..ac34c4086f38 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddable.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddable.kt
@@ -47,7 +47,7 @@ constructor(
         return conflatedCallbackFlow {
             val callback =
                 object : DeviceControlsController.Callback {
-                    override fun onControlsUpdate(position: Int?) {
+                    override fun onControlsAvailable(position: Int) {
                         position?.let { trySend(AutoAddSignal.Add(spec, position)) }
                         deviceControlsController.removeCallback()
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 201133288de5..ce11a1152c37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -16,7 +16,6 @@ package com.android.systemui.statusbar.phone;
 
 import static com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE;
 
-import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
@@ -334,9 +333,9 @@ public class AutoTileManager implements UserAwareController {
     private final DeviceControlsController.Callback mDeviceControlsCallback =
             new DeviceControlsController.Callback() {
         @Override
-        public void onControlsUpdate(@Nullable Integer position) {
+        public void onControlsAvailable(int position) {
             if (mAutoTracker.isAdded(DEVICE_CONTROLS)) return;
-            if (position != null && !hasTile(DEVICE_CONTROLS)) {
+            if (!hasTile(DEVICE_CONTROLS)) {
                 mHost.addTile(DEVICE_CONTROLS, position);
                 mAutoTracker.setTileAdded(DEVICE_CONTROLS);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
index f0949ac347ba..557a4e9b4b80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
@@ -24,7 +24,7 @@ interface DeviceControlsController {
         /**
          * If controls become available, initiate this callback with the desired position
          */
-        fun onControlsUpdate(position: Int?)
+        fun onControlsAvailable(position: Int)
 
         fun removeControlsAutoTracker()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
index 1224275aaf93..c2f14c10b5e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.policy
 import android.content.ComponentName
 import android.content.Context
 import android.content.SharedPreferences
-import android.provider.Settings
 import android.util.Log
 import com.android.systemui.res.R
 import com.android.systemui.controls.ControlsServiceInfo
@@ -29,7 +28,6 @@ import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.settings.UserContextProvider
 import com.android.systemui.statusbar.phone.AutoTileManager
 import com.android.systemui.statusbar.policy.DeviceControlsController.Callback
-import com.android.systemui.util.settings.SecureSettings
 import javax.inject.Inject
 
 /**
@@ -45,8 +43,7 @@ import javax.inject.Inject
 public class DeviceControlsControllerImpl @Inject constructor(
     private val context: Context,
     private val controlsComponent: ControlsComponent,
-    private val userContextProvider: UserContextProvider,
-    private val secureSettings: SecureSettings
+    private val userContextProvider: UserContextProvider
 ) : DeviceControlsController {
 
     private var callback: Callback? = null
@@ -74,7 +71,6 @@ public class DeviceControlsControllerImpl @Inject constructor(
         controlsComponent.getControlsController().ifPresent {
             if (!it.getFavorites().isEmpty()) {
                 position = QS_PRIORITY_POSITION
-                fireControlsUpdate()
             }
         }
     }
@@ -82,7 +78,7 @@ public class DeviceControlsControllerImpl @Inject constructor(
     /**
      * This migration logic assumes that something like [AutoTileManager] is tracking state
      * externally, and won't call this method after receiving a response via
-     * [Callback#onControlsUpdate], once per user. Otherwise the calculated position may be
+     * [Callback#onControlsAvailable], once per user. Otherwise the calculated position may be
      * incorrect.
      */
     override fun setCallback(callback: Callback) {
@@ -92,16 +88,14 @@ public class DeviceControlsControllerImpl @Inject constructor(
         }
         // Treat any additional call as a reset before recalculating
         removeCallback()
-        this.callback = callback
 
-        if (secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1) == 0) {
-            fireControlsUpdate()
-        } else {
-            checkMigrationToQs()
-            controlsComponent.getControlsListingController().ifPresent {
-                it.addCallback(listingCallback)
-            }
+        checkMigrationToQs()
+        controlsComponent.getControlsListingController().ifPresent {
+            it.addCallback(listingCallback)
         }
+
+        this.callback = callback
+        fireControlsAvailable()
     }
 
     override fun removeCallback() {
@@ -112,9 +106,11 @@ public class DeviceControlsControllerImpl @Inject constructor(
         }
     }
 
-    private fun fireControlsUpdate() {
-        Log.i(TAG, "Setting DeviceControlsTile position: $position")
-        callback?.onControlsUpdate(position)
+    private fun fireControlsAvailable() {
+        position?.let {
+            Log.i(TAG, "Setting DeviceControlsTile position: $it")
+            callback?.onControlsAvailable(it)
+        }
     }
 
     /**
@@ -165,7 +161,7 @@ public class DeviceControlsControllerImpl @Inject constructor(
                         if (position == null) {
                             position = QS_DEFAULT_POSITION
                         }
-                        fireControlsUpdate()
+                        fireControlsAvailable()
 
                         controlsComponent.getControlsListingController().ifPresent {
                             it.removeCallback(listingCallback)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index c98d5374311d..07f5bf2b010f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -23,6 +23,7 @@ import android.content.ContextWrapper
 import android.content.Intent
 import android.content.pm.ServiceInfo
 import android.os.UserHandle
+import android.provider.Settings
 import android.service.controls.Control
 import android.service.controls.DeviceTypes
 import android.service.controls.actions.ControlAction
@@ -150,6 +151,11 @@ class ControlsControllerImplTest : SysuiTestCase() {
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        Settings.Secure.putInt(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 1)
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 1, otherUser)
+
         whenever(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf())
         `when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
 
@@ -181,7 +187,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
                 mock(DumpManager::class.java)
         )
         controller.auxiliaryPersistenceWrapper = auxiliaryPersistenceWrapper
-
+        assertTrue(controller.available)
         verify(listingController).addCallback(capture(listingCallbackCaptor))
     }
 
@@ -550,6 +556,58 @@ class ControlsControllerImplTest : SysuiTestCase() {
         verify(listingController).changeUser(UserHandle.of(otherUser))
         assertTrue(controller.getFavorites().isEmpty())
         assertEquals(otherUser, controller.currentUserId)
+        assertTrue(controller.available)
+    }
+
+    @Test
+    fun testDisableFeature_notAvailable() {
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user)
+        controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, 0)
+        assertFalse(controller.available)
+    }
+
+    @Test
+    fun testDisableFeature_clearFavorites() {
+        controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
+        delayableExecutor.runAllReady()
+
+        assertFalse(controller.getFavorites().isEmpty())
+
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user)
+        controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, user)
+        assertTrue(controller.getFavorites().isEmpty())
+    }
+
+    @Test
+    fun testDisableFeature_noChangeForNotCurrentUser() {
+        controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
+        delayableExecutor.runAllReady()
+
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser)
+        controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, otherUser)
+
+        assertTrue(controller.available)
+        assertFalse(controller.getFavorites().isEmpty())
+    }
+
+    @Test
+    fun testCorrectUserSettingOnUserChange() {
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser)
+
+        val intent = Intent(Intent.ACTION_USER_SWITCHED).apply {
+            putExtra(Intent.EXTRA_USER_HANDLE, otherUser)
+        }
+        val pendingResult = mock(BroadcastReceiver.PendingResult::class.java)
+        `when`(pendingResult.sendingUserId).thenReturn(otherUser)
+        broadcastReceiverCaptor.value.pendingResult = pendingResult
+
+        broadcastReceiverCaptor.value.onReceive(mContext, intent)
+
+        assertFalse(controller.available)
     }
 
     @Test
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 54f66dc957d9..6cee88515bc5 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
@@ -106,6 +106,7 @@ class ControlsComponentTest : SysuiTestCase() {
 
     @Test
     fun testFeatureEnabledAfterBootVisibility() {
+        `when`(controller.available).thenReturn(true)
         `when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
             .thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT)
         val component = setupComponent(true)
@@ -115,6 +116,7 @@ class ControlsComponentTest : SysuiTestCase() {
 
     @Test
     fun testFeatureEnabledAndCannotShowOnLockScreenVisibility() {
+        `when`(controller.available).thenReturn(true)
         `when`(lockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED)
         `when`(keyguardStateController.isUnlocked()).thenReturn(false)
         controlsSettingsRepository.setCanShowControlsInLockscreen(false)
@@ -125,6 +127,7 @@ class ControlsComponentTest : SysuiTestCase() {
 
     @Test
     fun testFeatureEnabledAndCanShowOnLockScreenVisibility() {
+        `when`(controller.available).thenReturn(true)
         `when`(lockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED)
         `when`(keyguardStateController.isUnlocked()).thenReturn(false)
         controlsSettingsRepository.setCanShowControlsInLockscreen(true)
@@ -136,6 +139,7 @@ class ControlsComponentTest : SysuiTestCase() {
     @Test
     fun testFeatureEnabledAndCanShowWhileUnlockedVisibility() {
         controlsSettingsRepository.setCanShowControlsInLockscreen(false)
+        `when`(controller.available).thenReturn(true)
         `when`(lockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED)
         `when`(keyguardStateController.isUnlocked()).thenReturn(true)
         val component = setupComponent(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
index ca970bb41d56..567be0c91e60 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
@@ -113,6 +113,7 @@ class ControlsRequestDialogTest : SysuiTestCase() {
         intent.putExtra(ControlsProviderService.EXTRA_CONTROL, control)
 
         `when`(controller.currentUserId).thenReturn(USER_ID)
+        `when`(controller.available).thenReturn(true)
         `when`(listingController.getAppLabel(CONTROL_COMPONENT)).thenReturn(LABEL)
         `when`(controller.getFavoritesForComponent(CONTROL_COMPONENT)).thenReturn(emptyList())
 
@@ -144,4 +145,4 @@ class ControlsRequestDialogTest : SysuiTestCase() {
             assertEquals(control.deviceType, it.deviceType)
         }
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index 3bf59ca62024..e51cd2259978 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -118,6 +118,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
         spiedContext = spy(mContext)
         doNothing().`when`(spiedContext).startActivity(any(Intent::class.java))
         `when`(qsHost.context).thenReturn(spiedContext)
+        `when`(controlsController.available).thenReturn(true)
         `when`(controlsComponent.isEnabled()).thenReturn(true)
         `when`(controlsController.getPreferredSelection())
                 .thenReturn(SelectedItem.StructureItem(
@@ -180,6 +181,14 @@ class DeviceControlsTileTest : SysuiTestCase() {
         assertThat(tile.isAvailable).isFalse()
     }
 
+    @Test
+    fun testAvailableControlsSettingOff() {
+        `when`(controlsController.available).thenReturn(false)
+
+        tile = createTile()
+        assertThat(tile.isAvailable).isTrue()
+    }
+
     @Test
     fun testObservingCallback() {
         verify(controlsListingController).observe(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
index fb4ccb52929a..1703525b0fdf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.policy
 import android.content.ComponentName
 import android.content.Context
 import android.content.pm.ServiceInfo
-import android.provider.Settings
 import android.testing.AndroidTestingRunner
 
 import androidx.test.filters.SmallTest
@@ -39,7 +38,6 @@ import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Compan
 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.QS_DEFAULT_POSITION
 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.QS_PRIORITY_POSITION
 import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.settings.SecureSettings
 
 import java.util.Optional
 import java.util.function.Consumer
@@ -57,7 +55,6 @@ import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
 import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.anyObject
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -79,8 +76,6 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
     private lateinit var serviceInfo: ServiceInfo
     @Mock
     private lateinit var userContextProvider: UserContextProvider
-    @Mock
-    private lateinit var secureSettings: SecureSettings
     @Captor
     private lateinit var seedCallback: ArgumentCaptor<Consumer<SeedResponse>>
 
@@ -108,12 +103,9 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
         controller = DeviceControlsControllerImpl(
             mContext,
             controlsComponent,
-            userContextProvider,
-            secureSettings
+            userContextProvider
         )
 
-        `when`(secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1)).thenReturn(1)
-
         `when`(serviceInfo.componentName).thenReturn(TEST_COMPONENT)
         controlsServiceInfo = ControlsServiceInfo(mContext, serviceInfo)
 
@@ -130,16 +122,7 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
 
         verify(controlsListingController).addCallback(capture(listingCallbackCaptor))
         listingCallbackCaptor.value.onServicesUpdated(emptyList())
-        verify(callback, never()).onControlsUpdate(anyInt())
-    }
-
-    @Test
-    fun testCallbackWithNullValueWhenSettingIsDisabled() {
-        `when`(secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1)).thenReturn(0)
-        controller.setCallback(callback)
-
-        verify(controlsListingController, never()).addCallback(anyObject())
-        verify(callback).onControlsUpdate(null)
+        verify(callback, never()).onControlsAvailable(anyInt())
     }
 
     @Test
@@ -149,7 +132,7 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
 
         verify(controlsListingController).addCallback(capture(listingCallbackCaptor))
         listingCallbackCaptor.value.onServicesUpdated(listOf(controlsServiceInfo))
-        verify(callback).onControlsUpdate(QS_PRIORITY_POSITION)
+        verify(callback).onControlsAvailable(QS_PRIORITY_POSITION)
     }
 
     @Test
@@ -169,7 +152,7 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
             capture(seedCallback)
         )
         seedCallback.value.accept(SeedResponse(TEST_PKG, true))
-        verify(callback).onControlsUpdate(QS_DEFAULT_POSITION)
+        verify(callback).onControlsAvailable(QS_DEFAULT_POSITION)
     }
 
     @Test
-- 
GitLab