Controls UI - Support seeding for up to 6 structures

Limit to 36 controls: 6 structures with up to 6 controls per structure

Fixes: 153606605
Test: atest ControlsControllerImplTest

Change-Id: Ieddceda4a0902e4b42208680c7a77ee03514a16c
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index 4262c40..4e5aa00 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -98,9 +98,12 @@
      *
      * The service may be asked to provide a small number of recommended controls, in
      * order to suggest some controls to the user for favoriting. The controls shall be built using
-     * the stateless builder {@link Control.StatelessBuilder}. The number of controls requested
-     * through {@link Subscription#request} will be limited. Call {@link Subscriber#onComplete}
-     * when done, or {@link Subscriber#onError} for error scenarios.
+     * the stateless builder {@link Control.StatelessBuilder}. The total number of controls
+     * requested through {@link Subscription#request} will be restricted to a maximum. Within this
+     * larger limit, only 6 controls per structure will be loaded. Therefore, it is advisable to
+     * seed multiple structures if they exist. Any control sent over this limit  will be discarded.
+     * Call {@link Subscriber#onComplete} when done, or {@link Subscriber#onError} for error
+     * scenarios.
      */
     @Nullable
     public Publisher<Control> createPublisherForSuggested() {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index e84f439..58807f0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -46,7 +46,9 @@
     companion object {
         private const val TAG = "ControlsBindingControllerImpl"
         private const val MAX_CONTROLS_REQUEST = 100000L
-        private const val SUGGESTED_CONTROLS_REQUEST = 6L
+        private const val SUGGESTED_STRUCTURES = 6L
+        private const val SUGGESTED_CONTROLS_REQUEST =
+            ControlsControllerImpl.SUGGESTED_CONTROLS_PER_STRUCTURE * SUGGESTED_STRUCTURES
     }
 
     private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
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 f8f913e..dc727df 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -72,6 +72,7 @@
         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
@@ -396,9 +397,11 @@
                             val structure = it.structure ?: ""
                             val list = structureToControls.get(structure)
                                 ?: mutableListOf<ControlInfo>()
-                            list.add(
-                                ControlInfo(it.controlId, it.title, it.subtitle, it.deviceType))
-                            structureToControls.put(structure, list)
+                            if (list.size < SUGGESTED_CONTROLS_PER_STRUCTURE) {
+                                list.add(
+                                    ControlInfo(it.controlId, it.title, it.subtitle, it.deviceType))
+                                structureToControls.put(structure, list)
+                            }
                         }
 
                         structureToControls.forEach {
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 b388887..05e676d 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
@@ -797,11 +797,14 @@
     }
 
     @Test
-    fun testSeedFavoritesForComponent() {
+    fun testSeedFavoritesForComponentWithLimit() {
         var succeeded = false
-        val control = statelessBuilderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure)
-            .build()
 
+        val controls = mutableListOf<Control>()
+        for (i in 1..10) {
+            controls.add(statelessBuilderFromInfo(ControlInfo("id$i", TEST_CONTROL_TITLE,
+                TEST_CONTROL_SUBTITLE, TEST_DEVICE_TYPE), "testStructure").build())
+        }
         controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
             succeeded = accepted
         })
@@ -809,12 +812,19 @@
         verify(bindingController).bindAndLoadSuggested(eq(TEST_COMPONENT),
                 capture(controlLoadCallbackCaptor))
 
-        controlLoadCallbackCaptor.value.accept(listOf(control))
+        controlLoadCallbackCaptor.value.accept(controls)
 
         delayableExecutor.runAllReady()
 
-        assertEquals(listOf(TEST_STRUCTURE_INFO),
-            controller.getFavoritesForComponent(TEST_COMPONENT))
+        val structureInfo = controller.getFavoritesForComponent(TEST_COMPONENT)[0]
+        assertEquals(structureInfo.controls.size,
+            ControlsControllerImpl.SUGGESTED_CONTROLS_PER_STRUCTURE)
+
+        var i = 1
+        structureInfo.controls.forEach {
+            assertEquals(it.controlId, "id$i")
+            i++
+        }
         assertTrue(succeeded)
     }