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 com.android.systemui.controls.ui.SelectedItem
28 import java.util.function.Consumer
29
30 /**
31 * Controller to handle communication between different parts of the controls system.
32 *
33 * This controller is in charge of:
34 * * Keeping track of favorites
35 * * Determining and keeping track of whether controls are enabled
36 * * Listening for user change and propagating that message in the system
37 * * Communicate between the UI and the [ControlsBindingController]
38 *
39 * This controller being a [UserAwareController] means that all operations will be conducted on
40 * information for the current user only.
41 */
42 interface ControlsController : UserAwareController {
43
44 // SERVICE COMMUNICATION
45
46 /**
47 * Load all available [Control] for a given service.
48 *
49 * @param componentName the [ComponentName] of the [ControlsProviderService] to load from
50 * @param dataCallback a callback in which to retrieve the result
51 * @param cancelWrapper a callback to receive a [Runnable] that can be run to cancel the
52 * request
53 */
loadForComponentnull54 fun loadForComponent(
55 componentName: ComponentName,
56 dataCallback: Consumer<LoadData>,
57 cancelWrapper: Consumer<Runnable>
58 )
59
60 /**
61 * Request to subscribe for favorited controls per structure
62 *
63 * @param structureInfo structure to limit the subscription to
64 * @see [ControlsBindingController.subscribe]
65 */
66 fun subscribeToFavorites(structureInfo: StructureInfo)
67
68 /**
69 * Request to unsubscribe to the current provider.
70 *
71 * @see [ControlsBindingController.unsubscribe]
72 */
73 fun unsubscribe()
74
75 /**
76 * Notify a [ControlsProviderService] that an action has been performed on a [Control].
77 *
78 * @param componentName the name of the service that provides the [Control]
79 * @param controlInfo information of the [Control] receiving the action
80 * @param action action performed on the [Control]
81 * @see [ControlsBindingController.action]
82 */
83 fun action(componentName: ComponentName, controlInfo: ControlInfo, action: ControlAction)
84
85 /**
86 * Refresh the status of a [Control] with information provided from the service.
87 *
88 * @param componentName the name of the service that provides the [Control]
89 * @param control a stateful [Control] with updated information
90 * @see [ControlsUiController.onRefreshState]
91 */
92 fun refreshStatus(componentName: ComponentName, control: Control)
93
94 /**
95 * Indicate the result of a [ControlAction] performed on a [Control].
96 *
97 * @param componentName the name of the service that provides the [Control]
98 * @param controlId the id of the [Control] the actioned was performed on
99 * @param response the result of the action.
100 * @see [ControlsUiController.onActionResponse]
101 */
102 fun onActionResponse(
103 componentName: ComponentName,
104 controlId: String,
105 @ControlAction.ResponseResult response: Int
106 )
107
108 // FAVORITE MANAGEMENT
109
110 /**
111 * Send a request to seed favorites into the persisted XML file
112 *
113 * @param componentNames the list of components to seed controls from
114 * @param callback one [SeedResponse] per componentName
115 */
116 fun seedFavoritesForComponents(
117 componentNames: List<ComponentName>,
118 callback: Consumer<SeedResponse>
119 )
120
121 /**
122 * Callback to be informed when the seeding process has finished
123 *
124 * @param callback consumer accepts true if successful
125 * @return true if seeding is in progress and the callback was added
126 */
127 fun addSeedingFavoritesCallback(callback: Consumer<Boolean>): Boolean
128
129 /**
130 * Get all the favorites.
131 *
132 * @return a list of the structures that have at least one favorited control
133 */
134 fun getFavorites(): List<StructureInfo>
135
136 /**
137 * Get all the favorites for a given component.
138 *
139 * @param componentName the name of the service that provides the [Control]
140 * @return a list of the structures that have at least one favorited control
141 */
142 fun getFavoritesForComponent(componentName: ComponentName): List<StructureInfo>
143
144 /**
145 * Get all the favorites for a given structure.
146 *
147 * @param componentName the name of the service that provides the [Control]
148 * @param structureName the name of the structure
149 * @return a list of the current favorites in that structure
150 */
151 fun getFavoritesForStructure(
152 componentName: ComponentName,
153 structureName: CharSequence
154 ): List<ControlInfo>
155
156 /**
157 * Adds a single favorite to a given component and structure
158 * @param componentName the name of the service that provides the [Control]
159 * @param structureName the name of the structure that holds the [Control]
160 * @param controlInfo persistent information about the [Control] to be added.
161 */
162 fun addFavorite(
163 componentName: ComponentName,
164 structureName: CharSequence,
165 controlInfo: ControlInfo
166 )
167
168 /**
169 * Removes favorites for a given component
170 * @param componentName the name of the service that provides the [Control]
171 * @return true when favorites is scheduled for deletion
172 */
173 fun removeFavorites(componentName: ComponentName): Boolean
174
175 /**
176 * Replaces the favorites for the given structure.
177 *
178 * Calling this method will eliminate the previous selection of favorites and replace it with a
179 * new one.
180 *
181 * @param structureInfo common structure for all of the favorited controls
182 */
183 fun replaceFavoritesForStructure(structureInfo: StructureInfo)
184
185 /**
186 * Return the number of favorites for a given component.
187 *
188 * This call returns the same as `getFavoritesForComponent(componentName).size`.
189 *
190 * @param componentName the name of the component
191 * @return the number of current favorites for the given component
192 */
193 fun countFavoritesForComponent(componentName: ComponentName): Int
194
195 /** See [ControlsUiController.getPreferredSelectedItem]. */
196 fun getPreferredSelection(): SelectedItem
197
198 fun setPreferredSelection(selectedItem: SelectedItem)
199
200 /**
201 * Bind to a service that provides a Device Controls panel (embedded activity). This will allow
202 * the app to remain "warm", and reduce latency.
203 *
204 * @param component The [ComponentName] of the [ControlsProviderService] to bind.
205 */
206 fun bindComponentForPanel(componentName: ComponentName)
207
208 /**
209 * Interface for structure to pass data to [ControlsFavoritingActivity].
210 */
211 interface LoadData {
212 /**
213 * All of the available controls for the loaded [ControlsProviderService].
214 *
215 * This will indicate if they are currently a favorite and whether they were removed (a
216 * favorite but not retrieved on load).
217 */
218 val allControls: List<ControlStatus>
219
220 /**
221 * Ordered list of ids of favorite controls.
222 */
223 val favoritesIds: List<String>
224
225 /**
226 * Whether there was an error in loading.
227 *
228 * In this case, [allControls] will only contain those that were favorited and will not be
229 * marked as removed.
230 */
231 val errorOnLoad: Boolean
232 }
233 }
234
235 /**
236 * Creates a basic implementation of a [LoadData].
237 */
createLoadDataObjectnull238 fun createLoadDataObject(
239 allControls: List<ControlStatus>,
240 favorites: List<String>,
241 error: Boolean = false
242 ): ControlsController.LoadData {
243 return object : ControlsController.LoadData {
244 override val allControls = allControls
245 override val favoritesIds = favorites
246 override val errorOnLoad = error
247 }
248 }
249
250 data class SeedResponse(val packageName: String, val accepted: Boolean)
251