[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
diff --git a/remoteauth/service/Android.bp b/remoteauth/service/Android.bp
index 737fa32..3486d8c 100644
--- a/remoteauth/service/Android.bp
+++ b/remoteauth/service/Android.bp
@@ -39,6 +39,7 @@
         "framework-statsd",
     ],
     static_libs: [
+        "guava",
         "libprotobuf-java-lite",
         "fast-pair-lite-protos",
         "modules-utils-build",
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java
index d61ca37..2b5efff 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingCapabilities.java
@@ -17,10 +17,18 @@
 
 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 @@
 
     /** 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);
+        }
+    }
 }
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingManager.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingManager.java
new file mode 100644
index 0000000..989b5ed
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingManager.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+    }
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java
index d42ef51..9ef6bda 100644
--- a/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/RangingSession.java
@@ -19,6 +19,8 @@
 
 import androidx.annotation.IntDef;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.Executor;
 
 /**
@@ -35,6 +37,7 @@
 public abstract class RangingSession {
 
     /** Types of ranging error. */
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef(
             value = {
                 RANGING_ERROR_UNKNOWN,
diff --git a/remoteauth/service/java/com/android/server/remoteauth/ranging/SessionParameters.java b/remoteauth/service/java/com/android/server/remoteauth/ranging/SessionParameters.java
new file mode 100644
index 0000000..33c3203
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/ranging/SessionParameters.java
@@ -0,0 +1,222 @@
+/*
+ * 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);
+        }
+    }
+}