script-astra/Android/Sdk/sources/android-35/android/uwb/RangingSession.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

1405 lines
50 KiB
Java
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.uwb;
import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.os.Binder;
import android.os.Build;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.android.modules.utils.build.SdkLevel;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
/**
* This class provides a way to control an active UWB ranging session.
* <p>It also defines the required {@link RangingSession.Callback} that must be implemented
* in order to be notified of UWB ranging results and status events related to the
* {@link RangingSession}.
*
* <p>To get an instance of {@link RangingSession}, first use
* {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)} to request to open a
* session. Once the session is opened, a {@link RangingSession} object is provided through
* {@link RangingSession.Callback#onOpened(RangingSession)}. If opening a session fails, the failure
* is reported through {@link RangingSession.Callback#onOpenFailed(int, PersistableBundle)} with the
* failure reason.
*
* @hide
*/
@SystemApi
public final class RangingSession implements AutoCloseable {
private final String mTag = "Uwb.RangingSession[" + this + "]";
private final SessionHandle mSessionHandle;
private final IUwbAdapter mAdapter;
private final Executor mExecutor;
private final Callback mCallback;
private final String mChipId;
private enum State {
/**
* The state of the {@link RangingSession} until
* {@link RangingSession.Callback#onOpened(RangingSession)} is invoked
*/
INIT,
/**
* The {@link RangingSession} is initialized and ready to begin ranging
*/
IDLE,
/**
* The {@link RangingSession} is actively ranging
*/
ACTIVE,
/**
* The {@link RangingSession} is closed and may not be used for ranging.
*/
CLOSED
}
private State mState = State.INIT;
/**
* Interface for receiving {@link RangingSession} events
*/
public interface Callback {
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
REASON_UNKNOWN,
REASON_LOCAL_REQUEST,
REASON_REMOTE_REQUEST,
REASON_BAD_PARAMETERS,
REASON_GENERIC_ERROR,
REASON_MAX_SESSIONS_REACHED,
REASON_SYSTEM_POLICY,
REASON_PROTOCOL_SPECIFIC_ERROR,
REASON_MAX_RR_RETRY_REACHED,
REASON_SERVICE_DISCOVERY_FAILURE,
REASON_SERVICE_CONNECTION_FAILURE,
REASON_SE_NOT_SUPPORTED,
REASON_SE_INTERACTION_FAILURE,
REASON_INSUFFICIENT_SLOTS_PER_RR,
REASON_SYSTEM_REGULATION,
REASON_INBAND_SESSION_STOP,
})
@interface Reason {}
/**
* Indicates that the session was closed or failed to open due to an unknown reason
*/
int REASON_UNKNOWN = 0;
/**
* Indicates that the session was closed or failed to open because
* {@link AutoCloseable#close()} or {@link RangingSession#close()} was called
*/
int REASON_LOCAL_REQUEST = 1;
/**
* Indicates that the session was closed or failed to open due to an explicit request from
* the remote device.
*/
int REASON_REMOTE_REQUEST = 2;
/**
* Indicates that the session was closed or failed to open due to erroneous parameters
*/
int REASON_BAD_PARAMETERS = 3;
/**
* Indicates an error on this device besides the error code already listed
*/
int REASON_GENERIC_ERROR = 4;
/**
* Indicates that the number of currently open sessions supported by the device and
* additional sessions may not be opened.
*/
int REASON_MAX_SESSIONS_REACHED = 5;
/**
* Indicates that the local system policy caused the change, such
* as privacy policy, power management policy, permissions, and more.
*/
int REASON_SYSTEM_POLICY = 6;
/**
* Indicates a protocol specific error. The associated {@link PersistableBundle} should be
* consulted for additional information.
*/
int REASON_PROTOCOL_SPECIFIC_ERROR = 7;
/**
* Indicates that the max number of retry attempts for a ranging attempt has been reached.
*/
int REASON_MAX_RR_RETRY_REACHED = 9;
/**
* Indicates a failure to discover the service after activation.
*/
int REASON_SERVICE_DISCOVERY_FAILURE = 10;
/**
* Indicates a failure to connect to the service after discovery.
*/
int REASON_SERVICE_CONNECTION_FAILURE = 11;
/**
* The device doesnt support FiRA Applet.
*/
int REASON_SE_NOT_SUPPORTED = 12;
/**
* SE interactions failed.
*/
int REASON_SE_INTERACTION_FAILURE = 13;
/**
* Indicate insufficient slots per ranging round.
*/
int REASON_INSUFFICIENT_SLOTS_PER_RR = 14;
/**
* Indicate that a system regulation caused the change, such as no allowed UWB channels in
* the country.
*/
int REASON_SYSTEM_REGULATION = 15;
/**
* Indicates session was stopped due to inband signal.
*/
@FlaggedApi("com.android.uwb.flags.reason_inband_session_stop")
int REASON_INBAND_SESSION_STOP = 16;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
CONTROLEE_FAILURE_REASON_MAX_CONTROLEE_REACHED,
})
@interface ControleeFailureReason {}
/**
* Indicates that the session has reached the max number of controlees supported by the
* device. This is applicable to only one to many sessions and sent in response to a
* request to add a new controlee to an ongoing session.
*/
int CONTROLEE_FAILURE_REASON_MAX_CONTROLEE_REACHED = 0;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
DATA_FAILURE_REASON_DATA_SIZE_TOO_LARGE,
})
@interface DataFailureReason {}
/**
* Indicates that the size of the data being sent or received is too large.
*/
int DATA_FAILURE_REASON_DATA_SIZE_TOO_LARGE = 10;
/**
* Invoked when {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
* is successful
*
* @param session the newly opened {@link RangingSession}
*/
void onOpened(@NonNull RangingSession session);
/**
* Invoked if {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}}
* fails
*
* @param reason the failure reason
* @param params protocol specific parameters
*/
void onOpenFailed(@Reason int reason, @NonNull PersistableBundle params);
/**
* Invoked either,
* - when {@link RangingSession#start(PersistableBundle)} is successful if the session is
* using a custom profile, OR
* - when platform starts ranging after OOB discovery + negotiation if the session is
* using a platform defined profile.
* @param sessionInfo session specific parameters from the lower layers
*/
void onStarted(@NonNull PersistableBundle sessionInfo);
/**
* Invoked either,
* - when {@link RangingSession#start(PersistableBundle)} fails if
* the session is using a custom profile, OR
* - when platform fails ranging after OOB discovery + negotiation if the
* session is using a platform defined profile.
*
* @param reason the failure reason
* @param params protocol specific parameters
*/
void onStartFailed(@Reason int reason, @NonNull PersistableBundle params);
/**
* Invoked when a request to reconfigure the session succeeds
*
* @param params the updated ranging configuration
*/
void onReconfigured(@NonNull PersistableBundle params);
/**
* Invoked when a request to reconfigure the session fails
*
* @param reason reason the session failed to be reconfigured
* @param params protocol specific failure reasons
*/
void onReconfigureFailed(@Reason int reason, @NonNull PersistableBundle params);
/**
* Invoked when a request to stop the session succeeds
*
* @param reason reason for the session stop
* @param parameters protocol specific parameters related to the stop reason
*/
void onStopped(@Reason int reason, @NonNull PersistableBundle parameters);
/**
* Invoked when a request to stop the session fails
*
* @param reason reason the session failed to be stopped
* @param params protocol specific failure reasons
*/
void onStopFailed(@Reason int reason, @NonNull PersistableBundle params);
/**
* Invoked when session is either closed spontaneously, or per user request via
* {@link RangingSession#close()} or {@link AutoCloseable#close()}.
*
* @param reason reason for the session closure
* @param parameters protocol specific parameters related to the close reason
*/
void onClosed(@Reason int reason, @NonNull PersistableBundle parameters);
/**
* Called once per ranging interval even when a ranging measurement fails
*
* @param rangingReport ranging report for this interval's measurements
*/
void onReportReceived(@NonNull RangingReport rangingReport);
/**
* Invoked when a new controlee is added to an ongoing one-to many session.
*
* @param parameters protocol specific parameters for the new controlee
*/
default void onControleeAdded(@NonNull PersistableBundle parameters) {}
/**
* Invoked when a new controlee is added to an ongoing one-to many session.
*
* @param reason reason for the controlee add failure
* @param parameters protocol specific parameters related to the failure
*/
default void onControleeAddFailed(
@ControleeFailureReason int reason, @NonNull PersistableBundle parameters) {}
/**
* Invoked when an existing controlee is removed from an ongoing one-to many session.
*
* @param parameters protocol specific parameters for the existing controlee
*/
default void onControleeRemoved(@NonNull PersistableBundle parameters) {}
/**
* Invoked when a new controlee is added to an ongoing one-to many session.
*
* @param reason reason for the controlee remove failure
* @param parameters protocol specific parameters related to the failure
*/
default void onControleeRemoveFailed(
@ControleeFailureReason int reason, @NonNull PersistableBundle parameters) {}
/**
* Invoked when an ongoing session is successfully pauseed.
*
* @param parameters protocol specific parameters sent for suspension
*/
default void onPaused(@NonNull PersistableBundle parameters) {}
/**
* Invoked when an ongoing session suspension fails.
*
* @param reason reason for the suspension failure
* @param parameters protocol specific parameters for suspension failure
*/
default void onPauseFailed(@Reason int reason, @NonNull PersistableBundle parameters) {}
/**
* Invoked when a pauseed session is successfully resumed.
*
* @param parameters protocol specific parameters sent for suspension
*/
default void onResumed(@NonNull PersistableBundle parameters) {}
/**
* Invoked when a pauseed session resumption fails.
*
* @param reason reason for the resumption failure
* @param parameters protocol specific parameters for resumption failure
*/
default void onResumeFailed(@Reason int reason, @NonNull PersistableBundle parameters) {}
/**
* Invoked when data is successfully sent via {@link RangingSession#sendData(UwbAddress,
* PersistableBundle, byte[])}.
*
* @param remoteDeviceAddress remote device's address
* @param parameters protocol specific parameters sent for suspension
*/
default void onDataSent(@NonNull UwbAddress remoteDeviceAddress,
@NonNull PersistableBundle parameters) {}
/**
* Invoked when data send to a remote device via {@link RangingSession#sendData(UwbAddress,
* PersistableBundle, byte[])} fails.
*
* @param remoteDeviceAddress remote device's address
* @param reason reason for the resumption failure
* @param parameters protocol specific parameters for resumption failure
*/
default void onDataSendFailed(@NonNull UwbAddress remoteDeviceAddress,
@DataFailureReason int reason, @NonNull PersistableBundle parameters) {}
/**
* Invoked when data is received successfully from a remote device.
* The data is received piggybacked over RRM (initiator -> responder) or
* RIM (responder -> initiator).
* <p> This is only functional on a FIRA 2.0 compliant device.
*
* @param remoteDeviceAddress remote device's address
* @param data Raw data received
* @param parameters protocol specific parameters for the received data
*/
default void onDataReceived(@NonNull UwbAddress remoteDeviceAddress,
@NonNull PersistableBundle parameters, @NonNull byte[] data) {}
/**
* Invoked when data receive from a remote device fails.
*
* @param remoteDeviceAddress remote device's address
* @param reason reason for the reception failure
* @param parameters protocol specific parameters for resumption failure
*/
default void onDataReceiveFailed(@NonNull UwbAddress remoteDeviceAddress,
@DataFailureReason int reason, @NonNull PersistableBundle parameters) {}
/**
* Invoked when set data transfer phase config is called successfully
*
* @param parameters protocol specific parameters for set data transfer phase config success
*/
@FlaggedApi("com.android.uwb.flags.data_transfer_phase_config")
default void onDataTransferPhaseConfigured(@NonNull PersistableBundle parameters) {}
/**
* Invoked when set data transfer phase config is failed
*
* @param parameters protocol specific parameters for set data transfer phase config failure
*/
@FlaggedApi("com.android.uwb.flags.data_transfer_phase_config")
default void onDataTransferPhaseConfigFailed(@Reason int reason,
@NonNull PersistableBundle parameters) {}
/**
* Invoked when service is discovered via OOB.
* <p>
* If this a one to many session, this can be invoked multiple times to indicate different
* peers being discovered.
* </p>
*
* @param parameters protocol specific params for discovered service.
*/
default void onServiceDiscovered(@NonNull PersistableBundle parameters) {}
/**
* Invoked when service is connected via OOB.
* <p>
* If this a one to many session, this can be invoked multiple times to indicate different
* peers being connected.
* </p>
*
* @param parameters protocol specific params for connected service.
*/
default void onServiceConnected(@NonNull PersistableBundle parameters) {}
/**
* Invoked when a response/status is received for active ranging rounds update.
*
* @param parameters bundle of ranging rounds update status
*/
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
default void onRangingRoundsUpdateDtTagStatus(@NonNull PersistableBundle parameters) {}
/**
* Invoked when hybrid session controller is successfully configured.
*
* @param parameters protocol specific parameters sent for HUS session configuration
*/
@FlaggedApi("com.android.uwb.flags.hybrid_session_support")
default void onHybridSessionControllerConfigured(
@NonNull PersistableBundle parameters) {}
/**
* Invoked when hybrid session controller configuration fails.
*
* @param parameters protocol specific parameters for configuration failure
*/
@FlaggedApi("com.android.uwb.flags.hybrid_session_support")
default void onHybridSessionControllerConfigurationFailed(
@RangingChangeReason int reason, @NonNull PersistableBundle parameters) {
}
/**
* Invoked when hybrid session controlee is successfully configured.
*
* @param parameters protocol specific parameters sent for HUS session configuration
*/
@FlaggedApi("com.android.uwb.flags.hybrid_session_support")
default void onHybridSessionControleeConfigured(
@NonNull PersistableBundle parameters) {}
/**
*Invoked when hybrid session controlee configuration fails.
*
* @param parameters protocol specific parameters for configuration failure
*/
@FlaggedApi("com.android.uwb.flags.hybrid_session_support")
default void onHybridSessionControleeConfigurationFailed(
@RangingChangeReason int reason, @NonNull PersistableBundle parameters) {}
}
/**
* @hide
*/
public RangingSession(Executor executor, Callback callback, IUwbAdapter adapter,
SessionHandle sessionHandle) {
this(executor, callback, adapter, sessionHandle, /* chipId= */ null);
}
/**
* @hide
*/
public RangingSession(Executor executor, Callback callback, IUwbAdapter adapter,
SessionHandle sessionHandle, String chipId) {
mState = State.INIT;
mExecutor = executor;
mCallback = callback;
mAdapter = adapter;
mSessionHandle = sessionHandle;
mChipId = chipId;
}
/**
* @hide
*/
public boolean isOpen() {
return mState == State.IDLE || mState == State.ACTIVE;
}
/**
* If the session uses custom profile,
* Begins ranging for the session.
* <p>On successfully starting a ranging session,
* {@link RangingSession.Callback#onStarted(PersistableBundle)} is invoked.
* <p>On failure to start the session,
* {@link RangingSession.Callback#onStartFailed(int, PersistableBundle)}
* is invoked.
*
* If the session uses platform defined profile (like PACS),
* Begins OOB discovery for the service. Once the service is discovered,
* UWB session params are negotiated via OOB and a UWB session will be
* started.
* <p>On successfully discovering a service,
* {@link RangingSession.Callback#onServiceDiscovered(PersistableBundle)} is invoked.
* <p>On successfully connecting to a service,
* {@link RangingSession.Callback#onServiceConnected(PersistableBundle)} is invoked.
* <p>On successfully starting a ranging session,
* {@link RangingSession.Callback#onStarted(PersistableBundle)} is invoked.
* <p>On failure to start the session,
* {@link RangingSession.Callback#onStartFailed(int, PersistableBundle)}
* is invoked.
*
* @param params configuration parameters for starting the session
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void start(@NonNull PersistableBundle params) {
if (mState != State.IDLE) {
throw new IllegalStateException();
}
Log.v(mTag, "start - sessionHandle: " + mSessionHandle);
try {
mAdapter.startRanging(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Attempts to reconfigure the session with the given parameters
* <p>This call may be made when the session is open.
*
* <p>On successfully reconfiguring the session
* {@link RangingSession.Callback#onReconfigured(PersistableBundle)} is invoked.
*
* <p>On failure to reconfigure the session,
* {@link RangingSession.Callback#onReconfigureFailed(int, PersistableBundle)} is invoked.
*
* @param params the parameters to reconfigure and their new values
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void reconfigure(@NonNull PersistableBundle params) {
if (mState != State.ACTIVE && mState != State.IDLE) {
throw new IllegalStateException();
}
Log.v(mTag, "reconfigure - sessionHandle: " + mSessionHandle);
try {
mAdapter.reconfigureRanging(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Stops actively ranging
*
* <p>A session that has been stopped may be resumed by calling
* {@link RangingSession#start(PersistableBundle)} without the need to open a new session.
*
* <p>Stopping a {@link RangingSession} is useful when the lower layers should not discard
* the parameters of the session, or when a session needs to be able to be resumed quickly.
*
* <p>If the {@link RangingSession} is no longer needed, use {@link RangingSession#close()} to
* completely close the session and allow lower layers of the stack to perform necessarily
* cleanup.
*
* <p>Stopped sessions may be closed by the system at any time. In such a case,
* {@link RangingSession.Callback#onClosed(int, PersistableBundle)} is invoked.
*
* <p>On failure to stop the session,
* {@link RangingSession.Callback#onStopFailed(int, PersistableBundle)} is invoked.
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void stop() {
if (mState != State.ACTIVE) {
throw new IllegalStateException();
}
Log.v(mTag, "stop - sessionHandle: " + mSessionHandle);
try {
mAdapter.stopRanging(mSessionHandle);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Close the ranging session
*
* <p>After calling this function, in order resume ranging, a new {@link RangingSession} must
* be opened by calling
* {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}.
*
* <p>If this session is currently ranging, it will stop and close the session.
* <p>If the session is in the process of being opened, it will attempt to stop the session from
* being opened.
* <p>If the session is already closed, the registered
* {@link Callback#onClosed(int, PersistableBundle)} callback will still be invoked.
*
* <p>{@link Callback#onClosed(int, PersistableBundle)} will be invoked using the same callback
* object given to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
* when the {@link RangingSession} was opened. The callback will be invoked after each call to
* {@link #close()}, even if the {@link RangingSession} is already closed.
*/
@Override
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void close() {
if (mState == State.CLOSED) {
mExecutor.execute(() -> mCallback.onClosed(
Callback.REASON_LOCAL_REQUEST, new PersistableBundle()));
return;
}
Log.v(mTag, "close - sessionHandle: " + mSessionHandle);
try {
mAdapter.closeRanging(mSessionHandle);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Add a new controlee to an ongoing session.
* <p>This call may be made when the session is open.
*
* <p>On successfully adding a new controlee to the session
* {@link RangingSession.Callback#onControleeAdded(PersistableBundle)} is invoked.
*
* <p>On failure to add a new controlee to the session,
* {@link RangingSession.Callback#onControleeAddFailed(int, PersistableBundle)} is invoked.
*
* @param params the parameters for the new controlee
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void addControlee(@NonNull PersistableBundle params) {
if (mState != State.ACTIVE && mState != State.IDLE) {
throw new IllegalStateException();
}
Log.v(mTag, "addControlee - sessionHandle: " + mSessionHandle);
try {
mAdapter.addControlee(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Remove an existing controlee from an ongoing session.
* <p>This call may be made when the session is open.
*
* <p>On successfully removing an existing controlee from the session
* {@link RangingSession.Callback#onControleeRemoved(PersistableBundle)} is invoked.
*
* <p>On failure to remove an existing controlee from the session,
* {@link RangingSession.Callback#onControleeRemoveFailed(int, PersistableBundle)} is invoked.
*
* @param params the parameters for the existing controlee
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void removeControlee(@NonNull PersistableBundle params) {
if (mState != State.ACTIVE && mState != State.IDLE) {
throw new IllegalStateException();
}
Log.v(mTag, "removeControlee - sessionHandle: " + mSessionHandle);
try {
mAdapter.removeControlee(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Pauses an ongoing ranging session.
*
* <p>A session that has been pauseed may be resumed by calling
* {@link RangingSession#resume(PersistableBundle)} without the need to open a new session.
*
* <p>Pauseing a {@link RangingSession} is useful when the lower layers should skip a few
* ranging rounds for a session without stopping it.
*
* <p>If the {@link RangingSession} is no longer needed, use {@link RangingSession#stop()} or
* {@link RangingSession#close()} to completely close the session.
*
* <p>On successfully pausing the session,
* {@link RangingSession.Callback#onRangingPaused(PersistableBundle)} is invoked.
*
* <p>On failure to pause the session,
* {@link RangingSession.Callback#onRangingPauseFailed(int, PersistableBundle)} is invoked.
*
* @param params protocol specific parameters for pausing the session
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void pause(@NonNull PersistableBundle params) {
if (mState != State.ACTIVE) {
throw new IllegalStateException();
}
Log.v(mTag, "pause - sessionHandle: " + mSessionHandle);
try {
mAdapter.pause(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Resumes a pauseed ranging session.
*
* <p>A session that has been previously pauseed using
* {@link RangingSession#pause(PersistableBundle)} can be resumed by calling
* {@link RangingSession#resume(PersistableBundle)}.
*
* <p>On successfully resuming the session,
* {@link RangingSession.Callback#onRangingResumed(PersistableBundle)} is invoked.
*
* <p>On failure to resume the session,
* {@link RangingSession.Callback#onRangingResumeFailed(int, PersistableBundle)} is invoked.
*
* @param params protocol specific parameters the resuming the session
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void resume(@NonNull PersistableBundle params) {
if (mState != State.ACTIVE) {
throw new IllegalStateException();
}
Log.v(mTag, "resume - sessionHandle: " + mSessionHandle);
try {
mAdapter.resume(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Send data to a remote device which is part of this ongoing session.
* The data is sent by piggybacking the provided data over RRM (initiator -> responder) or
* RIM (responder -> initiator).
* <p>This is only functional on a FIRA 2.0 compliant device.
*
* <p>On successfully sending the data,
* {@link RangingSession.Callback#onDataSent(UwbAddress, PersistableBundle)} is invoked.
*
* <p>On failure to send the data,
* {@link RangingSession.Callback#onDataSendFailed(UwbAddress, int, PersistableBundle)} is
* invoked.
*
* @param remoteDeviceAddress remote device's address
* @param params protocol specific parameters the sending the data
* @param data Raw data to be sent
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void sendData(@NonNull UwbAddress remoteDeviceAddress,
@NonNull PersistableBundle params, @NonNull byte[] data) {
if (mState != State.ACTIVE) {
throw new IllegalStateException();
}
Log.v(mTag, "sendData - sessionHandle: " + mSessionHandle);
try {
mAdapter.sendData(mSessionHandle, remoteDeviceAddress, params, data);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Set data transfer phase configuration during ranging as well as dedicated data transfer.
* <p>This is only functional on a FIRA 2.0 compliant device.
*
* <p>On successfully sending the data transfer phase config,
* {@link RangingSession.Callback#onDataTransferPhaseConfigured(PersistableBundle)} is
* invoked.
*
* <p>On failure to send the data transfer phase config,
* {@link RangingSession.Callback#onDataTransferPhaseConfigFailed(PersistableBundle)} is
* invoked.
*
* @param params Protocol specific data transfer phase configuration parameters
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
@FlaggedApi("com.android.uwb.flags.data_transfer_phase_config")
public void setDataTransferPhaseConfig(@NonNull PersistableBundle params) {
if (!isOpen()) {
throw new IllegalStateException();
}
Log.v(mTag, "setDataTransferPhaseConfig - sessionHandle: " + mSessionHandle);
try {
mAdapter.setDataTransferPhaseConfig(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Update active ranging rounds for DT Tag.
*
* <p> On successfully sending the command,
* {@link RangingSession.Callback#onRangingRoundsUpdateDtTagStatus(PersistableBundle)}
* is invoked.
* @param params Parameters to configure active ranging rounds
*/
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void updateRangingRoundsDtTag(@NonNull PersistableBundle params) {
if (mState != State.ACTIVE && mState != State.IDLE) {
throw new IllegalStateException();
}
Log.v(mTag, "onRangingRoundsUpdateDtTag - sessionHandle: " + mSessionHandle);
try {
mAdapter.updateRangingRoundsDtTag(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Query max application data size which can be sent by UWBS in one ranging round.
*
* @throws IllegalStateException, when the ranging session is not in the appropriate state for
* this API to be called.
* @return max application data size
*/
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public int queryMaxDataSizeBytes() {
if (!isOpen()) {
throw new IllegalStateException("Ranging session is not open");
}
Log.v(mTag, "QueryMaxDataSizeBytes - sessionHandle: " + mSessionHandle);
try {
return mAdapter.queryMaxDataSizeBytes(mSessionHandle);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets the Hybrid UWB Session Controller Configuration.
*
* <p>On successfully setting the hybrid controller configuration,
* {@link RangingSession.Callback#onHybridSessionControllerConfigured(PersistableBundle)}
* is invoked.
*
* <p>On failing to set the hybrid controller configuration,
* {@link RangingSession.Callback#onHybridSessionControllerConfigurationFailed(int,
* PersistableBundle)} is invoked.
*
* @param params protocol specific parameters to configure the hybrid session controller
* @throws RemoteException if a remote error occurred
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
@FlaggedApi("com.android.uwb.flags.hybrid_session_support")
public void setHybridSessionControllerConfiguration(@NonNull PersistableBundle params) {
if (!isOpen()) {
throw new IllegalStateException("Ranging session is not open");
}
Log.v(mTag, "setHybridSessionControllerConfiguration - sessionHandle: " + mSessionHandle);
try {
mAdapter.setHybridSessionControllerConfiguration(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets the Hybrid UWB Session Controlee Configuration.
*
* <p>On successfully setting the hybrid Controlee configuration,
* {@link RangingSession.Callback#onHybridSessionControleeConfigured(PersistableBundle)}
* is invoked.
*
* <p>On failing to set the hybrid Controlee configuration,
* {@link RangingSession.Callback#onHybridSessionControleeConfigurationFailed(int,
* PersistableBundle)} is invoked.
*
* @param params protocol specific parameters to configure the hybrid session Controlee
* @throws RemoteException if a remote error occurred
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
@FlaggedApi("com.android.uwb.flags.hybrid_session_support")
public void setHybridSessionControleeConfiguration(@NonNull PersistableBundle params) {
if (!isOpen()) {
throw new IllegalStateException("Ranging session is not open");
}
Log.v(mTag, "setHybridSessionControleeConfiguration - sessionHandle: " + mSessionHandle);
try {
mAdapter.setHybridSessionControleeConfiguration(mSessionHandle, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
*/
public void onRangingOpened() {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingOpened invoked for a closed session");
return;
}
Log.v(mTag, "onRangingOpened - sessionHandle: " + mSessionHandle);
mState = State.IDLE;
executeCallback(() -> mCallback.onOpened(this));
}
/**
* @hide
*/
public void onRangingOpenFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingOpenFailed invoked for a closed session");
return;
}
Log.v(mTag, "onRangingOpenFailed - sessionHandle: " + mSessionHandle);
mState = State.CLOSED;
executeCallback(() -> mCallback.onOpenFailed(reason, params));
}
/**
* @hide
*/
public void onRangingStarted(@NonNull PersistableBundle parameters) {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingStarted invoked for a closed session");
return;
}
Log.v(mTag, "onRangingStarted - sessionHandle: " + mSessionHandle);
mState = State.ACTIVE;
executeCallback(() -> mCallback.onStarted(parameters));
}
/**
* @hide
*/
public void onRangingStartFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingStartFailed invoked for a closed session");
return;
}
Log.v(mTag, "onRangingStartFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onStartFailed(reason, params));
}
/**
* @hide
*/
public void onRangingReconfigured(@NonNull PersistableBundle params) {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingReconfigured invoked for a closed session");
return;
}
Log.v(mTag, "onRangingReconfigured - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onReconfigured(params));
}
/**
* @hide
*/
public void onRangingReconfigureFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingReconfigureFailed invoked for a closed session");
return;
}
Log.v(mTag, "onRangingReconfigureFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onReconfigureFailed(reason, params));
}
/**
* @hide
*/
public void onRangingStopped(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingStopped invoked for a closed session");
return;
}
Log.v(mTag, "onRangingStopped - sessionHandle: " + mSessionHandle);
mState = State.IDLE;
executeCallback(() -> mCallback.onStopped(reason, params));
}
/**
* @hide
*/
public void onRangingStopFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (mState == State.CLOSED) {
Log.w(mTag, "onRangingStopFailed invoked for a closed session");
return;
}
Log.v(mTag, "onRangingStopFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onStopFailed(reason, params));
}
/**
* @hide
*/
public void onRangingClosed(@Callback.Reason int reason,
@NonNull PersistableBundle parameters) {
mState = State.CLOSED;
Log.v(mTag, "onRangingClosed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onClosed(reason, parameters));
}
/**
* @hide
*/
public void onRangingResult(@NonNull RangingReport report) {
if (!isOpen()) {
Log.w(mTag, "onRangingResult invoked for non-open session");
return;
}
Log.v(mTag, "onRangingResult - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onReportReceived(report));
}
/**
* @hide
*/
public void onControleeAdded(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onControleeAdded invoked for non-open session");
return;
}
Log.v(mTag, "onControleeAdded - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onControleeAdded(params));
}
/**
* @hide
*/
public void onControleeAddFailed(@Callback.ControleeFailureReason int reason,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onControleeAddFailed invoked for non-open session");
return;
}
Log.v(mTag, "onControleeAddFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onControleeAddFailed(reason, params));
}
/**
* @hide
*/
public void onControleeRemoved(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onControleeRemoved invoked for non-open session");
return;
}
Log.v(mTag, "onControleeRemoved - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onControleeRemoved(params));
}
/**
* @hide
*/
public void onControleeRemoveFailed(@Callback.ControleeFailureReason int reason,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onControleeRemoveFailed invoked for non-open session");
return;
}
Log.v(mTag, "onControleeRemoveFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onControleeRemoveFailed(reason, params));
}
/**
* @hide
*/
public void onRangingPaused(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onRangingPaused invoked for non-open session");
return;
}
Log.v(mTag, "onRangingPaused - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onPaused(params));
}
/**
* @hide
*/
public void onRangingPauseFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onRangingPauseFailed invoked for non-open session");
return;
}
Log.v(mTag, "onRangingPauseFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onPauseFailed(reason, params));
}
/**
* @hide
*/
public void onRangingResumed(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onRangingResumed invoked for non-open session");
return;
}
Log.v(mTag, "onRangingResumed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onResumed(params));
}
/**
* @hide
*/
public void onRangingResumeFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onRangingResumeFailed invoked for non-open session");
return;
}
Log.v(mTag, "onRangingResumeFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onResumeFailed(reason, params));
}
/**
* @hide
*/
public void onDataSent(@NonNull UwbAddress remoteDeviceAddress,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onDataSent invoked for non-open session");
return;
}
Log.v(mTag, "onDataSent - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onDataSent(remoteDeviceAddress, params));
}
/**
* @hide
*/
public void onDataSendFailed(@NonNull UwbAddress remoteDeviceAddress,
@Callback.DataFailureReason int reason, @NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onDataSendFailed invoked for non-open session");
return;
}
Log.v(mTag, "onDataSendFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onDataSendFailed(remoteDeviceAddress, reason, params));
}
/**
* @hide
*/
public void onDataReceived(@NonNull UwbAddress remoteDeviceAddress,
@NonNull PersistableBundle params, @NonNull byte[] data) {
if (!isOpen()) {
Log.w(mTag, "onDataReceived invoked for non-open session");
return;
}
Log.v(mTag, "onDataReceived - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onDataReceived(remoteDeviceAddress, params, data));
}
/**
* @hide
*/
public void onDataReceiveFailed(@NonNull UwbAddress remoteDeviceAddress,
@Callback.DataFailureReason int reason, @NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onDataReceiveFailed invoked for non-open session");
return;
}
Log.v(mTag, "onDataReceiveFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onDataReceiveFailed(remoteDeviceAddress, reason, params));
}
/**
* @hide
*/
public void onDataTransferPhaseConfigured(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onDataTransferPhaseConfigured invoked for non-open session");
return;
}
Log.v(mTag, "onDataTransferPhaseConfigured - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onDataTransferPhaseConfigured(params));
}
/**
* @hide
*/
public void onDataTransferPhaseConfigFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onDataTransferPhaseConfigFailed invoked for non-open session");
return;
}
Log.v(mTag, "onDataTransferPhaseConfigFailed - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onDataTransferPhaseConfigFailed(reason, params));
}
/**
* @hide
*/
public void onServiceDiscovered(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onServiceDiscovered invoked for non-open session");
return;
}
Log.v(mTag, "onServiceDiscovered - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onServiceDiscovered(params));
}
/**
* @hide
*/
public void onServiceConnected(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onServiceConnected invoked for non-open session");
return;
}
Log.v(mTag, "onServiceConnected - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onServiceConnected(params));
}
/**
* @hide
*/
public void onRangingRoundsUpdateDtTagStatus(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onDlTDoARangingRoundsUpdateStatus invoked for non-open session");
return;
}
Log.v(mTag, "onDlTDoARangingRoundsUpdateStatus - sessionHandle: " + mSessionHandle);
if (SdkLevel.isAtLeastU()) {
executeCallback(() -> mCallback.onRangingRoundsUpdateDtTagStatus(params));
}
}
/**
* @hide
*/
public void onHybridSessionControllerConfigured(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onHybridSessionControllerConfigured invoked for non-open session");
return;
}
Log.v(mTag, "onHybridSessionControllerConfigured - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onHybridSessionControllerConfigured(params));
}
/**
* @hide
*/
public void onHybridSessionControllerConfigurationFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onHybridSessionControllerConfigurationFailed invoked for non-open"
+ "session");
return;
}
Log.v(mTag, "onHybridSessionControllerConfigurationFailed - sessionHandle: "
+ mSessionHandle);
executeCallback(() -> mCallback.onHybridSessionControllerConfigurationFailed(
reason, params));
}
/**
* @hide
*/
public void onHybridSessionControleeConfigured(@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onHybridSessionControleeConfigured invoked for non-open session");
return;
}
Log.v(mTag, "onHybridSessionControleeConfigured - sessionHandle: " + mSessionHandle);
executeCallback(() -> mCallback.onHybridSessionControleeConfigured(params));
}
/**
* @hide
*/
public void onHybridSessionControleeConfigurationFailed(@Callback.Reason int reason,
@NonNull PersistableBundle params) {
if (!isOpen()) {
Log.w(mTag, "onHybridSessionControleeConfigurationFailed invoked for non-open"
+ "session");
return;
}
Log.v(mTag, "onHybridSessionControleeConfigurationFailed - sessionHandle: "
+ mSessionHandle);
executeCallback(() -> mCallback.onHybridSessionControleeConfigurationFailed(
reason, params));
}
/**
* @hide
*/
private void executeCallback(@NonNull Runnable runnable) {
final long identity = Binder.clearCallingIdentity();
try {
mExecutor.execute(runnable);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
* Updates the UWB filter engine's pose information. This requires that the call to
* {@link UwbManager#openRangingSession} indicated an application pose source.
*
* @param parameters Parameters representing the session to update, and the pose information.
*/
@RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
public void updatePose(@NonNull PersistableBundle parameters) {
try {
mAdapter.updatePose(mSessionHandle, parameters);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}