1405 lines
50 KiB
Java
1405 lines
50 KiB
Java
/*
|
||
* 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 doesn’t 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();
|
||
}
|
||
}
|
||
}
|