1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.controls.controller
18 
19 import android.content.ComponentName
20 import android.service.controls.Control
21 import android.service.controls.ControlsProviderService
22 import android.service.controls.actions.ControlAction
23 import com.android.systemui.controls.ControlStatus
24 import com.android.systemui.util.UserAwareController
25 import com.android.systemui.controls.management.ControlsFavoritingActivity
26 import com.android.systemui.controls.ui.ControlsUiController
27 import java.util.function.Consumer
28 
29 /**
30  * Controller to handle communication between different parts of the controls system.
31  *
32  * This controller is in charge of:
33  *  * Keeping track of favorites
34  *  * Determining and keeping track of whether controls are enabled
35  *  * Listening for user change and propagating that message in the system
36  *  * Communicate between the UI and the [ControlsBindingController]
37  *
38  *  This controller being a [UserAwareController] means that all operations will be conducted on
39  *  information for the current user only.
40  */
41 interface ControlsController : UserAwareController {
42 
43     /**
44      * Whether the controls system is available for the current user.
45      */
46     val available: Boolean
47 
48     // SERVICE COMMUNICATION
49 
50     /**
51      * Load all available [Control] for a given service.
52      *
53      * @param componentName the [ComponentName] of the [ControlsProviderService] to load from
54      * @param dataCallback a callback in which to retrieve the result
55      * @param cancelWrapper a callback to receive a [Runnable] that can be run to cancel the
56      *                      request
57      */
loadForComponentnull58     fun loadForComponent(
59         componentName: ComponentName,
60         dataCallback: Consumer<LoadData>,
61         cancelWrapper: Consumer<Runnable>
62     )
63 
64     /**
65      * Request to subscribe for favorited controls per structure
66      *
67      * @param structureInfo structure to limit the subscription to
68      * @see [ControlsBindingController.subscribe]
69      */
70     fun subscribeToFavorites(structureInfo: StructureInfo)
71 
72     /**
73      * Request to unsubscribe to the current provider.
74      *
75      * @see [ControlsBindingController.unsubscribe]
76      */
77     fun unsubscribe()
78 
79     /**
80      * Notify a [ControlsProviderService] that an action has been performed on a [Control].
81      *
82      * @param componentName the name of the service that provides the [Control]
83      * @param controlInfo information of the [Control] receiving the action
84      * @param action action performed on the [Control]
85      * @see [ControlsBindingController.action]
86      */
87     fun action(componentName: ComponentName, controlInfo: ControlInfo, action: ControlAction)
88 
89     /**
90      * Refresh the status of a [Control] with information provided from the service.
91      *
92      * @param componentName the name of the service that provides the [Control]
93      * @param control a stateful [Control] with updated information
94      * @see [ControlsUiController.onRefreshState]
95      */
96     fun refreshStatus(componentName: ComponentName, control: Control)
97 
98     /**
99      * Indicate the result of a [ControlAction] performed on a [Control].
100      *
101      * @param componentName the name of the service that provides the [Control]
102      * @param controlId the id of the [Control] the actioned was performed on
103      * @param response the result of the action.
104      * @see [ControlsUiController.onActionResponse]
105      */
106     fun onActionResponse(
107         componentName: ComponentName,
108         controlId: String,
109         @ControlAction.ResponseResult response: Int
110     )
111 
112     // FAVORITE MANAGEMENT
113 
114     /**
115      * Send a request to seed favorites into the persisted XML file
116      *
117      * @param componentNames the list of components to seed controls from
118      * @param callback one [SeedResponse] per componentName
119      */
120     fun seedFavoritesForComponents(
121         componentNames: List<ComponentName>,
122         callback: Consumer<SeedResponse>
123     )
124 
125     /**
126      * Callback to be informed when the seeding process has finished
127      *
128      * @param callback consumer accepts true if successful
129      * @return true if seeding is in progress and the callback was added
130      */
131     fun addSeedingFavoritesCallback(callback: Consumer<Boolean>): Boolean
132 
133     /**
134      * Get all the favorites.
135      *
136      * @return a list of the structures that have at least one favorited control
137      */
138     fun getFavorites(): List<StructureInfo>
139 
140     /**
141      * Get all the favorites for a given component.
142      *
143      * @param componentName the name of the service that provides the [Control]
144      * @return a list of the structures that have at least one favorited control
145      */
146     fun getFavoritesForComponent(componentName: ComponentName): List<StructureInfo>
147 
148     /**
149      * Get all the favorites for a given structure.
150      *
151      * @param componentName the name of the service that provides the [Control]
152      * @param structureName the name of the structure
153      * @return a list of the current favorites in that structure
154      */
155     fun getFavoritesForStructure(
156         componentName: ComponentName,
157         structureName: CharSequence
158     ): List<ControlInfo>
159 
160     /**
161      * Adds a single favorite to a given component and structure
162      * @param componentName the name of the service that provides the [Control]
163      * @param structureName the name of the structure that holds the [Control]
164      * @param controlInfo persistent information about the [Control] to be added.
165      */
166     fun addFavorite(
167         componentName: ComponentName,
168         structureName: CharSequence,
169         controlInfo: ControlInfo
170     )
171 
172     /**
173      * Replaces the favorites for the given structure.
174      *
175      * Calling this method will eliminate the previous selection of favorites and replace it with a
176      * new one.
177      *
178      * @param structureInfo common structure for all of the favorited controls
179      */
180     fun replaceFavoritesForStructure(structureInfo: StructureInfo)
181 
182     /**
183      * Return the number of favorites for a given component.
184      *
185      * This call returns the same as `getFavoritesForComponent(componentName).size`.
186      *
187      * @param componentName the name of the component
188      * @return the number of current favorites for the given component
189      */
190     fun countFavoritesForComponent(componentName: ComponentName): Int
191 
192     /**
193      * Interface for structure to pass data to [ControlsFavoritingActivity].
194      */
195     interface LoadData {
196         /**
197          * All of the available controls for the loaded [ControlsProviderService].
198          *
199          * This will indicate if they are currently a favorite and whether they were removed (a
200          * favorite but not retrieved on load).
201          */
202         val allControls: List<ControlStatus>
203 
204         /**
205          * Ordered list of ids of favorite controls.
206          */
207         val favoritesIds: List<String>
208 
209         /**
210          * Whether there was an error in loading.
211          *
212          * In this case, [allControls] will only contain those that were favorited and will not be
213          * marked as removed.
214          */
215         val errorOnLoad: Boolean
216     }
217 }
218 
219 /**
220  * Creates a basic implementation of a [LoadData].
221  */
createLoadDataObjectnull222 fun createLoadDataObject(
223     allControls: List<ControlStatus>,
224     favorites: List<String>,
225     error: Boolean = false
226 ): ControlsController.LoadData {
227     return object : ControlsController.LoadData {
228         override val allControls = allControls
229         override val favoritesIds = favorites
230         override val errorOnLoad = error
231     }
232 }
233 
234 data class SeedResponse(val packageName: String, val accepted: Boolean)
235