• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.Manifest;
20 import android.annotation.FlaggedApi;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.os.Binder;
26 import android.os.Build;
27 import android.os.PersistableBundle;
28 import android.os.RemoteException;
29 import android.util.Log;
30 
31 import androidx.annotation.RequiresApi;
32 
33 import com.android.modules.utils.build.SdkLevel;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.util.concurrent.Executor;
38 
39 /**
40  * This class provides a way to control an active UWB ranging session.
41  * <p>It also defines the required {@link RangingSession.Callback} that must be implemented
42  * in order to be notified of UWB ranging results and status events related to the
43  * {@link RangingSession}.
44  *
45  * <p>To get an instance of {@link RangingSession}, first use
46  * {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)} to request to open a
47  * session. Once the session is opened, a {@link RangingSession} object is provided through
48  * {@link RangingSession.Callback#onOpened(RangingSession)}. If opening a session fails, the failure
49  * is reported through {@link RangingSession.Callback#onOpenFailed(int, PersistableBundle)} with the
50  * failure reason.
51  *
52  * @hide
53  */
54 @SystemApi
55 public final class RangingSession implements AutoCloseable {
56     private final String mTag = "Uwb.RangingSession[" + this + "]";
57     private final SessionHandle mSessionHandle;
58     private final IUwbAdapter mAdapter;
59     private final Executor mExecutor;
60     private final Callback mCallback;
61     private final String mChipId;
62 
63     private enum State {
64         /**
65          * The state of the {@link RangingSession} until
66          * {@link RangingSession.Callback#onOpened(RangingSession)} is invoked
67          */
68         INIT,
69 
70         /**
71          * The {@link RangingSession} is initialized and ready to begin ranging
72          */
73         IDLE,
74 
75         /**
76          * The {@link RangingSession} is actively ranging
77          */
78         ACTIVE,
79 
80         /**
81          * The {@link RangingSession} is closed and may not be used for ranging.
82          */
83         CLOSED
84     }
85 
86     private State mState = State.INIT;
87 
88     /**
89      * Interface for receiving {@link RangingSession} events
90      */
91     public interface Callback {
92         /**
93          * @hide
94          */
95         @Retention(RetentionPolicy.SOURCE)
96         @IntDef(value = {
97                 REASON_UNKNOWN,
98                 REASON_LOCAL_REQUEST,
99                 REASON_REMOTE_REQUEST,
100                 REASON_BAD_PARAMETERS,
101                 REASON_GENERIC_ERROR,
102                 REASON_MAX_SESSIONS_REACHED,
103                 REASON_SYSTEM_POLICY,
104                 REASON_PROTOCOL_SPECIFIC_ERROR,
105                 REASON_MAX_RR_RETRY_REACHED,
106                 REASON_SERVICE_DISCOVERY_FAILURE,
107                 REASON_SERVICE_CONNECTION_FAILURE,
108                 REASON_SE_NOT_SUPPORTED,
109                 REASON_SE_INTERACTION_FAILURE,
110                 REASON_INSUFFICIENT_SLOTS_PER_RR,
111                 REASON_SYSTEM_REGULATION,
112                 REASON_INBAND_SESSION_STOP,
113         })
114         @interface Reason {}
115 
116         /**
117          * Indicates that the session was closed or failed to open due to an unknown reason
118          */
119         int REASON_UNKNOWN = 0;
120 
121         /**
122          * Indicates that the session was closed or failed to open because
123          * {@link AutoCloseable#close()} or {@link RangingSession#close()} was called
124          */
125         int REASON_LOCAL_REQUEST = 1;
126 
127         /**
128          * Indicates that the session was closed or failed to open due to an explicit request from
129          * the remote device.
130          */
131         int REASON_REMOTE_REQUEST = 2;
132 
133         /**
134          * Indicates that the session was closed or failed to open due to erroneous parameters
135          */
136         int REASON_BAD_PARAMETERS = 3;
137 
138         /**
139          * Indicates an error on this device besides the error code already listed
140          */
141         int REASON_GENERIC_ERROR = 4;
142 
143         /**
144          * Indicates that the number of currently open sessions supported by the device and
145          * additional sessions may not be opened.
146          */
147         int REASON_MAX_SESSIONS_REACHED = 5;
148 
149         /**
150          * Indicates that the local system policy caused the change, such
151          * as privacy policy, power management policy, permissions, and more.
152          */
153         int REASON_SYSTEM_POLICY = 6;
154 
155         /**
156          * Indicates a protocol specific error. The associated {@link PersistableBundle} should be
157          * consulted for additional information.
158          */
159         int REASON_PROTOCOL_SPECIFIC_ERROR = 7;
160 
161         /**
162          * Indicates that the max number of retry attempts for a ranging attempt has been reached.
163          */
164         int REASON_MAX_RR_RETRY_REACHED = 9;
165 
166         /**
167          * Indicates a failure to discover the service after activation.
168          */
169         int REASON_SERVICE_DISCOVERY_FAILURE = 10;
170 
171         /**
172          * Indicates a failure to connect to the service after discovery.
173          */
174         int REASON_SERVICE_CONNECTION_FAILURE = 11;
175 
176         /**
177          * The device doesn’t support FiRA Applet.
178          */
179         int REASON_SE_NOT_SUPPORTED = 12;
180 
181         /**
182          * SE interactions failed.
183          */
184         int REASON_SE_INTERACTION_FAILURE = 13;
185 
186         /**
187          * Indicate insufficient slots per ranging round.
188          */
189         int REASON_INSUFFICIENT_SLOTS_PER_RR = 14;
190 
191         /**
192          * Indicate that a system regulation caused the change, such as no allowed UWB channels in
193          * the country.
194          */
195         int REASON_SYSTEM_REGULATION = 15;
196 
197         /**
198          * Indicates session was stopped due to inband signal.
199          */
200         @FlaggedApi("com.android.uwb.flags.reason_inband_session_stop")
201         int REASON_INBAND_SESSION_STOP = 16;
202 
203         /**
204          * @hide
205          */
206         @Retention(RetentionPolicy.SOURCE)
207         @IntDef(value = {
208                 CONTROLEE_FAILURE_REASON_MAX_CONTROLEE_REACHED,
209         })
210         @interface ControleeFailureReason {}
211 
212         /**
213          * Indicates that the session has reached the max number of controlees supported by the
214          * device. This is applicable to only one to many sessions and sent in response to a
215          * request to add a new controlee to an ongoing session.
216          */
217         int CONTROLEE_FAILURE_REASON_MAX_CONTROLEE_REACHED = 0;
218 
219         /**
220          * @hide
221          */
222         @Retention(RetentionPolicy.SOURCE)
223         @IntDef(value = {
224                 DATA_FAILURE_REASON_DATA_SIZE_TOO_LARGE,
225         })
226         @interface DataFailureReason {}
227 
228         /**
229          * Indicates that the size of the data being sent or received is too large.
230          */
231         int DATA_FAILURE_REASON_DATA_SIZE_TOO_LARGE = 10;
232 
233         /**
234          * Invoked when {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
235          * is successful
236          *
237          * @param session the newly opened {@link RangingSession}
238          */
onOpened(@onNull RangingSession session)239         void onOpened(@NonNull RangingSession session);
240 
241         /**
242          * Invoked if {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}}
243          * fails
244          *
245          * @param reason the failure reason
246          * @param params protocol specific parameters
247          */
onOpenFailed(@eason int reason, @NonNull PersistableBundle params)248         void onOpenFailed(@Reason int reason, @NonNull PersistableBundle params);
249 
250         /**
251          * Invoked either,
252          *  - when {@link RangingSession#start(PersistableBundle)} is successful if the session is
253          *    using a custom profile, OR
254          *  - when platform starts ranging after OOB discovery + negotiation if the session is
255          *    using a platform defined profile.
256          * @param sessionInfo session specific parameters from the lower layers
257          */
onStarted(@onNull PersistableBundle sessionInfo)258         void onStarted(@NonNull PersistableBundle sessionInfo);
259 
260         /**
261          * Invoked either,
262          *   - when {@link RangingSession#start(PersistableBundle)} fails if
263          *     the session is using a custom profile, OR
264          *   - when platform fails ranging after OOB discovery + negotiation if the
265          *     session is using a platform defined profile.
266          *
267          * @param reason the failure reason
268          * @param params protocol specific parameters
269          */
onStartFailed(@eason int reason, @NonNull PersistableBundle params)270         void onStartFailed(@Reason int reason, @NonNull PersistableBundle params);
271 
272         /**
273          * Invoked when a request to reconfigure the session succeeds
274          *
275          * @param params the updated ranging configuration
276          */
onReconfigured(@onNull PersistableBundle params)277         void onReconfigured(@NonNull PersistableBundle params);
278 
279         /**
280          * Invoked when a request to reconfigure the session fails
281          *
282          * @param reason reason the session failed to be reconfigured
283          * @param params protocol specific failure reasons
284          */
onReconfigureFailed(@eason int reason, @NonNull PersistableBundle params)285         void onReconfigureFailed(@Reason int reason, @NonNull PersistableBundle params);
286 
287         /**
288          * Invoked when a request to stop the session succeeds
289          *
290          * @param reason reason for the session stop
291          * @param parameters protocol specific parameters related to the stop reason
292          */
onStopped(@eason int reason, @NonNull PersistableBundle parameters)293         void onStopped(@Reason int reason, @NonNull PersistableBundle parameters);
294 
295         /**
296          * Invoked when a request to stop the session fails
297          *
298          * @param reason reason the session failed to be stopped
299          * @param params protocol specific failure reasons
300          */
onStopFailed(@eason int reason, @NonNull PersistableBundle params)301         void onStopFailed(@Reason int reason, @NonNull PersistableBundle params);
302 
303        /**
304          * Invoked when session is either closed spontaneously, or per user request via
305          * {@link RangingSession#close()} or {@link AutoCloseable#close()}.
306          *
307          * @param reason reason for the session closure
308          * @param parameters protocol specific parameters related to the close reason
309          */
onClosed(@eason int reason, @NonNull PersistableBundle parameters)310         void onClosed(@Reason int reason, @NonNull PersistableBundle parameters);
311 
312         /**
313          * Called once per ranging interval even when a ranging measurement fails
314          *
315          * @param rangingReport ranging report for this interval's measurements
316          */
onReportReceived(@onNull RangingReport rangingReport)317         void onReportReceived(@NonNull RangingReport rangingReport);
318 
319         /**
320          * Invoked when a new controlee is added to an ongoing one-to many session.
321          *
322          * @param parameters protocol specific parameters for the new controlee
323          */
onControleeAdded(@onNull PersistableBundle parameters)324         default void onControleeAdded(@NonNull PersistableBundle parameters) {}
325 
326         /**
327          * Invoked when a new controlee is added to an ongoing one-to many session.
328          *
329          * @param reason reason for the controlee add failure
330          * @param parameters protocol specific parameters related to the failure
331          */
onControleeAddFailed( @ontroleeFailureReason int reason, @NonNull PersistableBundle parameters)332         default void onControleeAddFailed(
333                 @ControleeFailureReason int reason, @NonNull PersistableBundle parameters) {}
334 
335         /**
336          * Invoked when an existing controlee is removed from an ongoing one-to many session.
337          *
338          * @param parameters protocol specific parameters for the existing controlee
339          */
onControleeRemoved(@onNull PersistableBundle parameters)340         default void onControleeRemoved(@NonNull PersistableBundle parameters) {}
341 
342         /**
343          * Invoked when a new controlee is added to an ongoing one-to many session.
344          *
345          * @param reason reason for the controlee remove failure
346          * @param parameters protocol specific parameters related to the failure
347          */
onControleeRemoveFailed( @ontroleeFailureReason int reason, @NonNull PersistableBundle parameters)348         default void onControleeRemoveFailed(
349                 @ControleeFailureReason int reason, @NonNull PersistableBundle parameters) {}
350 
351         /**
352          * Invoked when an ongoing session is successfully pauseed.
353          *
354          * @param parameters protocol specific parameters sent for suspension
355          */
onPaused(@onNull PersistableBundle parameters)356         default void onPaused(@NonNull PersistableBundle parameters) {}
357 
358         /**
359          * Invoked when an ongoing session suspension fails.
360          *
361          * @param reason reason for the suspension failure
362          * @param parameters protocol specific parameters for suspension failure
363          */
onPauseFailed(@eason int reason, @NonNull PersistableBundle parameters)364         default void onPauseFailed(@Reason int reason, @NonNull PersistableBundle parameters) {}
365 
366         /**
367          * Invoked when a pauseed session is successfully resumed.
368          *
369          * @param parameters protocol specific parameters sent for suspension
370          */
onResumed(@onNull PersistableBundle parameters)371         default void onResumed(@NonNull PersistableBundle parameters) {}
372 
373         /**
374          * Invoked when a pauseed session resumption fails.
375          *
376          * @param reason reason for the resumption failure
377          * @param parameters protocol specific parameters for resumption failure
378          */
onResumeFailed(@eason int reason, @NonNull PersistableBundle parameters)379         default void onResumeFailed(@Reason int reason, @NonNull PersistableBundle parameters) {}
380 
381         /**
382          * Invoked when data is successfully sent via {@link RangingSession#sendData(UwbAddress,
383          * PersistableBundle, byte[])}.
384          *
385          * @param remoteDeviceAddress remote device's address
386          * @param parameters protocol specific parameters sent for suspension
387          */
onDataSent(@onNull UwbAddress remoteDeviceAddress, @NonNull PersistableBundle parameters)388         default void onDataSent(@NonNull UwbAddress remoteDeviceAddress,
389                 @NonNull PersistableBundle parameters) {}
390 
391         /**
392          * Invoked when data send to a remote device via {@link RangingSession#sendData(UwbAddress,
393          * PersistableBundle, byte[])} fails.
394          *
395          * @param remoteDeviceAddress remote device's address
396          * @param reason reason for the resumption failure
397          * @param parameters protocol specific parameters for resumption failure
398          */
onDataSendFailed(@onNull UwbAddress remoteDeviceAddress, @DataFailureReason int reason, @NonNull PersistableBundle parameters)399         default void onDataSendFailed(@NonNull UwbAddress remoteDeviceAddress,
400                 @DataFailureReason int reason, @NonNull PersistableBundle parameters) {}
401 
402         /**
403          * Invoked when data is received successfully from a remote device.
404          * The data is received piggybacked over RRM (initiator -> responder) or
405          * RIM (responder -> initiator).
406          * <p> This is only functional on a FIRA 2.0 compliant device.
407          *
408          * @param remoteDeviceAddress remote device's address
409          * @param data Raw data received
410          * @param parameters protocol specific parameters for the received data
411          */
onDataReceived(@onNull UwbAddress remoteDeviceAddress, @NonNull PersistableBundle parameters, @NonNull byte[] data)412         default void onDataReceived(@NonNull UwbAddress remoteDeviceAddress,
413                 @NonNull PersistableBundle parameters, @NonNull byte[] data) {}
414 
415         /**
416          * Invoked when data receive from a remote device fails.
417          *
418          * @param remoteDeviceAddress remote device's address
419          * @param reason reason for the reception failure
420          * @param parameters protocol specific parameters for resumption failure
421          */
onDataReceiveFailed(@onNull UwbAddress remoteDeviceAddress, @DataFailureReason int reason, @NonNull PersistableBundle parameters)422         default void onDataReceiveFailed(@NonNull UwbAddress remoteDeviceAddress,
423                 @DataFailureReason int reason, @NonNull PersistableBundle parameters) {}
424 
425         /**
426          * Invoked when set data transfer phase config is called successfully
427          *
428          * @param parameters protocol specific parameters for set data transfer phase config success
429          */
430         @FlaggedApi("com.android.uwb.flags.data_transfer_phase_config")
onDataTransferPhaseConfigured(@onNull PersistableBundle parameters)431         default void onDataTransferPhaseConfigured(@NonNull PersistableBundle parameters) {}
432 
433         /**
434          * Invoked when set data transfer phase config is failed
435          *
436          * @param parameters protocol specific parameters for set data transfer phase config failure
437          */
438         @FlaggedApi("com.android.uwb.flags.data_transfer_phase_config")
onDataTransferPhaseConfigFailed(@eason int reason, @NonNull PersistableBundle parameters)439         default void onDataTransferPhaseConfigFailed(@Reason int reason,
440                 @NonNull PersistableBundle parameters) {}
441 
442         /**
443          * Invoked when service is discovered via OOB.
444          * <p>
445          * If this a one to many session, this can be invoked multiple times to indicate different
446          * peers being discovered.
447          * </p>
448          *
449          * @param parameters protocol specific params for discovered service.
450          */
onServiceDiscovered(@onNull PersistableBundle parameters)451         default void onServiceDiscovered(@NonNull PersistableBundle parameters) {}
452 
453         /**
454          * Invoked when service is connected via OOB.
455          * <p>
456          * If this a one to many session, this can be invoked multiple times to indicate different
457          * peers being connected.
458          * </p>
459          *
460          * @param parameters protocol specific params for connected service.
461          */
onServiceConnected(@onNull PersistableBundle parameters)462         default void onServiceConnected(@NonNull PersistableBundle parameters) {}
463 
464         /**
465          * Invoked when a response/status is received for active ranging rounds update.
466          *
467          * @param parameters bundle of ranging rounds update status
468          */
469         @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
onRangingRoundsUpdateDtTagStatus(@onNull PersistableBundle parameters)470         default void onRangingRoundsUpdateDtTagStatus(@NonNull PersistableBundle parameters) {}
471 
472         /**
473          * Invoked when hybrid session controller is successfully configured.
474          *
475          * @param parameters protocol specific parameters sent for HUS session configuration
476          */
477         @FlaggedApi("com.android.uwb.flags.hybrid_session_support")
onHybridSessionControllerConfigured( @onNull PersistableBundle parameters)478         default void onHybridSessionControllerConfigured(
479                 @NonNull PersistableBundle parameters) {}
480 
481         /**
482          * Invoked when hybrid session controller configuration fails.
483          *
484          * @param parameters protocol specific parameters for configuration failure
485          */
486         @FlaggedApi("com.android.uwb.flags.hybrid_session_support")
onHybridSessionControllerConfigurationFailed( @angingChangeReason int reason, @NonNull PersistableBundle parameters)487         default void onHybridSessionControllerConfigurationFailed(
488                 @RangingChangeReason int reason, @NonNull PersistableBundle parameters) {
489         }
490 
491         /**
492          * Invoked when hybrid session controlee is successfully configured.
493          *
494          * @param parameters protocol specific parameters sent for HUS session configuration
495          */
496         @FlaggedApi("com.android.uwb.flags.hybrid_session_support")
onHybridSessionControleeConfigured( @onNull PersistableBundle parameters)497         default void onHybridSessionControleeConfigured(
498                 @NonNull PersistableBundle parameters) {}
499 
500         /**
501          *Invoked when hybrid session controlee configuration fails.
502          *
503          * @param parameters protocol specific parameters for configuration failure
504          */
505         @FlaggedApi("com.android.uwb.flags.hybrid_session_support")
onHybridSessionControleeConfigurationFailed( @angingChangeReason int reason, @NonNull PersistableBundle parameters)506         default void onHybridSessionControleeConfigurationFailed(
507                 @RangingChangeReason int reason, @NonNull PersistableBundle parameters) {}
508     }
509 
510     /**
511      * @hide
512      */
RangingSession(Executor executor, Callback callback, IUwbAdapter adapter, SessionHandle sessionHandle)513     public RangingSession(Executor executor, Callback callback, IUwbAdapter adapter,
514             SessionHandle sessionHandle) {
515         this(executor, callback, adapter, sessionHandle, /* chipId= */ null);
516     }
517 
518     /**
519      * @hide
520      */
RangingSession(Executor executor, Callback callback, IUwbAdapter adapter, SessionHandle sessionHandle, String chipId)521     public RangingSession(Executor executor, Callback callback, IUwbAdapter adapter,
522             SessionHandle sessionHandle, String chipId) {
523         mState = State.INIT;
524         mExecutor = executor;
525         mCallback = callback;
526         mAdapter = adapter;
527         mSessionHandle = sessionHandle;
528         mChipId = chipId;
529     }
530 
531     /**
532      * @hide
533      */
isOpen()534     public boolean isOpen() {
535         return mState == State.IDLE || mState == State.ACTIVE;
536     }
537 
538     /**
539      * If the session uses custom profile,
540      *    Begins ranging for the session.
541      *    <p>On successfully starting a ranging session,
542      *    {@link RangingSession.Callback#onStarted(PersistableBundle)} is invoked.
543      *    <p>On failure to start the session,
544      *    {@link RangingSession.Callback#onStartFailed(int, PersistableBundle)}
545      *    is invoked.
546      *
547      * If the session uses platform defined profile (like PACS),
548      *    Begins OOB discovery for the service. Once the service is discovered,
549      *    UWB session params are negotiated via OOB and a UWB session will be
550      *    started.
551      *    <p>On successfully discovering a service,
552      *    {@link RangingSession.Callback#onServiceDiscovered(PersistableBundle)} is invoked.
553      *    <p>On successfully connecting to a service,
554      *    {@link RangingSession.Callback#onServiceConnected(PersistableBundle)} is invoked.
555      *    <p>On successfully starting a ranging session,
556      *    {@link RangingSession.Callback#onStarted(PersistableBundle)} is invoked.
557      *    <p>On failure to start the session,
558      *    {@link RangingSession.Callback#onStartFailed(int, PersistableBundle)}
559      *    is invoked.
560      *
561      * @param params configuration parameters for starting the session
562      */
563     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
start(@onNull PersistableBundle params)564     public void start(@NonNull PersistableBundle params) {
565         if (mState != State.IDLE) {
566             throw new IllegalStateException();
567         }
568 
569         Log.v(mTag, "start - sessionHandle: " + mSessionHandle);
570         try {
571             mAdapter.startRanging(mSessionHandle, params);
572         } catch (RemoteException e) {
573             throw e.rethrowFromSystemServer();
574         }
575     }
576 
577     /**
578      * Attempts to reconfigure the session with the given parameters
579      * <p>This call may be made when the session is open.
580      *
581      * <p>On successfully reconfiguring the session
582      * {@link RangingSession.Callback#onReconfigured(PersistableBundle)} is invoked.
583      *
584      * <p>On failure to reconfigure the session,
585      * {@link RangingSession.Callback#onReconfigureFailed(int, PersistableBundle)} is invoked.
586      *
587      * @param params the parameters to reconfigure and their new values
588      */
589     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
reconfigure(@onNull PersistableBundle params)590     public void reconfigure(@NonNull PersistableBundle params) {
591         if (mState != State.ACTIVE && mState != State.IDLE) {
592             throw new IllegalStateException();
593         }
594 
595         Log.v(mTag, "reconfigure - sessionHandle: " + mSessionHandle);
596         try {
597             mAdapter.reconfigureRanging(mSessionHandle, params);
598         } catch (RemoteException e) {
599             throw e.rethrowFromSystemServer();
600         }
601     }
602 
603     /**
604      * Stops actively ranging
605      *
606      * <p>A session that has been stopped may be resumed by calling
607      * {@link RangingSession#start(PersistableBundle)} without the need to open a new session.
608      *
609      * <p>Stopping a {@link RangingSession} is useful when the lower layers should not discard
610      * the parameters of the session, or when a session needs to be able to be resumed quickly.
611      *
612      * <p>If the {@link RangingSession} is no longer needed, use {@link RangingSession#close()} to
613      * completely close the session and allow lower layers of the stack to perform necessarily
614      * cleanup.
615      *
616      * <p>Stopped sessions may be closed by the system at any time. In such a case,
617      * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} is invoked.
618      *
619      * <p>On failure to stop the session,
620      * {@link RangingSession.Callback#onStopFailed(int, PersistableBundle)} is invoked.
621      */
622     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
stop()623     public void stop() {
624         if (mState != State.ACTIVE) {
625             throw new IllegalStateException();
626         }
627 
628         Log.v(mTag, "stop - sessionHandle: " + mSessionHandle);
629         try {
630             mAdapter.stopRanging(mSessionHandle);
631         } catch (RemoteException e) {
632             throw e.rethrowFromSystemServer();
633         }
634     }
635 
636     /**
637      * Close the ranging session
638      *
639      * <p>After calling this function, in order resume ranging, a new {@link RangingSession} must
640      * be opened by calling
641      * {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}.
642      *
643      * <p>If this session is currently ranging, it will stop and close the session.
644      * <p>If the session is in the process of being opened, it will attempt to stop the session from
645      * being opened.
646      * <p>If the session is already closed, the registered
647      * {@link Callback#onClosed(int, PersistableBundle)} callback will still be invoked.
648      *
649      * <p>{@link Callback#onClosed(int, PersistableBundle)} will be invoked using the same callback
650      * object given to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
651      * when the {@link RangingSession} was opened. The callback will be invoked after each call to
652      * {@link #close()}, even if the {@link RangingSession} is already closed.
653      */
654     @Override
655     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
close()656     public void close() {
657         if (mState == State.CLOSED) {
658             mExecutor.execute(() -> mCallback.onClosed(
659                     Callback.REASON_LOCAL_REQUEST, new PersistableBundle()));
660             return;
661         }
662 
663         Log.v(mTag, "close - sessionHandle: " + mSessionHandle);
664         try {
665             mAdapter.closeRanging(mSessionHandle);
666         } catch (RemoteException e) {
667             throw e.rethrowFromSystemServer();
668         }
669     }
670 
671     /**
672      * Add a new controlee to an ongoing session.
673      * <p>This call may be made when the session is open.
674      *
675      * <p>On successfully adding a new controlee to the session
676      * {@link RangingSession.Callback#onControleeAdded(PersistableBundle)} is invoked.
677      *
678      * <p>On failure to add a new controlee to the session,
679      * {@link RangingSession.Callback#onControleeAddFailed(int, PersistableBundle)} is invoked.
680      *
681      * @param params the parameters for the new controlee
682      */
683     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
addControlee(@onNull PersistableBundle params)684     public void addControlee(@NonNull PersistableBundle params) {
685         if (mState != State.ACTIVE && mState != State.IDLE) {
686             throw new IllegalStateException();
687         }
688 
689         Log.v(mTag, "addControlee - sessionHandle: " + mSessionHandle);
690         try {
691             mAdapter.addControlee(mSessionHandle, params);
692         } catch (RemoteException e) {
693             throw e.rethrowFromSystemServer();
694         }
695     }
696 
697     /**
698      * Remove an existing controlee from an ongoing session.
699      * <p>This call may be made when the session is open.
700      *
701      * <p>On successfully removing an existing controlee from the session
702      * {@link RangingSession.Callback#onControleeRemoved(PersistableBundle)} is invoked.
703      *
704      * <p>On failure to remove an existing controlee from the session,
705      * {@link RangingSession.Callback#onControleeRemoveFailed(int, PersistableBundle)} is invoked.
706      *
707      * @param params the parameters for the existing controlee
708      */
709     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
removeControlee(@onNull PersistableBundle params)710     public void removeControlee(@NonNull PersistableBundle params) {
711         if (mState != State.ACTIVE && mState != State.IDLE) {
712             throw new IllegalStateException();
713         }
714 
715         Log.v(mTag, "removeControlee - sessionHandle: " + mSessionHandle);
716         try {
717             mAdapter.removeControlee(mSessionHandle, params);
718         } catch (RemoteException e) {
719             throw e.rethrowFromSystemServer();
720         }
721     }
722 
723     /**
724      * Pauses an ongoing ranging session.
725      *
726      * <p>A session that has been pauseed may be resumed by calling
727      * {@link RangingSession#resume(PersistableBundle)} without the need to open a new session.
728      *
729      * <p>Pauseing a {@link RangingSession} is useful when the lower layers should skip a few
730      * ranging rounds for a session without stopping it.
731      *
732      * <p>If the {@link RangingSession} is no longer needed, use {@link RangingSession#stop()} or
733      * {@link RangingSession#close()} to completely close the session.
734      *
735      * <p>On successfully pausing the session,
736      * {@link RangingSession.Callback#onRangingPaused(PersistableBundle)} is invoked.
737      *
738      * <p>On failure to pause the session,
739      * {@link RangingSession.Callback#onRangingPauseFailed(int, PersistableBundle)} is invoked.
740      *
741      * @param params protocol specific parameters for pausing the session
742      */
743     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
pause(@onNull PersistableBundle params)744     public void pause(@NonNull PersistableBundle params) {
745         if (mState != State.ACTIVE) {
746             throw new IllegalStateException();
747         }
748 
749         Log.v(mTag, "pause - sessionHandle: " + mSessionHandle);
750         try {
751             mAdapter.pause(mSessionHandle, params);
752         } catch (RemoteException e) {
753             throw e.rethrowFromSystemServer();
754         }
755     }
756 
757     /**
758      * Resumes a pauseed ranging session.
759      *
760      * <p>A session that has been previously pauseed using
761      * {@link RangingSession#pause(PersistableBundle)} can be resumed by calling
762      * {@link RangingSession#resume(PersistableBundle)}.
763      *
764      * <p>On successfully resuming the session,
765      * {@link RangingSession.Callback#onRangingResumed(PersistableBundle)} is invoked.
766      *
767      * <p>On failure to resume the session,
768      * {@link RangingSession.Callback#onRangingResumeFailed(int, PersistableBundle)} is invoked.
769      *
770      * @param params protocol specific parameters the resuming the session
771      */
772     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
resume(@onNull PersistableBundle params)773     public void resume(@NonNull PersistableBundle params) {
774         if (mState != State.ACTIVE) {
775             throw new IllegalStateException();
776         }
777 
778         Log.v(mTag, "resume - sessionHandle: " + mSessionHandle);
779         try {
780             mAdapter.resume(mSessionHandle, params);
781         } catch (RemoteException e) {
782             throw e.rethrowFromSystemServer();
783         }
784     }
785 
786     /**
787      * Send data to a remote device which is part of this ongoing session.
788      * The data is sent by piggybacking the provided data over RRM (initiator -> responder) or
789      * RIM (responder -> initiator).
790      * <p>This is only functional on a FIRA 2.0 compliant device.
791      *
792      * <p>On successfully sending the data,
793      * {@link RangingSession.Callback#onDataSent(UwbAddress, PersistableBundle)} is invoked.
794      *
795      * <p>On failure to send the data,
796      * {@link RangingSession.Callback#onDataSendFailed(UwbAddress, int, PersistableBundle)} is
797      * invoked.
798      *
799      * @param remoteDeviceAddress remote device's address
800      * @param params protocol specific parameters the sending the data
801      * @param data Raw data to be sent
802      */
803     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
sendData(@onNull UwbAddress remoteDeviceAddress, @NonNull PersistableBundle params, @NonNull byte[] data)804     public void sendData(@NonNull UwbAddress remoteDeviceAddress,
805             @NonNull PersistableBundle params, @NonNull byte[] data) {
806         if (mState != State.ACTIVE) {
807             throw new IllegalStateException();
808         }
809 
810         Log.v(mTag, "sendData - sessionHandle: " + mSessionHandle);
811         try {
812             mAdapter.sendData(mSessionHandle, remoteDeviceAddress, params, data);
813         } catch (RemoteException e) {
814             throw e.rethrowFromSystemServer();
815         }
816     }
817 
818     /**
819      * Set data transfer phase configuration during ranging as well as dedicated data transfer.
820      * <p>This is only functional on a FIRA 2.0 compliant device.
821      *
822      * <p>On successfully sending the data transfer phase config,
823      * {@link RangingSession.Callback#onDataTransferPhaseConfigured(PersistableBundle)} is
824      * invoked.
825      *
826      * <p>On failure to send the data transfer phase config,
827      * {@link RangingSession.Callback#onDataTransferPhaseConfigFailed(PersistableBundle)} is
828      * invoked.
829      *
830      * @param params Protocol specific data transfer phase configuration parameters
831      */
832     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
833     @FlaggedApi("com.android.uwb.flags.data_transfer_phase_config")
setDataTransferPhaseConfig(@onNull PersistableBundle params)834     public void setDataTransferPhaseConfig(@NonNull PersistableBundle params) {
835         if (!isOpen()) {
836             throw new IllegalStateException();
837         }
838 
839         Log.v(mTag, "setDataTransferPhaseConfig - sessionHandle: " + mSessionHandle);
840         try {
841             mAdapter.setDataTransferPhaseConfig(mSessionHandle, params);
842         } catch (RemoteException e) {
843             throw e.rethrowFromSystemServer();
844         }
845     }
846 
847     /**
848      * Update active ranging rounds for DT Tag.
849      *
850      * <p> On successfully sending the command,
851      * {@link RangingSession.Callback#onRangingRoundsUpdateDtTagStatus(PersistableBundle)}
852      * is invoked.
853      * @param params Parameters to configure active ranging rounds
854      */
855     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
856     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
updateRangingRoundsDtTag(@onNull PersistableBundle params)857     public void updateRangingRoundsDtTag(@NonNull PersistableBundle params) {
858         if (mState != State.ACTIVE && mState != State.IDLE) {
859             throw new IllegalStateException();
860         }
861 
862         Log.v(mTag, "onRangingRoundsUpdateDtTag - sessionHandle: " + mSessionHandle);
863         try {
864             mAdapter.updateRangingRoundsDtTag(mSessionHandle, params);
865         } catch (RemoteException e) {
866             throw e.rethrowFromSystemServer();
867         }
868     }
869 
870     /**
871      * Query max application data size which can be sent by UWBS in one ranging round.
872      *
873      * @throws IllegalStateException, when the ranging session is not in the appropriate state for
874      * this API to be called.
875      * @return max application data size
876      */
877     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
878     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
queryMaxDataSizeBytes()879     public int queryMaxDataSizeBytes() {
880         if (!isOpen()) {
881             throw new IllegalStateException("Ranging session is not open");
882         }
883 
884         Log.v(mTag, "QueryMaxDataSizeBytes - sessionHandle: " + mSessionHandle);
885         try {
886             return mAdapter.queryMaxDataSizeBytes(mSessionHandle);
887         } catch (RemoteException e) {
888             throw e.rethrowFromSystemServer();
889         }
890     }
891 
892     /**
893      * Sets the Hybrid UWB Session Controller Configuration.
894      *
895      * <p>On successfully setting the hybrid controller configuration,
896      * {@link RangingSession.Callback#onHybridSessionControllerConfigured(PersistableBundle)}
897      * is invoked.
898      *
899      * <p>On failing to set the hybrid controller configuration,
900      * {@link RangingSession.Callback#onHybridSessionControllerConfigurationFailed(int,
901      * PersistableBundle)} is invoked.
902      *
903      * @param params protocol specific parameters to configure the hybrid session controller
904      * @throws RemoteException if a remote error occurred
905      */
906     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
907     @FlaggedApi("com.android.uwb.flags.hybrid_session_support")
setHybridSessionControllerConfiguration(@onNull PersistableBundle params)908     public void setHybridSessionControllerConfiguration(@NonNull PersistableBundle params) {
909         if (!isOpen()) {
910             throw new IllegalStateException("Ranging session is not open");
911         }
912 
913         Log.v(mTag, "setHybridSessionControllerConfiguration - sessionHandle: " + mSessionHandle);
914         try {
915             mAdapter.setHybridSessionControllerConfiguration(mSessionHandle, params);
916         } catch (RemoteException e) {
917             throw e.rethrowFromSystemServer();
918         }
919     }
920 
921     /**
922      * Sets the Hybrid UWB Session Controlee Configuration.
923      *
924      * <p>On successfully setting the hybrid Controlee configuration,
925      * {@link RangingSession.Callback#onHybridSessionControleeConfigured(PersistableBundle)}
926      * is invoked.
927      *
928      * <p>On failing to set the hybrid Controlee configuration,
929      * {@link RangingSession.Callback#onHybridSessionControleeConfigurationFailed(int,
930      * PersistableBundle)} is invoked.
931      *
932      * @param params protocol specific parameters to configure the hybrid session Controlee
933      * @throws RemoteException if a remote error occurred
934      */
935     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
936     @FlaggedApi("com.android.uwb.flags.hybrid_session_support")
setHybridSessionControleeConfiguration(@onNull PersistableBundle params)937     public void setHybridSessionControleeConfiguration(@NonNull PersistableBundle params) {
938         if (!isOpen()) {
939             throw new IllegalStateException("Ranging session is not open");
940         }
941 
942         Log.v(mTag, "setHybridSessionControleeConfiguration - sessionHandle: " + mSessionHandle);
943         try {
944             mAdapter.setHybridSessionControleeConfiguration(mSessionHandle, params);
945         } catch (RemoteException e) {
946             throw e.rethrowFromSystemServer();
947         }
948     }
949 
950     /**
951      * @hide
952      */
onRangingOpened()953     public void onRangingOpened() {
954         if (mState == State.CLOSED) {
955             Log.w(mTag, "onRangingOpened invoked for a closed session");
956             return;
957         }
958 
959         Log.v(mTag, "onRangingOpened - sessionHandle: " + mSessionHandle);
960         mState = State.IDLE;
961         executeCallback(() -> mCallback.onOpened(this));
962     }
963 
964     /**
965      * @hide
966      */
onRangingOpenFailed(@allback.Reason int reason, @NonNull PersistableBundle params)967     public void onRangingOpenFailed(@Callback.Reason int reason,
968             @NonNull PersistableBundle params) {
969         if (mState == State.CLOSED) {
970             Log.w(mTag, "onRangingOpenFailed invoked for a closed session");
971             return;
972         }
973 
974         Log.v(mTag, "onRangingOpenFailed - sessionHandle: " + mSessionHandle);
975         mState = State.CLOSED;
976         executeCallback(() -> mCallback.onOpenFailed(reason, params));
977     }
978 
979     /**
980      * @hide
981      */
onRangingStarted(@onNull PersistableBundle parameters)982     public void onRangingStarted(@NonNull PersistableBundle parameters) {
983         if (mState == State.CLOSED) {
984             Log.w(mTag, "onRangingStarted invoked for a closed session");
985             return;
986         }
987 
988         Log.v(mTag, "onRangingStarted - sessionHandle: " + mSessionHandle);
989         mState = State.ACTIVE;
990         executeCallback(() -> mCallback.onStarted(parameters));
991     }
992 
993     /**
994      * @hide
995      */
onRangingStartFailed(@allback.Reason int reason, @NonNull PersistableBundle params)996     public void onRangingStartFailed(@Callback.Reason int reason,
997             @NonNull PersistableBundle params) {
998         if (mState == State.CLOSED) {
999             Log.w(mTag, "onRangingStartFailed invoked for a closed session");
1000             return;
1001         }
1002 
1003         Log.v(mTag, "onRangingStartFailed - sessionHandle: " + mSessionHandle);
1004         executeCallback(() -> mCallback.onStartFailed(reason, params));
1005     }
1006 
1007     /**
1008      * @hide
1009      */
onRangingReconfigured(@onNull PersistableBundle params)1010     public void onRangingReconfigured(@NonNull PersistableBundle params) {
1011         if (mState == State.CLOSED) {
1012             Log.w(mTag, "onRangingReconfigured invoked for a closed session");
1013             return;
1014         }
1015 
1016         Log.v(mTag, "onRangingReconfigured - sessionHandle: " + mSessionHandle);
1017         executeCallback(() -> mCallback.onReconfigured(params));
1018     }
1019 
1020     /**
1021      * @hide
1022      */
onRangingReconfigureFailed(@allback.Reason int reason, @NonNull PersistableBundle params)1023     public void onRangingReconfigureFailed(@Callback.Reason int reason,
1024             @NonNull PersistableBundle params) {
1025         if (mState == State.CLOSED) {
1026             Log.w(mTag, "onRangingReconfigureFailed invoked for a closed session");
1027             return;
1028         }
1029 
1030         Log.v(mTag, "onRangingReconfigureFailed - sessionHandle: " + mSessionHandle);
1031         executeCallback(() -> mCallback.onReconfigureFailed(reason, params));
1032     }
1033 
1034     /**
1035      * @hide
1036      */
onRangingStopped(@allback.Reason int reason, @NonNull PersistableBundle params)1037     public void onRangingStopped(@Callback.Reason int reason,
1038             @NonNull PersistableBundle params) {
1039         if (mState == State.CLOSED) {
1040             Log.w(mTag, "onRangingStopped invoked for a closed session");
1041             return;
1042         }
1043 
1044         Log.v(mTag, "onRangingStopped - sessionHandle: " + mSessionHandle);
1045         mState = State.IDLE;
1046         executeCallback(() -> mCallback.onStopped(reason, params));
1047     }
1048 
1049     /**
1050      * @hide
1051      */
onRangingStopFailed(@allback.Reason int reason, @NonNull PersistableBundle params)1052     public void onRangingStopFailed(@Callback.Reason int reason,
1053             @NonNull PersistableBundle params) {
1054         if (mState == State.CLOSED) {
1055             Log.w(mTag, "onRangingStopFailed invoked for a closed session");
1056             return;
1057         }
1058 
1059         Log.v(mTag, "onRangingStopFailed - sessionHandle: " + mSessionHandle);
1060         executeCallback(() -> mCallback.onStopFailed(reason, params));
1061     }
1062 
1063     /**
1064      * @hide
1065      */
onRangingClosed(@allback.Reason int reason, @NonNull PersistableBundle parameters)1066     public void onRangingClosed(@Callback.Reason int reason,
1067             @NonNull PersistableBundle parameters) {
1068         mState = State.CLOSED;
1069         Log.v(mTag, "onRangingClosed - sessionHandle: " + mSessionHandle);
1070         executeCallback(() -> mCallback.onClosed(reason, parameters));
1071     }
1072 
1073     /**
1074      * @hide
1075      */
onRangingResult(@onNull RangingReport report)1076     public void onRangingResult(@NonNull RangingReport report) {
1077         if (!isOpen()) {
1078             Log.w(mTag, "onRangingResult invoked for non-open session");
1079             return;
1080         }
1081 
1082         Log.v(mTag, "onRangingResult - sessionHandle: " + mSessionHandle);
1083         executeCallback(() -> mCallback.onReportReceived(report));
1084     }
1085 
1086     /**
1087      * @hide
1088      */
onControleeAdded(@onNull PersistableBundle params)1089     public void onControleeAdded(@NonNull PersistableBundle params) {
1090         if (!isOpen()) {
1091             Log.w(mTag, "onControleeAdded invoked for non-open session");
1092             return;
1093         }
1094 
1095         Log.v(mTag, "onControleeAdded - sessionHandle: " + mSessionHandle);
1096         executeCallback(() -> mCallback.onControleeAdded(params));
1097     }
1098 
1099     /**
1100      * @hide
1101      */
onControleeAddFailed(@allback.ControleeFailureReason int reason, @NonNull PersistableBundle params)1102     public void onControleeAddFailed(@Callback.ControleeFailureReason int reason,
1103             @NonNull PersistableBundle params) {
1104         if (!isOpen()) {
1105             Log.w(mTag, "onControleeAddFailed invoked for non-open session");
1106             return;
1107         }
1108 
1109         Log.v(mTag, "onControleeAddFailed - sessionHandle: " + mSessionHandle);
1110         executeCallback(() -> mCallback.onControleeAddFailed(reason, params));
1111     }
1112 
1113     /**
1114      * @hide
1115      */
onControleeRemoved(@onNull PersistableBundle params)1116     public void onControleeRemoved(@NonNull PersistableBundle params) {
1117         if (!isOpen()) {
1118             Log.w(mTag, "onControleeRemoved invoked for non-open session");
1119             return;
1120         }
1121 
1122         Log.v(mTag, "onControleeRemoved - sessionHandle: " + mSessionHandle);
1123         executeCallback(() -> mCallback.onControleeRemoved(params));
1124     }
1125 
1126     /**
1127      * @hide
1128      */
onControleeRemoveFailed(@allback.ControleeFailureReason int reason, @NonNull PersistableBundle params)1129     public void onControleeRemoveFailed(@Callback.ControleeFailureReason int reason,
1130             @NonNull PersistableBundle params) {
1131         if (!isOpen()) {
1132             Log.w(mTag, "onControleeRemoveFailed invoked for non-open session");
1133             return;
1134         }
1135 
1136         Log.v(mTag, "onControleeRemoveFailed - sessionHandle: " + mSessionHandle);
1137         executeCallback(() -> mCallback.onControleeRemoveFailed(reason, params));
1138     }
1139 
1140     /**
1141      * @hide
1142      */
onRangingPaused(@onNull PersistableBundle params)1143     public void onRangingPaused(@NonNull PersistableBundle params) {
1144         if (!isOpen()) {
1145             Log.w(mTag, "onRangingPaused invoked for non-open session");
1146             return;
1147         }
1148 
1149         Log.v(mTag, "onRangingPaused - sessionHandle: " + mSessionHandle);
1150         executeCallback(() -> mCallback.onPaused(params));
1151     }
1152 
1153     /**
1154      * @hide
1155      */
onRangingPauseFailed(@allback.Reason int reason, @NonNull PersistableBundle params)1156     public void onRangingPauseFailed(@Callback.Reason int reason,
1157             @NonNull PersistableBundle params) {
1158         if (!isOpen()) {
1159             Log.w(mTag, "onRangingPauseFailed invoked for non-open session");
1160             return;
1161         }
1162 
1163         Log.v(mTag, "onRangingPauseFailed - sessionHandle: " + mSessionHandle);
1164         executeCallback(() -> mCallback.onPauseFailed(reason, params));
1165     }
1166 
1167     /**
1168      * @hide
1169      */
onRangingResumed(@onNull PersistableBundle params)1170     public void onRangingResumed(@NonNull PersistableBundle params) {
1171         if (!isOpen()) {
1172             Log.w(mTag, "onRangingResumed invoked for non-open session");
1173             return;
1174         }
1175 
1176         Log.v(mTag, "onRangingResumed - sessionHandle: " + mSessionHandle);
1177         executeCallback(() -> mCallback.onResumed(params));
1178     }
1179 
1180     /**
1181      * @hide
1182      */
onRangingResumeFailed(@allback.Reason int reason, @NonNull PersistableBundle params)1183     public void onRangingResumeFailed(@Callback.Reason int reason,
1184             @NonNull PersistableBundle params) {
1185         if (!isOpen()) {
1186             Log.w(mTag, "onRangingResumeFailed invoked for non-open session");
1187             return;
1188         }
1189 
1190         Log.v(mTag, "onRangingResumeFailed - sessionHandle: " + mSessionHandle);
1191         executeCallback(() -> mCallback.onResumeFailed(reason, params));
1192     }
1193 
1194     /**
1195      * @hide
1196      */
onDataSent(@onNull UwbAddress remoteDeviceAddress, @NonNull PersistableBundle params)1197     public void onDataSent(@NonNull UwbAddress remoteDeviceAddress,
1198             @NonNull PersistableBundle params) {
1199         if (!isOpen()) {
1200             Log.w(mTag, "onDataSent invoked for non-open session");
1201             return;
1202         }
1203 
1204         Log.v(mTag, "onDataSent - sessionHandle: " + mSessionHandle);
1205         executeCallback(() -> mCallback.onDataSent(remoteDeviceAddress, params));
1206     }
1207 
1208     /**
1209      * @hide
1210      */
onDataSendFailed(@onNull UwbAddress remoteDeviceAddress, @Callback.DataFailureReason int reason, @NonNull PersistableBundle params)1211     public void onDataSendFailed(@NonNull UwbAddress remoteDeviceAddress,
1212             @Callback.DataFailureReason int reason, @NonNull PersistableBundle params) {
1213         if (!isOpen()) {
1214             Log.w(mTag, "onDataSendFailed invoked for non-open session");
1215             return;
1216         }
1217 
1218         Log.v(mTag, "onDataSendFailed - sessionHandle: " + mSessionHandle);
1219         executeCallback(() -> mCallback.onDataSendFailed(remoteDeviceAddress, reason, params));
1220     }
1221 
1222     /**
1223      * @hide
1224      */
onDataReceived(@onNull UwbAddress remoteDeviceAddress, @NonNull PersistableBundle params, @NonNull byte[] data)1225     public void onDataReceived(@NonNull UwbAddress remoteDeviceAddress,
1226             @NonNull PersistableBundle params, @NonNull byte[] data) {
1227         if (!isOpen()) {
1228             Log.w(mTag, "onDataReceived invoked for non-open session");
1229             return;
1230         }
1231 
1232         Log.v(mTag, "onDataReceived - sessionHandle: " + mSessionHandle);
1233         executeCallback(() -> mCallback.onDataReceived(remoteDeviceAddress, params, data));
1234     }
1235 
1236     /**
1237      * @hide
1238      */
onDataReceiveFailed(@onNull UwbAddress remoteDeviceAddress, @Callback.DataFailureReason int reason, @NonNull PersistableBundle params)1239     public void onDataReceiveFailed(@NonNull UwbAddress remoteDeviceAddress,
1240             @Callback.DataFailureReason int reason, @NonNull PersistableBundle params) {
1241         if (!isOpen()) {
1242             Log.w(mTag, "onDataReceiveFailed invoked for non-open session");
1243             return;
1244         }
1245 
1246         Log.v(mTag, "onDataReceiveFailed - sessionHandle: " + mSessionHandle);
1247         executeCallback(() -> mCallback.onDataReceiveFailed(remoteDeviceAddress, reason, params));
1248     }
1249 
1250     /**
1251      * @hide
1252      */
onDataTransferPhaseConfigured(@onNull PersistableBundle params)1253     public void onDataTransferPhaseConfigured(@NonNull PersistableBundle params) {
1254         if (!isOpen()) {
1255             Log.w(mTag, "onDataTransferPhaseConfigured invoked for non-open session");
1256             return;
1257         }
1258 
1259         Log.v(mTag, "onDataTransferPhaseConfigured - sessionHandle: " + mSessionHandle);
1260         executeCallback(() -> mCallback.onDataTransferPhaseConfigured(params));
1261     }
1262 
1263     /**
1264      * @hide
1265      */
onDataTransferPhaseConfigFailed(@allback.Reason int reason, @NonNull PersistableBundle params)1266     public void onDataTransferPhaseConfigFailed(@Callback.Reason int reason,
1267             @NonNull PersistableBundle params) {
1268         if (!isOpen()) {
1269             Log.w(mTag, "onDataTransferPhaseConfigFailed invoked for non-open session");
1270             return;
1271         }
1272 
1273         Log.v(mTag, "onDataTransferPhaseConfigFailed - sessionHandle: " + mSessionHandle);
1274         executeCallback(() -> mCallback.onDataTransferPhaseConfigFailed(reason, params));
1275     }
1276 
1277     /**
1278      * @hide
1279      */
onServiceDiscovered(@onNull PersistableBundle params)1280     public void onServiceDiscovered(@NonNull PersistableBundle params) {
1281         if (!isOpen()) {
1282             Log.w(mTag, "onServiceDiscovered invoked for non-open session");
1283             return;
1284         }
1285 
1286         Log.v(mTag, "onServiceDiscovered - sessionHandle: " + mSessionHandle);
1287         executeCallback(() -> mCallback.onServiceDiscovered(params));
1288     }
1289 
1290     /**
1291      * @hide
1292      */
onServiceConnected(@onNull PersistableBundle params)1293     public void onServiceConnected(@NonNull PersistableBundle params) {
1294         if (!isOpen()) {
1295             Log.w(mTag, "onServiceConnected invoked for non-open session");
1296             return;
1297         }
1298 
1299         Log.v(mTag, "onServiceConnected - sessionHandle: " + mSessionHandle);
1300         executeCallback(() -> mCallback.onServiceConnected(params));
1301     }
1302 
1303     /**
1304      * @hide
1305      */
onRangingRoundsUpdateDtTagStatus(@onNull PersistableBundle params)1306     public void onRangingRoundsUpdateDtTagStatus(@NonNull PersistableBundle params) {
1307         if (!isOpen()) {
1308             Log.w(mTag, "onDlTDoARangingRoundsUpdateStatus invoked for non-open session");
1309             return;
1310         }
1311 
1312         Log.v(mTag, "onDlTDoARangingRoundsUpdateStatus - sessionHandle: " + mSessionHandle);
1313         if (SdkLevel.isAtLeastU()) {
1314             executeCallback(() -> mCallback.onRangingRoundsUpdateDtTagStatus(params));
1315         }
1316     }
1317 
1318     /**
1319      * @hide
1320      */
onHybridSessionControllerConfigured(@onNull PersistableBundle params)1321     public void onHybridSessionControllerConfigured(@NonNull PersistableBundle params) {
1322         if (!isOpen()) {
1323             Log.w(mTag, "onHybridSessionControllerConfigured invoked for non-open session");
1324             return;
1325         }
1326 
1327         Log.v(mTag, "onHybridSessionControllerConfigured - sessionHandle: " + mSessionHandle);
1328         executeCallback(() -> mCallback.onHybridSessionControllerConfigured(params));
1329     }
1330 
1331     /**
1332      * @hide
1333      */
onHybridSessionControllerConfigurationFailed(@allback.Reason int reason, @NonNull PersistableBundle params)1334     public void onHybridSessionControllerConfigurationFailed(@Callback.Reason int reason,
1335             @NonNull PersistableBundle params) {
1336         if (!isOpen()) {
1337             Log.w(mTag, "onHybridSessionControllerConfigurationFailed invoked for non-open"
1338                     + "session");
1339             return;
1340         }
1341 
1342         Log.v(mTag, "onHybridSessionControllerConfigurationFailed - sessionHandle: "
1343                 + mSessionHandle);
1344         executeCallback(() -> mCallback.onHybridSessionControllerConfigurationFailed(
1345                 reason, params));
1346     }
1347 
1348     /**
1349      * @hide
1350      */
onHybridSessionControleeConfigured(@onNull PersistableBundle params)1351     public void onHybridSessionControleeConfigured(@NonNull PersistableBundle params) {
1352         if (!isOpen()) {
1353             Log.w(mTag, "onHybridSessionControleeConfigured invoked for non-open session");
1354             return;
1355         }
1356 
1357         Log.v(mTag, "onHybridSessionControleeConfigured - sessionHandle: " + mSessionHandle);
1358         executeCallback(() -> mCallback.onHybridSessionControleeConfigured(params));
1359     }
1360 
1361     /**
1362      * @hide
1363      */
onHybridSessionControleeConfigurationFailed(@allback.Reason int reason, @NonNull PersistableBundle params)1364     public void onHybridSessionControleeConfigurationFailed(@Callback.Reason int reason,
1365             @NonNull PersistableBundle params) {
1366         if (!isOpen()) {
1367             Log.w(mTag, "onHybridSessionControleeConfigurationFailed invoked for non-open"
1368                     + "session");
1369             return;
1370         }
1371 
1372         Log.v(mTag, "onHybridSessionControleeConfigurationFailed - sessionHandle: "
1373                 + mSessionHandle);
1374         executeCallback(() -> mCallback.onHybridSessionControleeConfigurationFailed(
1375                 reason, params));
1376     }
1377 
1378     /**
1379      * @hide
1380      */
executeCallback(@onNull Runnable runnable)1381     private void executeCallback(@NonNull Runnable runnable) {
1382         final long identity = Binder.clearCallingIdentity();
1383         try {
1384             mExecutor.execute(runnable);
1385         } finally {
1386             Binder.restoreCallingIdentity(identity);
1387         }
1388     }
1389 
1390     /**
1391      * Updates the UWB filter engine's pose information. This requires that the call to
1392      * {@link UwbManager#openRangingSession} indicated an application pose source.
1393      *
1394      * @param parameters Parameters representing the session to update, and the pose information.
1395      */
1396     @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
updatePose(@onNull PersistableBundle parameters)1397     public void updatePose(@NonNull PersistableBundle parameters) {
1398         try {
1399             mAdapter.updatePose(mSessionHandle, parameters);
1400         } catch (RemoteException e) {
1401             throw e.rethrowFromSystemServer();
1402         }
1403     }
1404 }
1405