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 */ 54 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 */ 238 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