[remoteauth] Add RangingSession interfaces

* Initial commit to define interfaces and data structures for ranging
  session.

Test: atest RemoteAuthUnitTests
Bug: 290675597
Change-Id: I1eb54c079a212e8d3599b156899d0c46c6b6d636
This commit is contained in:
Jin Chen 2023-07-31 14:53:53 -07:00
commit 2ff4b6b403
9 changed files with 453 additions and 4 deletions

View file

@ -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"],
}

View file

@ -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.

View file

@ -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;
}

View file

@ -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 {}

View file

@ -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);
}
}
}

View file

@ -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) {}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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());
}
}