Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 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.content.Context |
| 21 | import android.content.Intent |
| 22 | import android.content.ServiceConnection |
| 23 | import android.os.Binder |
| 24 | import android.os.Bundle |
| 25 | import android.os.IBinder |
| 26 | import android.os.RemoteException |
Fabian Kozynski | 7988bd4 | 2020-01-30 12:21:52 -0500 | [diff] [blame] | 27 | import android.os.UserHandle |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 28 | import android.service.controls.ControlsProviderService |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 29 | import android.service.controls.ControlsProviderService.CALLBACK_BUNDLE |
| 30 | import android.service.controls.ControlsProviderService.CALLBACK_TOKEN |
Fabian Kozynski | 1bb26b5 | 2020-01-08 18:20:36 -0500 | [diff] [blame] | 31 | import android.service.controls.IControlsActionCallback |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 32 | import android.service.controls.IControlsProvider |
Fabian Kozynski | 1bb26b5 | 2020-01-08 18:20:36 -0500 | [diff] [blame] | 33 | import android.service.controls.IControlsSubscriber |
| 34 | import android.service.controls.IControlsSubscription |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 35 | import android.service.controls.actions.ControlAction |
| 36 | import android.util.ArraySet |
| 37 | import android.util.Log |
| 38 | import com.android.internal.annotations.GuardedBy |
| 39 | import com.android.systemui.util.concurrency.DelayableExecutor |
| 40 | import java.util.concurrent.TimeUnit |
| 41 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 42 | /** |
| 43 | * Manager for the lifecycle of the connection to a given [ControlsProviderService]. |
| 44 | * |
| 45 | * This class handles binding and unbinding and requests to the service. The class will queue |
| 46 | * requests until the service is connected and dispatch them then. |
| 47 | * |
| 48 | * @property context A SystemUI context for binding to the services |
| 49 | * @property executor A delayable executor for posting timeouts |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 50 | * @property actionCallbackService a callback interface to hand the remote service for sending |
| 51 | * action responses |
| 52 | * @property subscriberService an "subscriber" interface for requesting and accepting updates for |
| 53 | * controls from the service. |
| 54 | * @property user the user for whose this service should be bound. |
| 55 | * @property componentName the name of the component for the service. |
| 56 | */ |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 57 | class ControlsProviderLifecycleManager( |
| 58 | private val context: Context, |
| 59 | private val executor: DelayableExecutor, |
Fabian Kozynski | 1bb26b5 | 2020-01-08 18:20:36 -0500 | [diff] [blame] | 60 | private val actionCallbackService: IControlsActionCallback.Stub, |
Fabian Kozynski | 7988bd4 | 2020-01-30 12:21:52 -0500 | [diff] [blame] | 61 | val user: UserHandle, |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 62 | val componentName: ComponentName |
| 63 | ) : IBinder.DeathRecipient { |
| 64 | |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 65 | val token: IBinder = Binder() |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 66 | private var requiresBound = false |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 67 | @GuardedBy("queuedServiceMethods") |
| 68 | private val queuedServiceMethods: MutableSet<ServiceMethod> = ArraySet() |
Fabian Kozynski | 1bb26b5 | 2020-01-08 18:20:36 -0500 | [diff] [blame] | 69 | private var wrapper: ServiceWrapper? = null |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 70 | private var bindTryCount = 0 |
| 71 | private val TAG = javaClass.simpleName |
| 72 | private var onLoadCanceller: Runnable? = null |
| 73 | |
| 74 | companion object { |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 75 | private const val BIND_RETRY_DELAY = 1000L // ms |
Fabian Kozynski | 2833f45 | 2020-02-14 16:50:04 -0500 | [diff] [blame] | 76 | private const val LOAD_TIMEOUT_SECONDS = 30L // seconds |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 77 | private const val MAX_BIND_RETRIES = 5 |
| 78 | private const val DEBUG = true |
Matt Pietal | 94ff20f | 2020-03-23 15:37:46 -0400 | [diff] [blame] | 79 | private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | private val intent = Intent().apply { |
| 83 | component = componentName |
| 84 | putExtra(CALLBACK_BUNDLE, Bundle().apply { |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 85 | putBinder(CALLBACK_TOKEN, token) |
| 86 | }) |
| 87 | } |
| 88 | |
| 89 | private fun bindService(bind: Boolean) { |
Matt Pietal | 313f37d | 2020-02-24 11:27:22 -0500 | [diff] [blame] | 90 | executor.execute { |
| 91 | requiresBound = bind |
| 92 | if (bind) { |
| 93 | if (bindTryCount != MAX_BIND_RETRIES) { |
| 94 | if (DEBUG) { |
| 95 | Log.d(TAG, "Binding service $intent") |
| 96 | } |
| 97 | bindTryCount++ |
| 98 | try { |
| 99 | context.bindServiceAsUser(intent, serviceConnection, BIND_FLAGS, user) |
| 100 | } catch (e: SecurityException) { |
| 101 | Log.e(TAG, "Failed to bind to service", e) |
| 102 | } |
| 103 | } |
| 104 | } else { |
| 105 | if (DEBUG) { |
| 106 | Log.d(TAG, "Unbinding service $intent") |
| 107 | } |
| 108 | bindTryCount = 0 |
| 109 | wrapper?.run { |
| 110 | context.unbindService(serviceConnection) |
| 111 | } |
| 112 | wrapper = null |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 113 | } |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 114 | } |
| 115 | } |
| 116 | |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 117 | private val serviceConnection = object : ServiceConnection { |
| 118 | override fun onServiceConnected(name: ComponentName, service: IBinder) { |
| 119 | if (DEBUG) Log.d(TAG, "onServiceConnected $name") |
| 120 | bindTryCount = 0 |
Fabian Kozynski | 1bb26b5 | 2020-01-08 18:20:36 -0500 | [diff] [blame] | 121 | wrapper = ServiceWrapper(IControlsProvider.Stub.asInterface(service)) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 122 | try { |
| 123 | service.linkToDeath(this@ControlsProviderLifecycleManager, 0) |
| 124 | } catch (_: RemoteException) {} |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 125 | handlePendingServiceMethods() |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | override fun onServiceDisconnected(name: ComponentName?) { |
| 129 | if (DEBUG) Log.d(TAG, "onServiceDisconnected $name") |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 130 | wrapper = null |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 131 | bindService(false) |
| 132 | } |
| 133 | } |
| 134 | |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 135 | private fun handlePendingServiceMethods() { |
| 136 | val queue = synchronized(queuedServiceMethods) { |
| 137 | ArraySet(queuedServiceMethods).also { |
| 138 | queuedServiceMethods.clear() |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 139 | } |
| 140 | } |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 141 | queue.forEach { |
| 142 | it.run() |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 143 | } |
| 144 | } |
| 145 | |
| 146 | override fun binderDied() { |
| 147 | if (wrapper == null) return |
| 148 | wrapper = null |
| 149 | if (requiresBound) { |
| 150 | if (DEBUG) { |
| 151 | Log.d(TAG, "binderDied") |
| 152 | } |
| 153 | // Try rebinding some time later |
| 154 | } |
| 155 | } |
| 156 | |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 157 | private fun queueServiceMethod(sm: ServiceMethod) { |
| 158 | synchronized(queuedServiceMethods) { |
| 159 | queuedServiceMethods.add(sm) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 160 | } |
| 161 | } |
| 162 | |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 163 | private fun invokeOrQueue(sm: ServiceMethod) { |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 164 | wrapper?.run { |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 165 | sm.run() |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 166 | } ?: run { |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 167 | queueServiceMethod(sm) |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 168 | bindService(true) |
| 169 | } |
| 170 | } |
| 171 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 172 | /** |
Matt Pietal | d0553b0 | 2020-02-13 07:08:58 -0500 | [diff] [blame] | 173 | * Request a call to [IControlsProvider.load]. |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 174 | * |
| 175 | * If the service is not bound, the call will be queued and the service will be bound first. |
Matt Pietal | d0553b0 | 2020-02-13 07:08:58 -0500 | [diff] [blame] | 176 | * The service will be unbound after the controls are returned or the call times out. |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 177 | * |
Matt Pietal | d0553b0 | 2020-02-13 07:08:58 -0500 | [diff] [blame] | 178 | * @param subscriber the subscriber that manages coordination for loading controls |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 179 | */ |
Matt Pietal | d0553b0 | 2020-02-13 07:08:58 -0500 | [diff] [blame] | 180 | fun maybeBindAndLoad(subscriber: IControlsSubscriber.Stub) { |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 181 | onLoadCanceller = executor.executeDelayed({ |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 182 | // Didn't receive a response in time, log and send back error |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 183 | Log.d(TAG, "Timeout waiting onLoad for $componentName") |
Matt Pietal | d0553b0 | 2020-02-13 07:08:58 -0500 | [diff] [blame] | 184 | subscriber.onError(token, "Timeout waiting onLoad") |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 185 | unbindService() |
Fabian Kozynski | 2833f45 | 2020-02-14 16:50:04 -0500 | [diff] [blame] | 186 | }, LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 187 | |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 188 | invokeOrQueue(Load(subscriber)) |
| 189 | } |
| 190 | |
| 191 | /** |
| 192 | * Request a call to [IControlsProvider.loadSuggested]. |
| 193 | * |
| 194 | * If the service is not bound, the call will be queued and the service will be bound first. |
Matt Pietal | cd757c8 | 2020-04-08 10:20:48 -0400 | [diff] [blame] | 195 | * The service will be unbound if the call times out. |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 196 | * |
| 197 | * @param subscriber the subscriber that manages coordination for loading controls |
| 198 | */ |
| 199 | fun maybeBindAndLoadSuggested(subscriber: IControlsSubscriber.Stub) { |
| 200 | onLoadCanceller = executor.executeDelayed({ |
| 201 | // Didn't receive a response in time, log and send back error |
| 202 | Log.d(TAG, "Timeout waiting onLoadSuggested for $componentName") |
| 203 | subscriber.onError(token, "Timeout waiting onLoadSuggested") |
| 204 | unbindService() |
| 205 | }, LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) |
| 206 | |
| 207 | invokeOrQueue(Suggest(subscriber)) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 208 | } |
| 209 | |
Fabian Kozynski | 8b14c30 | 2020-03-11 17:20:38 -0400 | [diff] [blame] | 210 | fun cancelLoadTimeout() { |
| 211 | onLoadCanceller?.run() |
| 212 | onLoadCanceller = null |
| 213 | } |
| 214 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 215 | /** |
| 216 | * Request a subscription to the [Publisher] returned by [ControlsProviderService.publisherFor] |
| 217 | * |
| 218 | * If the service is not bound, the call will be queued and the service will be bound first. |
| 219 | * |
| 220 | * @param controlIds a list of the ids of controls to send status back. |
| 221 | */ |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 222 | fun maybeBindAndSubscribe(controlIds: List<String>, subscriber: IControlsSubscriber) = |
| 223 | invokeOrQueue(Subscribe(controlIds, subscriber)) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 224 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 225 | /** |
| 226 | * Request a call to [ControlsProviderService.performControlAction]. |
| 227 | * |
| 228 | * If the service is not bound, the call will be queued and the service will be bound first. |
| 229 | * |
| 230 | * @param controlId the id of the [Control] the action is performed on |
| 231 | * @param action the action performed |
| 232 | */ |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 233 | fun maybeBindAndSendAction(controlId: String, action: ControlAction) = |
| 234 | invokeOrQueue(Action(controlId, action)) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 235 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 236 | /** |
| 237 | * Starts the subscription to the [ControlsProviderService] and requests status of controls. |
| 238 | * |
Matt Pietal | 26fd9a0 | 2020-03-10 14:59:25 -0400 | [diff] [blame] | 239 | * @param subscription the subscription to use to request controls |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 240 | * @see maybeBindAndLoad |
| 241 | */ |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 242 | fun startSubscription(subscription: IControlsSubscription, requestLimit: Long) { |
Matt Pietal | 26fd9a0 | 2020-03-10 14:59:25 -0400 | [diff] [blame] | 243 | if (DEBUG) { |
| 244 | Log.d(TAG, "startSubscription: $subscription") |
| 245 | } |
Matt Pietal | cd757c8 | 2020-04-08 10:20:48 -0400 | [diff] [blame] | 246 | |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 247 | wrapper?.request(subscription, requestLimit) |
Fabian Kozynski | 1bb26b5 | 2020-01-08 18:20:36 -0500 | [diff] [blame] | 248 | } |
| 249 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 250 | /** |
Matt Pietal | 26fd9a0 | 2020-03-10 14:59:25 -0400 | [diff] [blame] | 251 | * Cancels the subscription to the [ControlsProviderService]. |
| 252 | * |
| 253 | * @param subscription the subscription to cancel |
| 254 | * @see maybeBindAndLoad |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 255 | */ |
Matt Pietal | 26fd9a0 | 2020-03-10 14:59:25 -0400 | [diff] [blame] | 256 | fun cancelSubscription(subscription: IControlsSubscription) { |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 257 | if (DEBUG) { |
Matt Pietal | 26fd9a0 | 2020-03-10 14:59:25 -0400 | [diff] [blame] | 258 | Log.d(TAG, "cancelSubscription: $subscription") |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 259 | } |
Matt Pietal | cd757c8 | 2020-04-08 10:20:48 -0400 | [diff] [blame] | 260 | |
Matt Pietal | 26fd9a0 | 2020-03-10 14:59:25 -0400 | [diff] [blame] | 261 | wrapper?.cancel(subscription) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 262 | } |
| 263 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 264 | /** |
| 265 | * Request bind to the service. |
| 266 | */ |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 267 | fun bindService() { |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 268 | bindService(true) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 269 | } |
| 270 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 271 | /** |
| 272 | * Request unbind from the service. |
| 273 | */ |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 274 | fun unbindService() { |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 275 | onLoadCanceller?.run() |
| 276 | onLoadCanceller = null |
| 277 | |
| 278 | bindService(false) |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 279 | } |
| 280 | |
Fabian Kozynski | 7988bd4 | 2020-01-30 12:21:52 -0500 | [diff] [blame] | 281 | override fun toString(): String { |
| 282 | return StringBuilder("ControlsProviderLifecycleManager(").apply { |
| 283 | append("component=$componentName") |
| 284 | append(", user=$user") |
Fabian Kozynski | 7988bd4 | 2020-01-30 12:21:52 -0500 | [diff] [blame] | 285 | append(")") |
| 286 | }.toString() |
| 287 | } |
| 288 | |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 289 | /** |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 290 | * Service methods that can be queued or invoked, and are retryable for failure scenarios |
Fabian Kozynski | 9c459e5 | 2020-02-12 09:08:15 -0500 | [diff] [blame] | 291 | */ |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 292 | abstract inner class ServiceMethod { |
| 293 | fun run() { |
| 294 | if (!callWrapper()) { |
| 295 | queueServiceMethod(this) |
| 296 | binderDied() |
| 297 | } |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 298 | } |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 299 | |
| 300 | internal abstract fun callWrapper(): Boolean |
| 301 | } |
| 302 | |
| 303 | inner class Load(val subscriber: IControlsSubscriber.Stub) : ServiceMethod() { |
| 304 | override fun callWrapper(): Boolean { |
| 305 | if (DEBUG) { |
| 306 | Log.d(TAG, "load $componentName") |
| 307 | } |
| 308 | return wrapper?.load(subscriber) ?: false |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 309 | } |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 310 | } |
| 311 | |
| 312 | inner class Suggest(val subscriber: IControlsSubscriber.Stub) : ServiceMethod() { |
| 313 | override fun callWrapper(): Boolean { |
| 314 | if (DEBUG) { |
| 315 | Log.d(TAG, "suggest $componentName") |
| 316 | } |
| 317 | return wrapper?.loadSuggested(subscriber) ?: false |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 318 | } |
Matt Pietal | 6126644 | 2020-03-17 12:53:44 -0400 | [diff] [blame] | 319 | } |
| 320 | inner class Subscribe( |
| 321 | val list: List<String>, |
| 322 | val subscriber: IControlsSubscriber |
| 323 | ) : ServiceMethod() { |
| 324 | override fun callWrapper(): Boolean { |
| 325 | if (DEBUG) { |
| 326 | Log.d(TAG, "subscribe $componentName - $list") |
| 327 | } |
| 328 | |
| 329 | return wrapper?.subscribe(list, subscriber) ?: false |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | inner class Action(val id: String, val action: ControlAction) : ServiceMethod() { |
| 334 | override fun callWrapper(): Boolean { |
| 335 | if (DEBUG) { |
| 336 | Log.d(TAG, "onAction $componentName - $id") |
| 337 | } |
| 338 | return wrapper?.action(id, action, actionCallbackService) ?: false |
Fabian Kozynski | f10b6ab | 2019-12-27 09:31:04 -0500 | [diff] [blame] | 339 | } |
| 340 | } |
Matt Pietal | 019feaa | 2020-01-31 14:51:37 -0500 | [diff] [blame] | 341 | } |