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.android.internal.util.Preconditions.checkNotNull; 20 21 import android.annotation.NonNull; 22 import android.os.Build.VERSION_CODES; 23 import android.os.PersistableBundle; 24 import android.uwb.UwbManager; 25 26 import androidx.annotation.IntRange; 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_RAN_MULTIPLIER = "ran_multiplier"; 46 private static final String KEY_CHANNEL = "channel"; 47 private static final String KEY_NUM_CHAPS_PER_SLOT = "num_chaps_per_slot"; 48 private static final String KEY_NUM_RESPONDER_NODES = "num_responder_nodes"; 49 private static final String KEY_NUM_SLOTS_PER_ROUND = "num_slots_per_round"; 50 private static final String KEY_SYNC_CODE_INDEX = "sync_code_index"; 51 private static final String KEY_HOPPING_CONFIG_MODE = "hopping_config_mode"; 52 private static final String KEY_HOPPING_SEQUENCE = "hopping_sequence"; 53 54 private final CccProtocolVersion mProtocolVersion; 55 @UwbConfig private final int mUwbConfig; 56 private final CccPulseShapeCombo mPulseShapeCombo; 57 private final int mSessionId; 58 private final int mRanMultiplier; 59 @Channel private final int mChannel; 60 private final int mNumChapsPerSlot; 61 private final int mNumResponderNodes; 62 private final int mNumSlotsPerRound; 63 @SyncCodeIndex private final int mSyncCodeIndex; 64 @HoppingConfigMode private final int mHoppingConfigMode; 65 @HoppingSequence private final int mHoppingSequence; 66 CccOpenRangingParams( CccProtocolVersion protocolVersion, @UwbConfig int uwbConfig, CccPulseShapeCombo pulseShapeCombo, int sessionId, int ranMultiplier, @Channel int channel, int numChapsPerSlot, int numResponderNodes, int numSlotsPerRound, @SyncCodeIndex int syncCodeIndex, @HoppingConfigMode int hoppingConfigMode, @HoppingSequence int hoppingSequence)67 private CccOpenRangingParams( 68 CccProtocolVersion protocolVersion, 69 @UwbConfig int uwbConfig, 70 CccPulseShapeCombo pulseShapeCombo, 71 int sessionId, 72 int ranMultiplier, 73 @Channel int channel, 74 int numChapsPerSlot, 75 int numResponderNodes, 76 int numSlotsPerRound, 77 @SyncCodeIndex int syncCodeIndex, 78 @HoppingConfigMode int hoppingConfigMode, 79 @HoppingSequence int hoppingSequence) { 80 mProtocolVersion = protocolVersion; 81 mUwbConfig = uwbConfig; 82 mPulseShapeCombo = pulseShapeCombo; 83 mSessionId = sessionId; 84 mRanMultiplier = ranMultiplier; 85 mChannel = channel; 86 mNumChapsPerSlot = numChapsPerSlot; 87 mNumResponderNodes = numResponderNodes; 88 mNumSlotsPerRound = numSlotsPerRound; 89 mSyncCodeIndex = syncCodeIndex; 90 mHoppingConfigMode = hoppingConfigMode; 91 mHoppingSequence = hoppingSequence; 92 } 93 94 @Override getBundleVersion()95 protected int getBundleVersion() { 96 return BUNDLE_VERSION_CURRENT; 97 } 98 99 @Override toBundle()100 public PersistableBundle toBundle() { 101 PersistableBundle bundle = super.toBundle(); 102 bundle.putString(KEY_PROTOCOL_VERSION, mProtocolVersion.toString()); 103 bundle.putInt(KEY_UWB_CONFIG, mUwbConfig); 104 bundle.putString(KEY_PULSE_SHAPE_COMBO, mPulseShapeCombo.toString()); 105 bundle.putInt(KEY_SESSION_ID, mSessionId); 106 bundle.putInt(KEY_RAN_MULTIPLIER, mRanMultiplier); 107 bundle.putInt(KEY_CHANNEL, mChannel); 108 bundle.putInt(KEY_NUM_CHAPS_PER_SLOT, mNumChapsPerSlot); 109 bundle.putInt(KEY_NUM_RESPONDER_NODES, mNumResponderNodes); 110 bundle.putInt(KEY_NUM_SLOTS_PER_ROUND, mNumSlotsPerRound); 111 bundle.putInt(KEY_SYNC_CODE_INDEX, mSyncCodeIndex); 112 bundle.putInt(KEY_HOPPING_CONFIG_MODE, mHoppingConfigMode); 113 bundle.putInt(KEY_HOPPING_SEQUENCE, mHoppingSequence); 114 return bundle; 115 } 116 fromBundle(PersistableBundle bundle)117 public static CccOpenRangingParams fromBundle(PersistableBundle bundle) { 118 if (!isCorrectProtocol(bundle)) { 119 throw new IllegalArgumentException("Invalid protocol"); 120 } 121 122 switch (getBundleVersion(bundle)) { 123 case BUNDLE_VERSION_1: 124 return parseBundleVersion1(bundle); 125 126 default: 127 throw new IllegalArgumentException("unknown bundle version"); 128 } 129 } 130 parseBundleVersion1(PersistableBundle bundle)131 private static CccOpenRangingParams parseBundleVersion1(PersistableBundle bundle) { 132 return new Builder() 133 .setProtocolVersion( 134 CccProtocolVersion.fromString( 135 checkNotNull(bundle.getString(KEY_PROTOCOL_VERSION)))) 136 .setUwbConfig(bundle.getInt(KEY_UWB_CONFIG)) 137 .setPulseShapeCombo( 138 CccPulseShapeCombo.fromString( 139 checkNotNull(bundle.getString(KEY_PULSE_SHAPE_COMBO)))) 140 .setSessionId(bundle.getInt(KEY_SESSION_ID)) 141 .setRanMultiplier(bundle.getInt(KEY_RAN_MULTIPLIER)) 142 .setChannel(bundle.getInt(KEY_CHANNEL)) 143 .setNumChapsPerSlot(bundle.getInt(KEY_NUM_CHAPS_PER_SLOT)) 144 .setNumResponderNodes(bundle.getInt(KEY_NUM_RESPONDER_NODES)) 145 .setNumSlotsPerRound(bundle.getInt(KEY_NUM_SLOTS_PER_ROUND)) 146 .setSyncCodeIndex(bundle.getInt(KEY_SYNC_CODE_INDEX)) 147 .setHoppingConfigMode(bundle.getInt(KEY_HOPPING_CONFIG_MODE)) 148 .setHoppingSequence(bundle.getInt(KEY_HOPPING_SEQUENCE)) 149 .build(); 150 } 151 getProtocolVersion()152 public CccProtocolVersion getProtocolVersion() { 153 return mProtocolVersion; 154 } 155 156 @UwbConfig getUwbConfig()157 public int getUwbConfig() { 158 return mUwbConfig; 159 } 160 getPulseShapeCombo()161 public CccPulseShapeCombo getPulseShapeCombo() { 162 return mPulseShapeCombo; 163 } 164 getSessionId()165 public int getSessionId() { 166 return mSessionId; 167 } 168 169 @IntRange(from = 0, to = 255) getRanMultiplier()170 public int getRanMultiplier() { 171 return mRanMultiplier; 172 } 173 174 @Channel getChannel()175 public int getChannel() { 176 return mChannel; 177 } 178 getNumChapsPerSlot()179 public int getNumChapsPerSlot() { 180 return mNumChapsPerSlot; 181 } 182 getNumResponderNodes()183 public int getNumResponderNodes() { 184 return mNumResponderNodes; 185 } 186 getNumSlotsPerRound()187 public int getNumSlotsPerRound() { 188 return mNumSlotsPerRound; 189 } 190 191 @SyncCodeIndex getSyncCodeIndex()192 public int getSyncCodeIndex() { 193 return mSyncCodeIndex; 194 } 195 196 @HoppingConfigMode getHoppingConfigMode()197 public int getHoppingConfigMode() { 198 return mHoppingConfigMode; 199 } 200 201 @HoppingSequence getHoppingSequence()202 public int getHoppingSequence() { 203 return mHoppingSequence; 204 } 205 206 /** Builder */ 207 public static final class Builder { 208 private RequiredParam<CccProtocolVersion> mProtocolVersion = new RequiredParam<>(); 209 @UwbConfig private RequiredParam<Integer> mUwbConfig = new RequiredParam<>(); 210 private RequiredParam<CccPulseShapeCombo> mPulseShapeCombo = new RequiredParam<>(); 211 private RequiredParam<Integer> mSessionId = new RequiredParam<>(); 212 private RequiredParam<Integer> mRanMultiplier = new RequiredParam<>(); 213 @Channel private RequiredParam<Integer> mChannel = new RequiredParam<>(); 214 @ChapsPerSlot private RequiredParam<Integer> mNumChapsPerSlot = new RequiredParam<>(); 215 private RequiredParam<Integer> mNumResponderNodes = new RequiredParam<>(); 216 @SlotsPerRound private RequiredParam<Integer> mNumSlotsPerRound = new RequiredParam<>(); 217 @SyncCodeIndex private RequiredParam<Integer> mSyncCodeIndex = new RequiredParam<>(); 218 219 @HoppingConfigMode 220 private RequiredParam<Integer> mHoppingConfigMode = new RequiredParam<>(); 221 222 @HoppingSequence private RequiredParam<Integer> mHoppingSequence = new RequiredParam<>(); 223 Builder()224 public Builder() {} 225 Builder(@onNull Builder builder)226 public Builder(@NonNull Builder builder) { 227 mProtocolVersion.set(builder.mProtocolVersion.get()); 228 mUwbConfig.set(builder.mUwbConfig.get()); 229 mPulseShapeCombo.set(builder.mPulseShapeCombo.get()); 230 mSessionId.set(builder.mSessionId.get()); 231 mRanMultiplier.set(builder.mRanMultiplier.get()); 232 mChannel.set(builder.mChannel.get()); 233 mNumChapsPerSlot.set(builder.mNumChapsPerSlot.get()); 234 mNumResponderNodes.set(builder.mNumResponderNodes.get()); 235 mNumSlotsPerRound.set(builder.mNumSlotsPerRound.get()); 236 mSyncCodeIndex.set(builder.mSyncCodeIndex.get()); 237 mHoppingConfigMode.set(builder.mHoppingConfigMode.get()); 238 mHoppingSequence.set(builder.mHoppingSequence.get()); 239 } 240 setProtocolVersion(CccProtocolVersion version)241 public Builder setProtocolVersion(CccProtocolVersion version) { 242 mProtocolVersion.set(version); 243 return this; 244 } 245 setUwbConfig(@wbConfig int uwbConfig)246 public Builder setUwbConfig(@UwbConfig int uwbConfig) { 247 mUwbConfig.set(uwbConfig); 248 return this; 249 } 250 setPulseShapeCombo(CccPulseShapeCombo pulseShapeCombo)251 public Builder setPulseShapeCombo(CccPulseShapeCombo pulseShapeCombo) { 252 mPulseShapeCombo.set(pulseShapeCombo); 253 return this; 254 } 255 setSessionId(int sessionId)256 public Builder setSessionId(int sessionId) { 257 mSessionId.set(sessionId); 258 return this; 259 } 260 setRanMultiplier(int ranMultiplier)261 public Builder setRanMultiplier(int ranMultiplier) { 262 mRanMultiplier.set(ranMultiplier); 263 return this; 264 } 265 setChannel(@hannel int channel)266 public Builder setChannel(@Channel int channel) { 267 mChannel.set(channel); 268 return this; 269 } 270 setNumChapsPerSlot(@hapsPerSlot int numChapsPerSlot)271 public Builder setNumChapsPerSlot(@ChapsPerSlot int numChapsPerSlot) { 272 mNumChapsPerSlot.set(numChapsPerSlot); 273 return this; 274 } 275 setNumResponderNodes(int numResponderNodes)276 public Builder setNumResponderNodes(int numResponderNodes) { 277 mNumResponderNodes.set(numResponderNodes); 278 return this; 279 } 280 setNumSlotsPerRound(@lotsPerRound int numSlotsPerRound)281 public Builder setNumSlotsPerRound(@SlotsPerRound int numSlotsPerRound) { 282 mNumSlotsPerRound.set(numSlotsPerRound); 283 return this; 284 } 285 setSyncCodeIndex(@yncCodeIndex int syncCodeIndex)286 public Builder setSyncCodeIndex(@SyncCodeIndex int syncCodeIndex) { 287 mSyncCodeIndex.set(syncCodeIndex); 288 return this; 289 } 290 setHoppingConfigMode(@oppingConfigMode int hoppingConfigMode)291 public Builder setHoppingConfigMode(@HoppingConfigMode int hoppingConfigMode) { 292 mHoppingConfigMode.set(hoppingConfigMode); 293 return this; 294 } 295 setHoppingSequence(@oppingSequence int hoppingSequence)296 public Builder setHoppingSequence(@HoppingSequence int hoppingSequence) { 297 mHoppingSequence.set(hoppingSequence); 298 return this; 299 } 300 build()301 public CccOpenRangingParams build() { 302 return new CccOpenRangingParams( 303 mProtocolVersion.get(), 304 mUwbConfig.get(), 305 mPulseShapeCombo.get(), 306 mSessionId.get(), 307 mRanMultiplier.get(), 308 mChannel.get(), 309 mNumChapsPerSlot.get(), 310 mNumResponderNodes.get(), 311 mNumSlotsPerRound.get(), 312 mSyncCodeIndex.get(), 313 mHoppingConfigMode.get(), 314 mHoppingSequence.get()); 315 } 316 } 317 } 318