1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.remoteauth.ranging; 17 18 import static com.android.server.remoteauth.ranging.RangingCapabilities.RANGING_METHOD_UNKNOWN; 19 20 import android.annotation.NonNull; 21 22 import androidx.annotation.IntDef; 23 24 import com.android.internal.util.Preconditions; 25 import com.android.server.remoteauth.ranging.RangingCapabilities.RangingMethod; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * The set of parameters to create a ranging session. 32 * 33 * <p>Required parameters must be provided, else {@link Builder} will throw an exception. The 34 * optional parameters only need to be provided if the functionality is necessary to the session, 35 * see the setter functions of the {@link Builder} for detailed info of each parameter. 36 */ 37 public class SessionParameters { 38 39 /** Ranging device role. */ 40 @Retention(RetentionPolicy.SOURCE) 41 @IntDef( 42 value = { 43 DEVICE_ROLE_UNKNOWN, 44 DEVICE_ROLE_INITIATOR, 45 DEVICE_ROLE_RESPONDER, 46 }) 47 public @interface DeviceRole {} 48 49 /** Unknown device role. */ 50 public static final int DEVICE_ROLE_UNKNOWN = 0x0; 51 52 /** Device that initiates the ranging. */ 53 public static final int DEVICE_ROLE_INITIATOR = 0x1; 54 55 /** Device that responds to ranging. */ 56 public static final int DEVICE_ROLE_RESPONDER = 0x2; 57 58 /* Required parameters */ 59 private final String mDeviceId; 60 @RangingMethod private final int mRangingMethod; 61 @DeviceRole private final int mDeviceRole; 62 63 /* Optional parameters */ 64 private final float mLowerProximityBoundaryM; 65 private final float mUpperProximityBoundaryM; 66 private final boolean mAutoDeriveParams; 67 private final byte[] mBaseKey; 68 private final byte[] mSyncData; 69 getDeviceId()70 public String getDeviceId() { 71 return mDeviceId; 72 } 73 74 @RangingMethod getRangingMethod()75 public int getRangingMethod() { 76 return mRangingMethod; 77 } 78 79 @DeviceRole getDeviceRole()80 public int getDeviceRole() { 81 return mDeviceRole; 82 } 83 getLowerProximityBoundaryM()84 public float getLowerProximityBoundaryM() { 85 return mLowerProximityBoundaryM; 86 } 87 getUpperProximityBoundaryM()88 public float getUpperProximityBoundaryM() { 89 return mUpperProximityBoundaryM; 90 } 91 getAutoDeriveParams()92 public boolean getAutoDeriveParams() { 93 return mAutoDeriveParams; 94 } 95 getBaseKey()96 public byte[] getBaseKey() { 97 return mBaseKey; 98 } 99 getSyncData()100 public byte[] getSyncData() { 101 return mSyncData; 102 } 103 SessionParameters( String deviceId, @RangingMethod int rangingMethod, @DeviceRole int deviceRole, float lowerProximityBoundaryM, float upperProximityBoundaryM, boolean autoDeriveParams, byte[] baseKey, byte[] syncData)104 private SessionParameters( 105 String deviceId, 106 @RangingMethod int rangingMethod, 107 @DeviceRole int deviceRole, 108 float lowerProximityBoundaryM, 109 float upperProximityBoundaryM, 110 boolean autoDeriveParams, 111 byte[] baseKey, 112 byte[] syncData) { 113 mDeviceId = deviceId; 114 mRangingMethod = rangingMethod; 115 mDeviceRole = deviceRole; 116 mLowerProximityBoundaryM = lowerProximityBoundaryM; 117 mUpperProximityBoundaryM = upperProximityBoundaryM; 118 mAutoDeriveParams = autoDeriveParams; 119 mBaseKey = baseKey; 120 mSyncData = syncData; 121 } 122 123 /** Builder class for {@link SessionParameters}. */ 124 public static final class Builder { 125 private String mDeviceId = new String(""); 126 @RangingMethod private int mRangingMethod = RANGING_METHOD_UNKNOWN; 127 @DeviceRole private int mDeviceRole = DEVICE_ROLE_UNKNOWN; 128 private float mLowerProximityBoundaryM; 129 private float mUpperProximityBoundaryM; 130 private boolean mAutoDeriveParams = false; 131 private byte[] mBaseKey = new byte[] {}; 132 private byte[] mSyncData = new byte[] {}; 133 134 /** 135 * Sets the device id. 136 * 137 * <p>This is used as the identity included in the {@link SessionInfo} for all {@link 138 * RangingCallback}s. 139 */ setDeviceId(@onNull String deviceId)140 public Builder setDeviceId(@NonNull String deviceId) { 141 mDeviceId = deviceId; 142 return this; 143 } 144 145 /** 146 * Sets the {@link RangingMethod} to be used for the {@link RangingSession}. 147 * 148 * <p>Note: The ranging method should be ones in the list return by {@link 149 * RangingCapabilities#getSupportedRangingMethods}; 150 */ setRangingMethod(@angingMethod int rangingMethod)151 public Builder setRangingMethod(@RangingMethod int rangingMethod) { 152 mRangingMethod = rangingMethod; 153 return this; 154 } 155 156 /** Sets the {@link DeviceRole} to be used for the {@link RangingSession}. */ setDeviceRole(@eviceRole int deviceRole)157 public Builder setDeviceRole(@DeviceRole int deviceRole) { 158 mDeviceRole = deviceRole; 159 return this; 160 } 161 162 /** 163 * Sets the lower proximity boundary in meters, must be greater than or equals to zero. 164 * 165 * <p>This value is used to compute the {@link ProximityState} = {@link 166 * PROXIMITY_STATE_INSIDE} if lowerProximityBoundaryM <= proximity <= 167 * upperProximityBoundaryM, else {@link PROXIMITY_STATE_OUTSIDE}. 168 */ setLowerProximityBoundaryM(float lowerProximityBoundaryM)169 public Builder setLowerProximityBoundaryM(float lowerProximityBoundaryM) { 170 mLowerProximityBoundaryM = lowerProximityBoundaryM; 171 return this; 172 } 173 174 /** 175 * Sets the upper proximity boundary in meters, must be greater than or equals to 176 * lowerProximityBoundaryM. 177 * 178 * <p>This value is used to compute the {@link ProximityState} = {@link 179 * PROXIMITY_STATE_INSIDE} if lowerProximityBoundaryM <= proximity <= 180 * upperProximityBoundaryM, else {@link PROXIMITY_STATE_OUTSIDE}. 181 */ setUpperProximityBoundaryM(float upperProximityBoundaryM)182 public Builder setUpperProximityBoundaryM(float upperProximityBoundaryM) { 183 mUpperProximityBoundaryM = upperProximityBoundaryM; 184 return this; 185 } 186 187 /** 188 * Sets the auto derive ranging parameters flag. Defaults to false. 189 * 190 * <p>This enables the {@link RangingSession} to automatically derive all possible {@link 191 * RangingParameters} at each {@link RangingSession#start} using the provided {@link 192 * #setBaseKey} and {@link #setSyncData}, which shall be securely shared between the ranging 193 * devices out of band. 194 */ setAutoDeriveParams(boolean autoDeriveParams)195 public Builder setAutoDeriveParams(boolean autoDeriveParams) { 196 mAutoDeriveParams = autoDeriveParams; 197 return this; 198 } 199 200 /** 201 * Sets the base key. Only required if {@link #setAutoDeriveParams} is set to true. 202 * 203 * @param baseKey baseKey must be 16 or 32 bytes. 204 * @throws NullPointerException if baseKey is null 205 */ setBaseKey(@onNull byte[] baseKey)206 public Builder setBaseKey(@NonNull byte[] baseKey) { 207 Preconditions.checkNotNull(baseKey); 208 mBaseKey = baseKey; 209 return this; 210 } 211 212 /** 213 * Sets the sync data. Only required if {@link #setAutoDeriveParams} is set to true. 214 * 215 * @param syncData syncData must be 16 bytes. 216 * @throws NullPointerException if syncData is null 217 */ setSyncData(@onNull byte[] syncData)218 public Builder setSyncData(@NonNull byte[] syncData) { 219 Preconditions.checkNotNull(syncData); 220 mSyncData = syncData; 221 return this; 222 } 223 224 /** 225 * Builds {@link SessionParameters}. 226 * 227 * @throws IllegalArgumentException if any parameter is invalid. 228 */ build()229 public SessionParameters build() { 230 Preconditions.checkArgument(!mDeviceId.isEmpty(), "deviceId must not be empty."); 231 Preconditions.checkArgument( 232 mRangingMethod != RANGING_METHOD_UNKNOWN, "Unknown rangingMethod"); 233 Preconditions.checkArgument(mDeviceRole != DEVICE_ROLE_UNKNOWN, "Unknown deviceRole"); 234 Preconditions.checkArgument( 235 mLowerProximityBoundaryM >= 0, 236 "Negative lowerProximityBoundaryM: " + mLowerProximityBoundaryM); 237 Preconditions.checkArgument( 238 mLowerProximityBoundaryM <= mUpperProximityBoundaryM, 239 "lowerProximityBoundaryM is greater than upperProximityBoundaryM: " 240 + mLowerProximityBoundaryM 241 + " > " 242 + mUpperProximityBoundaryM); 243 // If mAutoDeriveParams is false, mBaseKey and mSyncData will not be used. 244 if (mAutoDeriveParams) { 245 Preconditions.checkArgument( 246 mBaseKey.length == 16 || mBaseKey.length == 32, 247 "Invalid baseKey length: " + mBaseKey.length); 248 Preconditions.checkArgument( 249 mSyncData.length == 16, "Invalid syncData length: " + mSyncData.length); 250 } 251 252 return new SessionParameters( 253 mDeviceId, 254 mRangingMethod, 255 mDeviceRole, 256 mLowerProximityBoundaryM, 257 mUpperProximityBoundaryM, 258 mAutoDeriveParams, 259 mBaseKey, 260 mSyncData); 261 } 262 } 263 } 264