summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Brian Stack <bstack@google.com> 2020-12-08 14:15:34 -0800
committer Brian Stack <bstack@google.com> 2021-01-07 13:25:39 -0800
commit674c30d330104b9c48d6b7e3e52cda3ec16b528c (patch)
treef9f906165ea7d6cf66fd9b0a99fb0107dcefbf06
parent659ccfc928e11f613559665b37d61c9d0f3dee64 (diff)
Add control functions to RangingSession
Adds start, stop and reconfigure functions to UWB's RangingSession along with associated callbacks in RangingSession.Callback. This change also modifies the UwbManager.openRangingSession function to only open a ranging session and not actively start ranging. In order to start ranging, use RangingSession.start() once RangingSession.Callback.onRangingOpened has been called. The Ranging Session API now consists of: UwbManager.openRangingSession RangingSession.start RangingSession.stop RangingSession.reconfigure RangingSession.close Bug: 173799002 Bug: 170323306 Test: atest UwbManagerTests Change-Id: I4cc7fbc1bb1cd3b0e75aa9cc57a1ad59d39d6f50
-rw-r--r--core/java/android/uwb/IUwbAdapter.aidl84
-rw-r--r--core/java/android/uwb/IUwbRangingCallbacks.aidl67
-rw-r--r--core/java/android/uwb/RangingChangeReason.aidl (renamed from core/java/android/uwb/CloseReason.aidl)25
-rw-r--r--core/java/android/uwb/RangingManager.java154
-rw-r--r--core/java/android/uwb/RangingSession.java363
-rw-r--r--core/java/android/uwb/StartFailureReason.aidl52
-rw-r--r--core/java/android/uwb/UwbManager.java14
-rw-r--r--core/tests/uwbtests/src/android/uwb/RangingManagerTest.java166
-rw-r--r--core/tests/uwbtests/src/android/uwb/RangingSessionTest.java244
9 files changed, 861 insertions, 308 deletions
diff --git a/core/java/android/uwb/IUwbAdapter.aidl b/core/java/android/uwb/IUwbAdapter.aidl
index 2c8b2e462510..b9c55081a103 100644
--- a/core/java/android/uwb/IUwbAdapter.aidl
+++ b/core/java/android/uwb/IUwbAdapter.aidl
@@ -119,42 +119,96 @@ interface IUwbAdapter {
PersistableBundle getSpecificationInfo();
/**
- * Request to start a new ranging session
+ * Request to open a new ranging session
*
- * This function must return before calling IUwbAdapterCallbacks
- * #onRangingStarted, #onRangingClosed, or #onRangingResult.
+ * This function must return before calling any functions in
+ * IUwbAdapterCallbacks.
*
- * A ranging session does not need to be started before returning.
+ * This function does not start the ranging session, but all necessary
+ * components must be initialized and ready to start a new ranging
+ * session prior to calling IUwbAdapterCallback#onRangingOpened.
*
- * IUwbAdapterCallbacks#onRangingStarted must be called within
- * RANGING_SESSION_START_THRESHOLD_MS milliseconds of #startRanging being called
- * if the ranging session is scheduled to start successfully.
+ * IUwbAdapterCallbacks#onRangingOpened must be called within
+ * RANGING_SESSION_OPEN_THRESHOLD_MS milliseconds of #openRanging being
+ * called if the ranging session is opened successfully.
*
- * IUwbAdapterCallbacks#onRangingStartFailed must be called within
- * RANGING_SESSION_START_THRESHOLD_MS milliseconds of #startRanging being called
- * if the ranging session fails to be scheduled to start successfully.
+ * IUwbAdapterCallbacks#onRangingOpenFailed must be called within
+ * RANGING_SESSION_OPEN_THRESHOLD_MS milliseconds of #openRanging being called
+ * if the ranging session fails to be opened.
*
* @param rangingCallbacks the callbacks used to deliver ranging information
* @param parameters the configuration to use for ranging
* @return a SessionHandle used to identify this ranging request
*/
- SessionHandle startRanging(in IUwbRangingCallbacks rangingCallbacks,
- in PersistableBundle parameters);
+ SessionHandle openRanging(in IUwbRangingCallbacks rangingCallbacks,
+ in PersistableBundle parameters);
+
+ /**
+ * Request to start ranging
+ *
+ * IUwbAdapterCallbacks#onRangingStarted must be called within
+ * RANGING_SESSION_START_THRESHOLD_MS milliseconds of #startRanging being
+ * called if the ranging session starts successfully.
+ *
+ * IUwbAdapterCallbacks#onRangingStartFailed must be called within
+ * RANGING_SESSION_START_THRESHOLD_MS milliseconds of #startRanging being
+ * called if the ranging session fails to be started.
+ *
+ * @param sessionHandle the session handle to start ranging for
+ * @param parameters additional configuration required to start ranging
+ */
+ void startRanging(in SessionHandle sessionHandle,
+ in PersistableBundle parameters);
+
+ /**
+ * Request to reconfigure ranging
+ *
+ * IUwbAdapterCallbacks#onRangingReconfigured must be called after
+ * successfully reconfiguring the session.
+ *
+ * IUwbAdapterCallbacks#onRangingReconfigureFailed must be called after
+ * failing to reconfigure the session.
+ *
+ * A session must not be modified by a failed call to #reconfigureRanging.
+ *
+ * @param sessionHandle the session handle to start ranging for
+ * @param parameters the parameters to reconfigure and their new values
+ */
+ void reconfigureRanging(in SessionHandle sessionHandle,
+ in PersistableBundle parameters);
+
+ /**
+ * Request to stop ranging
+ *
+ * IUwbAdapterCallbacks#onRangingStopped must be called after
+ * successfully stopping the session.
+ *
+ * IUwbAdapterCallbacks#onRangingStopFailed must be called after failing
+ * to stop the session.
+ *
+ * @param sessionHandle the session handle to stop ranging for
+ */
+ void stopRanging(in SessionHandle sessionHandle);
/**
- * Stop and close ranging for the session associated with the given handle
+ * Close ranging for the session associated with the given handle
*
* Calling with an invalid handle or a handle that has already been closed
* is a no-op.
*
* IUwbAdapterCallbacks#onRangingClosed must be called within
- * RANGING_SESSION_CLOSE_THRESHOLD_MS of #stopRanging being called.
+ * RANGING_SESSION_CLOSE_THRESHOLD_MS of #closeRanging being called.
*
- * @param sessionHandle the session handle to stop ranging for
+ * @param sessionHandle the session handle to close ranging for
*/
void closeRanging(in SessionHandle sessionHandle);
/**
+ * The maximum allowed time to open a ranging session.
+ */
+ const int RANGING_SESSION_OPEN_THRESHOLD_MS = 3000; // Value TBD
+
+ /**
* The maximum allowed time to start a ranging session.
*/
const int RANGING_SESSION_START_THRESHOLD_MS = 3000; // Value TBD
diff --git a/core/java/android/uwb/IUwbRangingCallbacks.aidl b/core/java/android/uwb/IUwbRangingCallbacks.aidl
index 1fc3bfd818c3..f71f3ff7ad44 100644
--- a/core/java/android/uwb/IUwbRangingCallbacks.aidl
+++ b/core/java/android/uwb/IUwbRangingCallbacks.aidl
@@ -17,16 +17,33 @@
package android.uwb;
import android.os.PersistableBundle;
-import android.uwb.CloseReason;
+import android.uwb.RangingChangeReason;
import android.uwb.RangingReport;
import android.uwb.SessionHandle;
-import android.uwb.StartFailureReason;
/**
* @hide
*/
interface IUwbRangingCallbacks {
/**
+ * Called when the ranging session has been opened
+ *
+ * @param sessionHandle the session the callback is being invoked for
+ */
+ void onRangingOpened(in SessionHandle sessionHandle);
+
+ /**
+ * Called when a ranging session fails to start
+ *
+ * @param sessionHandle the session the callback is being invoked for
+ * @param reason the reason the session failed to start
+ * @param parameters protocol specific parameters
+ */
+ void onRangingOpenFailed(in SessionHandle sessionHandle,
+ RangingChangeReason reason,
+ in PersistableBundle parameters);
+
+ /**
* Called when ranging has started
*
* May output parameters generated by the lower layers that must be sent to the
@@ -47,8 +64,49 @@ interface IUwbRangingCallbacks {
* @param reason the reason the session failed to start
* @param parameters protocol specific parameters
*/
- void onRangingStartFailed(in SessionHandle sessionHandle, StartFailureReason reason,
+ void onRangingStartFailed(in SessionHandle sessionHandle,
+ RangingChangeReason reason,
in PersistableBundle parameters);
+
+ /**
+ * Called when ranging has been reconfigured
+ *
+ * @param sessionHandle the session the callback is being invoked for
+ * @param parameters the updated ranging configuration
+ */
+ void onRangingReconfigured(in SessionHandle sessionHandle,
+ in PersistableBundle parameters);
+
+ /**
+ * Called when a ranging session fails to be reconfigured
+ *
+ * @param sessionHandle the session the callback is being invoked for
+ * @param reason the reason the session failed to reconfigure
+ * @param parameters protocol specific parameters
+ */
+ void onRangingReconfigureFailed(in SessionHandle sessionHandle,
+ RangingChangeReason reason,
+ in PersistableBundle parameters);
+
+ /**
+ * Called when the ranging session has been stopped
+ *
+ * @param sessionHandle the session the callback is being invoked for
+ */
+
+ void onRangingStopped(in SessionHandle sessionHandle);
+
+ /**
+ * Called when a ranging session fails to stop
+ *
+ * @param sessionHandle the session the callback is being invoked for
+ * @param reason the reason the session failed to stop
+ * @param parameters protocol specific parameters
+ */
+ void onRangingStopFailed(in SessionHandle sessionHandle,
+ RangingChangeReason reason,
+ in PersistableBundle parameters);
+
/**
* Called when a ranging session is closed
*
@@ -56,7 +114,8 @@ interface IUwbRangingCallbacks {
* @param reason the reason the session was closed
* @param parameters protocol specific parameters
*/
- void onRangingClosed(in SessionHandle sessionHandle, CloseReason reason,
+ void onRangingClosed(in SessionHandle sessionHandle,
+ RangingChangeReason reason,
in PersistableBundle parameters);
/**
diff --git a/core/java/android/uwb/CloseReason.aidl b/core/java/android/uwb/RangingChangeReason.aidl
index bef129e2c1c7..19d4b3949d07 100644
--- a/core/java/android/uwb/CloseReason.aidl
+++ b/core/java/android/uwb/RangingChangeReason.aidl
@@ -20,39 +20,44 @@ package android.uwb;
* @hide
*/
@Backing(type="int")
-enum CloseReason {
+enum RangingChangeReason {
/**
* Unknown reason
*/
UNKNOWN,
/**
- * A local API call triggered the close, such as a call to
- * IUwbAdapter.stopRanging.
+ * A local API call triggered the change, such as a call to
+ * IUwbAdapter.closeRanging.
*/
LOCAL_API,
/**
- * The maximum number of sessions has been reached. This error may be generated
- * for an active session if a higher priority session begins.
+ * The maximum number of sessions has been reached. This may be generated for
+ * an active session if a higher priority session begins.
*/
MAX_SESSIONS_REACHED,
/**
- * The system state has changed resulting in the session ending (e.g. the user
- * disables UWB, or the user's locale changes and an active channel is no longer
- * permitted to be used).
+ * The system state has changed resulting in the session changing (e.g. the
+ * user disables UWB, or the user's locale changes and an active channel is no
+ * longer permitted to be used).
*/
SYSTEM_POLICY,
/**
- * The remote device has requested to terminate the session
+ * The remote device has requested to change the session
*/
REMOTE_REQUEST,
/**
- * The session was closed for a protocol specific reason
+ * The session changed for a protocol specific reason
*/
PROTOCOL_SPECIFIC,
+
+ /**
+ * The provided parameters were invalid
+ */
+ BAD_PARAMETERS,
}
diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java
index a9bf4abe566a..5ac95d49c1bb 100644
--- a/core/java/android/uwb/RangingManager.java
+++ b/core/java/android/uwb/RangingManager.java
@@ -50,7 +50,7 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
@NonNull RangingSession.Callback callbacks) {
SessionHandle sessionHandle;
try {
- sessionHandle = mAdapter.startRanging(this, params);
+ sessionHandle = mAdapter.openRanging(this, params);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -59,7 +59,7 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
if (hasSession(sessionHandle)) {
Log.w(TAG, "Newly created session unexpectedly reuses an active SessionHandle");
executor.execute(() -> callbacks.onClosed(
- RangingSession.Callback.CLOSE_REASON_LOCAL_GENERIC_ERROR,
+ RangingSession.Callback.REASON_GENERIC_ERROR,
new PersistableBundle()));
}
@@ -75,6 +75,67 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
}
@Override
+ public void onRangingOpened(SessionHandle sessionHandle) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG,
+ "onRangingOpened - received unexpected SessionHandle: " + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingOpened();
+ }
+ }
+
+ @Override
+ public void onRangingOpenFailed(SessionHandle sessionHandle, @RangingChangeReason int reason,
+ PersistableBundle parameters) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG,
+ "onRangingOpened - received unexpected SessionHandle: " + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingOpenFailed(convertToReason(reason), parameters);
+ mRangingSessionTable.remove(sessionHandle);
+ }
+ }
+
+ @Override
+ public void onRangingReconfigured(SessionHandle sessionHandle, PersistableBundle parameters) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG,
+ "onRangingReconfigured - received unexpected SessionHandle: "
+ + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingReconfigured(parameters);
+ }
+ }
+
+ @Override
+ public void onRangingReconfigureFailed(SessionHandle sessionHandle,
+ @RangingChangeReason int reason, PersistableBundle params) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG, "onRangingStartFailed - received unexpected SessionHandle: "
+ + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingReconfigureFailed(convertToReason(reason), params);
+ }
+ }
+
+
+ @Override
public void onRangingStarted(SessionHandle sessionHandle, PersistableBundle parameters) {
synchronized (this) {
if (!hasSession(sessionHandle)) {
@@ -89,7 +150,7 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
}
@Override
- public void onRangingStartFailed(SessionHandle sessionHandle, int reason,
+ public void onRangingStartFailed(SessionHandle sessionHandle, @RangingChangeReason int reason,
PersistableBundle params) {
synchronized (this) {
if (!hasSession(sessionHandle)) {
@@ -99,13 +160,42 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
}
RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingClosed(convertStartFailureToCloseReason(reason), params);
- mRangingSessionTable.remove(sessionHandle);
+ session.onRangingStartFailed(convertToReason(reason), params);
+ }
+ }
+
+ @Override
+ public void onRangingStopped(SessionHandle sessionHandle) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG, "onRangingStopped - received unexpected SessionHandle: "
+ + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingStopped();
}
}
@Override
- public void onRangingClosed(SessionHandle sessionHandle, int reason, PersistableBundle params) {
+ public void onRangingStopFailed(SessionHandle sessionHandle, @RangingChangeReason int reason,
+ PersistableBundle parameters) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG, "onRangingStopFailed - received unexpected SessionHandle: "
+ + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingStopFailed(convertToReason(reason), parameters);
+ }
+ }
+
+ @Override
+ public void onRangingClosed(SessionHandle sessionHandle, @RangingChangeReason int reason,
+ PersistableBundle params) {
synchronized (this) {
if (!hasSession(sessionHandle)) {
Log.w(TAG, "onRangingClosed - received unexpected SessionHandle: " + sessionHandle);
@@ -113,7 +203,7 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
}
RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingClosed(convertToCloseReason(reason), params);
+ session.onRangingClosed(convertToReason(reason), params);
mRangingSessionTable.remove(sessionHandle);
}
}
@@ -131,48 +221,30 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
}
}
- @RangingSession.Callback.CloseReason
- private static int convertToCloseReason(@CloseReason int reason) {
+ @RangingSession.Callback.Reason
+ private static int convertToReason(@RangingChangeReason int reason) {
switch (reason) {
- case CloseReason.LOCAL_API:
- return RangingSession.Callback.CLOSE_REASON_LOCAL_CLOSE_API;
-
- case CloseReason.MAX_SESSIONS_REACHED:
- return RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED;
-
- case CloseReason.SYSTEM_POLICY:
- return RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY;
+ case RangingChangeReason.LOCAL_API:
+ return RangingSession.Callback.REASON_LOCAL_REQUEST;
- case CloseReason.REMOTE_REQUEST:
- return RangingSession.Callback.CLOSE_REASON_REMOTE_REQUEST;
+ case RangingChangeReason.MAX_SESSIONS_REACHED:
+ return RangingSession.Callback.REASON_MAX_SESSIONS_REACHED;
- case CloseReason.PROTOCOL_SPECIFIC:
- return RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC;
-
- case CloseReason.UNKNOWN:
- default:
- return RangingSession.Callback.CLOSE_REASON_UNKNOWN;
- }
- }
-
- @RangingSession.Callback.CloseReason
- private static int convertStartFailureToCloseReason(@StartFailureReason int reason) {
- switch (reason) {
- case StartFailureReason.BAD_PARAMETERS:
- return RangingSession.Callback.CLOSE_REASON_LOCAL_BAD_PARAMETERS;
+ case RangingChangeReason.SYSTEM_POLICY:
+ return RangingSession.Callback.REASON_SYSTEM_POLICY;
- case StartFailureReason.MAX_SESSIONS_REACHED:
- return RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED;
+ case RangingChangeReason.REMOTE_REQUEST:
+ return RangingSession.Callback.REASON_REMOTE_REQUEST;
- case StartFailureReason.SYSTEM_POLICY:
- return RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY;
+ case RangingChangeReason.PROTOCOL_SPECIFIC:
+ return RangingSession.Callback.REASON_PROTOCOL_SPECIFIC_ERROR;
- case StartFailureReason.PROTOCOL_SPECIFIC:
- return RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC;
+ case RangingChangeReason.BAD_PARAMETERS:
+ return RangingSession.Callback.REASON_BAD_PARAMETERS;
- case StartFailureReason.UNKNOWN:
+ case RangingChangeReason.UNKNOWN:
default:
- return RangingSession.Callback.CLOSE_REASON_UNKNOWN;
+ return RangingSession.Callback.REASON_UNKNOWN;
}
}
}
diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java
index b0dbd85c0812..0f87af415825 100644
--- a/core/java/android/uwb/RangingSession.java
+++ b/core/java/android/uwb/RangingSession.java
@@ -36,9 +36,9 @@ import java.util.concurrent.Executor;
* <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#onOpenSuccess(RangingSession, PersistableBundle)}. If opening a
- * session fails, the failure is reported through
- * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} with the failure reason.
+ * {@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
*/
@@ -50,103 +50,162 @@ public final class RangingSession implements AutoCloseable {
private final Callback mCallback;
private enum State {
+ /**
+ * The state of the {@link RangingSession} until
+ * {@link RangingSession.Callback#onOpened(RangingSession)} is invoked
+ */
INIT,
- OPEN,
- CLOSED,
+
+ /**
+ * 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;
+ private State mState = State.INIT;
/**
* Interface for receiving {@link RangingSession} events
*/
public interface Callback {
/**
- * Invoked when {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
- * is successful
- *
- * @param session the newly opened {@link RangingSession}
- * @param sessionInfo session specific parameters from lower layers
- */
- void onOpenSuccess(@NonNull RangingSession session, @NonNull PersistableBundle sessionInfo);
-
- /**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
- CLOSE_REASON_UNKNOWN,
- CLOSE_REASON_LOCAL_CLOSE_API,
- CLOSE_REASON_LOCAL_BAD_PARAMETERS,
- CLOSE_REASON_LOCAL_GENERIC_ERROR,
- CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED,
- CLOSE_REASON_LOCAL_SYSTEM_POLICY,
- CLOSE_REASON_REMOTE_GENERIC_ERROR,
- CLOSE_REASON_REMOTE_REQUEST})
- @interface CloseReason {}
+ 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})
+ @interface Reason {}
/**
* Indicates that the session was closed or failed to open due to an unknown reason
*/
- int CLOSE_REASON_UNKNOWN = 0;
+ 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 CLOSE_REASON_LOCAL_CLOSE_API = 1;
+ int REASON_LOCAL_REQUEST = 1;
/**
- * Indicates that the session failed to open due to erroneous parameters passed
- * to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
+ * Indicates that the session was closed or failed to open due to an explicit request from
+ * the remote device.
*/
- int CLOSE_REASON_LOCAL_BAD_PARAMETERS = 2;
+ int REASON_REMOTE_REQUEST = 2;
/**
- * Indicates that the session was closed due to some local error on this device besides the
- * error code already listed
+ * Indicates that the session was closed or failed to open due to erroneous parameters
*/
- int CLOSE_REASON_LOCAL_GENERIC_ERROR = 3;
+ int REASON_BAD_PARAMETERS = 3;
/**
- * Indicates that the session failed to open because the number of currently open sessions
- * is equal to {@link UwbManager#getMaxSimultaneousSessions()}
+ * Indicates an error on this device besides the error code already listed
*/
- int CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED = 4;
+ int REASON_GENERIC_ERROR = 4;
/**
- * Indicates that the session was closed or failed to open due to local system policy, such
+ * Indicates that the number of currently open sessions is equal to
+ * {@link UwbManager#getMaxSimultaneousSessions()} 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 CLOSE_REASON_LOCAL_SYSTEM_POLICY = 5;
+ int REASON_SYSTEM_POLICY = 6;
/**
- * Indicates that the session was closed or failed to open due to an error with the remote
- * device besides error codes already listed.
+ * Indicates a protocol specific error. The associated {@link PersistableBundle} should be
+ * consulted for additional information.
*/
- int CLOSE_REASON_REMOTE_GENERIC_ERROR = 6;
+ int REASON_PROTOCOL_SPECIFIC_ERROR = 7;
/**
- * Indicates that the session was closed or failed to open due to an explicit request from
- * the remote device.
+ * 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 when {@link RangingSession#start(PersistableBundle)} is successful
+ * @param sessionInfo session specific parameters from the lower layers
+ */
+ void onStarted(@NonNull PersistableBundle sessionInfo);
+
+ /**
+ * Invoked when {@link RangingSession#start(PersistableBundle)} fails
+ *
+ * @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
*/
- int CLOSE_REASON_REMOTE_REQUEST = 7;
+ void onReconfigureFailed(@Reason int reason, @NonNull PersistableBundle params);
/**
- * Indicates that the session was closed for a protocol specific reason. The associated
- * {@link PersistableBundle} should be consulted for additional information.
+ * Invoked when a request to stop the session succeeds
*/
- int CLOSE_REASON_PROTOCOL_SPECIFIC = 8;
+ void onStopped();
/**
+ * 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()}, or when session failed
- * to open.
+ * {@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(@CloseReason int reason, @NonNull PersistableBundle parameters);
+ void onClosed(@Reason int reason, @NonNull PersistableBundle parameters);
/**
* Called once per ranging interval even when a ranging measurement fails
@@ -172,12 +231,95 @@ public final class RangingSession implements AutoCloseable {
* @hide
*/
public boolean isOpen() {
- return mState == State.OPEN;
+ return mState == State.IDLE || mState == State.ACTIVE;
+ }
+
+ /**
+ * 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.
+ *
+ * @param params configuration parameters for starting the session
+ */
+ public void start(@NonNull PersistableBundle params) {
+ if (mState != State.IDLE) {
+ throw new IllegalStateException();
+ }
+
+ 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
+ */
+ public void reconfigure(@NonNull PersistableBundle params) {
+ if (mState != State.ACTIVE && mState != State.IDLE) {
+ throw new IllegalStateException();
+ }
+
+ 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.
+ */
+ public void stop() {
+ if (mState != State.ACTIVE) {
+ throw new IllegalStateException();
+ }
+
+ try {
+ mAdapter.stopRanging(mSessionHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
* Close the ranging session
- * <p>If this session is currently open, it will close and stop the 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
@@ -192,7 +334,7 @@ public final class RangingSession implements AutoCloseable {
public void close() {
if (mState == State.CLOSED) {
mExecutor.execute(() -> mCallback.onClosed(
- Callback.CLOSE_REASON_LOCAL_CLOSE_API, new PersistableBundle()));
+ Callback.REASON_LOCAL_REQUEST, new PersistableBundle()));
return;
}
@@ -206,32 +348,114 @@ public final class RangingSession implements AutoCloseable {
/**
* @hide
*/
+ public void onRangingOpened() {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingOpened invoked for a closed session");
+ return;
+ }
+
+ mState = State.IDLE;
+ executeCallback(() -> mCallback.onOpened(this));
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingOpenFailed(@Callback.Reason int reason,
+ @NonNull PersistableBundle params) {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingOpenFailed invoked for a closed session");
+ return;
+ }
+
+ mState = State.CLOSED;
+ executeCallback(() -> mCallback.onOpenFailed(reason, params));
+ }
+
+ /**
+ * @hide
+ */
public void onRangingStarted(@NonNull PersistableBundle parameters) {
if (mState == State.CLOSED) {
Log.w(TAG, "onRangingStarted invoked for a closed session");
return;
}
- mState = State.OPEN;
- final long identity = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onOpenSuccess(this, parameters));
- } finally {
- Binder.restoreCallingIdentity(identity);
+ mState = State.ACTIVE;
+ executeCallback(() -> mCallback.onStarted(parameters));
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingStartFailed(@Callback.Reason int reason,
+ @NonNull PersistableBundle params) {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingStartFailed invoked for a closed session");
+ return;
}
+
+ executeCallback(() -> mCallback.onStartFailed(reason, params));
}
/**
* @hide
*/
- public void onRangingClosed(@Callback.CloseReason int reason, PersistableBundle parameters) {
- mState = State.CLOSED;
- final long identity = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onClosed(reason, parameters));
- } finally {
- Binder.restoreCallingIdentity(identity);
+ public void onRangingReconfigured(@NonNull PersistableBundle params) {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingReconfigured invoked for a closed session");
+ return;
+ }
+
+ executeCallback(() -> mCallback.onReconfigured(params));
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingReconfigureFailed(@Callback.Reason int reason,
+ @NonNull PersistableBundle params) {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingReconfigureFailed invoked for a closed session");
+ return;
+ }
+
+ executeCallback(() -> mCallback.onReconfigureFailed(reason, params));
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingStopped() {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingStopped invoked for a closed session");
+ return;
}
+
+ mState = State.IDLE;
+ executeCallback(() -> mCallback.onStopped());
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingStopFailed(@Callback.Reason int reason,
+ @NonNull PersistableBundle params) {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingStopFailed invoked for a closed session");
+ return;
+ }
+
+ executeCallback(() -> mCallback.onStopFailed(reason, params));
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingClosed(@Callback.Reason int reason,
+ @NonNull PersistableBundle parameters) {
+ mState = State.CLOSED;
+ executeCallback(() -> mCallback.onClosed(reason, parameters));
}
/**
@@ -243,9 +467,16 @@ public final class RangingSession implements AutoCloseable {
return;
}
+ executeCallback(() -> mCallback.onReportReceived(report));
+ }
+
+ /**
+ * @hide
+ */
+ private void executeCallback(@NonNull Runnable runnable) {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> mCallback.onReportReceived(report));
+ mExecutor.execute(runnable);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/uwb/StartFailureReason.aidl b/core/java/android/uwb/StartFailureReason.aidl
deleted file mode 100644
index 4d9c962f529b..000000000000
--- a/core/java/android/uwb/StartFailureReason.aidl
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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;
-
-/**
- * @hide
- */
-@Backing(type="int")
-enum StartFailureReason {
- /**
- * Unknown start failure reason
- */
- UNKNOWN,
-
- /**
- * The provided parameters were invalid and ranging could not start
- */
- BAD_PARAMETERS,
-
- /**
- * The maximum number of sessions has been reached. This error may be generated
- * for an active session if a higher priority session begins.
- */
- MAX_SESSIONS_REACHED,
-
- /**
- * The system state has changed resulting in the session ending (e.g. the user
- * disables UWB, or the user's locale changes and an active channel is no longer
- * permitted to be used).
- */
- SYSTEM_POLICY,
-
- /**
- * The session could not start because of a protocol specific reason.
- */
- PROTOCOL_SPECIFIC,
-}
-
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index f4d801868e18..15ee5b5f22eb 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -369,13 +369,13 @@ public final class UwbManager {
/**
* Open a {@link RangingSession} with the given parameters
- * <p>This function is asynchronous and will return before ranging begins. The
- * {@link RangingSession.Callback#onOpenSuccess(RangingSession, PersistableBundle)} function is
- * called with a {@link RangingSession} object used to control ranging when the session is
- * successfully opened.
+ * <p>The {@link RangingSession.Callback#onOpened(RangingSession)} function is called with a
+ * {@link RangingSession} object used to control ranging when the session is successfully
+ * opened.
*
- * <p>If a session cannot be opened, then {@link RangingSession.Callback#onClosed(int)} will be
- * invoked with the appropriate {@link RangingSession.Callback.CloseReason}.
+ * <p>If a session cannot be opened, then
+ * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} will be invoked with the
+ * appropriate {@link RangingSession.Callback.Reason}.
*
* <p>An open {@link RangingSession} will be automatically closed if client application process
* dies.
@@ -391,7 +391,7 @@ public final class UwbManager {
* @return an {@link AutoCloseable} that is able to be used to close or cancel the opening of a
* {@link RangingSession} that has been requested through {@link #openRangingSession}
* but has not yet been made available by
- * {@link RangingSession.Callback#onOpenSuccess}.
+ * {@link RangingSession.Callback#onOpened(RangingSession)}.
*/
@NonNull
public AutoCloseable openRangingSession(@NonNull PersistableBundle parameters,
diff --git a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
index 6df1c3ed220f..c01bb75c32aa 100644
--- a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
+++ b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
@@ -45,14 +45,14 @@ public class RangingManagerTest {
private static final IUwbAdapter ADAPTER = mock(IUwbAdapter.class);
private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
private static final PersistableBundle PARAMS = new PersistableBundle();
- private static final @CloseReason int CLOSE_REASON = CloseReason.UNKNOWN;
+ private static final @RangingChangeReason int REASON = RangingChangeReason.UNKNOWN;
@Test
- public void testOpenSession_StartRangingInvoked() throws RemoteException {
+ public void testOpenSession_OpenRangingInvoked() throws RemoteException {
RangingManager rangingManager = new RangingManager(ADAPTER);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
rangingManager.openSession(PARAMS, EXECUTOR, callback);
- verify(ADAPTER, times(1)).startRanging(eq(rangingManager), eq(PARAMS));
+ verify(ADAPTER, times(1)).openRanging(eq(rangingManager), eq(PARAMS));
}
@Test
@@ -60,7 +60,7 @@ public class RangingManagerTest {
RangingManager rangingManager = new RangingManager(ADAPTER);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
SessionHandle handle = new SessionHandle(1);
- when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ when(ADAPTER.openRanging(any(), any())).thenReturn(handle);
rangingManager.openSession(PARAMS, EXECUTOR, callback);
@@ -73,34 +73,34 @@ public class RangingManagerTest {
}
@Test
- public void testOnRangingStarted_ValidSessionHandle() throws RemoteException {
+ public void testOnRangingOpened_ValidSessionHandle() throws RemoteException {
RangingManager rangingManager = new RangingManager(ADAPTER);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
SessionHandle handle = new SessionHandle(1);
- when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ when(ADAPTER.openRanging(any(), any())).thenReturn(handle);
rangingManager.openSession(PARAMS, EXECUTOR, callback);
- rangingManager.onRangingStarted(handle, PARAMS);
- verify(callback, times(1)).onOpenSuccess(any(), any());
+ rangingManager.onRangingOpened(handle);
+ verify(callback, times(1)).onOpened(any());
}
@Test
- public void testOnRangingStarted_InvalidSessionHandle() throws RemoteException {
+ public void testOnRangingOpened_InvalidSessionHandle() throws RemoteException {
RangingManager rangingManager = new RangingManager(ADAPTER);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- rangingManager.onRangingStarted(new SessionHandle(2), PARAMS);
- verify(callback, times(0)).onOpenSuccess(any(), any());
+ rangingManager.onRangingOpened(new SessionHandle(2));
+ verify(callback, times(0)).onOpened(any());
}
@Test
- public void testOnRangingStarted_MultipleSessionsRegistered() throws RemoteException {
+ public void testOnRangingOpened_MultipleSessionsRegistered() throws RemoteException {
SessionHandle sessionHandle1 = new SessionHandle(1);
SessionHandle sessionHandle2 = new SessionHandle(2);
RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
- when(ADAPTER.startRanging(any(), any()))
+ when(ADAPTER.openRanging(any(), any()))
.thenReturn(sessionHandle1)
.thenReturn(sessionHandle2);
@@ -108,25 +108,50 @@ public class RangingManagerTest {
rangingManager.openSession(PARAMS, EXECUTOR, callback1);
rangingManager.openSession(PARAMS, EXECUTOR, callback2);
- rangingManager.onRangingStarted(sessionHandle1, PARAMS);
- verify(callback1, times(1)).onOpenSuccess(any(), any());
- verify(callback2, times(0)).onOpenSuccess(any(), any());
+ rangingManager.onRangingOpened(sessionHandle1);
+ verify(callback1, times(1)).onOpened(any());
+ verify(callback2, times(0)).onOpened(any());
- rangingManager.onRangingStarted(sessionHandle2, PARAMS);
- verify(callback1, times(1)).onOpenSuccess(any(), any());
- verify(callback2, times(1)).onOpenSuccess(any(), any());
+ rangingManager.onRangingOpened(sessionHandle2);
+ verify(callback1, times(1)).onOpened(any());
+ verify(callback2, times(1)).onOpened(any());
}
@Test
- public void testOnRangingClosed_OnRangingClosedCalled() throws RemoteException {
+ public void testCorrectCallbackInvoked() throws RemoteException {
RangingManager rangingManager = new RangingManager(ADAPTER);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
SessionHandle handle = new SessionHandle(1);
- when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ when(ADAPTER.openRanging(any(), any())).thenReturn(handle);
+
rangingManager.openSession(PARAMS, EXECUTOR, callback);
+ rangingManager.onRangingOpened(handle);
+ verify(callback, times(1)).onOpened(any());
+
+ rangingManager.onRangingStarted(handle, PARAMS);
+ verify(callback, times(1)).onStarted(eq(PARAMS));
+
+ rangingManager.onRangingStartFailed(handle, REASON, PARAMS);
+ verify(callback, times(1)).onStartFailed(eq(REASON), eq(PARAMS));
+
+ RangingReport report = UwbTestUtils.getRangingReports(1);
+ rangingManager.onRangingResult(handle, report);
+ verify(callback, times(1)).onReportReceived(eq(report));
- rangingManager.onRangingClosed(handle, CLOSE_REASON, PARAMS);
- verify(callback, times(1)).onClosed(anyInt(), any());
+ rangingManager.onRangingReconfigured(handle, PARAMS);
+ verify(callback, times(1)).onReconfigured(eq(PARAMS));
+
+ rangingManager.onRangingReconfigureFailed(handle, REASON, PARAMS);
+ verify(callback, times(1)).onReconfigureFailed(eq(REASON), eq(PARAMS));
+
+ rangingManager.onRangingStopped(handle);
+ verify(callback, times(1)).onStopped();
+
+ rangingManager.onRangingStopFailed(handle, REASON, PARAMS);
+ verify(callback, times(1)).onStopFailed(eq(REASON), eq(PARAMS));
+
+ rangingManager.onRangingClosed(handle, REASON, PARAMS);
+ verify(callback, times(1)).onClosed(eq(REASON), eq(PARAMS));
}
@Test
@@ -138,7 +163,7 @@ public class RangingManagerTest {
RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
- when(ADAPTER.startRanging(any(), any()))
+ when(ADAPTER.openRanging(any(), any()))
.thenReturn(sessionHandle1)
.thenReturn(sessionHandle2);
@@ -146,37 +171,23 @@ public class RangingManagerTest {
rangingManager.openSession(PARAMS, EXECUTOR, callback1);
rangingManager.openSession(PARAMS, EXECUTOR, callback2);
- rangingManager.onRangingClosed(sessionHandle1, CLOSE_REASON, PARAMS);
+ rangingManager.onRangingClosed(sessionHandle1, REASON, PARAMS);
verify(callback1, times(1)).onClosed(anyInt(), any());
verify(callback2, times(0)).onClosed(anyInt(), any());
- rangingManager.onRangingClosed(sessionHandle2, CLOSE_REASON, PARAMS);
+ rangingManager.onRangingClosed(sessionHandle2, REASON, PARAMS);
verify(callback1, times(1)).onClosed(anyInt(), any());
verify(callback2, times(1)).onClosed(anyInt(), any());
}
@Test
- public void testOnRangingReport_OnReportReceived() throws RemoteException {
- RangingManager rangingManager = new RangingManager(ADAPTER);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- SessionHandle handle = new SessionHandle(1);
- when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
- rangingManager.openSession(PARAMS, EXECUTOR, callback);
- rangingManager.onRangingStarted(handle, PARAMS);
-
- RangingReport report = UwbTestUtils.getRangingReports(1);
- rangingManager.onRangingResult(handle, report);
- verify(callback, times(1)).onReportReceived(eq(report));
- }
-
- @Test
public void testOnRangingReport_MultipleSessionsRegistered() throws RemoteException {
SessionHandle sessionHandle1 = new SessionHandle(1);
SessionHandle sessionHandle2 = new SessionHandle(2);
RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
- when(ADAPTER.startRanging(any(), any()))
+ when(ADAPTER.openRanging(any(), any()))
.thenReturn(sessionHandle1)
.thenReturn(sessionHandle2);
@@ -196,65 +207,54 @@ public class RangingManagerTest {
}
@Test
- public void testOnClose_Reasons() throws RemoteException {
- runOnClose_Reason(CloseReason.LOCAL_API,
- RangingSession.Callback.CLOSE_REASON_LOCAL_CLOSE_API);
+ public void testReasons() throws RemoteException {
+ runReason(RangingChangeReason.LOCAL_API,
+ RangingSession.Callback.REASON_LOCAL_REQUEST);
+
+ runReason(RangingChangeReason.MAX_SESSIONS_REACHED,
+ RangingSession.Callback.REASON_MAX_SESSIONS_REACHED);
- runOnClose_Reason(CloseReason.MAX_SESSIONS_REACHED,
- RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED);
+ runReason(RangingChangeReason.PROTOCOL_SPECIFIC,
+ RangingSession.Callback.REASON_PROTOCOL_SPECIFIC_ERROR);
- runOnClose_Reason(CloseReason.PROTOCOL_SPECIFIC,
- RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC);
+ runReason(RangingChangeReason.REMOTE_REQUEST,
+ RangingSession.Callback.REASON_REMOTE_REQUEST);
- runOnClose_Reason(CloseReason.REMOTE_REQUEST,
- RangingSession.Callback.CLOSE_REASON_REMOTE_REQUEST);
+ runReason(RangingChangeReason.SYSTEM_POLICY,
+ RangingSession.Callback.REASON_SYSTEM_POLICY);
- runOnClose_Reason(CloseReason.SYSTEM_POLICY,
- RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY);
+ runReason(RangingChangeReason.BAD_PARAMETERS,
+ RangingSession.Callback.REASON_BAD_PARAMETERS);
- runOnClose_Reason(CloseReason.UNKNOWN,
- RangingSession.Callback.CLOSE_REASON_UNKNOWN);
+ runReason(RangingChangeReason.UNKNOWN,
+ RangingSession.Callback.REASON_UNKNOWN);
}
- private void runOnClose_Reason(@CloseReason int reasonIn,
- @RangingSession.Callback.CloseReason int reasonOut) throws RemoteException {
+ private void runReason(@RangingChangeReason int reasonIn,
+ @RangingSession.Callback.Reason int reasonOut) throws RemoteException {
RangingManager rangingManager = new RangingManager(ADAPTER);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
SessionHandle handle = new SessionHandle(1);
- when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ when(ADAPTER.openRanging(any(), any())).thenReturn(handle);
rangingManager.openSession(PARAMS, EXECUTOR, callback);
- rangingManager.onRangingClosed(handle, reasonIn, PARAMS);
- verify(callback, times(1)).onClosed(eq(reasonOut), eq(PARAMS));
- }
-
- @Test
- public void testStartFailureReasons() throws RemoteException {
- runOnRangingStartFailed_Reason(StartFailureReason.BAD_PARAMETERS,
- RangingSession.Callback.CLOSE_REASON_LOCAL_BAD_PARAMETERS);
+ rangingManager.onRangingOpenFailed(handle, reasonIn, PARAMS);
+ verify(callback, times(1)).onOpenFailed(eq(reasonOut), eq(PARAMS));
- runOnRangingStartFailed_Reason(StartFailureReason.MAX_SESSIONS_REACHED,
- RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED);
+ // Open a new session
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+ rangingManager.onRangingOpened(handle);
- runOnRangingStartFailed_Reason(StartFailureReason.PROTOCOL_SPECIFIC,
- RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC);
+ rangingManager.onRangingStartFailed(handle, reasonIn, PARAMS);
+ verify(callback, times(1)).onStartFailed(eq(reasonOut), eq(PARAMS));
- runOnRangingStartFailed_Reason(StartFailureReason.SYSTEM_POLICY,
- RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY);
+ rangingManager.onRangingReconfigureFailed(handle, reasonIn, PARAMS);
+ verify(callback, times(1)).onReconfigureFailed(eq(reasonOut), eq(PARAMS));
- runOnRangingStartFailed_Reason(StartFailureReason.UNKNOWN,
- RangingSession.Callback.CLOSE_REASON_UNKNOWN);
- }
-
- private void runOnRangingStartFailed_Reason(@StartFailureReason int reasonIn,
- @RangingSession.Callback.CloseReason int reasonOut) throws RemoteException {
- RangingManager rangingManager = new RangingManager(ADAPTER);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- SessionHandle handle = new SessionHandle(1);
- when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
- rangingManager.openSession(PARAMS, EXECUTOR, callback);
+ rangingManager.onRangingStopFailed(handle, reasonIn, PARAMS);
+ verify(callback, times(1)).onStopFailed(eq(reasonOut), eq(PARAMS));
- rangingManager.onRangingStartFailed(handle, reasonIn, PARAMS);
+ rangingManager.onRangingClosed(handle, reasonIn, PARAMS);
verify(callback, times(1)).onClosed(eq(reasonOut), eq(PARAMS));
}
}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
index 702c68ebc9de..e5eea26f5d11 100644
--- a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
+++ b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
@@ -19,9 +19,11 @@ package android.uwb;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -34,6 +36,8 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.util.concurrent.Executor;
@@ -43,47 +47,48 @@ import java.util.concurrent.Executor;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class RangingSessionTest {
- private static final IUwbAdapter ADAPTER = mock(IUwbAdapter.class);
private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
private static final PersistableBundle PARAMS = new PersistableBundle();
- private static final @RangingSession.Callback.CloseReason int CLOSE_REASON =
- RangingSession.Callback.CLOSE_REASON_LOCAL_GENERIC_ERROR;
+ private static final @RangingSession.Callback.Reason int REASON =
+ RangingSession.Callback.REASON_GENERIC_ERROR;
@Test
- public void testOnRangingStarted_OnOpenSuccessCalled() {
+ public void testOnRangingOpened_OnOpenSuccessCalled() {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
verifyOpenState(session, false);
- session.onRangingStarted(PARAMS);
+ session.onRangingOpened();
verifyOpenState(session, true);
// Verify that the onOpenSuccess callback was invoked
- verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(1)).onOpened(eq(session));
verify(callback, times(0)).onClosed(anyInt(), any());
}
@Test
- public void testOnRangingStarted_CannotOpenClosedSession() {
+ public void testOnRangingOpened_CannotOpenClosedSession() {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- session.onRangingStarted(PARAMS);
+ session.onRangingOpened();
verifyOpenState(session, true);
- verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(1)).onOpened(eq(session));
verify(callback, times(0)).onClosed(anyInt(), any());
- session.onRangingClosed(CLOSE_REASON, PARAMS);
+ session.onRangingClosed(REASON, PARAMS);
verifyOpenState(session, false);
- verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(1)).onOpened(eq(session));
verify(callback, times(1)).onClosed(anyInt(), any());
// Now invoke the ranging started callback and ensure the session remains closed
- session.onRangingStarted(PARAMS);
+ session.onRangingOpened();
verifyOpenState(session, false);
- verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(1)).onOpened(eq(session));
verify(callback, times(1)).onClosed(anyInt(), any());
}
@@ -91,27 +96,30 @@ public class RangingSessionTest {
public void testOnRangingClosed_OnClosedCalledWhenSessionNotOpen() {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
verifyOpenState(session, false);
- session.onRangingClosed(CLOSE_REASON, PARAMS);
+ session.onRangingClosed(REASON, PARAMS);
verifyOpenState(session, false);
// Verify that the onOpenSuccess callback was invoked
- verify(callback, times(0)).onOpenSuccess(eq(session), any());
+ verify(callback, times(0)).onOpened(eq(session));
verify(callback, times(1)).onClosed(anyInt(), any());
}
- @Test public void testOnRangingClosed_OnClosedCalled() {
+ @Test
+ public void testOnRangingClosed_OnClosedCalled() {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
session.onRangingStarted(PARAMS);
- session.onRangingClosed(CLOSE_REASON, PARAMS);
+ session.onRangingClosed(REASON, PARAMS);
verify(callback, times(1)).onClosed(anyInt(), any());
verifyOpenState(session, false);
- session.onRangingClosed(CLOSE_REASON, PARAMS);
+ session.onRangingClosed(REASON, PARAMS);
verify(callback, times(2)).onClosed(anyInt(), any());
}
@@ -119,7 +127,8 @@ public class RangingSessionTest {
public void testOnRangingResult_OnReportReceivedCalled() {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
verifyOpenState(session, false);
session.onRangingStarted(PARAMS);
@@ -131,11 +140,83 @@ public class RangingSessionTest {
}
@Test
- public void testClose() throws RemoteException {
+ public void testStart_CannotStartIfAlreadyStarted() throws RemoteException {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
+ doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
+ session.onRangingOpened();
+
+ session.start(PARAMS);
+ verify(callback, times(1)).onStarted(any());
+
+ // Calling start again should throw an illegal state
+ verifyThrowIllegalState(() -> session.start(PARAMS));
+ verify(callback, times(1)).onStarted(any());
+ }
+
+ @Test
+ public void testStop_CannotStopIfAlreadyStopped() throws RemoteException {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
+ doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
+ doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any());
+ session.onRangingOpened();
+ session.start(PARAMS);
+
+ verifyNoThrowIllegalState(session::stop);
+ verify(callback, times(1)).onStopped();
+
+ // Calling stop again should throw an illegal state
+ verifyThrowIllegalState(session::stop);
+ verify(callback, times(1)).onStopped();
+ }
+
+ @Test
+ public void testReconfigure_OnlyWhenOpened() throws RemoteException {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
+ doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
+ doAnswer(new ReconfigureAnswer(session)).when(adapter).reconfigureRanging(any(), any());
+
+ verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
+ verify(callback, times(0)).onReconfigured(any());
+ verifyOpenState(session, false);
+
+ session.onRangingOpened();
+ verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
+ verify(callback, times(1)).onReconfigured(any());
+ verifyOpenState(session, true);
+
session.onRangingStarted(PARAMS);
+ verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
+ verify(callback, times(2)).onReconfigured(any());
+ verifyOpenState(session, true);
+
+ session.onRangingStopped();
+ verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
+ verify(callback, times(3)).onReconfigured(any());
+ verifyOpenState(session, true);
+
+
+ session.onRangingClosed(REASON, PARAMS);
+ verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
+ verify(callback, times(3)).onReconfigured(any());
+ verifyOpenState(session, false);
+ }
+
+ @Test
+ public void testClose_NoCallbackUntilInvoked() throws RemoteException {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
+ session.onRangingOpened();
// Calling close multiple times should invoke closeRanging until the session receives
// the onClosed callback.
@@ -143,7 +224,7 @@ public class RangingSessionTest {
for (int i = 1; i <= totalCallsBeforeOnRangingClosed; i++) {
session.close();
verifyOpenState(session, true);
- verify(ADAPTER, times(i)).closeRanging(handle);
+ verify(adapter, times(i)).closeRanging(handle);
verify(callback, times(0)).onClosed(anyInt(), any());
}
@@ -151,18 +232,47 @@ public class RangingSessionTest {
// the session's close.
final int totalCallsAfterOnRangingClosed = 2;
for (int i = 1; i <= totalCallsAfterOnRangingClosed; i++) {
- session.onRangingClosed(CLOSE_REASON, PARAMS);
+ session.onRangingClosed(REASON, PARAMS);
verifyOpenState(session, false);
- verify(ADAPTER, times(totalCallsBeforeOnRangingClosed)).closeRanging(handle);
+ verify(adapter, times(totalCallsBeforeOnRangingClosed)).closeRanging(handle);
verify(callback, times(i)).onClosed(anyInt(), any());
}
}
@Test
+ public void testClose_OnClosedCalled() throws RemoteException {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
+ doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
+ session.onRangingOpened();
+
+ session.close();
+ verify(callback, times(1)).onClosed(anyInt(), any());
+ }
+
+ @Test
+ public void testClose_CannotInteractFurther() throws RemoteException {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
+ doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
+ session.close();
+
+ verifyThrowIllegalState(() -> session.start(PARAMS));
+ verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
+ verifyThrowIllegalState(() -> session.stop());
+ verifyNoThrowIllegalState(() -> session.close());
+ }
+
+ @Test
public void testOnRangingResult_OnReportReceivedCalledWhenOpen() {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
assertFalse(session.isOpen());
session.onRangingStarted(PARAMS);
@@ -178,7 +288,8 @@ public class RangingSessionTest {
public void testOnRangingResult_OnReportReceivedNotCalledWhenNotOpen() {
SessionHandle handle = new SessionHandle(123);
RangingSession.Callback callback = mock(RangingSession.Callback.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ IUwbAdapter adapter = mock(IUwbAdapter.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
assertFalse(session.isOpen());
@@ -191,4 +302,77 @@ public class RangingSessionTest {
private void verifyOpenState(RangingSession session, boolean expected) {
assertEquals(expected, session.isOpen());
}
+
+ private void verifyThrowIllegalState(Runnable runnable) {
+ try {
+ runnable.run();
+ fail();
+ } catch (IllegalStateException e) {
+ // Pass
+ }
+ }
+
+ private void verifyNoThrowIllegalState(Runnable runnable) {
+ try {
+ runnable.run();
+ } catch (IllegalStateException e) {
+ fail();
+ }
+ }
+
+ abstract class AdapterAnswer implements Answer {
+ protected RangingSession mSession;
+
+ protected AdapterAnswer(RangingSession session) {
+ mSession = session;
+ }
+ }
+
+ class StartAnswer extends AdapterAnswer {
+ StartAnswer(RangingSession session) {
+ super(session);
+ }
+
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ mSession.onRangingStarted(PARAMS);
+ return null;
+ }
+ }
+
+ class ReconfigureAnswer extends AdapterAnswer {
+ ReconfigureAnswer(RangingSession session) {
+ super(session);
+ }
+
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ mSession.onRangingReconfigured(PARAMS);
+ return null;
+ }
+ }
+
+ class StopAnswer extends AdapterAnswer {
+ StopAnswer(RangingSession session) {
+ super(session);
+ }
+
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ mSession.onRangingStopped();
+ return null;
+ }
+ }
+
+ class CloseAnswer extends AdapterAnswer {
+ CloseAnswer(RangingSession session) {
+ super(session);
+ }
+
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ mSession.onRangingClosed(REASON, PARAMS);
+ return null;
+ }
+ }
}