[remoteauth] Add RangingSession interfaces
* Initial commit to define interfaces and data structures for ranging
session.
Test: atest RemoteAuthUnitTests
Bug: 290675597
Change-Id: I1eb54c079a212e8d3599b156899d0c46c6b6d636
diff --git a/remoteauth/service/Android.bp b/remoteauth/service/Android.bp
index c3a9fb3..737fa32 100644
--- a/remoteauth/service/Android.bp
+++ b/remoteauth/service/Android.bp
@@ -27,7 +27,7 @@
srcs: [":remoteauth-service-srcs"],
defaults: [
- "framework-system-server-module-defaults"
+ "framework-system-server-module-defaults",
],
libs: [
"androidx.annotation_annotation",
@@ -69,7 +69,7 @@
name: "statslog-remoteauth-java-gen",
tools: ["stats-log-api-gen"],
cmd: "$(location stats-log-api-gen) --java $(out) --module remoteauth " +
- " --javaPackage com.android.server.remoteauth.proto --javaClass RemoteAuthStatsLog" +
- " --minApiLevel 33",
+ " --javaPackage com.android.server.remoteauth.proto --javaClass RemoteAuthStatsLog" +
+ " --minApiLevel 33",
out: ["com/android/server/remoteauth/proto/RemoteAuthStatsLog.java"],
}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/README.md b/remoteauth/service/java/com/android/server/remoteauth/README.md
index 2f8b096..b2b5aab 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/README.md
+++ b/remoteauth/service/java/com/android/server/remoteauth/README.md
@@ -1,4 +1,8 @@
This is the source root for the RemoteAuthService
-## Remote connectivity manager
+## Connectivity
Provides the connectivity manager to manage connections with the peer device.
+
+## Ranging
+Provides the ranging manager to perform ranging with the peer devices.
+
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java
new file mode 100644
index 0000000..d61ca37
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.remoteauth.ranging;
+
+import androidx.annotation.IntDef;
+
+/** The ranging capabilities of the device. */
+public class RangingCapabilities {
+
+ /** Possible ranging methods */
+ @IntDef(
+ value = {
+ RANGING_METHOD_UNKNOWN,
+ RANGING_METHOD_UWB,
+ })
+ public @interface RangingMethod {}
+
+ /** Unknown ranging method. */
+ public static final int RANGING_METHOD_UNKNOWN = 0x0;
+
+ /** Ultra-wideband ranging. */
+ public static final int RANGING_METHOD_UWB = 0x1;
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingParameters.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingParameters.java
new file mode 100644
index 0000000..923730c
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingParameters.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.remoteauth.ranging;
+
+/** The set of parameters to start ranging. */
+public class RangingParameters {}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingReport.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingReport.java
new file mode 100644
index 0000000..5e582b1
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingReport.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.remoteauth.ranging;
+
+import androidx.annotation.IntDef;
+
+/** Holds ranging report data. */
+public class RangingReport {
+
+ /**
+ * State of the proximity based on detected distance compared against specified near and far
+ * boundaries.
+ */
+ @IntDef(
+ value = {
+ PROXIMITY_STATE_UNKNOWN,
+ PROXIMITY_STATE_INSIDE,
+ PROXIMITY_STATE_OUTSIDE,
+ })
+ public @interface ProximityState {}
+
+ /** Unknown proximity state. */
+ public static final int PROXIMITY_STATE_UNKNOWN = 0x0;
+
+ /**
+ * Proximity is inside the lower and upper proximity boundary. lowerProximityBoundaryM <=
+ * proximity <= upperProximityBoundaryM
+ */
+ public static final int PROXIMITY_STATE_INSIDE = 0x1;
+
+ /**
+ * Proximity is outside the lower and upper proximity boundary. proximity <
+ * lowerProximityBoundaryM OR upperProximityBoundaryM < proximity
+ */
+ public static final int PROXIMITY_STATE_OUTSIDE = 0x2;
+
+ private final float mDistanceM;
+ @ProximityState private final int mProximityState;
+
+ /**
+ * Gets the distance measurement in meters.
+ *
+ * <p>Value may be negative for devices in very close proximity.
+ *
+ * @return distance in meters
+ */
+ public float getDistanceM() {
+ return mDistanceM;
+ }
+
+ /**
+ * Gets the {@link ProximityState}.
+ *
+ * <p>The state is computed based on {@link #getDistanceM} and proximity related session
+ * parameters.
+ *
+ * @return proximity state
+ */
+ @ProximityState
+ public int getProximityState() {
+ return mProximityState;
+ }
+
+ private RangingReport(float distanceM, @ProximityState int proximityState) {
+ mDistanceM = distanceM;
+ mProximityState = proximityState;
+ }
+
+ /** Builder class for {@link RangingReport}. */
+ public static final class Builder {
+ private float mDistanceM;
+ @ProximityState private int mProximityState;
+
+ /** Sets the distance in meters. */
+ public Builder setDistanceM(float distanceM) {
+ mDistanceM = distanceM;
+ return this;
+ }
+
+ /** Sets the proximity state. */
+ public Builder setProximityState(@ProximityState int proximityState) {
+ mProximityState = proximityState;
+ return this;
+ }
+
+ /** Builds {@link RangingReport}. */
+ public RangingReport build() {
+ return new RangingReport(mDistanceM, mProximityState);
+ }
+ }
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java
new file mode 100644
index 0000000..d42ef51
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.remoteauth.ranging;
+
+import android.annotation.NonNull;
+
+import androidx.annotation.IntDef;
+
+import java.util.concurrent.Executor;
+
+/**
+ * The controller for starting and stopping ranging during which callers receive callbacks with
+ * {@link RangingReport}s and {@link RangingError}s."
+ *
+ * <p>A session can be started and stopped multiple times. After starting, updates ({@link
+ * RangingReport}, {@link RangingError}, etc) will be reported via the provided {@link
+ * RangingCallback}. BaseKey and SyncData are used for auto derivation of supported ranging
+ * parameters, which will be implementation specific.
+ *
+ * <p>Ranging method specific implementation shall be implemented in the extended class.
+ */
+public abstract class RangingSession {
+
+ /** Types of ranging error. */
+ @IntDef(
+ value = {
+ RANGING_ERROR_UNKNOWN,
+ })
+ public @interface RangingError {}
+
+ /** Unknown ranging error type. */
+ public static final int RANGING_ERROR_UNKNOWN = 0x0;
+
+ /** Interface for ranging update callbacks. */
+ public interface RangingCallback {
+ /**
+ * Call upon new {@link RangingReport}.
+ *
+ * @param sessionInfo info about this ranging session.
+ * @param rangingReport new ranging report
+ */
+ void onRangingReport(SessionInfo sessionInfo, RangingReport rangingReport);
+
+ /**
+ * Call upon any ranging error events.
+ *
+ * @param sessionInfo info about this ranging session.
+ * @param rangingError error type
+ */
+ void onError(SessionInfo sessionInfo, @RangingError int rangingError);
+ }
+
+ /**
+ * Starts ranging based on the given {@link RangingParameters}.
+ *
+ * <p>Start can be called again after {@link #stop()} has been called, else it will result in a
+ * no-op.
+ *
+ * @param rangingParameters parameters to start the ranging.
+ * @param executor Executor to run the rangingCallback.
+ * @param rangingCallback callback to notify of ranging events.
+ */
+ public abstract void start(
+ @NonNull RangingParameters rangingParameters,
+ @NonNull Executor executor,
+ @NonNull RangingCallback rangingCallback);
+
+ /**
+ * Stops ranging.
+ *
+ * <p>Calling stop without first calling {@link #start()} will result in a no-op.
+ */
+ public abstract void stop();
+
+ /**
+ * Resets the base key that's used to derive all possible ranging parameters. The baseKey shall
+ * be reset whenever there is a risk that it may no longer be valid and secured. For example,
+ * the secure connection between the devices is lost.
+ *
+ * @param baseKey new baseKey must be 16 or 32 bytes.
+ */
+ public void resetBaseKey(byte[] baseKey) {}
+
+ /**
+ * Resets the synchronization by giving a new syncData used for ranging parameters derivation.
+ * Resetting the syncData is not required before each {@link #start}, but the more time the
+ * derivations are done before resetting syncData, the higher the risk the derivation will be
+ * out of sync between the devices. Therefore, syncData shall be refreshed in a best effort
+ * manner.
+ *
+ * @param syncData new syncData must be 16 bytes.
+ */
+ public void resetSyncData(byte[] syncData) {}
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/SessionInfo.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/SessionInfo.java
new file mode 100644
index 0000000..5e4fc48
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/SessionInfo.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.remoteauth.ranging;
+
+import static com.android.server.remoteauth.ranging.RangingCapabilities.RANGING_METHOD_UNKNOWN;
+
+import com.android.internal.util.Preconditions;
+import com.android.server.remoteauth.ranging.RangingCapabilities.RangingMethod;
+
+/** Information about the {@link RangingSession}. */
+public class SessionInfo {
+
+ private final String mDeviceId;
+ @RangingMethod private final int mRangingMethod;
+
+ public String getDeviceId() {
+ return mDeviceId;
+ }
+
+ @RangingMethod
+ public int getRangingMethod() {
+ return mRangingMethod;
+ }
+
+ private SessionInfo(String deviceId, @RangingMethod int rangingMethod) {
+ mDeviceId = deviceId;
+ mRangingMethod = rangingMethod;
+ }
+
+ /** Builder class for {@link SessionInfo}. */
+ public static final class Builder {
+ private String mDeviceId = "";
+ @RangingMethod private int mRangingMethod = RANGING_METHOD_UNKNOWN;
+
+ /** Sets the device id. */
+ public Builder setDeviceId(String deviceId) {
+ mDeviceId = deviceId;
+ return this;
+ }
+
+ /** Sets the ranging method. */
+ public Builder setRangingMethod(@RangingMethod int rangingMethod) {
+ mRangingMethod = rangingMethod;
+ return this;
+ }
+
+ /** Builds {@link SessionInfo}. */
+ public SessionInfo build() {
+ Preconditions.checkArgument(!mDeviceId.isEmpty(), "deviceId must not be empty.");
+ Preconditions.checkArgument(
+ mRangingMethod != RANGING_METHOD_UNKNOWN, "Unknown rangingMethod");
+ return new SessionInfo(mDeviceId, mRangingMethod);
+ }
+ }
+}
diff --git a/remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/RangingReportTest.java b/remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/RangingReportTest.java
new file mode 100644
index 0000000..6ac56ea
--- /dev/null
+++ b/remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/RangingReportTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.remoteauth.ranging;
+
+import static com.android.server.remoteauth.ranging.RangingReport.PROXIMITY_STATE_INSIDE;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.server.remoteauth.ranging.RangingReport.ProximityState;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit test for {@link RangingReport}. */
+@RunWith(AndroidJUnit4.class)
+public class RangingReportTest {
+
+ private static final float TEST_DISTANCE_M = 1.5f;
+ @ProximityState private static final int TEST_PROXIMITY_STATE = PROXIMITY_STATE_INSIDE;
+
+ @Test
+ public void testBuildingRangingReport_success() {
+ final RangingReport rangingReport =
+ new RangingReport.Builder()
+ .setDistanceM(TEST_DISTANCE_M)
+ .setProximityState(TEST_PROXIMITY_STATE)
+ .build();
+
+ assertEquals(rangingReport.getDistanceM(), TEST_DISTANCE_M, 0.0f);
+ assertEquals(rangingReport.getProximityState(), TEST_PROXIMITY_STATE);
+ }
+}
diff --git a/remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/SessionInfoTest.java b/remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/SessionInfoTest.java
new file mode 100644
index 0000000..9364092
--- /dev/null
+++ b/remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/SessionInfoTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.remoteauth.ranging;
+
+import static com.android.server.remoteauth.ranging.RangingCapabilities.RANGING_METHOD_UWB;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.server.remoteauth.ranging.RangingCapabilities.RangingMethod;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit test for {@link SessionInfo}. */
+@RunWith(AndroidJUnit4.class)
+public class SessionInfoTest {
+
+ private static final String TEST_DEVICE_ID = new String("test_device_id");
+ private static final @RangingMethod int TEST_RANGING_METHOD = RANGING_METHOD_UWB;
+
+ @Test
+ public void testBuildingSessionInfo_success() {
+ final SessionInfo sessionInfo =
+ new SessionInfo.Builder()
+ .setDeviceId(TEST_DEVICE_ID)
+ .setRangingMethod(TEST_RANGING_METHOD)
+ .build();
+
+ assertEquals(sessionInfo.getDeviceId(), TEST_DEVICE_ID);
+ assertEquals(sessionInfo.getRangingMethod(), TEST_RANGING_METHOD);
+ }
+
+ @Test
+ public void testBuildingSessionInfo_invalidDeviceId() {
+ final SessionInfo.Builder builder =
+ new SessionInfo.Builder().setRangingMethod(TEST_RANGING_METHOD);
+
+ assertThrows(IllegalArgumentException.class, () -> builder.build());
+ }
+
+ @Test
+ public void testBuildingSessionInfo_invalidRangingMethod() {
+ final SessionInfo.Builder builder = new SessionInfo.Builder().setDeviceId(TEST_DEVICE_ID);
+
+ assertThrows(IllegalArgumentException.class, () -> builder.build());
+ }
+}