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