summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Joy Babafemi <jbabs@google.com> 2021-04-21 23:50:23 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2021-04-21 23:50:23 +0000
commitca5c906ab58488995ebb59a4df1b3d0473643e35 (patch)
tree367da708ee6e6a4f30ab9efaf784aff6f8de295c
parenteb52e08c30b04a28f97497b71ef8eb42c3dc773d (diff)
parent17b112aef8051a899c21f99102b10fc00774a654 (diff)
Merge "UWB: Add setUwbEnabled System API." am: 17b112aef8
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1683089 Change-Id: Icb9adae4bd40e937dc0ff702da04f8ecbdd77f1d
-rw-r--r--core/api/system-current.txt5
-rw-r--r--core/java/android/uwb/AdapterState.aidl38
-rw-r--r--core/java/android/uwb/AdapterStateListener.java63
-rw-r--r--core/java/android/uwb/IUwbAdapter.aidl13
-rw-r--r--core/java/android/uwb/IUwbAdapterStateCallbacks.aidl13
-rw-r--r--core/java/android/uwb/UwbManager.java48
-rw-r--r--core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java63
7 files changed, 201 insertions, 42 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e376fb82f498..2e4043654d44 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12606,12 +12606,15 @@ package android.uwb {
}
public static interface UwbManager.AdapterStateCallback {
- method public void onStateChanged(boolean, int);
+ method public void onStateChanged(int, int);
field public static final int STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED = 1; // 0x1
field public static final int STATE_CHANGED_REASON_ERROR_UNKNOWN = 4; // 0x4
field public static final int STATE_CHANGED_REASON_SESSION_STARTED = 0; // 0x0
field public static final int STATE_CHANGED_REASON_SYSTEM_BOOT = 3; // 0x3
field public static final int STATE_CHANGED_REASON_SYSTEM_POLICY = 2; // 0x2
+ field public static final int STATE_DISABLED = 0; // 0x0
+ field public static final int STATE_ENABLED_ACTIVE = 2; // 0x2
+ field public static final int STATE_ENABLED_INACTIVE = 1; // 0x1
}
}
diff --git a/core/java/android/uwb/AdapterState.aidl b/core/java/android/uwb/AdapterState.aidl
new file mode 100644
index 000000000000..991f64a0c0ae
--- /dev/null
+++ b/core/java/android/uwb/AdapterState.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 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 AdapterState {
+ /**
+ * The state when UWB is disabled.
+ */
+ STATE_DISABLED,
+
+ /**
+ * The state when UWB is enabled but has no active sessions.
+ */
+ STATE_ENABLED_INACTIVE,
+
+ /**
+ * The state when UWB is enabled and has active sessions.
+ */
+ STATE_ENABLED_ACTIVE,
+} \ No newline at end of file
diff --git a/core/java/android/uwb/AdapterStateListener.java b/core/java/android/uwb/AdapterStateListener.java
index 8875af385238..b9900951591f 100644
--- a/core/java/android/uwb/AdapterStateListener.java
+++ b/core/java/android/uwb/AdapterStateListener.java
@@ -21,6 +21,7 @@ import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
import android.uwb.UwbManager.AdapterStateCallback;
+import android.uwb.UwbManager.AdapterStateCallback.State;
import android.uwb.UwbManager.AdapterStateCallback.StateChangedReason;
import java.util.HashMap;
@@ -40,7 +41,8 @@ public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub {
@StateChangedReason
private int mAdapterStateChangeReason = AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN;
- private boolean mAdapterEnabledState = false;
+ @State
+ private int mAdapterState = AdapterStateCallback.STATE_DISABLED;
public AdapterStateListener(@NonNull IUwbAdapter adapter) {
mAdapter = adapter;
@@ -66,7 +68,7 @@ public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub {
mIsRegistered = true;
} catch (RemoteException e) {
Log.w(TAG, "Failed to register adapter state callback");
- executor.execute(() -> callback.onStateChanged(false,
+ executor.execute(() -> callback.onStateChanged(mAdapterState,
AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN));
}
} else {
@@ -99,6 +101,42 @@ public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub {
}
}
+ /**
+ * Sets the adapter enabled state
+ *
+ * @param isEnabled value of new adapter state
+ */
+ public void setEnabled(boolean isEnabled) {
+ synchronized (this) {
+ if (!mIsRegistered) {
+ return;
+ } else {
+ try {
+ mAdapter.setEnabled(isEnabled);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set adapter state");
+ sendErrorState();
+ }
+ }
+ }
+ }
+
+ private void sendErrorState() {
+ synchronized (this) {
+ for (AdapterStateCallback callback: mCallbackMap.keySet()) {
+ Executor executor = mCallbackMap.get(callback);
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onStateChanged(
+ mAdapterState, mAdapterStateChangeReason));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+ }
+
private void sendCurrentState(@NonNull AdapterStateCallback callback) {
synchronized (this) {
Executor executor = mCallbackMap.get(callback);
@@ -106,7 +144,7 @@ public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub {
final long identity = Binder.clearCallingIdentity();
try {
executor.execute(() -> callback.onStateChanged(
- mAdapterEnabledState, mAdapterStateChangeReason));
+ mAdapterState, mAdapterStateChangeReason));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -114,12 +152,13 @@ public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub {
}
@Override
- public void onAdapterStateChanged(boolean isEnabled, int reason) {
+ public void onAdapterStateChanged(int state, int reason) {
synchronized (this) {
@StateChangedReason int localReason =
convertToStateChangedReason(reason);
- mAdapterEnabledState = isEnabled;
+ @State int localState = convertToState(state);
mAdapterStateChangeReason = localReason;
+ mAdapterState = localState;
for (AdapterStateCallback cb : mCallbackMap.keySet()) {
sendCurrentState(cb);
}
@@ -146,4 +185,18 @@ public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub {
return AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN;
}
}
+
+ private static @State int convertToState(@AdapterState int state) {
+ switch (state) {
+ case AdapterState.STATE_ENABLED_INACTIVE:
+ return AdapterStateCallback.STATE_ENABLED_INACTIVE;
+
+ case AdapterState.STATE_ENABLED_ACTIVE:
+ return AdapterStateCallback.STATE_ENABLED_ACTIVE;
+
+ case AdapterState.STATE_DISABLED:
+ default:
+ return AdapterStateCallback.STATE_DISABLED;
+ }
+ }
}
diff --git a/core/java/android/uwb/IUwbAdapter.aidl b/core/java/android/uwb/IUwbAdapter.aidl
index 30da248e9e87..5804d04bdba7 100644
--- a/core/java/android/uwb/IUwbAdapter.aidl
+++ b/core/java/android/uwb/IUwbAdapter.aidl
@@ -145,6 +145,19 @@ interface IUwbAdapter {
*/
void closeRanging(in SessionHandle sessionHandle);
+ /**
+ * Disables or enables UWB for a user
+ *
+ * The provided callback's IUwbAdapterStateCallbacks#onAdapterStateChanged
+ * function must be called immediately following state change.
+ *
+ * @param enabled value representing intent to disable or enable UWB. If
+ * true, any subsequent calls to #openRanging will be allowed. If false,
+ * all active ranging sessions will be closed and subsequent calls to
+ * #openRanging will be disallowed.
+ */
+ void setEnabled(boolean enabled);
+
/**
* The maximum allowed time to open a ranging session.
*/
diff --git a/core/java/android/uwb/IUwbAdapterStateCallbacks.aidl b/core/java/android/uwb/IUwbAdapterStateCallbacks.aidl
index d928eabae465..d3b34c632bcc 100644
--- a/core/java/android/uwb/IUwbAdapterStateCallbacks.aidl
+++ b/core/java/android/uwb/IUwbAdapterStateCallbacks.aidl
@@ -17,16 +17,17 @@
package android.uwb;
import android.uwb.StateChangeReason;
+import android.uwb.AdapterState;
/**
* @hide
*/
interface IUwbAdapterStateCallbacks {
/**
- * Called whenever the adapter state changes
- *
- * @param isEnabled true if the adapter is enabled, false otherwise
- * @param reason the reason that the state has changed
- */
- void onAdapterStateChanged(boolean isEnabled, StateChangeReason reason);
+ * Called whenever the adapter state changes
+ *
+ * @param state UWB state; enabled_active, enabled_inactive, or disabled.
+ * @param reason the reason that the state has changed
+ */
+ void onAdapterStateChanged(AdapterState state, StateChangeReason reason);
} \ No newline at end of file
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index 844bbbe7970b..9116c49d0764 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -70,6 +70,16 @@ public final class UwbManager {
@interface StateChangedReason {}
/**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ STATE_ENABLED_INACTIVE,
+ STATE_ENABLED_ACTIVE,
+ STATE_DISABLED})
+ @interface State {}
+
+ /**
* Indicates that the state change was due to opening of first UWB session
*/
int STATE_CHANGED_REASON_SESSION_STARTED = 0;
@@ -95,22 +105,41 @@ public final class UwbManager {
int STATE_CHANGED_REASON_ERROR_UNKNOWN = 4;
/**
+ * Indicates that UWB is disabled on device
+ */
+ int STATE_DISABLED = 0;
+ /**
+ * Indicates that UWB is enabled on device but has no active ranging sessions
+ */
+ int STATE_ENABLED_INACTIVE = 1;
+
+ /**
+ * Indicates that UWB is enabled and has active ranging session
+ */
+ int STATE_ENABLED_ACTIVE = 2;
+
+ /**
* Invoked when underlying UWB adapter's state is changed
* <p>Invoked with the adapter's current state after registering an
* {@link AdapterStateCallback} using
* {@link UwbManager#registerAdapterStateCallback(Executor, AdapterStateCallback)}.
*
- * <p>Possible values for the state to change are
+ * <p>Possible reasons for the state to change are
* {@link #STATE_CHANGED_REASON_SESSION_STARTED},
* {@link #STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED},
* {@link #STATE_CHANGED_REASON_SYSTEM_POLICY},
* {@link #STATE_CHANGED_REASON_SYSTEM_BOOT},
* {@link #STATE_CHANGED_REASON_ERROR_UNKNOWN}.
*
- * @param isEnabled true when UWB adapter is enabled, false when it is disabled
+ * <p>Possible values for the UWB state are
+ * {@link #STATE_ENABLED_INACTIVE},
+ * {@link #STATE_ENABLED_ACTIVE},
+ * {@link #STATE_DISABLED}.
+ *
+ * @param state the UWB state; inactive, active or disabled
* @param reason the reason for the state change
*/
- void onStateChanged(boolean isEnabled, @StateChangedReason int reason);
+ void onStateChanged(@State int state, @StateChangedReason int reason);
}
/**
@@ -241,4 +270,17 @@ public final class UwbManager {
@NonNull RangingSession.Callback callbacks) {
return mRangingManager.openSession(parameters, executor, callbacks);
}
+
+ /**
+ * Disables or enables UWB for a user
+ *
+ * @param enabled value representing intent to disable or enable UWB. If true any subsequent
+ * calls to IUwbAdapter#openRanging will be allowed. If false, all active ranging sessions will
+ * be closed and subsequent calls to IUwbAdapter#openRanging will be disallowed.
+ *
+ * @hide
+ */
+ public void setUwbEnabled(boolean enabled) {
+ mAdapterStateListener.setEnabled(enabled);
+ }
}
diff --git a/core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java b/core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java
index ce67ef7868e8..bdaf63021503 100644
--- a/core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java
+++ b/core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java
@@ -17,7 +17,6 @@
package android.uwb;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
@@ -55,7 +54,7 @@ public class AdapterStateListenerTest {
Object[] args = invocation.getArguments();
IUwbAdapterStateCallbacks cb = (IUwbAdapterStateCallbacks) args[0];
try {
- cb.onAdapterStateChanged(false, StateChangeReason.UNKNOWN);
+ cb.onAdapterStateChanged(AdapterState.STATE_DISABLED, StateChangeReason.UNKNOWN);
} catch (RemoteException e) {
// Nothing to do
}
@@ -76,7 +75,7 @@ public class AdapterStateListenerTest {
private static void verifyCallbackStateChangedInvoked(
AdapterStateCallback callback, int numTimes) {
- verify(callback, times(numTimes)).onStateChanged(anyBoolean(), anyInt());
+ verify(callback, times(numTimes)).onStateChanged(anyInt(), anyInt());
}
@Test
@@ -151,7 +150,8 @@ public class AdapterStateListenerTest {
verifyCallbackStateChangedInvoked(callback, 1);
// Invoke a state change and ensure the callback is only called once
- adapterStateListener.onAdapterStateChanged(false, StateChangeReason.UNKNOWN);
+ adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
+ StateChangeReason.UNKNOWN);
verifyCallbackStateChangedInvoked(callback, 2);
}
@@ -182,13 +182,15 @@ public class AdapterStateListenerTest {
verifyCallbackStateChangedInvoked(callback, 0);
// Manually invoke the callback and ensure callback is not invoked
- adapterStateListener.onAdapterStateChanged(false, StateChangeReason.UNKNOWN);
+ adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
+ StateChangeReason.UNKNOWN);
verify(executor, times(2)).execute(any());
verifyCallbackStateChangedInvoked(callback, 0);
// Run the command that the executor receives
doAnswer(new ExecutorAnswer(true)).when(executor).execute(any());
- adapterStateListener.onAdapterStateChanged(false, StateChangeReason.UNKNOWN);
+ adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
+ StateChangeReason.UNKNOWN);
verify(executor, times(3)).execute(any());
verifyCallbackStateChangedInvoked(callback, 1);
}
@@ -227,7 +229,8 @@ public class AdapterStateListenerTest {
}
// Invoke a state change and ensure all callbacks are invoked
- adapterStateListener.onAdapterStateChanged(true, StateChangeReason.ALL_SESSIONS_CLOSED);
+ adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
+ StateChangeReason.ALL_SESSIONS_CLOSED);
for (AdapterStateCallback callback : callbacks) {
verifyCallbackStateChangedInvoked(callback, 2);
}
@@ -242,32 +245,36 @@ public class AdapterStateListenerTest {
adapterStateListener.register(getExecutor(), callback);
runStateChangeValue(StateChangeReason.ALL_SESSIONS_CLOSED,
- AdapterStateCallback.STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED);
+ AdapterState.STATE_ENABLED_INACTIVE,
+ AdapterStateCallback.STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED,
+ AdapterStateCallback.STATE_ENABLED_INACTIVE);
- runStateChangeValue(StateChangeReason.SESSION_STARTED,
- AdapterStateCallback.STATE_CHANGED_REASON_SESSION_STARTED);
+ runStateChangeValue(StateChangeReason.SESSION_STARTED, AdapterState.STATE_ENABLED_ACTIVE,
+ AdapterStateCallback.STATE_CHANGED_REASON_SESSION_STARTED,
+ AdapterStateCallback.STATE_ENABLED_ACTIVE);
- runStateChangeValue(StateChangeReason.SYSTEM_BOOT,
- AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_BOOT);
+ runStateChangeValue(StateChangeReason.SYSTEM_BOOT, AdapterState.STATE_DISABLED,
+ AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_BOOT,
+ AdapterStateCallback.STATE_DISABLED);
- runStateChangeValue(StateChangeReason.SYSTEM_POLICY,
- AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
+ runStateChangeValue(StateChangeReason.SYSTEM_POLICY, AdapterState.STATE_DISABLED,
+ AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY,
+ AdapterStateCallback.STATE_DISABLED);
- runStateChangeValue(StateChangeReason.UNKNOWN,
- AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN);
+ runStateChangeValue(StateChangeReason.UNKNOWN, AdapterState.STATE_DISABLED,
+ AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN,
+ AdapterStateCallback.STATE_DISABLED);
}
- private void runStateChangeValue(@StateChangeReason int reasonIn,
- @AdapterStateCallback.StateChangedReason int reasonOut) {
+ private void runStateChangeValue(@StateChangeReason int reasonIn, @AdapterState int stateIn,
+ @AdapterStateCallback.StateChangedReason int reasonOut,
+ @AdapterStateCallback.State int stateOut) {
AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
AdapterStateCallback callback = mock(AdapterStateCallback.class);
adapterStateListener.register(getExecutor(), callback);
- adapterStateListener.onAdapterStateChanged(false, reasonIn);
- verify(callback, times(1)).onStateChanged(false, reasonOut);
-
- adapterStateListener.onAdapterStateChanged(true, reasonIn);
- verify(callback, times(1)).onStateChanged(true, reasonOut);
+ adapterStateListener.onAdapterStateChanged(stateIn, reasonIn);
+ verify(callback, times(1)).onStateChanged(stateOut, reasonOut);
}
@Test
@@ -280,7 +287,8 @@ public class AdapterStateListenerTest {
Object[] args = invocation.getArguments();
IUwbAdapterStateCallbacks cb = (IUwbAdapterStateCallbacks) args[0];
try {
- cb.onAdapterStateChanged(true, StateChangeReason.SESSION_STARTED);
+ cb.onAdapterStateChanged(AdapterState.STATE_ENABLED_ACTIVE,
+ StateChangeReason.SESSION_STARTED);
} catch (RemoteException e) {
// Nothing to do
}
@@ -291,7 +299,7 @@ public class AdapterStateListenerTest {
doAnswer(registerAnswer).when(mUwbAdapter).registerAdapterStateCallbacks(any());
adapterStateListener.register(getExecutor(), callback);
- verify(callback).onStateChanged(true,
+ verify(callback).onStateChanged(AdapterStateCallback.STATE_ENABLED_ACTIVE,
AdapterStateCallback.STATE_CHANGED_REASON_SESSION_STARTED);
}
@@ -302,10 +310,11 @@ public class AdapterStateListenerTest {
AdapterStateCallback callback2 = mock(AdapterStateCallback.class);
adapterStateListener.register(getExecutor(), callback1);
- adapterStateListener.onAdapterStateChanged(true, StateChangeReason.SYSTEM_BOOT);
+ adapterStateListener.onAdapterStateChanged(AdapterState.STATE_ENABLED_ACTIVE,
+ StateChangeReason.SYSTEM_BOOT);
adapterStateListener.register(getExecutor(), callback2);
- verify(callback2).onStateChanged(true,
+ verify(callback2).onStateChanged(AdapterStateCallback.STATE_ENABLED_ACTIVE,
AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_BOOT);
}
}