Skip to content
Snippets Groups Projects
Commit 393e6111 authored by Jin Chen's avatar Jin Chen
Browse files

[remoteauth] Add RangingManager interfaces

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

Test: atest RemoteAuthUnitTests
Bug: 290675597, 292549287
Change-Id: Ic9fbf2f909249586f13f8d7be3069ba8ad3bd779
parent 2ff4b6b4
No related branches found
No related tags found
No related merge requests found
......@@ -39,6 +39,7 @@ java_library {
"framework-statsd",
],
static_libs: [
"guava",
"libprotobuf-java-lite",
"fast-pair-lite-protos",
"modules-utils-build",
......
......@@ -17,10 +17,18 @@ package com.android.server.remoteauth.ranging;
import androidx.annotation.IntDef;
import com.google.common.collect.ImmutableList;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
/** The ranging capabilities of the device. */
public class RangingCapabilities {
/** Possible ranging methods */
@Retention(RetentionPolicy.SOURCE)
@IntDef(
value = {
RANGING_METHOD_UNKNOWN,
......@@ -33,4 +41,35 @@ public class RangingCapabilities {
/** Ultra-wideband ranging. */
public static final int RANGING_METHOD_UWB = 0x1;
private final ImmutableList<Integer> mSupportedRangingMethods;
/**
* Gets the list of supported ranging methods of the device.
*
* @return list of {@link RangingMethod}
*/
public ImmutableList<Integer> getSupportedRangingMethods() {
return mSupportedRangingMethods;
}
private RangingCapabilities(List<Integer> supportedRangingMethods) {
mSupportedRangingMethods = ImmutableList.copyOf(supportedRangingMethods);
}
/** Builder class for {@link RangingCapabilities}. */
public static final class Builder {
private List<Integer> mSupportedRangingMethods = new ArrayList<>();
/** Adds a supported {@link RangingMethod} */
public Builder addSupportedRangingMethods(@RangingMethod int rangingMethod) {
mSupportedRangingMethods.add(rangingMethod);
return this;
}
/** Builds {@link RangingCapabilities}. */
public RangingCapabilities build() {
return new RangingCapabilities(mSupportedRangingMethods);
}
}
}
/*
* 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.content.Context;
/**
* Manages the creation of generic device to device ranging session and obtaining device's ranging
* capabilities.
*
* <p>Out-of-band channel for ranging capabilities/parameters exchange is assumed being handled
* outside of this class.
*/
public class RangingManager {
public RangingManager(Context context) {}
/**
* Gets the {@link RangingCapabilities} of this device.
*
* @return RangingCapabilities.
*/
public RangingCapabilities getRangingCapabilities() {
return null;
}
/**
* Creates a {@link RangingSession} based on the given {@link SessionParameters}, which shall be
* provided based on the rangingCapabilities of the device.
*
* @param sessionParameters parameters used to setup the session.
* @return the created RangingSession.
*/
public RangingSession createSession(SessionParameters sessionParameters) {
return null;
}
}
......@@ -19,6 +19,8 @@ import android.annotation.NonNull;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
/**
......@@ -35,6 +37,7 @@ import java.util.concurrent.Executor;
public abstract class RangingSession {
/** Types of ranging error. */
@Retention(RetentionPolicy.SOURCE)
@IntDef(
value = {
RANGING_ERROR_UNKNOWN,
......
/*
* 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 android.annotation.NonNull;
import com.android.internal.util.Preconditions;
import com.android.server.remoteauth.ranging.RangingCapabilities.RangingMethod;
/**
* The set of parameters to create a ranging session.
*
* <p>Required parameters must be provided, else {@link Builder} will throw an exception. The
* optional parameters only need to be provided if the functionality is necessary to the session,
* see the setter functions of the {@link Builder} for detailed info of each parameter.
*/
public class SessionParameters {
/* Required parameters */
private final String mDeviceId;
@RangingMethod private final int mRangingMethod;
/* Optional parameters */
private final float mLowerProximityBoundaryM;
private final float mUpperProximityBoundaryM;
private final boolean mAutoDeriveParams;
private final byte[] mBaseKey;
private final byte[] mSyncData;
public String getDeviceId() {
return mDeviceId;
}
@RangingMethod
public int getRangingMethod() {
return mRangingMethod;
}
public float getLowerProximityBoundaryM() {
return mLowerProximityBoundaryM;
}
public float getUpperProximityBoundaryM() {
return mUpperProximityBoundaryM;
}
public boolean getAutoDeriveParams() {
return mAutoDeriveParams;
}
public byte[] getBaseKey() {
return mBaseKey;
}
public byte[] getSyncData() {
return mSyncData;
}
private SessionParameters(
String deviceId,
@RangingMethod int rangingMethod,
float lowerProximityBoundaryM,
float upperProximityBoundaryM,
boolean autoDeriveParams,
byte[] baseKey,
byte[] syncData) {
mDeviceId = deviceId;
mRangingMethod = rangingMethod;
mLowerProximityBoundaryM = lowerProximityBoundaryM;
mUpperProximityBoundaryM = upperProximityBoundaryM;
mAutoDeriveParams = autoDeriveParams;
mBaseKey = baseKey;
mSyncData = syncData;
}
/** Builder class for {@link SessionParameters}. */
public static final class Builder {
private String mDeviceId = new String("");
@RangingMethod private int mRangingMethod = RANGING_METHOD_UNKNOWN;
private float mLowerProximityBoundaryM;
private float mUpperProximityBoundaryM;
private boolean mAutoDeriveParams = false;
private byte[] mBaseKey = new byte[] {};
private byte[] mSyncData = new byte[] {};
/**
* Sets the device id.
*
* <p>This is used as the identity included in the {@link SessionInfo} for all {@link
* RangingCallback}s.
*/
public Builder setDeviceId(@NonNull String deviceId) {
mDeviceId = deviceId;
return this;
}
/**
* Sets the {@link RangingMethod} to be used for the {@link RangingSession}.
*
* <p>Note: The ranging method should be ones in the list return by {@link
* RangingCapabilities#getSupportedRangingMethods};
*/
public Builder setRangingMethod(@RangingMethod int rangingMethod) {
mRangingMethod = rangingMethod;
return this;
}
/**
* Sets the lower proximity boundary in meters, must be greater than or equals to zero.
*
* <p>This value is used to compute the {@link ProximityState} = {@link
* PROXIMITY_STATE_INSIDE} if lowerProximityBoundaryM <= proximity <=
* upperProximityBoundaryM, else {@link PROXIMITY_STATE_OUTSIDE}.
*/
public Builder setLowerProximityBoundaryM(float lowerProximityBoundaryM) {
mLowerProximityBoundaryM = lowerProximityBoundaryM;
return this;
}
/**
* Sets the upper proximity boundary in meters, must be greater than or equals to
* lowerProximityBoundaryM.
*
* <p>This value is used to compute the {@link ProximityState} = {@link
* PROXIMITY_STATE_INSIDE} if lowerProximityBoundaryM <= proximity <=
* upperProximityBoundaryM, else {@link PROXIMITY_STATE_OUTSIDE}.
*/
public Builder setUpperProximityBoundaryM(float upperProximityBoundaryM) {
mUpperProximityBoundaryM = upperProximityBoundaryM;
return this;
}
/**
* Sets the auto derive ranging parameters flag. Defaults to false.
*
* <p>This enables the {@link RangingSession} to automatically derive all possible {@link
* RangingParameters} at each {@link RangingSession#start} using the provided {@link
* #setBaseKey} and {@link #setSyncData}, which shall be securely shared between the ranging
* devices out of band.
*/
public Builder setAutoDeriveParams(boolean autoDeriveParams) {
mAutoDeriveParams = autoDeriveParams;
return this;
}
/**
* Sets the base key. Only required if {@link #setAutoDeriveParams} is set to true.
*
* @param baseKey baseKey must be 16 or 32 bytes.
* @throws NullPointerException if baseKey is null
*/
public Builder setBaseKey(@NonNull byte[] baseKey) {
Preconditions.checkNotNull(baseKey);
mBaseKey = baseKey;
return this;
}
/**
* Sets the sync data. Only required if {@link #setAutoDeriveParams} is set to true.
*
* @param syncData syncData must be 16 bytes.
* @throws NullPointerException if syncData is null
*/
public Builder setSyncData(@NonNull byte[] syncData) {
Preconditions.checkNotNull(syncData);
mSyncData = syncData;
return this;
}
/**
* Builds {@link SessionParameters}.
*
* @throws IllegalArgumentException if any parameter is invalid.
*/
public SessionParameters build() {
Preconditions.checkArgument(!mDeviceId.isEmpty(), "deviceId must not be empty.");
Preconditions.checkArgument(
mRangingMethod != RANGING_METHOD_UNKNOWN, "Unknown rangingMethod");
Preconditions.checkArgument(
mLowerProximityBoundaryM >= 0,
"Negative lowerProximityBoundaryM: " + mLowerProximityBoundaryM);
Preconditions.checkArgument(
mLowerProximityBoundaryM <= mUpperProximityBoundaryM,
"lowerProximityBoundaryM is greater than upperProximityBoundaryM: "
+ mLowerProximityBoundaryM
+ " > "
+ mUpperProximityBoundaryM);
// If mAutoDeriveParams is false, mBaseKey and mSyncData will not be used.
if (mAutoDeriveParams) {
Preconditions.checkArgument(
mBaseKey.length == 16 || mBaseKey.length == 32,
"Invalid baseKey length: " + mBaseKey.length);
Preconditions.checkArgument(
mSyncData.length == 16, "Invalid syncData length: " + mSyncData.length);
}
return new SessionParameters(
mDeviceId,
mRangingMethod,
mLowerProximityBoundaryM,
mUpperProximityBoundaryM,
mAutoDeriveParams,
mBaseKey,
mSyncData);
}
}
}
/*
* 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 androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit test for {@link RangingCapabilities}. */
@RunWith(AndroidJUnit4.class)
public class RangingCapabilitiesTest {
@Test
public void testBuildingRangingCapabilities_success() {
final RangingCapabilities rangingCapabilities =
new RangingCapabilities.Builder()
.addSupportedRangingMethods(RANGING_METHOD_UWB)
.build();
assertEquals(rangingCapabilities.getSupportedRangingMethods().size(), 1);
assertEquals(
(int) rangingCapabilities.getSupportedRangingMethods().get(0), RANGING_METHOD_UWB);
}
}
/*
* 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.assertArrayEquals;
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 tests for {@link SessionParameters}. */
@RunWith(AndroidJUnit4.class)
public class SessionParametersTest {
private static final String TEST_DEVICE_ID = "test_device_id";
@RangingMethod private static final int TEST_RANGING_METHOD = RANGING_METHOD_UWB;
private static final float TEST_LOWER_PROXIMITY_BOUNDARY_M = 1.0f;
private static final float TEST_UPPER_PROXIMITY_BOUNDARY_M = 2.5f;
private static final boolean TEST_AUTO_DERIVE_PARAMS = true;
private static final byte[] TEST_BASE_KEY =
new byte[] {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f
};
private static final byte[] TEST_SYNC_DATA =
new byte[] {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x00
};
@Test
public void testBuildingSessionParameters_success() {
final SessionParameters sessionParameters =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setAutoDeriveParams(TEST_AUTO_DERIVE_PARAMS)
.setBaseKey(TEST_BASE_KEY)
.setSyncData(TEST_SYNC_DATA)
.build();
assertEquals(sessionParameters.getDeviceId(), TEST_DEVICE_ID);
assertEquals(sessionParameters.getRangingMethod(), TEST_RANGING_METHOD);
assertEquals(
sessionParameters.getLowerProximityBoundaryM(),
TEST_LOWER_PROXIMITY_BOUNDARY_M,
0.0f);
assertEquals(
sessionParameters.getUpperProximityBoundaryM(),
TEST_UPPER_PROXIMITY_BOUNDARY_M,
0.0f);
assertEquals(sessionParameters.getAutoDeriveParams(), TEST_AUTO_DERIVE_PARAMS);
assertArrayEquals(sessionParameters.getBaseKey(), TEST_BASE_KEY);
assertArrayEquals(sessionParameters.getSyncData(), TEST_SYNC_DATA);
}
@Test
public void testBuildingSessionParameters_invalidDeviceId() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setBaseKey(TEST_BASE_KEY)
.setSyncData(TEST_SYNC_DATA);
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
@Test
public void testBuildingSessionParameters_invalidRangingMethod() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setBaseKey(TEST_BASE_KEY)
.setSyncData(TEST_SYNC_DATA);
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
@Test
public void testBuildingSessionParameters_invalidLowerProximityBoundaryM() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(-1.0f)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setBaseKey(TEST_BASE_KEY)
.setSyncData(TEST_SYNC_DATA);
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
@Test
public void testBuildingSessionParameters_invalidUpperProximityBoundaryM() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M - 0.1f)
.setBaseKey(TEST_BASE_KEY)
.setSyncData(TEST_SYNC_DATA);
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
@Test
public void testBuildingSessionParameters_disableAutoDeriveParams() {
final boolean autoDeriveParams = false;
final SessionParameters sessionParameters =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setAutoDeriveParams(autoDeriveParams)
.build();
assertEquals(sessionParameters.getAutoDeriveParams(), autoDeriveParams);
assertArrayEquals(sessionParameters.getBaseKey(), new byte[] {});
assertArrayEquals(sessionParameters.getSyncData(), new byte[] {});
}
@Test
public void testBuildingSessionParameters_emptyBaseKey() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setAutoDeriveParams(TEST_AUTO_DERIVE_PARAMS)
.setSyncData(TEST_SYNC_DATA);
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
@Test
public void testBuildingSessionParameters_invalidBaseKey() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setAutoDeriveParams(TEST_AUTO_DERIVE_PARAMS)
.setBaseKey(new byte[] {0x00, 0x01, 0x02, 0x13})
.setSyncData(TEST_SYNC_DATA);
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
@Test
public void testBuildingSessionParameters_emptySyncData() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setAutoDeriveParams(TEST_AUTO_DERIVE_PARAMS)
.setBaseKey(TEST_BASE_KEY);
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
@Test
public void testBuildingSessionParameters_invalidSyncData() {
final SessionParameters.Builder builder =
new SessionParameters.Builder()
.setDeviceId(TEST_DEVICE_ID)
.setRangingMethod(TEST_RANGING_METHOD)
.setLowerProximityBoundaryM(TEST_LOWER_PROXIMITY_BOUNDARY_M)
.setUpperProximityBoundaryM(TEST_UPPER_PROXIMITY_BOUNDARY_M)
.setAutoDeriveParams(TEST_AUTO_DERIVE_PARAMS)
.setBaseKey(TEST_BASE_KEY)
.setSyncData(new byte[] {0x00, 0x01, 0x02, 0x13});
assertThrows(IllegalArgumentException.class, () -> builder.build());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment