1 /* 2 * Copyright (C) 2024 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 android.app.ondeviceintelligence; 18 19 import static android.app.ondeviceintelligence.flags.Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE; 20 21 import android.Manifest; 22 import android.annotation.CallbackExecutor; 23 import android.annotation.FlaggedApi; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.RequiresPermission; 27 import android.annotation.SystemApi; 28 import android.annotation.SystemService; 29 import android.content.Context; 30 import android.graphics.Bitmap; 31 import android.os.Binder; 32 import android.os.Bundle; 33 import android.os.CancellationSignal; 34 import android.os.IBinder; 35 import android.os.ICancellationSignal; 36 import android.os.OutcomeReceiver; 37 import android.os.PersistableBundle; 38 import android.os.RemoteCallback; 39 import android.os.RemoteException; 40 import android.system.OsConstants; 41 import android.util.Log; 42 43 import androidx.annotation.IntDef; 44 45 import com.android.internal.infra.AndroidFuture; 46 47 import java.lang.annotation.ElementType; 48 import java.lang.annotation.Retention; 49 import java.lang.annotation.RetentionPolicy; 50 import java.lang.annotation.Target; 51 import java.util.List; 52 import java.util.concurrent.Executor; 53 import java.util.function.LongConsumer; 54 55 /** 56 * Allows granted apps to manage on-device intelligence service configured on the device. Typical 57 * calling pattern will be to query and setup a required feature before proceeding to request 58 * processing. 59 * 60 * The contracts in this Manager class are designed to be open-ended in general, to allow 61 * interoperability. Therefore, it is recommended that implementations of this system-service 62 * expose this API to the clients via a separate sdk or library which has more defined contract. 63 * 64 * @hide 65 */ 66 @SystemApi 67 @SystemService(Context.ON_DEVICE_INTELLIGENCE_SERVICE) 68 @FlaggedApi(FLAG_ENABLE_ON_DEVICE_INTELLIGENCE) 69 public final class OnDeviceIntelligenceManager { 70 /** 71 * @hide 72 */ 73 public static final String API_VERSION_BUNDLE_KEY = "ApiVersionBundleKey"; 74 75 /** 76 * @hide 77 */ 78 public static final String AUGMENT_REQUEST_CONTENT_BUNDLE_KEY = 79 "AugmentRequestContentBundleKey"; 80 81 private static final String TAG = "OnDeviceIntelligence"; 82 private final Context mContext; 83 private final IOnDeviceIntelligenceManager mService; 84 85 /** 86 * @hide 87 */ OnDeviceIntelligenceManager(Context context, IOnDeviceIntelligenceManager service)88 public OnDeviceIntelligenceManager(Context context, IOnDeviceIntelligenceManager service) { 89 mContext = context; 90 mService = service; 91 } 92 93 /** 94 * Asynchronously get the version of the underlying remote implementation. 95 * 96 * @param versionConsumer consumer to populate the version of remote implementation. 97 * @param callbackExecutor executor to run the callback on. 98 */ 99 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) getVersion( @onNull @allbackExecutor Executor callbackExecutor, @NonNull LongConsumer versionConsumer)100 public void getVersion( 101 @NonNull @CallbackExecutor Executor callbackExecutor, 102 @NonNull LongConsumer versionConsumer) { 103 try { 104 RemoteCallback callback = new RemoteCallback(result -> { 105 if (result == null) { 106 Binder.withCleanCallingIdentity( 107 () -> callbackExecutor.execute(() -> versionConsumer.accept(0))); 108 } 109 long version = result.getLong(API_VERSION_BUNDLE_KEY); 110 Binder.withCleanCallingIdentity( 111 () -> callbackExecutor.execute(() -> versionConsumer.accept(version))); 112 }); 113 mService.getVersion(callback); 114 } catch (RemoteException e) { 115 throw e.rethrowFromSystemServer(); 116 } 117 } 118 119 120 /** 121 * Get package name configured for providing the remote implementation for this system service. 122 */ 123 @Nullable 124 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) getRemoteServicePackageName()125 public String getRemoteServicePackageName() { 126 String result; 127 try { 128 result = mService.getRemoteServicePackageName(); 129 } catch (RemoteException e) { 130 throw e.rethrowFromSystemServer(); 131 } 132 return result; 133 } 134 135 /** 136 * Asynchronously get feature for a given id. 137 * 138 * @param featureId the identifier pointing to the feature. 139 * @param featureReceiver callback to populate the feature object for given identifier. 140 * @param callbackExecutor executor to run the callback on. 141 */ 142 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) getFeature( int featureId, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull OutcomeReceiver<Feature, OnDeviceIntelligenceException> featureReceiver)143 public void getFeature( 144 int featureId, 145 @NonNull @CallbackExecutor Executor callbackExecutor, 146 @NonNull OutcomeReceiver<Feature, OnDeviceIntelligenceException> featureReceiver) { 147 try { 148 IFeatureCallback callback = 149 new IFeatureCallback.Stub() { 150 @Override 151 public void onSuccess(Feature result) { 152 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 153 () -> featureReceiver.onResult(result))); 154 } 155 156 @Override 157 public void onFailure(int errorCode, String errorMessage, 158 PersistableBundle errorParams) { 159 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 160 () -> featureReceiver.onError( 161 new OnDeviceIntelligenceException( 162 errorCode, errorMessage, errorParams)))); 163 } 164 }; 165 mService.getFeature(featureId, callback); 166 } catch (RemoteException e) { 167 throw e.rethrowFromSystemServer(); 168 } 169 } 170 171 /** 172 * Asynchronously get a list of features that are supported for the caller. 173 * 174 * @param featureListReceiver callback to populate the list of features. 175 * @param callbackExecutor executor to run the callback on. 176 */ 177 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) listFeatures( @onNull @allbackExecutor Executor callbackExecutor, @NonNull OutcomeReceiver<List<Feature>, OnDeviceIntelligenceException> featureListReceiver)178 public void listFeatures( 179 @NonNull @CallbackExecutor Executor callbackExecutor, 180 @NonNull OutcomeReceiver<List<Feature>, OnDeviceIntelligenceException> featureListReceiver) { 181 try { 182 IListFeaturesCallback callback = 183 new IListFeaturesCallback.Stub() { 184 @Override 185 public void onSuccess(List<Feature> result) { 186 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 187 () -> featureListReceiver.onResult(result))); 188 } 189 190 @Override 191 public void onFailure(int errorCode, String errorMessage, 192 PersistableBundle errorParams) { 193 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 194 () -> featureListReceiver.onError( 195 new OnDeviceIntelligenceException( 196 errorCode, errorMessage, errorParams)))); 197 } 198 }; 199 mService.listFeatures(callback); 200 } catch (RemoteException e) { 201 throw e.rethrowFromSystemServer(); 202 } 203 } 204 205 /** 206 * This method should be used to fetch details about a feature which need some additional 207 * computation, that can be inefficient to return in all calls to {@link #getFeature}. Callers 208 * and implementation can utilize the {@link Feature#getFeatureParams()} to pass hint on what 209 * details are expected by the caller. 210 * 211 * @param feature the feature to check status for. 212 * @param featureDetailsReceiver callback to populate the feature details to. 213 * @param callbackExecutor executor to run the callback on. 214 */ 215 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) getFeatureDetails(@onNull Feature feature, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull OutcomeReceiver<FeatureDetails, OnDeviceIntelligenceException> featureDetailsReceiver)216 public void getFeatureDetails(@NonNull Feature feature, 217 @NonNull @CallbackExecutor Executor callbackExecutor, 218 @NonNull OutcomeReceiver<FeatureDetails, OnDeviceIntelligenceException> featureDetailsReceiver) { 219 try { 220 IFeatureDetailsCallback callback = new IFeatureDetailsCallback.Stub() { 221 222 @Override 223 public void onSuccess(FeatureDetails result) { 224 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 225 () -> featureDetailsReceiver.onResult(result))); 226 } 227 228 @Override 229 public void onFailure(int errorCode, String errorMessage, 230 PersistableBundle errorParams) { 231 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 232 () -> featureDetailsReceiver.onError( 233 new OnDeviceIntelligenceException(errorCode, 234 errorMessage, errorParams)))); 235 } 236 }; 237 mService.getFeatureDetails(feature, callback); 238 } catch (RemoteException e) { 239 throw e.rethrowFromSystemServer(); 240 } 241 } 242 243 /** 244 * This method handles downloading all model and config files required to process requests 245 * sent against a given feature. The caller can listen to updates on the download status via 246 * the callback. 247 * 248 * Note: If a feature was already requested for downloaded previously, the onDownloadFailed 249 * callback would be invoked with {@link DownloadCallback#DOWNLOAD_FAILURE_STATUS_DOWNLOADING}. 250 * In such cases, clients should query the feature status via {@link #getFeatureDetails} to 251 * check on the feature's download status. 252 * 253 * @param feature feature to request download for. 254 * @param callback callback to populate updates about download status. 255 * @param cancellationSignal signal to invoke cancellation on the operation in the remote 256 * implementation. 257 * @param callbackExecutor executor to run the callback on. 258 */ 259 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) requestFeatureDownload(@onNull Feature feature, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull DownloadCallback callback)260 public void requestFeatureDownload(@NonNull Feature feature, 261 @Nullable CancellationSignal cancellationSignal, 262 @NonNull @CallbackExecutor Executor callbackExecutor, 263 @NonNull DownloadCallback callback) { 264 try { 265 IDownloadCallback downloadCallback = new IDownloadCallback.Stub() { 266 267 @Override 268 public void onDownloadStarted(long bytesToDownload) { 269 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 270 () -> callback.onDownloadStarted(bytesToDownload))); 271 } 272 273 @Override 274 public void onDownloadProgress(long bytesDownloaded) { 275 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 276 () -> callback.onDownloadProgress(bytesDownloaded))); 277 } 278 279 @Override 280 public void onDownloadFailed(int failureStatus, String errorMessage, 281 PersistableBundle errorParams) { 282 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 283 () -> callback.onDownloadFailed(failureStatus, errorMessage, 284 errorParams))); 285 } 286 287 @Override 288 public void onDownloadCompleted(PersistableBundle downloadParams) { 289 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 290 () -> callback.onDownloadCompleted(downloadParams))); 291 } 292 }; 293 294 mService.requestFeatureDownload(feature, 295 configureRemoteCancellationFuture(cancellationSignal, callbackExecutor), 296 downloadCallback); 297 } catch (RemoteException e) { 298 throw e.rethrowFromSystemServer(); 299 } 300 } 301 302 303 /** 304 * The methods computes the token related information for a given request payload using the 305 * provided {@link Feature}. 306 * 307 * @param feature feature associated with the request. 308 * @param request request and associated params represented by the Bundle 309 * data. 310 * @param outcomeReceiver callback to populate the token info or exception in case of 311 * failure. 312 * @param cancellationSignal signal to invoke cancellation on the operation in the remote 313 * implementation. 314 * @param callbackExecutor executor to run the callback on. 315 */ 316 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) requestTokenInfo(@onNull Feature feature, @NonNull @InferenceParams Bundle request, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull OutcomeReceiver<TokenInfo, OnDeviceIntelligenceException> outcomeReceiver)317 public void requestTokenInfo(@NonNull Feature feature, @NonNull @InferenceParams Bundle request, 318 @Nullable CancellationSignal cancellationSignal, 319 @NonNull @CallbackExecutor Executor callbackExecutor, 320 @NonNull OutcomeReceiver<TokenInfo, 321 OnDeviceIntelligenceException> outcomeReceiver) { 322 try { 323 ITokenInfoCallback callback = new ITokenInfoCallback.Stub() { 324 @Override 325 public void onSuccess(TokenInfo tokenInfo) { 326 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 327 () -> outcomeReceiver.onResult(tokenInfo))); 328 } 329 330 @Override 331 public void onFailure(int errorCode, String errorMessage, 332 PersistableBundle errorParams) { 333 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 334 () -> outcomeReceiver.onError( 335 new OnDeviceIntelligenceException( 336 errorCode, errorMessage, errorParams)))); 337 } 338 }; 339 340 mService.requestTokenInfo(feature, request, 341 configureRemoteCancellationFuture(cancellationSignal, callbackExecutor), 342 callback); 343 } catch (RemoteException e) { 344 throw e.rethrowFromSystemServer(); 345 } 346 } 347 348 349 /** 350 * Asynchronously Process a request based on the associated params, to populate a 351 * response in 352 * {@link OutcomeReceiver#onResult} callback or failure callback status code if there 353 * was a 354 * failure. 355 * 356 * @param feature feature associated with the request. 357 * @param request request and associated params represented by the Bundle 358 * data. 359 * @param requestType type of request being sent for processing the content. 360 * @param cancellationSignal signal to invoke cancellation. 361 * @param processingSignal signal to send custom signals in the 362 * remote implementation. 363 * @param callbackExecutor executor to run the callback on. 364 * @param processingCallback callback to populate the response content and 365 * associated params. 366 */ 367 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) processRequest(@onNull Feature feature, @NonNull @InferenceParams Bundle request, @RequestType int requestType, @Nullable CancellationSignal cancellationSignal, @Nullable ProcessingSignal processingSignal, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull ProcessingCallback processingCallback)368 public void processRequest(@NonNull Feature feature, @NonNull @InferenceParams Bundle request, 369 @RequestType int requestType, 370 @Nullable CancellationSignal cancellationSignal, 371 @Nullable ProcessingSignal processingSignal, 372 @NonNull @CallbackExecutor Executor callbackExecutor, 373 @NonNull ProcessingCallback processingCallback) { 374 try { 375 IResponseCallback callback = new IResponseCallback.Stub() { 376 @Override 377 public void onSuccess(@InferenceParams Bundle result) { 378 Binder.withCleanCallingIdentity(() -> { 379 callbackExecutor.execute(() -> processingCallback.onResult(result)); 380 }); 381 } 382 383 @Override 384 public void onFailure(int errorCode, String errorMessage, 385 PersistableBundle errorParams) { 386 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 387 () -> processingCallback.onError( 388 new OnDeviceIntelligenceException( 389 errorCode, errorMessage, errorParams)))); 390 } 391 392 @Override 393 public void onDataAugmentRequest(@NonNull @InferenceParams Bundle request, 394 @NonNull RemoteCallback contentCallback) { 395 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 396 () -> processingCallback.onDataAugmentRequest(request, result -> { 397 Bundle bundle = new Bundle(); 398 bundle.putParcelable(AUGMENT_REQUEST_CONTENT_BUNDLE_KEY, result); 399 callbackExecutor.execute(() -> contentCallback.sendResult(bundle)); 400 }))); 401 } 402 }; 403 404 405 mService.processRequest(feature, request, requestType, 406 configureRemoteCancellationFuture(cancellationSignal, callbackExecutor), 407 configureRemoteProcessingSignalFuture(processingSignal, callbackExecutor), 408 callback); 409 410 } catch (RemoteException e) { 411 throw e.rethrowFromSystemServer(); 412 } 413 } 414 415 /** 416 * Variation of {@link #processRequest} that asynchronously processes a request in a 417 * streaming 418 * fashion, where new content is pushed to caller in chunks via the 419 * {@link StreamingProcessingCallback#onPartialResult}. After the streaming is complete, 420 * the service should call {@link StreamingProcessingCallback#onResult} and can optionally 421 * populate the complete the full response {@link Bundle} as part of the callback in cases 422 * when the final response contains an enhanced aggregation of the contents already 423 * streamed. 424 * 425 * @param feature feature associated with the request. 426 * @param request request and associated params represented by the Bundle 427 * data. 428 * @param requestType type of request being sent for processing the content. 429 * @param cancellationSignal signal to invoke cancellation. 430 * @param processingSignal signal to send custom signals in the 431 * remote implementation. 432 * @param streamingProcessingCallback streaming callback to populate the response content and 433 * associated params. 434 * @param callbackExecutor executor to run the callback on. 435 */ 436 @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) processRequestStreaming(@onNull Feature feature, @NonNull @InferenceParams Bundle request, @RequestType int requestType, @Nullable CancellationSignal cancellationSignal, @Nullable ProcessingSignal processingSignal, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull StreamingProcessingCallback streamingProcessingCallback)437 public void processRequestStreaming(@NonNull Feature feature, 438 @NonNull @InferenceParams Bundle request, 439 @RequestType int requestType, 440 @Nullable CancellationSignal cancellationSignal, 441 @Nullable ProcessingSignal processingSignal, 442 @NonNull @CallbackExecutor Executor callbackExecutor, 443 @NonNull StreamingProcessingCallback streamingProcessingCallback) { 444 try { 445 IStreamingResponseCallback callback = new IStreamingResponseCallback.Stub() { 446 @Override 447 public void onNewContent(@InferenceParams Bundle result) { 448 Binder.withCleanCallingIdentity(() -> { 449 callbackExecutor.execute( 450 () -> streamingProcessingCallback.onPartialResult(result)); 451 }); 452 } 453 454 @Override 455 public void onSuccess(@InferenceParams Bundle result) { 456 Binder.withCleanCallingIdentity(() -> { 457 callbackExecutor.execute( 458 () -> streamingProcessingCallback.onResult(result)); 459 }); 460 } 461 462 @Override 463 public void onFailure(int errorCode, String errorMessage, 464 PersistableBundle errorParams) { 465 Binder.withCleanCallingIdentity(() -> { 466 callbackExecutor.execute( 467 () -> streamingProcessingCallback.onError( 468 new OnDeviceIntelligenceException( 469 errorCode, errorMessage, errorParams))); 470 }); 471 } 472 473 474 @Override 475 public void onDataAugmentRequest(@NonNull @InferenceParams Bundle content, 476 @NonNull RemoteCallback contentCallback) { 477 Binder.withCleanCallingIdentity(() -> callbackExecutor.execute( 478 () -> streamingProcessingCallback.onDataAugmentRequest(content, 479 contentResponse -> { 480 Bundle bundle = new Bundle(); 481 bundle.putParcelable(AUGMENT_REQUEST_CONTENT_BUNDLE_KEY, 482 contentResponse); 483 callbackExecutor.execute( 484 () -> contentCallback.sendResult(bundle)); 485 }))); 486 } 487 }; 488 489 mService.processRequestStreaming( 490 feature, request, requestType, 491 configureRemoteCancellationFuture(cancellationSignal, callbackExecutor), 492 configureRemoteProcessingSignalFuture(processingSignal, callbackExecutor), 493 callback); 494 } catch (RemoteException e) { 495 throw e.rethrowFromSystemServer(); 496 } 497 } 498 499 /** 500 * This is primarily intended to be used to attribute/blame on-device intelligence power usage, 501 * via the configured remote implementation, to its actual caller. 502 * 503 * @param startTimeEpochMillis epoch millis used to filter the InferenceInfo events. 504 * @return InferenceInfo events since the passed in startTimeEpochMillis. 505 * 506 * @hide 507 */ 508 @RequiresPermission(Manifest.permission.DUMP) getLatestInferenceInfo(long startTimeEpochMillis)509 public List<InferenceInfo> getLatestInferenceInfo(long startTimeEpochMillis) { 510 try { 511 return mService.getLatestInferenceInfo(startTimeEpochMillis); 512 } catch (RemoteException e) { 513 throw e.rethrowFromSystemServer(); 514 } 515 } 516 517 518 /** Request inference with provided Bundle and Params. */ 519 public static final int REQUEST_TYPE_INFERENCE = 0; 520 521 /** 522 * Prepares the remote implementation environment for e.g.loading inference runtime etc 523 * .which 524 * are time consuming beforehand to remove overhead and allow quick processing of requests 525 * thereof. 526 */ 527 public static final int REQUEST_TYPE_PREPARE = 1; 528 529 /** Request Embeddings of the passed-in Bundle. */ 530 public static final int REQUEST_TYPE_EMBEDDINGS = 2; 531 532 /** 533 * @hide 534 */ 535 @IntDef(value = { 536 REQUEST_TYPE_INFERENCE, 537 REQUEST_TYPE_PREPARE, 538 REQUEST_TYPE_EMBEDDINGS 539 }, open = true) 540 @Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.PARAMETER, 541 ElementType.FIELD}) 542 @Retention(RetentionPolicy.SOURCE) 543 public @interface RequestType { 544 } 545 546 /** 547 * {@link Bundle}s annotated with this type will be validated that they are in-effect read-only 548 * when passed via Binder IPC. Following restrictions apply : 549 * <ul> 550 * <li> {@link PersistableBundle}s are allowed.</li> 551 * <li> Any primitive types or their collections can be added as usual.</li> 552 * <li>IBinder objects should *not* be added.</li> 553 * <li>Parcelable data which has no active-objects, should be added as 554 * {@link Bundle#putByteArray}</li> 555 * <li>Parcelables have active-objects, only following types will be allowed</li> 556 * <ul> 557 * <li>{@link android.os.ParcelFileDescriptor} opened in 558 * {@link android.os.ParcelFileDescriptor#MODE_READ_ONLY}</li> 559 * </ul> 560 * </ul> 561 * 562 * In all other scenarios the system-server might throw a 563 * {@link android.os.BadParcelableException} if the Bundle validation fails. 564 * 565 * @hide 566 */ 567 @Target({ElementType.PARAMETER, ElementType.FIELD}) 568 public @interface StateParams { 569 } 570 571 /** 572 * This is an extension of {@link StateParams} but for purpose of inference few other types are 573 * also allowed as read-only, as listed below. 574 * 575 * <li>{@link Bitmap} set as immutable.</li> 576 * <li>{@link android.database.CursorWindow}</li> 577 * <li>{@link android.os.SharedMemory} set to {@link OsConstants#PROT_READ}</li> 578 * </ul> 579 * </ul> 580 * 581 * In all other scenarios the system-server might throw a 582 * {@link android.os.BadParcelableException} if the Bundle validation fails. 583 * 584 * @hide 585 */ 586 @Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.TYPE_USE}) 587 public @interface InferenceParams { 588 } 589 590 /** 591 * This is an extension of {@link StateParams} with the exception that it allows writing 592 * {@link Bitmap} as part of the response. 593 * 594 * In all other scenarios the system-server might throw a 595 * {@link android.os.BadParcelableException} if the Bundle validation fails. 596 * 597 * @hide 598 */ 599 @Target({ElementType.PARAMETER, ElementType.FIELD}) 600 public @interface ResponseParams { 601 } 602 603 @Nullable configureRemoteCancellationFuture( @ullable CancellationSignal cancellationSignal, @NonNull Executor callbackExecutor)604 private static AndroidFuture<IBinder> configureRemoteCancellationFuture( 605 @Nullable CancellationSignal cancellationSignal, 606 @NonNull Executor callbackExecutor) { 607 if (cancellationSignal == null) { 608 return null; 609 } 610 AndroidFuture<IBinder> cancellationFuture = new AndroidFuture<>(); 611 cancellationFuture.whenCompleteAsync( 612 (cancellationTransport, error) -> { 613 if (error != null || cancellationTransport == null) { 614 Log.e(TAG, "Unable to receive the remote cancellation signal.", error); 615 } else { 616 cancellationSignal.setRemote( 617 ICancellationSignal.Stub.asInterface(cancellationTransport)); 618 } 619 }, callbackExecutor); 620 return cancellationFuture; 621 } 622 623 @Nullable configureRemoteProcessingSignalFuture( ProcessingSignal processingSignal, Executor executor)624 private static AndroidFuture<IBinder> configureRemoteProcessingSignalFuture( 625 ProcessingSignal processingSignal, Executor executor) { 626 if (processingSignal == null) { 627 return null; 628 } 629 AndroidFuture<IBinder> processingSignalFuture = new AndroidFuture<>(); 630 processingSignalFuture.whenCompleteAsync( 631 (transport, error) -> { 632 if (error != null || transport == null) { 633 Log.e(TAG, "Unable to receive the remote processing signal.", error); 634 } else { 635 processingSignal.setRemote(IProcessingSignal.Stub.asInterface(transport)); 636 } 637 }, executor); 638 return processingSignalFuture; 639 } 640 641 642 } 643