From 2ff4b6b403ba08383bbd8339fbf6f26b4fa400e3 Mon Sep 17 00:00:00 2001 From: Jin Chen Date: Mon, 31 Jul 2023 14:53:53 -0700 Subject: [PATCH] [remoteauth] Add RangingSession interfaces * Initial commit to define interfaces and data structures for ranging session. Test: atest RemoteAuthUnitTests Bug: 290675597 Change-Id: I1eb54c079a212e8d3599b156899d0c46c6b6d636 --- remoteauth/service/Android.bp | 6 +- .../com/android/server/remoteauth/README.md | 6 +- .../ranging/RangingCapabilities.java | 36 ++++++ .../remoteauth/ranging/RangingParameters.java | 19 ++++ .../remoteauth/ranging/RangingReport.java | 104 +++++++++++++++++ .../remoteauth/ranging/RangingSession.java | 107 ++++++++++++++++++ .../remoteauth/ranging/SessionInfo.java | 69 +++++++++++ .../remoteauth/ranging/RangingReportTest.java | 47 ++++++++ .../remoteauth/ranging/SessionInfoTest.java | 63 +++++++++++ 9 files changed, 453 insertions(+), 4 deletions(-) create mode 100644 remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java create mode 100644 remoteauth/service/java/com/android/server/remoteauth/ranging/RangingParameters.java create mode 100644 remoteauth/service/java/com/android/server/remoteauth/ranging/RangingReport.java create mode 100644 remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java create mode 100644 remoteauth/service/java/com/android/server/remoteauth/ranging/SessionInfo.java create mode 100644 remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/RangingReportTest.java create mode 100644 remoteauth/tests/unit/src/com/android/server/remoteauth/ranging/SessionInfoTest.java diff --git a/remoteauth/service/Android.bp b/remoteauth/service/Android.bp index c3a9fb3045..737fa32624 100644 --- a/remoteauth/service/Android.bp +++ b/remoteauth/service/Android.bp @@ -27,7 +27,7 @@ java_library { srcs: [":remoteauth-service-srcs"], defaults: [ - "framework-system-server-module-defaults" + "framework-system-server-module-defaults", ], libs: [ "androidx.annotation_annotation", @@ -69,7 +69,7 @@ genrule { 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 2f8b096c39..b2b5aab969 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 0000000000..d61ca378f2 --- /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 0000000000..923730cc05 --- /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 0000000000..5e582b124e --- /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. + * + *

Value may be negative for devices in very close proximity. + * + * @return distance in meters + */ + public float getDistanceM() { + return mDistanceM; + } + + /** + * Gets the {@link ProximityState}. + * + *

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 0000000000..d42ef51ab3 --- /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." + * + *

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. + * + *

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}. + * + *

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. + * + *

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 0000000000..5e4fc486b2 --- /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 0000000000..6ac56eac98 --- /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 0000000000..9364092fa8 --- /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()); + } +}