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