1 /* 2 * Copyright 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 android.uwb; 18 19 import static com.android.internal.util.Preconditions.checkNotNull; 20 21 import android.Manifest.permission; 22 import android.annotation.CallbackExecutor; 23 import android.annotation.FlaggedApi; 24 import android.annotation.IntDef; 25 import android.annotation.IntRange; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.RequiresPermission; 29 import android.annotation.SuppressLint; 30 import android.annotation.SystemApi; 31 import android.annotation.SystemService; 32 import android.content.Context; 33 import android.os.Binder; 34 import android.os.Build; 35 import android.os.CancellationSignal; 36 import android.os.PersistableBundle; 37 import android.os.RemoteException; 38 import android.util.Log; 39 40 import androidx.annotation.RequiresApi; 41 42 import com.android.internal.annotations.GuardedBy; 43 44 import java.lang.annotation.Retention; 45 import java.lang.annotation.RetentionPolicy; 46 import java.util.List; 47 import java.util.Objects; 48 import java.util.concurrent.Executor; 49 import java.util.function.Consumer; 50 51 /** 52 * This class provides a way to perform Ultra Wideband (UWB) operations such as querying the 53 * device's capabilities and determining the distance and angle between the local device and a 54 * remote device. 55 * 56 * <p>To get a {@link UwbManager}, call the <code>Context.getSystemService(UwbManager.class)</code>. 57 * 58 * <p> Note: This API surface uses opaque {@link PersistableBundle} params. These params are to be 59 * created using the provided UWB support library. The support library is present in this 60 * location on AOSP: <code>packages/modules/Uwb/service/support_lib/</code> 61 * 62 * @hide 63 */ 64 @SystemApi 65 @SystemService(Context.UWB_SERVICE) 66 public final class UwbManager { 67 private static final String TAG = "UwbManager"; 68 69 private final Context mContext; 70 private final IUwbAdapter mUwbAdapter; 71 private final AdapterStateListener mAdapterStateListener; 72 private final RangingManager mRangingManager; 73 private final UwbVendorUciCallbackListener mUwbVendorUciCallbackListener; 74 private final UwbOemExtensionCallbackListener mUwbOemExtensionCallbackListener; 75 76 /** 77 * Interface for receiving UWB adapter state changes 78 */ 79 public interface AdapterStateCallback { 80 /** 81 * @hide 82 */ 83 @Retention(RetentionPolicy.SOURCE) 84 @IntDef(value = { 85 STATE_CHANGED_REASON_SESSION_STARTED, 86 STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED, 87 STATE_CHANGED_REASON_SYSTEM_POLICY, 88 STATE_CHANGED_REASON_SYSTEM_BOOT, 89 STATE_CHANGED_REASON_ERROR_UNKNOWN, 90 STATE_CHANGED_REASON_SYSTEM_REGULATION}) 91 @interface StateChangedReason {} 92 93 /** 94 * @hide 95 */ 96 @Retention(RetentionPolicy.SOURCE) 97 @IntDef(value = { 98 STATE_ENABLED_INACTIVE, 99 STATE_ENABLED_ACTIVE, 100 STATE_DISABLED, 101 STATE_ENABLED_HW_IDLE}) 102 @interface State {} 103 104 /** 105 * Indicates that the state change was due to opening of first UWB session 106 */ 107 int STATE_CHANGED_REASON_SESSION_STARTED = 0; 108 109 /** 110 * Indicates that the state change was due to closure of all UWB sessions 111 */ 112 int STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED = 1; 113 114 /** 115 * Indicates that the state change was due to changes in system policy 116 */ 117 int STATE_CHANGED_REASON_SYSTEM_POLICY = 2; 118 119 /** 120 * Indicates that the current state is due to a system boot 121 */ 122 int STATE_CHANGED_REASON_SYSTEM_BOOT = 3; 123 124 /** 125 * Indicates that the state change was due to some unknown error 126 */ 127 int STATE_CHANGED_REASON_ERROR_UNKNOWN = 4; 128 129 /** 130 * Indicates that the state change is due to a system regulation. 131 */ 132 int STATE_CHANGED_REASON_SYSTEM_REGULATION = 5; 133 134 /** 135 * Indicates that UWB is disabled on device 136 */ 137 int STATE_DISABLED = 0; 138 /** 139 * Indicates that UWB is enabled on device but has no active ranging sessions 140 */ 141 int STATE_ENABLED_INACTIVE = 1; 142 143 /** 144 * Indicates that UWB is enabled and has active ranging session 145 */ 146 int STATE_ENABLED_ACTIVE = 2; 147 148 /** 149 * The state when UWB is enabled by user but the hardware is not enabled since no clients 150 * have requested for it. 151 * Only sent if the device supports {@link #isUwbHwIdleTurnOffEnabled()} feature. 152 */ 153 @FlaggedApi("com.android.uwb.flags.hw_state") 154 int STATE_ENABLED_HW_IDLE = 3; 155 156 /** 157 * Invoked when underlying UWB adapter's state is changed 158 * <p>Invoked with the adapter's current state after registering an 159 * {@link AdapterStateCallback} using 160 * {@link UwbManager#registerAdapterStateCallback(Executor, AdapterStateCallback)}. 161 * 162 * <p>Possible reasons for the state to change are 163 * {@link #STATE_CHANGED_REASON_SESSION_STARTED}, 164 * {@link #STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED}, 165 * {@link #STATE_CHANGED_REASON_SYSTEM_POLICY}, 166 * {@link #STATE_CHANGED_REASON_SYSTEM_BOOT}, 167 * {@link #STATE_CHANGED_REASON_ERROR_UNKNOWN}. 168 * {@link #STATE_CHANGED_REASON_SYSTEM_REGULATION}. 169 * 170 * <p>Possible values for the UWB state are 171 * {@link #STATE_ENABLED_INACTIVE}, 172 * {@link #STATE_ENABLED_ACTIVE}, 173 * {@link #STATE_DISABLED}. 174 * 175 * @param state the UWB state; inactive, active or disabled 176 * @param reason the reason for the state change 177 */ onStateChanged(@tate int state, @StateChangedReason int reason)178 void onStateChanged(@State int state, @StateChangedReason int reason); 179 } 180 181 /** 182 * Abstract class for receiving ADF provisioning state. 183 * Should be extended by applications and set when calling 184 * {@link UwbManager#provisionProfileAdfByScript(PersistableBundle, Executor, 185 * AdfProvisionStateCallback)} 186 */ 187 public abstract static class AdfProvisionStateCallback { 188 private final AdfProvisionStateCallbackProxy mAdfProvisionStateCallbackProxy; 189 AdfProvisionStateCallback()190 public AdfProvisionStateCallback() { 191 mAdfProvisionStateCallbackProxy = new AdfProvisionStateCallbackProxy(); 192 } 193 194 /** 195 * @hide 196 */ 197 @Retention(RetentionPolicy.SOURCE) 198 @IntDef(value = { 199 REASON_INVALID_OID, 200 REASON_SE_FAILURE, 201 REASON_UNKNOWN 202 }) 203 @interface Reason { } 204 205 /** 206 * Indicates that the OID provided was not valid. 207 */ 208 public static final int REASON_INVALID_OID = 1; 209 210 /** 211 * Indicates that there was some SE (secure element) failure while provisioning. 212 */ 213 public static final int REASON_SE_FAILURE = 2; 214 215 /** 216 * No known reason for the failure. 217 */ 218 public static final int REASON_UNKNOWN = 3; 219 220 /** 221 * Invoked when {@link UwbManager#provisionProfileAdfByScript(PersistableBundle, Executor, 222 * AdfProvisionStateCallback)} is successful. 223 * 224 * @param params protocol specific params that provide the caller with provisioning info 225 **/ onProfileAdfsProvisioned(@onNull PersistableBundle params)226 public abstract void onProfileAdfsProvisioned(@NonNull PersistableBundle params); 227 228 /** 229 * Invoked when {@link UwbManager#provisionProfileAdfByScript(PersistableBundle, Executor, 230 * AdfProvisionStateCallback)} fails. 231 * 232 * @param reason Reason for failure 233 * @param params protocol specific parameters to indicate failure reason 234 */ onProfileAdfsProvisionFailed( @eason int reason, @NonNull PersistableBundle params)235 public abstract void onProfileAdfsProvisionFailed( 236 @Reason int reason, @NonNull PersistableBundle params); 237 238 /*package*/ 239 @NonNull getProxy()240 AdfProvisionStateCallbackProxy getProxy() { 241 return mAdfProvisionStateCallbackProxy; 242 } 243 244 private static class AdfProvisionStateCallbackProxy extends 245 IUwbAdfProvisionStateCallbacks.Stub { 246 private final Object mLock = new Object(); 247 @Nullable 248 @GuardedBy("mLock") 249 private Executor mExecutor; 250 @Nullable 251 @GuardedBy("mLock") 252 private AdfProvisionStateCallback mCallback; 253 AdfProvisionStateCallbackProxy()254 AdfProvisionStateCallbackProxy() { 255 mCallback = null; 256 mExecutor = null; 257 } 258 initProxy(@onNull Executor executor, @NonNull AdfProvisionStateCallback callback)259 /*package*/ void initProxy(@NonNull Executor executor, 260 @NonNull AdfProvisionStateCallback callback) { 261 synchronized (mLock) { 262 mExecutor = executor; 263 mCallback = callback; 264 } 265 } 266 cleanUpProxy()267 /*package*/ void cleanUpProxy() { 268 synchronized (mLock) { 269 mExecutor = null; 270 mCallback = null; 271 } 272 } 273 274 @Override onProfileAdfsProvisioned(@onNull PersistableBundle params)275 public void onProfileAdfsProvisioned(@NonNull PersistableBundle params) { 276 Log.v(TAG, "AdfProvisionStateCallbackProxy: onProfileAdfsProvisioned : " + params); 277 AdfProvisionStateCallback callback; 278 Executor executor; 279 synchronized (mLock) { 280 executor = mExecutor; 281 callback = mCallback; 282 } 283 if (callback == null || executor == null) { 284 return; 285 } 286 Binder.clearCallingIdentity(); 287 executor.execute(() -> callback.onProfileAdfsProvisioned(params)); 288 cleanUpProxy(); 289 } 290 291 @Override onProfileAdfsProvisionFailed(@dfProvisionStateCallback.Reason int reason, @NonNull PersistableBundle params)292 public void onProfileAdfsProvisionFailed(@AdfProvisionStateCallback.Reason int reason, 293 @NonNull PersistableBundle params) { 294 Log.v(TAG, "AdfProvisionStateCallbackProxy: onProfileAdfsProvisionFailed : " 295 + reason + ", " + params); 296 AdfProvisionStateCallback callback; 297 Executor executor; 298 synchronized (mLock) { 299 executor = mExecutor; 300 callback = mCallback; 301 } 302 if (callback == null || executor == null) { 303 return; 304 } 305 Binder.clearCallingIdentity(); 306 executor.execute(() -> callback.onProfileAdfsProvisionFailed(reason, params)); 307 cleanUpProxy(); 308 } 309 } 310 } 311 312 /** 313 * Interface for receiving vendor UCI responses and notifications. 314 */ 315 public interface UwbVendorUciCallback { 316 /** 317 * Invoked when a vendor specific UCI response is received. 318 * 319 * @param gid Group ID of the command. This needs to be one of the vendor reserved GIDs from 320 * the UCI specification. 321 * @param oid Opcode ID of the command. This is left to the OEM / vendor to decide. 322 * @param payload containing vendor Uci message payload. 323 */ onVendorUciResponse( @ntRangefrom = 0, to = 15) int gid, int oid, @NonNull byte[] payload)324 void onVendorUciResponse( 325 @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload); 326 327 /** 328 * Invoked when a vendor specific UCI notification is received. 329 * 330 * @param gid Group ID of the command. This needs to be one of the vendor reserved GIDs from 331 * the UCI specification. 332 * @param oid Opcode ID of the command. This is left to the OEM / vendor to decide. 333 * @param payload containing vendor Uci message payload. 334 */ onVendorUciNotification( @ntRangefrom = 9, to = 15) int gid, int oid, @NonNull byte[] payload)335 void onVendorUciNotification( 336 @IntRange(from = 9, to = 15) int gid, int oid, @NonNull byte[] payload); 337 } 338 339 340 /** 341 * @hide 342 * Vendor configuration successful for the session 343 */ 344 public static final int VENDOR_SET_SESSION_CONFIGURATION_SUCCESS = 0; 345 346 /** 347 * @hide 348 * Failure to set vendor configuration for the session 349 */ 350 public static final int VENDOR_SET_SESSION_CONFIGURATION_FAILURE = 1; 351 352 /** 353 * @hide 354 */ 355 @Retention(RetentionPolicy.SOURCE) 356 @IntDef(value = { 357 VENDOR_SET_SESSION_CONFIGURATION_SUCCESS, 358 VENDOR_SET_SESSION_CONFIGURATION_FAILURE, 359 }) 360 @interface VendorConfigStatus {} 361 362 363 /** 364 * Interface for Oem extensions on ongoing session 365 */ 366 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 367 public interface UwbOemExtensionCallback { 368 /** 369 * Invoked when session status changes. 370 * 371 * @param sessionStatusBundle session related info 372 */ onSessionStatusNotificationReceived(@onNull PersistableBundle sessionStatusBundle)373 void onSessionStatusNotificationReceived(@NonNull PersistableBundle sessionStatusBundle); 374 375 /** 376 * Invoked when DeviceStatusNotification is received from UCI. 377 * 378 * @param deviceStatusBundle device state 379 */ onDeviceStatusNotificationReceived(@onNull PersistableBundle deviceStatusBundle)380 void onDeviceStatusNotificationReceived(@NonNull PersistableBundle deviceStatusBundle); 381 382 /** 383 * Invoked when session configuration is complete. 384 * 385 * @param openSessionBundle Session Params 386 * @return Error code 387 */ onSessionConfigurationComplete( @onNull PersistableBundle openSessionBundle)388 @NonNull @VendorConfigStatus int onSessionConfigurationComplete( 389 @NonNull PersistableBundle openSessionBundle); 390 391 /** 392 * Invoked when ranging report is generated. 393 * 394 * @param rangingReport ranging report generated 395 * @return Oem modified ranging report 396 */ onRangingReportReceived( @onNull RangingReport rangingReport)397 @NonNull RangingReport onRangingReportReceived( 398 @NonNull RangingReport rangingReport); 399 400 /** 401 * Invoked to check pointed target decision by Oem. 402 * 403 * @param pointedTargetBundle pointed target params 404 * @return Oem pointed status 405 */ onCheckPointedTarget(@onNull PersistableBundle pointedTargetBundle)406 boolean onCheckPointedTarget(@NonNull PersistableBundle pointedTargetBundle); 407 } 408 409 /** 410 * Use <code>Context.getSystemService(UwbManager.class)</code> to get an instance. 411 * 412 * @param ctx Context of the client. 413 * @param adapter an instance of an {@link android.uwb.IUwbAdapter} 414 * @hide 415 */ UwbManager(@onNull Context ctx, @NonNull IUwbAdapter adapter)416 public UwbManager(@NonNull Context ctx, @NonNull IUwbAdapter adapter) { 417 mContext = ctx; 418 mUwbAdapter = adapter; 419 mAdapterStateListener = new AdapterStateListener(adapter); 420 mRangingManager = new RangingManager(adapter); 421 mUwbVendorUciCallbackListener = new UwbVendorUciCallbackListener(adapter); 422 mUwbOemExtensionCallbackListener = new UwbOemExtensionCallbackListener(adapter); 423 } 424 425 /** 426 * Register an {@link AdapterStateCallback} to listen for UWB adapter state changes 427 * <p>The provided callback will be invoked by the given {@link Executor}. 428 * 429 * <p>When first registering a callback, the callbacks's 430 * {@link AdapterStateCallback#onStateChanged(int, int)} is immediately invoked to indicate 431 * the current state of the underlying UWB adapter with the most recent 432 * {@link AdapterStateCallback.StateChangedReason} that caused the change. 433 * 434 * @param executor an {@link Executor} to execute given callback 435 * @param callback user implementation of the {@link AdapterStateCallback} 436 */ 437 @RequiresPermission(permission.UWB_PRIVILEGED) registerAdapterStateCallback(@onNull @allbackExecutor Executor executor, @NonNull AdapterStateCallback callback)438 public void registerAdapterStateCallback(@NonNull @CallbackExecutor Executor executor, 439 @NonNull AdapterStateCallback callback) { 440 mAdapterStateListener.register(executor, callback); 441 } 442 443 /** 444 * Unregister the specified {@link AdapterStateCallback} 445 * <p>The same {@link AdapterStateCallback} object used when calling 446 * {@link #registerAdapterStateCallback(Executor, AdapterStateCallback)} must be used. 447 * 448 * <p>Callbacks are automatically unregistered when application process goes away 449 * 450 * @param callback user implementation of the {@link AdapterStateCallback} 451 */ 452 @RequiresPermission(permission.UWB_PRIVILEGED) unregisterAdapterStateCallback(@onNull AdapterStateCallback callback)453 public void unregisterAdapterStateCallback(@NonNull AdapterStateCallback callback) { 454 mAdapterStateListener.unregister(callback); 455 } 456 457 /** 458 * Register an {@link UwbVendorUciCallback} to listen for UWB vendor responses and notifications 459 * <p>The provided callback will be invoked by the given {@link Executor}. 460 * 461 * <p>When first registering a callback, the callbacks's 462 * {@link UwbVendorUciCallback#onVendorUciCallBack(byte[])} is immediately invoked to 463 * notify the vendor notification. 464 * 465 * @param executor an {@link Executor} to execute given callback 466 * @param callback user implementation of the {@link UwbVendorUciCallback} 467 */ 468 @RequiresPermission(permission.UWB_PRIVILEGED) registerUwbVendorUciCallback(@onNull @allbackExecutor Executor executor, @NonNull UwbVendorUciCallback callback)469 public void registerUwbVendorUciCallback(@NonNull @CallbackExecutor Executor executor, 470 @NonNull UwbVendorUciCallback callback) { 471 mUwbVendorUciCallbackListener.register(executor, callback); 472 } 473 474 /** 475 * Unregister the specified {@link UwbVendorUciCallback} 476 * 477 * <p>The same {@link UwbVendorUciCallback} object used when calling 478 * {@link #registerUwbVendorUciCallback(Executor, UwbVendorUciCallback)} must be used. 479 * 480 * <p>Callbacks are automatically unregistered when application process goes away 481 * 482 * @param callback user implementation of the {@link UwbVendorUciCallback} 483 */ unregisterUwbVendorUciCallback(@onNull UwbVendorUciCallback callback)484 public void unregisterUwbVendorUciCallback(@NonNull UwbVendorUciCallback callback) { 485 mUwbVendorUciCallbackListener.unregister(callback); 486 } 487 488 /** 489 * Register an {@link UwbOemExtensionCallback} to listen for UWB oem extension callbacks 490 * <p>The provided callback will be invoked by the given {@link Executor}. 491 * 492 * @param executor an {@link Executor} to execute given callback 493 * @param callback oem implementation of {@link UwbOemExtensionCallback} 494 */ 495 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 496 @RequiresPermission(permission.UWB_PRIVILEGED) registerUwbOemExtensionCallback(@onNull @allbackExecutor Executor executor, @NonNull UwbOemExtensionCallback callback)497 public void registerUwbOemExtensionCallback(@NonNull @CallbackExecutor Executor executor, 498 @NonNull UwbOemExtensionCallback callback) { 499 mUwbOemExtensionCallbackListener.register(executor, callback); 500 } 501 502 /** 503 * Unregister the specified {@link UwbOemExtensionCallback} 504 * 505 * <p>The same {@link UwbOemExtensionCallback} object used when calling 506 * {@link #registerUwbOemExtensionCallback(Executor, UwbOemExtensionCallback)} must be used. 507 * 508 * <p>Callbacks are automatically unregistered when an application process goes away 509 * 510 * @param callback oem implementation of {@link UwbOemExtensionCallback} 511 */ 512 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 513 @RequiresPermission(permission.UWB_PRIVILEGED) unregisterUwbOemExtensionCallback(@onNull UwbOemExtensionCallback callback)514 public void unregisterUwbOemExtensionCallback(@NonNull UwbOemExtensionCallback callback) { 515 mUwbOemExtensionCallbackListener.unregister(callback); 516 } 517 518 /** 519 * Get a {@link PersistableBundle} with the supported UWB protocols and parameters. 520 * <p>The {@link PersistableBundle} should be parsed using a support library 521 * 522 * <p>Android reserves the '^android.*' namespace</p> 523 * 524 * @return {@link PersistableBundle} of the device's supported UWB protocols and parameters 525 */ 526 @NonNull 527 @RequiresPermission(permission.UWB_PRIVILEGED) getSpecificationInfo()528 public PersistableBundle getSpecificationInfo() { 529 return getSpecificationInfoInternal(/* chipId= */ null); 530 } 531 532 /** 533 * Get a {@link PersistableBundle} with the supported UWB protocols and parameters. 534 * 535 * @see #getSpecificationInfo() if you don't need multi-HAL support 536 * 537 * @param chipId identifier of UWB chip for multi-HAL devices 538 * 539 * @return {@link PersistableBundle} of the device's supported UWB protocols and parameters 540 */ 541 // TODO(b/205614701): Add documentation about how to find the relevant chipId 542 @NonNull 543 @RequiresPermission(permission.UWB_PRIVILEGED) getSpecificationInfo(@onNull String chipId)544 public PersistableBundle getSpecificationInfo(@NonNull String chipId) { 545 checkNotNull(chipId); 546 return getSpecificationInfoInternal(chipId); 547 } 548 getSpecificationInfoInternal(String chipId)549 private PersistableBundle getSpecificationInfoInternal(String chipId) { 550 try { 551 return mUwbAdapter.getSpecificationInfo(chipId); 552 } catch (RemoteException e) { 553 throw e.rethrowFromSystemServer(); 554 } 555 } 556 557 /** 558 * Get uwbs timestamp in micros. 559 * 560 * @return uwb device timestamp in micros. 561 */ 562 @NonNull 563 @RequiresPermission(permission.UWB_PRIVILEGED) 564 @FlaggedApi("com.android.uwb.flags.query_timestamp_micros") queryUwbsTimestampMicros()565 public long queryUwbsTimestampMicros() { 566 try { 567 return mUwbAdapter.queryUwbsTimestampMicros(); 568 } catch (RemoteException e) { 569 throw e.rethrowFromSystemServer(); 570 } 571 } 572 573 /** 574 * Get the timestamp resolution for events in nanoseconds 575 * <p>This value defines the maximum error of all timestamps for events reported to 576 * {@link RangingSession.Callback}. 577 * 578 * @return the timestamp resolution in nanoseconds 579 */ 580 @SuppressLint("MethodNameUnits") 581 @RequiresPermission(permission.UWB_PRIVILEGED) elapsedRealtimeResolutionNanos()582 public long elapsedRealtimeResolutionNanos() { 583 return elapsedRealtimeResolutionNanosInternal(/* chipId= */ null); 584 } 585 586 /** 587 * Get the timestamp resolution for events in nanoseconds 588 * 589 * @see #elapsedRealtimeResolutionNanos() if you don't need multi-HAL support 590 * 591 * @param chipId identifier of UWB chip for multi-HAL devices 592 * 593 * @return the timestamp resolution in nanoseconds 594 */ 595 @SuppressLint("MethodNameUnits") 596 @RequiresPermission(permission.UWB_PRIVILEGED) elapsedRealtimeResolutionNanos(@onNull String chipId)597 public long elapsedRealtimeResolutionNanos(@NonNull String chipId) { 598 checkNotNull(chipId); 599 return elapsedRealtimeResolutionNanosInternal(chipId); 600 } 601 elapsedRealtimeResolutionNanosInternal(String chipId)602 private long elapsedRealtimeResolutionNanosInternal(String chipId) { 603 try { 604 return mUwbAdapter.getTimestampResolutionNanos(chipId); 605 } catch (RemoteException e) { 606 throw e.rethrowFromSystemServer(); 607 } 608 } 609 610 /** 611 * Open a {@link RangingSession} with the given parameters 612 * <p>The {@link RangingSession.Callback#onOpened(RangingSession)} function is called with a 613 * {@link RangingSession} object used to control ranging when the session is successfully 614 * opened. 615 * 616 * if this session uses FIRA defined profile (not custom profile), this triggers: 617 * - OOB discovery using service UUID 618 * - OOB connection establishment after discovery for session params 619 * negotiation. 620 * - Secure element interactions needed for dynamic STS based session establishment. 621 * - Setup the UWB session based on the parameters negotiated via OOB. 622 * - Note: The OOB flow requires additional BLE Permissions 623 * {permission.BLUETOOTH_ADVERTISE/permission.BLUETOOTH_SCAN 624 * and permission.BLUETOOTH_CONNECT}. 625 * 626 * <p>If a session cannot be opened, then 627 * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} will be invoked with the 628 * appropriate {@link RangingSession.Callback.Reason}. 629 * 630 * <p>An open {@link RangingSession} will be automatically closed if client application process 631 * dies. 632 * 633 * <p>A UWB support library must be used in order to construct the {@code parameter} 634 * {@link PersistableBundle}. 635 * 636 * @param parameters the parameters that define the ranging session 637 * @param executor {@link Executor} to run callbacks 638 * @param callbacks {@link RangingSession.Callback} to associate with the 639 * {@link RangingSession} that is being opened. 640 * 641 * @return an {@link CancellationSignal} that is able to be used to cancel the opening of a 642 * {@link RangingSession} that has been requested through {@link #openRangingSession} 643 * but has not yet been made available by 644 * {@link RangingSession.Callback#onOpened(RangingSession)}. 645 */ 646 @NonNull 647 @RequiresPermission(allOf = { 648 permission.UWB_PRIVILEGED, 649 permission.UWB_RANGING 650 }) openRangingSession(@onNull PersistableBundle parameters, @NonNull @CallbackExecutor Executor executor, @NonNull RangingSession.Callback callbacks)651 public CancellationSignal openRangingSession(@NonNull PersistableBundle parameters, 652 @NonNull @CallbackExecutor Executor executor, 653 @NonNull RangingSession.Callback callbacks) { 654 return openRangingSessionInternal(parameters, executor, callbacks, /* chipId= */ null); 655 } 656 657 /** 658 * Open a {@link RangingSession} with the given parameters on a specific UWB subsystem 659 * 660 * @see #openRangingSession(PersistableBundle, Executor, RangingSession.Callback) if you don't 661 * need multi-HAL support 662 * 663 * @param parameters the parameters that define the ranging session 664 * @param executor {@link Executor} to run callbacks 665 * @param callbacks {@link RangingSession.Callback} to associate with the 666 * {@link RangingSession} that is being opened. 667 * @param chipId identifier of UWB chip for multi-HAL devices 668 * 669 * @return an {@link CancellationSignal} that is able to be used to cancel the opening of a 670 * {@link RangingSession} that has been requested through {@link #openRangingSession} 671 * but has not yet been made available by 672 * {@link RangingSession.Callback#onOpened(RangingSession)}. 673 */ 674 @NonNull 675 @RequiresPermission(allOf = { 676 permission.UWB_PRIVILEGED, 677 permission.UWB_RANGING 678 }) openRangingSession(@onNull PersistableBundle parameters, @NonNull @CallbackExecutor Executor executor, @NonNull RangingSession.Callback callbacks, @SuppressLint("ListenerLast") @NonNull String chipId)679 public CancellationSignal openRangingSession(@NonNull PersistableBundle parameters, 680 @NonNull @CallbackExecutor Executor executor, 681 @NonNull RangingSession.Callback callbacks, 682 @SuppressLint("ListenerLast") @NonNull String chipId) { 683 checkNotNull(chipId); 684 return openRangingSessionInternal(parameters, executor, callbacks, chipId); 685 } 686 openRangingSessionInternal(PersistableBundle parameters, Executor executor, RangingSession.Callback callbacks, String chipId)687 private CancellationSignal openRangingSessionInternal(PersistableBundle parameters, 688 Executor executor, RangingSession.Callback callbacks, String chipId) { 689 return mRangingManager.openSession( 690 mContext.getAttributionSource(), parameters, executor, callbacks, chipId); 691 } 692 693 /** 694 * Returns the current enabled/disabled state for UWB. 695 * 696 * Possible values are: 697 * AdapterStateCallback#STATE_DISABLED 698 * AdapterStateCallback#STATE_ENABLED_INACTIVE 699 * AdapterStateCallback#STATE_ENABLED_ACTIVE 700 * 701 * @return value representing current enabled/disabled state for UWB. 702 */ getAdapterState()703 public @AdapterStateCallback.State int getAdapterState() { 704 return mAdapterStateListener.getAdapterState(); 705 } 706 707 /** 708 * Whether UWB is enabled or disabled. 709 * 710 * <p> 711 * If disabled, this could indicate that either 712 * <li> User has toggled UWB off from settings, OR </li> 713 * <li> UWB subsystem has shut down due to a fatal error. </li> 714 * </p> 715 * 716 * @return true if enabled, false otherwise. 717 * 718 * @see #getAdapterState() 719 * @see #setUwbEnabled(boolean) 720 */ isUwbEnabled()721 public boolean isUwbEnabled() { 722 int adapterState = getAdapterState(); 723 return adapterState != AdapterStateCallback.STATE_DISABLED; 724 } 725 726 /** 727 * Disables or enables UWB by the user. 728 * 729 * If enabled any subsequent calls to 730 * {@link #openRangingSession(PersistableBundle, Executor, RangingSession.Callback)} will be 731 * allowed. If disabled, all active ranging sessions will be closed and subsequent calls to 732 * {@link #openRangingSession(PersistableBundle, Executor, RangingSession.Callback)} will be 733 * disallowed. 734 * 735 * @param enabled value representing intent to disable or enable UWB. 736 */ 737 @RequiresPermission(permission.UWB_PRIVILEGED) setUwbEnabled(boolean enabled)738 public void setUwbEnabled(boolean enabled) { 739 mAdapterStateListener.setEnabled(enabled); 740 } 741 742 /** 743 * Whether UWB hardware will automatically turn off when there are no clients requesting it. 744 * This feature is only turned on non-phone form factor devices which needs to keep the UWB 745 * hardware turned to avoid battery drain. 746 * 747 * <p> 748 * If the device supports automatically turning off UWB hardware, the state of UWB hardware 749 * is controlled by: 750 * <li> UWB user toggle state or Airplane mode state, AND </li> 751 * <li> Whether any clients are actively enabling UWB </li> 752 * </p> 753 * 754 * @return true if enabled, false otherwise. 755 * 756 * @see #isUwbHwEnableRequested() 757 * @see #requestUwbHwEnable(boolean) 758 */ 759 @FlaggedApi("com.android.uwb.flags.hw_state") 760 @RequiresPermission(permission.UWB_PRIVILEGED) isUwbHwIdleTurnOffEnabled()761 public boolean isUwbHwIdleTurnOffEnabled() { 762 try { 763 return mUwbAdapter.isHwIdleTurnOffEnabled(); 764 } catch (RemoteException e) { 765 throw e.rethrowFromSystemServer(); 766 } 767 } 768 769 /** 770 * Whether this client has requested for UWB hardware to be enabled or disabled. 771 * Only supported on devices which supports hw idle turn off (indicated by 772 * {@link #isUwbHwIdleTurnOffEnabled()}) 773 * 774 * <p> 775 * This does not indicate the global state of UWB, this only indicates whether this app 776 * (identified by {@link Context#getAttributionSource()}) has requested for UWB hardware to be 777 * enabled or disabled. 778 * </p> 779 * 780 * @return true if enabled, false otherwise. 781 * @throws IllegalStateException if the device does not support this feature 782 * 783 * @see #isUwbHwIdleTurnOffEnabled() 784 * @see #requestUwbHwEnable(boolean) 785 */ 786 @FlaggedApi("com.android.uwb.flags.hw_state") 787 @RequiresPermission(permission.UWB_PRIVILEGED) isUwbHwEnableRequested()788 public boolean isUwbHwEnableRequested() { 789 try { 790 return mUwbAdapter.isHwEnableRequested(mContext.getAttributionSource()); 791 } catch (RemoteException e) { 792 throw e.rethrowFromSystemServer(); 793 } 794 } 795 796 /** 797 * This client has requested for UWB hardware to be enabled or disabled. 798 * Only supported on devices which supports hw idle turn off (indicated by 799 * {@link #isUwbHwIdleTurnOffEnabled()}) 800 * 801 * <p> 802 * This does not indicate the global state of UWB, this only indicates whether this app 803 * (identified by {@link Context#getAttributionSource()}) has requested for UWB hardware to be 804 * enabled or disabled. 805 * If UWB is enabled by the user and has at least 1 privileged client requesting UWB toggle on, 806 * then UWB hardware is enabled, else the UWB hardware is disabled. 807 * </p> 808 * 809 * @param enabled value representing intent to disable or enable UWB. 810 * @throws IllegalStateException if the device does not support this feature 811 * 812 * @see #isUwbHwIdleTurnOffEnabled() 813 * @see #isUwbHwEnableRequested() () 814 */ 815 @FlaggedApi("com.android.uwb.flags.hw_state") 816 @RequiresPermission(permission.UWB_PRIVILEGED) requestUwbHwEnabled(boolean enabled)817 public void requestUwbHwEnabled(boolean enabled) { 818 try { 819 mUwbAdapter.requestHwEnabled( 820 enabled, mContext.getAttributionSource(), 821 new Binder(mContext.getPackageName())); 822 } catch (RemoteException e) { 823 throw e.rethrowFromSystemServer(); 824 } 825 } 826 827 /** 828 * Returns a list of UWB chip infos in a {@link PersistableBundle}. 829 * 830 * Callers can invoke methods on a specific UWB chip by passing its {@code chipId} to the 831 * method, which can be determined by calling: 832 * <pre> 833 * List<PersistableBundle> chipInfos = getChipInfos(); 834 * for (PersistableBundle chipInfo : chipInfos) { 835 * String chipId = ChipInfoParams.fromBundle(chipInfo).getChipId(); 836 * } 837 * </pre> 838 * 839 * @return list of {@link PersistableBundle} containing info about UWB chips for a multi-HAL 840 * system, or a list of info for a single chip for a single HAL system. 841 */ 842 @RequiresPermission(permission.UWB_PRIVILEGED) 843 @NonNull getChipInfos()844 public List<PersistableBundle> getChipInfos() { 845 try { 846 return mUwbAdapter.getChipInfos(); 847 } catch (RemoteException e) { 848 throw e.rethrowFromSystemServer(); 849 } 850 } 851 852 /** 853 * Returns the default UWB chip identifier. 854 * 855 * If callers do not pass a specific {@code chipId} to UWB methods, then the method will be 856 * invoked on the default chip, which is determined at system initialization from a 857 * configuration file. 858 * 859 * @return default UWB chip identifier for a multi-HAL system, or the identifier of the only UWB 860 * chip in a single HAL system. 861 */ 862 @RequiresPermission(permission.UWB_PRIVILEGED) 863 @NonNull getDefaultChipId()864 public String getDefaultChipId() { 865 try { 866 return mUwbAdapter.getDefaultChipId(); 867 } catch (RemoteException e) { 868 throw e.rethrowFromSystemServer(); 869 } 870 } 871 872 /** 873 * Register the UWB service profile. 874 * This profile instance is persisted by the platform until explicitly removed 875 * using {@link #removeServiceProfile(PersistableBundle)} 876 * 877 * @param parameters the parameters that define the service profile. 878 * @return Protocol specific params to be used as handle for triggering the profile. 879 */ 880 @RequiresPermission(permission.UWB_PRIVILEGED) 881 @NonNull addServiceProfile(@onNull PersistableBundle parameters)882 public PersistableBundle addServiceProfile(@NonNull PersistableBundle parameters) { 883 try { 884 return mUwbAdapter.addServiceProfile(parameters); 885 } catch (RemoteException e) { 886 throw e.rethrowFromSystemServer(); 887 } 888 } 889 890 /** 891 * Successfully removed the service profile. 892 */ 893 public static final int REMOVE_SERVICE_PROFILE_SUCCESS = 0; 894 895 /** 896 * Failed to remove service since the service profile is unknown. 897 */ 898 public static final int REMOVE_SERVICE_PROFILE_ERROR_UNKNOWN_SERVICE = 1; 899 900 /** 901 * Failed to remove service due to some internal error while processing the request. 902 */ 903 public static final int REMOVE_SERVICE_PROFILE_ERROR_INTERNAL = 2; 904 905 /** 906 * @hide 907 */ 908 @Retention(RetentionPolicy.SOURCE) 909 @IntDef(value = { 910 REMOVE_SERVICE_PROFILE_SUCCESS, 911 REMOVE_SERVICE_PROFILE_ERROR_UNKNOWN_SERVICE, 912 REMOVE_SERVICE_PROFILE_ERROR_INTERNAL 913 }) 914 @interface RemoveServiceProfile {} 915 916 /** 917 * Remove the service profile registered with {@link #addServiceProfile} and 918 * all related resources. 919 * 920 * @param parameters the parameters that define the service profile. 921 * 922 * @return true if the service profile is removed, false otherwise. 923 */ 924 @RequiresPermission(permission.UWB_PRIVILEGED) removeServiceProfile(@onNull PersistableBundle parameters)925 public @RemoveServiceProfile int removeServiceProfile(@NonNull PersistableBundle parameters) { 926 try { 927 return mUwbAdapter.removeServiceProfile(parameters); 928 } catch (RemoteException e) { 929 throw e.rethrowFromSystemServer(); 930 } 931 } 932 933 /** 934 * Get all service profiles initialized with {@link #addServiceProfile} 935 * 936 * @return the parameters that define the service profiles. 937 */ 938 @RequiresPermission(permission.UWB_PRIVILEGED) 939 @NonNull getAllServiceProfiles()940 public PersistableBundle getAllServiceProfiles() { 941 try { 942 return mUwbAdapter.getAllServiceProfiles(); 943 } catch (RemoteException e) { 944 throw e.rethrowFromSystemServer(); 945 } 946 } 947 948 /** 949 * Get the list of ADF (application defined file) provisioning authorities available for the UWB 950 * applet in SE (secure element). 951 * 952 * @param serviceProfileBundle Parameters representing the profile to use. 953 * @return The list of key information of ADF provisioning authority defined in FiRa 954 * CSML 8.2.2.7.2.4 and 8.2.2.14.4.1.2. 955 */ 956 @RequiresPermission(permission.UWB_PRIVILEGED) 957 @NonNull getAdfProvisioningAuthorities( @onNull PersistableBundle serviceProfileBundle)958 public PersistableBundle getAdfProvisioningAuthorities( 959 @NonNull PersistableBundle serviceProfileBundle) { 960 try { 961 return mUwbAdapter.getAdfProvisioningAuthorities(serviceProfileBundle); 962 } catch (RemoteException e) { 963 throw e.rethrowFromSystemServer(); 964 } 965 } 966 967 /** 968 * Get certificate information for the UWB applet in SE (secure element) that can be used to 969 * provision ADF (application defined file). 970 * 971 * @param serviceProfileBundle Parameters representing the profile to use. 972 * @return The Fira applet certificate information defined in FiRa CSML 7.3.4.3 and 973 * 8.2.2.14.4.1.1 974 */ 975 @RequiresPermission(permission.UWB_PRIVILEGED) 976 @NonNull getAdfCertificateInfo( @onNull PersistableBundle serviceProfileBundle)977 public PersistableBundle getAdfCertificateInfo( 978 @NonNull PersistableBundle serviceProfileBundle) { 979 try { 980 return mUwbAdapter.getAdfCertificateAndInfo(serviceProfileBundle); 981 } catch (RemoteException e) { 982 throw e.rethrowFromSystemServer(); 983 } 984 } 985 986 /** 987 * Mechanism to provision ADFs (application defined file) in the UWB applet present in SE 988 * (secure element) for a profile instance. 989 * 990 * @param serviceProfileBundle Parameters representing the profile to use. 991 * @param executor an {@link Executor} to execute given callback 992 * @param callback user implementation of the {@link AdapterStateCallback} 993 */ provisionProfileAdfByScript(@onNull PersistableBundle serviceProfileBundle, @NonNull @CallbackExecutor Executor executor, @NonNull AdfProvisionStateCallback callback)994 public void provisionProfileAdfByScript(@NonNull PersistableBundle serviceProfileBundle, 995 @NonNull @CallbackExecutor Executor executor, 996 @NonNull AdfProvisionStateCallback callback) { 997 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 998 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 999 AdfProvisionStateCallback.AdfProvisionStateCallbackProxy proxy = callback.getProxy(); 1000 proxy.initProxy(executor, callback); 1001 try { 1002 mUwbAdapter.provisionProfileAdfByScript(serviceProfileBundle, proxy); 1003 } catch (RemoteException e) { 1004 throw e.rethrowFromSystemServer(); 1005 } 1006 } 1007 1008 /** 1009 * Successfully removed the profile ADF. 1010 */ 1011 public static final int REMOVE_PROFILE_ADF_SUCCESS = 0; 1012 1013 /** 1014 * Failed to remove ADF since the service profile is unknown. 1015 */ 1016 public static final int REMOVE_PROFILE_ADF_ERROR_UNKNOWN_SERVICE = 1; 1017 1018 /** 1019 * Failed to remove ADF due to some internal error while processing the request. 1020 */ 1021 public static final int REMOVE_PROFILE_ADF_ERROR_INTERNAL = 2; 1022 1023 /** 1024 * @hide 1025 */ 1026 @Retention(RetentionPolicy.SOURCE) 1027 @IntDef(value = { 1028 REMOVE_PROFILE_ADF_SUCCESS, 1029 REMOVE_PROFILE_ADF_ERROR_UNKNOWN_SERVICE, 1030 REMOVE_PROFILE_ADF_ERROR_INTERNAL 1031 }) 1032 @interface RemoveProfileAdf {} 1033 1034 /** 1035 * Remove the ADF (application defined file) provisioned by {@link #provisionProfileAdfByScript} 1036 * 1037 * @param serviceProfileBundle Parameters representing the profile to use. 1038 * @return true if the ADF is removed, false otherwise. 1039 */ 1040 @RequiresPermission(permission.UWB_PRIVILEGED) removeProfileAdf(@onNull PersistableBundle serviceProfileBundle)1041 public @RemoveProfileAdf int removeProfileAdf(@NonNull PersistableBundle serviceProfileBundle) { 1042 try { 1043 return mUwbAdapter.removeProfileAdf(serviceProfileBundle); 1044 } catch (RemoteException e) { 1045 throw e.rethrowFromSystemServer(); 1046 } 1047 } 1048 1049 /** 1050 * Successfully sent the UCI message. 1051 */ 1052 public static final int SEND_VENDOR_UCI_SUCCESS = 0; 1053 1054 /** 1055 * Failed to send the UCI message because of an error returned from the HAL interface. 1056 */ 1057 public static final int SEND_VENDOR_UCI_ERROR_HW = 1; 1058 1059 /** 1060 * Failed to send the UCI message since UWB is toggled off. 1061 */ 1062 public static final int SEND_VENDOR_UCI_ERROR_OFF = 2; 1063 1064 /** 1065 * Failed to send the UCI message since UWB UCI command is malformed. 1066 * GID. 1067 */ 1068 public static final int SEND_VENDOR_UCI_ERROR_INVALID_ARGS = 3; 1069 1070 /** 1071 * Failed to send the UCI message since UWB GID used is invalid. 1072 */ 1073 public static final int SEND_VENDOR_UCI_ERROR_INVALID_GID = 4; 1074 1075 /** 1076 * @hide 1077 */ 1078 @Retention(RetentionPolicy.SOURCE) 1079 @IntDef(value = { 1080 SEND_VENDOR_UCI_SUCCESS, 1081 SEND_VENDOR_UCI_ERROR_HW, 1082 SEND_VENDOR_UCI_ERROR_OFF, 1083 SEND_VENDOR_UCI_ERROR_INVALID_ARGS, 1084 SEND_VENDOR_UCI_ERROR_INVALID_GID, 1085 }) 1086 @interface SendVendorUciStatus {} 1087 1088 /** 1089 * Message Type for UCI Command. 1090 */ 1091 public static final int MESSAGE_TYPE_COMMAND = 1; 1092 /** 1093 * Message Type for C-APDU (Command - Application Protocol Data Unit), 1094 * used for communication with secure component. 1095 */ 1096 public static final int MESSAGE_TYPE_TEST_1 = 4; 1097 1098 /** 1099 * Message Type for R-APDU (Response - Application Protocol Data Unit), 1100 * used for communication with secure component. 1101 */ 1102 public static final int MESSAGE_TYPE_TEST_2 = 5; 1103 1104 /** 1105 * @hide 1106 */ 1107 @Retention(RetentionPolicy.SOURCE) 1108 @IntDef(value = { 1109 MESSAGE_TYPE_COMMAND, 1110 MESSAGE_TYPE_TEST_1, 1111 MESSAGE_TYPE_TEST_2, 1112 }) 1113 @interface MessageType {} 1114 1115 /** 1116 * Send Vendor specific Uci Messages. 1117 * 1118 * The format of the UCI messages are defined in the UCI specification. The platform is 1119 * responsible for fragmenting the payload if necessary. 1120 * 1121 * @param gid Group ID of the command. This needs to be one of the vendor reserved GIDs from 1122 * the UCI specification. 1123 * @param oid Opcode ID of the command. This is left to the OEM / vendor to decide. 1124 * @param payload containing vendor Uci message payload. 1125 */ 1126 @NonNull 1127 @RequiresPermission(permission.UWB_PRIVILEGED) sendVendorUciMessage( @ntRangefrom = 0, to = 15) int gid, int oid, @NonNull byte[] payload)1128 public @SendVendorUciStatus int sendVendorUciMessage( 1129 @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload) { 1130 Objects.requireNonNull(payload, "Payload must not be null"); 1131 try { 1132 return mUwbAdapter.sendVendorUciMessage(MESSAGE_TYPE_COMMAND, gid, oid, payload); 1133 } catch (RemoteException e) { 1134 throw e.rethrowFromSystemServer(); 1135 } 1136 } 1137 1138 /** 1139 * Send Vendor specific Uci Messages with custom message type. 1140 * 1141 * The format of the UCI messages are defined in the UCI specification. The platform is 1142 * responsible for fragmenting the payload if necessary. 1143 * 1144 * Note that mt (message type) is added at the beginning of method parameters as it is more 1145 * distinctive than other parameters and was requested from vendor. 1146 * 1147 * @param mt Message Type of the command 1148 * @param gid Group ID of the command. This needs to be one of the vendor reserved GIDs from 1149 * the UCI specification 1150 * @param oid Opcode ID of the command. This is left to the OEM / vendor to decide 1151 * @param payload containing vendor Uci message payload 1152 */ 1153 @NonNull 1154 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1155 @RequiresPermission(permission.UWB_PRIVILEGED) sendVendorUciMessage(@essageType int mt, @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload)1156 public @SendVendorUciStatus int sendVendorUciMessage(@MessageType int mt, 1157 @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload) { 1158 Objects.requireNonNull(payload, "Payload must not be null"); 1159 try { 1160 return mUwbAdapter.sendVendorUciMessage(mt, gid, oid, payload); 1161 } catch (RemoteException e) { 1162 throw e.rethrowFromSystemServer(); 1163 } 1164 } 1165 1166 private static class OnUwbActivityEnergyInfoProxy 1167 extends IOnUwbActivityEnergyInfoListener.Stub { 1168 private final Object mLock = new Object(); 1169 @Nullable @GuardedBy("mLock") private Executor mExecutor; 1170 @Nullable @GuardedBy("mLock") private Consumer<UwbActivityEnergyInfo> mListener; 1171 OnUwbActivityEnergyInfoProxy(Executor executor, Consumer<UwbActivityEnergyInfo> listener)1172 OnUwbActivityEnergyInfoProxy(Executor executor, 1173 Consumer<UwbActivityEnergyInfo> listener) { 1174 mExecutor = executor; 1175 mListener = listener; 1176 } 1177 1178 @Override onUwbActivityEnergyInfo(UwbActivityEnergyInfo info)1179 public void onUwbActivityEnergyInfo(UwbActivityEnergyInfo info) { 1180 Executor executor; 1181 Consumer<UwbActivityEnergyInfo> listener; 1182 synchronized (mLock) { 1183 if (mExecutor == null || mListener == null) { 1184 return; 1185 } 1186 executor = mExecutor; 1187 listener = mListener; 1188 // null out to allow garbage collection, prevent triggering listener more than once 1189 mExecutor = null; 1190 mListener = null; 1191 } 1192 Binder.clearCallingIdentity(); 1193 executor.execute(() -> listener.accept(info)); 1194 } 1195 } 1196 1197 /** 1198 * Request to get the current {@link UwbActivityEnergyInfo} asynchronously. 1199 * 1200 * @param executor the executor that the listener will be invoked on 1201 * @param listener the listener that will receive the {@link UwbActivityEnergyInfo} object 1202 * when it becomes available. The listener will be triggered at most once for 1203 * each call to this method. 1204 */ 1205 @RequiresPermission(permission.UWB_PRIVILEGED) getUwbActivityEnergyInfoAsync( @onNull @allbackExecutor Executor executor, @NonNull Consumer<UwbActivityEnergyInfo> listener)1206 public void getUwbActivityEnergyInfoAsync( 1207 @NonNull @CallbackExecutor Executor executor, 1208 @NonNull Consumer<UwbActivityEnergyInfo> listener) { 1209 Objects.requireNonNull(executor, "executor cannot be null"); 1210 Objects.requireNonNull(listener, "listener cannot be null"); 1211 try { 1212 mUwbAdapter.getUwbActivityEnergyInfoAsync( 1213 new OnUwbActivityEnergyInfoProxy(executor, listener)); 1214 } catch (RemoteException e) { 1215 throw e.rethrowFromSystemServer(); 1216 } 1217 } 1218 } 1219