1 /* 2 * Copyright (C) 2021 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 17 package com.google.uwb.support.ccc; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 21 import android.os.Build.VERSION_CODES; 22 import android.os.PersistableBundle; 23 import android.uwb.UwbManager; 24 25 import androidx.annotation.IntRange; 26 import androidx.annotation.NonNull; 27 import androidx.annotation.RequiresApi; 28 29 import com.google.uwb.support.base.RequiredParam; 30 31 /** 32 * Defines parameters for CCC open operation 33 * 34 * <p>This is passed as a bundle to the service API {@link UwbManager#openRangingSession}. 35 */ 36 @RequiresApi(VERSION_CODES.LOLLIPOP) 37 public class CccOpenRangingParams extends CccParams { 38 private static final int BUNDLE_VERSION_1 = 1; 39 private static final int BUNDLE_VERSION_CURRENT = BUNDLE_VERSION_1; 40 41 private static final String KEY_PROTOCOL_VERSION = "protocol_version"; 42 private static final String KEY_UWB_CONFIG = "uwb_config"; 43 private static final String KEY_PULSE_SHAPE_COMBO = "pulse_shape_combo"; 44 private static final String KEY_SESSION_ID = "session_id"; 45 private static final String KEY_SESSION_TYPE = "session_type"; 46 private static final String KEY_RAN_MULTIPLIER = "ran_multiplier"; 47 private static final String KEY_CHANNEL = "channel"; 48 private static final String KEY_NUM_CHAPS_PER_SLOT = "num_chaps_per_slot"; 49 private static final String KEY_NUM_RESPONDER_NODES = "num_responder_nodes"; 50 private static final String KEY_NUM_SLOTS_PER_ROUND = "num_slots_per_round"; 51 private static final String KEY_SYNC_CODE_INDEX = "sync_code_index"; 52 private static final String KEY_HOPPING_CONFIG_MODE = "hopping_config_mode"; 53 private static final String KEY_HOPPING_SEQUENCE = "hopping_sequence"; 54 private static final String KEY_LAST_STS_INDEX_USED = "last_sts_index_used"; 55 private static final String KEY_INITIATION_TIME_MS = "initiation_time_ms"; 56 57 private final CccProtocolVersion mProtocolVersion; 58 @UwbConfig private final int mUwbConfig; 59 private final CccPulseShapeCombo mPulseShapeCombo; 60 private final int mSessionId; 61 @SessionType private final int mSessionType; 62 private final int mRanMultiplier; 63 @Channel private final int mChannel; 64 private final int mNumChapsPerSlot; 65 private final int mNumResponderNodes; 66 private final int mNumSlotsPerRound; 67 @SyncCodeIndex private final int mSyncCodeIndex; 68 @HoppingConfigMode private final int mHoppingConfigMode; 69 @HoppingSequence private final int mHoppingSequence; 70 private final int mLastStsIndexUsed; 71 private final long mInitiationTimeMs; 72 CccOpenRangingParams( CccProtocolVersion protocolVersion, @UwbConfig int uwbConfig, CccPulseShapeCombo pulseShapeCombo, int sessionId, @SessionType int sessionType, int ranMultiplier, @Channel int channel, int numChapsPerSlot, int numResponderNodes, int numSlotsPerRound, @SyncCodeIndex int syncCodeIndex, @HoppingConfigMode int hoppingConfigMode, @HoppingSequence int hoppingSequence, int lastStsIndexUsed, long initiationTimeMs)73 private CccOpenRangingParams( 74 CccProtocolVersion protocolVersion, 75 @UwbConfig int uwbConfig, 76 CccPulseShapeCombo pulseShapeCombo, 77 int sessionId, 78 @SessionType int sessionType, 79 int ranMultiplier, 80 @Channel int channel, 81 int numChapsPerSlot, 82 int numResponderNodes, 83 int numSlotsPerRound, 84 @SyncCodeIndex int syncCodeIndex, 85 @HoppingConfigMode int hoppingConfigMode, 86 @HoppingSequence int hoppingSequence, 87 int lastStsIndexUsed, 88 long initiationTimeMs) { 89 mProtocolVersion = protocolVersion; 90 mUwbConfig = uwbConfig; 91 mPulseShapeCombo = pulseShapeCombo; 92 mSessionId = sessionId; 93 mSessionType = sessionType; 94 mRanMultiplier = ranMultiplier; 95 mChannel = channel; 96 mNumChapsPerSlot = numChapsPerSlot; 97 mNumResponderNodes = numResponderNodes; 98 mNumSlotsPerRound = numSlotsPerRound; 99 mSyncCodeIndex = syncCodeIndex; 100 mHoppingConfigMode = hoppingConfigMode; 101 mHoppingSequence = hoppingSequence; 102 mLastStsIndexUsed = lastStsIndexUsed; 103 mInitiationTimeMs = initiationTimeMs; 104 } 105 106 @Override getBundleVersion()107 protected int getBundleVersion() { 108 return BUNDLE_VERSION_CURRENT; 109 } 110 111 @Override toBundle()112 public PersistableBundle toBundle() { 113 PersistableBundle bundle = super.toBundle(); 114 bundle.putString(KEY_PROTOCOL_VERSION, mProtocolVersion.toString()); 115 bundle.putInt(KEY_UWB_CONFIG, mUwbConfig); 116 bundle.putString(KEY_PULSE_SHAPE_COMBO, mPulseShapeCombo.toString()); 117 bundle.putInt(KEY_SESSION_ID, mSessionId); 118 bundle.putInt(KEY_SESSION_TYPE, mSessionType); 119 bundle.putInt(KEY_RAN_MULTIPLIER, mRanMultiplier); 120 bundle.putInt(KEY_CHANNEL, mChannel); 121 bundle.putInt(KEY_NUM_CHAPS_PER_SLOT, mNumChapsPerSlot); 122 bundle.putInt(KEY_NUM_RESPONDER_NODES, mNumResponderNodes); 123 bundle.putInt(KEY_NUM_SLOTS_PER_ROUND, mNumSlotsPerRound); 124 bundle.putInt(KEY_SYNC_CODE_INDEX, mSyncCodeIndex); 125 bundle.putInt(KEY_HOPPING_CONFIG_MODE, mHoppingConfigMode); 126 bundle.putInt(KEY_HOPPING_SEQUENCE, mHoppingSequence); 127 bundle.putInt(KEY_LAST_STS_INDEX_USED, mLastStsIndexUsed); 128 bundle.putLong(KEY_INITIATION_TIME_MS, mInitiationTimeMs); 129 return bundle; 130 } 131 fromBundle(PersistableBundle bundle)132 public static CccOpenRangingParams fromBundle(PersistableBundle bundle) { 133 if (!isCorrectProtocol(bundle)) { 134 throw new IllegalArgumentException("Invalid protocol"); 135 } 136 137 switch (getBundleVersion(bundle)) { 138 case BUNDLE_VERSION_1: 139 return parseBundleVersion1(bundle); 140 141 default: 142 throw new IllegalArgumentException("unknown bundle version"); 143 } 144 } 145 parseBundleVersion1(PersistableBundle bundle)146 private static CccOpenRangingParams parseBundleVersion1(PersistableBundle bundle) { 147 return new Builder() 148 .setProtocolVersion( 149 CccProtocolVersion.fromString( 150 checkNotNull(bundle.getString(KEY_PROTOCOL_VERSION)))) 151 .setUwbConfig(bundle.getInt(KEY_UWB_CONFIG)) 152 .setPulseShapeCombo( 153 CccPulseShapeCombo.fromString( 154 checkNotNull(bundle.getString(KEY_PULSE_SHAPE_COMBO)))) 155 .setSessionId(bundle.getInt(KEY_SESSION_ID)) 156 .setRanMultiplier(bundle.getInt(KEY_RAN_MULTIPLIER)) 157 .setChannel(bundle.getInt(KEY_CHANNEL)) 158 .setNumChapsPerSlot(bundle.getInt(KEY_NUM_CHAPS_PER_SLOT)) 159 .setNumResponderNodes(bundle.getInt(KEY_NUM_RESPONDER_NODES)) 160 .setNumSlotsPerRound(bundle.getInt(KEY_NUM_SLOTS_PER_ROUND)) 161 .setSyncCodeIndex(bundle.getInt(KEY_SYNC_CODE_INDEX)) 162 .setHoppingConfigMode(bundle.getInt(KEY_HOPPING_CONFIG_MODE)) 163 .setHoppingSequence(bundle.getInt(KEY_HOPPING_SEQUENCE)) 164 .setLastStsIndexUsed(bundle.getInt( 165 KEY_LAST_STS_INDEX_USED, CccParams.LAST_STS_INDEX_USED_UNSET)) 166 .setInitiationTimeMs(bundle.getLong(KEY_INITIATION_TIME_MS)) 167 .build(); 168 } 169 getProtocolVersion()170 public CccProtocolVersion getProtocolVersion() { 171 return mProtocolVersion; 172 } 173 174 @UwbConfig getUwbConfig()175 public int getUwbConfig() { 176 return mUwbConfig; 177 } 178 getPulseShapeCombo()179 public CccPulseShapeCombo getPulseShapeCombo() { 180 return mPulseShapeCombo; 181 } 182 getSessionId()183 public int getSessionId() { 184 return mSessionId; 185 } 186 187 @SessionType getSessionType()188 public int getSessionType() { 189 return mSessionType; 190 } 191 192 @IntRange(from = 0, to = 255) getRanMultiplier()193 public int getRanMultiplier() { 194 return mRanMultiplier; 195 } 196 197 @Channel getChannel()198 public int getChannel() { 199 return mChannel; 200 } 201 getNumChapsPerSlot()202 public int getNumChapsPerSlot() { 203 return mNumChapsPerSlot; 204 } 205 getNumResponderNodes()206 public int getNumResponderNodes() { 207 return mNumResponderNodes; 208 } 209 getNumSlotsPerRound()210 public int getNumSlotsPerRound() { 211 return mNumSlotsPerRound; 212 } 213 214 @SyncCodeIndex getSyncCodeIndex()215 public int getSyncCodeIndex() { 216 return mSyncCodeIndex; 217 } 218 219 @HoppingConfigMode getHoppingConfigMode()220 public int getHoppingConfigMode() { 221 return mHoppingConfigMode; 222 } 223 224 @HoppingSequence getHoppingSequence()225 public int getHoppingSequence() { 226 return mHoppingSequence; 227 } 228 getLastStsIndexUsed()229 public int getLastStsIndexUsed() { 230 return mLastStsIndexUsed; 231 } 232 getInitiationTimeMs()233 public long getInitiationTimeMs() { 234 return mInitiationTimeMs; 235 } 236 237 /** Builder */ 238 public static final class Builder { 239 private RequiredParam<CccProtocolVersion> mProtocolVersion = new RequiredParam<>(); 240 @UwbConfig private RequiredParam<Integer> mUwbConfig = new RequiredParam<>(); 241 private RequiredParam<CccPulseShapeCombo> mPulseShapeCombo = new RequiredParam<>(); 242 private RequiredParam<Integer> mSessionId = new RequiredParam<>(); 243 @SessionType private int mSessionType = CccParams.SESSION_TYPE_CCC; 244 private RequiredParam<Integer> mRanMultiplier = new RequiredParam<>(); 245 @Channel private RequiredParam<Integer> mChannel = new RequiredParam<>(); 246 @ChapsPerSlot private RequiredParam<Integer> mNumChapsPerSlot = new RequiredParam<>(); 247 private RequiredParam<Integer> mNumResponderNodes = new RequiredParam<>(); 248 @SlotsPerRound private RequiredParam<Integer> mNumSlotsPerRound = new RequiredParam<>(); 249 @SyncCodeIndex private RequiredParam<Integer> mSyncCodeIndex = new RequiredParam<>(); 250 251 @HoppingConfigMode 252 private RequiredParam<Integer> mHoppingConfigMode = new RequiredParam<>(); 253 254 @HoppingSequence private RequiredParam<Integer> mHoppingSequence = new RequiredParam<>(); 255 256 private int mLastStsIndexUsed = CccParams.LAST_STS_INDEX_USED_UNSET; 257 258 private long mInitiationTimeMs = 0; 259 Builder()260 public Builder() {} 261 Builder(@onNull Builder builder)262 public Builder(@NonNull Builder builder) { 263 mProtocolVersion.set(builder.mProtocolVersion.get()); 264 mUwbConfig.set(builder.mUwbConfig.get()); 265 mPulseShapeCombo.set(builder.mPulseShapeCombo.get()); 266 mSessionId.set(builder.mSessionId.get()); 267 mSessionType = builder.mSessionType; 268 mRanMultiplier.set(builder.mRanMultiplier.get()); 269 mChannel.set(builder.mChannel.get()); 270 mNumChapsPerSlot.set(builder.mNumChapsPerSlot.get()); 271 mNumResponderNodes.set(builder.mNumResponderNodes.get()); 272 mNumSlotsPerRound.set(builder.mNumSlotsPerRound.get()); 273 mSyncCodeIndex.set(builder.mSyncCodeIndex.get()); 274 mHoppingConfigMode.set(builder.mHoppingConfigMode.get()); 275 mHoppingSequence.set(builder.mHoppingSequence.get()); 276 mLastStsIndexUsed = builder.mLastStsIndexUsed; 277 mInitiationTimeMs = builder.mInitiationTimeMs; 278 } 279 Builder(@onNull CccOpenRangingParams params)280 public Builder(@NonNull CccOpenRangingParams params) { 281 mProtocolVersion.set(params.mProtocolVersion); 282 mUwbConfig.set(params.mUwbConfig); 283 mPulseShapeCombo.set(params.mPulseShapeCombo); 284 mSessionId.set(params.mSessionId); 285 mSessionType = params.mSessionType; 286 mRanMultiplier.set(params.mRanMultiplier); 287 mChannel.set(params.mChannel); 288 mNumChapsPerSlot.set(params.mNumChapsPerSlot); 289 mNumResponderNodes.set(params.mNumResponderNodes); 290 mNumSlotsPerRound.set(params.mNumSlotsPerRound); 291 mSyncCodeIndex.set(params.mSyncCodeIndex); 292 mHoppingConfigMode.set(params.mHoppingConfigMode); 293 mHoppingSequence.set(params.mHoppingSequence); 294 } 295 setProtocolVersion(CccProtocolVersion version)296 public Builder setProtocolVersion(CccProtocolVersion version) { 297 mProtocolVersion.set(version); 298 return this; 299 } 300 setUwbConfig(@wbConfig int uwbConfig)301 public Builder setUwbConfig(@UwbConfig int uwbConfig) { 302 mUwbConfig.set(uwbConfig); 303 return this; 304 } 305 setPulseShapeCombo(CccPulseShapeCombo pulseShapeCombo)306 public Builder setPulseShapeCombo(CccPulseShapeCombo pulseShapeCombo) { 307 mPulseShapeCombo.set(pulseShapeCombo); 308 return this; 309 } 310 setSessionId(int sessionId)311 public Builder setSessionId(int sessionId) { 312 mSessionId.set(sessionId); 313 return this; 314 } 315 setRanMultiplier(int ranMultiplier)316 public Builder setRanMultiplier(int ranMultiplier) { 317 mRanMultiplier.set(ranMultiplier); 318 return this; 319 } 320 setChannel(@hannel int channel)321 public Builder setChannel(@Channel int channel) { 322 mChannel.set(channel); 323 return this; 324 } 325 setNumChapsPerSlot(@hapsPerSlot int numChapsPerSlot)326 public Builder setNumChapsPerSlot(@ChapsPerSlot int numChapsPerSlot) { 327 mNumChapsPerSlot.set(numChapsPerSlot); 328 return this; 329 } 330 setNumResponderNodes(int numResponderNodes)331 public Builder setNumResponderNodes(int numResponderNodes) { 332 mNumResponderNodes.set(numResponderNodes); 333 return this; 334 } 335 setNumSlotsPerRound(@lotsPerRound int numSlotsPerRound)336 public Builder setNumSlotsPerRound(@SlotsPerRound int numSlotsPerRound) { 337 mNumSlotsPerRound.set(numSlotsPerRound); 338 return this; 339 } 340 setSyncCodeIndex(@yncCodeIndex int syncCodeIndex)341 public Builder setSyncCodeIndex(@SyncCodeIndex int syncCodeIndex) { 342 mSyncCodeIndex.set(syncCodeIndex); 343 return this; 344 } 345 setHoppingConfigMode(@oppingConfigMode int hoppingConfigMode)346 public Builder setHoppingConfigMode(@HoppingConfigMode int hoppingConfigMode) { 347 mHoppingConfigMode.set(hoppingConfigMode); 348 return this; 349 } 350 setHoppingSequence(@oppingSequence int hoppingSequence)351 public Builder setHoppingSequence(@HoppingSequence int hoppingSequence) { 352 mHoppingSequence.set(hoppingSequence); 353 return this; 354 } 355 setLastStsIndexUsed(int lastStsIndexUsed)356 public Builder setLastStsIndexUsed(int lastStsIndexUsed) { 357 mLastStsIndexUsed = lastStsIndexUsed; 358 return this; 359 } 360 361 /** Set initiation time in ms */ setInitiationTimeMs(long initiationTimeMs)362 public Builder setInitiationTimeMs(long initiationTimeMs) { 363 mInitiationTimeMs = initiationTimeMs; 364 return this; 365 } 366 build()367 public CccOpenRangingParams build() { 368 return new CccOpenRangingParams( 369 mProtocolVersion.get(), 370 mUwbConfig.get(), 371 mPulseShapeCombo.get(), 372 mSessionId.get(), 373 mSessionType, 374 mRanMultiplier.get(), 375 mChannel.get(), 376 mNumChapsPerSlot.get(), 377 mNumResponderNodes.get(), 378 mNumSlotsPerRound.get(), 379 mSyncCodeIndex.get(), 380 mHoppingConfigMode.get(), 381 mHoppingSequence.get(), 382 mLastStsIndexUsed, 383 mInitiationTimeMs); 384 } 385 } 386 } 387