1 /*
2  * Copyright (C) 2022 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.android.server.uwb.secure.csml;
18 
19 import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_180;
20 import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_90;
21 import static com.android.server.uwb.config.CapabilityParam.AOA_ELEVATION;
22 import static com.android.server.uwb.config.CapabilityParam.AOA_FOM;
23 
24 import android.uwb.UwbAddress;
25 
26 import androidx.annotation.NonNull;
27 import androidx.annotation.Nullable;
28 
29 import com.android.server.uwb.params.TlvBuffer;
30 import com.android.server.uwb.params.TlvDecoderBuffer;
31 
32 import com.google.uwb.support.fira.FiraParams;
33 import com.google.uwb.support.fira.FiraProtocolVersion;
34 
35 import java.nio.ByteBuffer;
36 import java.util.EnumSet;
37 import java.util.Optional;
38 
39 /**
40  * CONFIGURATION_PARAMS defined in 8.5.3.3.
41  */
42 public class ConfigurationParams {
43 
44     public static final int FIRA_PHY_VERSION = 0x80;
45     public static final int FIRA_MAC_VERSION = 0x81;
46     public static final int DEVICE_ROLES = 0x82;
47     public static final int RANGING_METHOD = 0x83;
48     public static final int STS_CONFIG = 0x84;
49     public static final int MULTI_NODE_MODE = 0x85;
50     public static final int RANGING_TIME_STRUCT = 0x86;
51     public static final int SCHEDULED_MODE = 0x87;
52     public static final int HOPPING_MODE = 0x88;
53     public static final int BLOCK_STRIDING = 0x89;
54     public static final int UWB_INITIATION_TIME = 0x8A;
55     public static final int CHANNEL = 0x8B;
56     public static final int RFRAME_CONFIG = 0x8C;
57     public static final int CC_CONSTRAINT_LENGTH = 0x8D;
58     public static final int PRF_MODE = 0X8E;
59     public static final int SP0_PHY_SET = 0x8F;
60     public static final int SP1_PHY_SET = 0x90;
61     public static final int SP3_PHY_SET = 0x91;
62     public static final int PREAMBLE_CODE_INDEX = 0x92;
63     public static final int RESULT_REPORT_CONFIG = 0x93;
64     public static final int MAC_ADDRESS_MODE = 0x94;
65     public static final int CONTROLEE_SHORT_MAC_ADDRESS = 0x95;
66     public static final int CONTROLLER_MAC_ADDRESS = 0x96;
67     public static final int SLOTS_PER_RR = 0x97;
68     public static final int MAX_CONTENTION_PHASE_LENGTH = 0x98;
69     public static final int SLOT_DURATION = 0x99;
70     public static final int RANGING_INTERVAL = 0x9A;
71     public static final int KEY_ROTATION_RATE = 0x9B;
72     public static final int MAC_FCS_TYPE = 0x9C;
73     public static final int MAX_RR_RETRY = 0x9D;
74     public static final int CONFIGURATION_PARAMS_MAX_COUNT = 30;
75 
76     public final FiraProtocolVersion mPhyVersion;
77     public final FiraProtocolVersion mMacVersion;
78     public final Optional<Integer> mDeviceRole;
79     public final Optional<Integer> mRangingMethod;
80     public final Optional<Integer> mStsConfig;
81     public final Optional<Integer> mMultiNodeMode;
82     public final Optional<Byte> mRangingTimeStruct;
83     public final Optional<Integer> mScheduleMode;
84     public final Optional<Boolean> mHoppingMode;
85     public final Optional<Boolean> mBlockStriding;
86     public final Optional<Boolean> mUwbInitiationTime;
87     public final Optional<Integer> mChannel;
88     public final Optional<Integer> mRframeConfig;
89     public final Optional<Integer> mCcConstraintLength;
90     public final Optional<Integer> mPrfMode;
91     public final Optional<Integer> mSp0PhyParameterSet;
92     public final Optional<Integer> mSp1PhyParameterSet;
93     public final Optional<Integer> mSp3PhyParameterSet;
94     public final Optional<Integer> mPreambleCodeIndex;
95     public final Optional<EnumSet<FiraParams.AoaCapabilityFlag>> mResultReportConfig;
96     public final Optional<Integer> mMacAddressMode;
97     public final Optional<UwbAddress> mControleeShortMacAddress;
98     public final Optional<UwbAddress> mControllerMacAddress;
99     public final Optional<Integer> mSlotsPerRangingRound;
100     public final Optional<Integer> mMaxContentionPhaseLength;
101     public final Optional<Integer> mSlotDuration;
102     public final Optional<Integer> mRangingIntervalMs;
103     public final Optional<Integer> mKeyRotationRate;
104     public final Optional<Integer> mMacFcsType;
105     public final Optional<Integer> mMaxRangingRoundRetry;
106 
ConfigurationParams( FiraProtocolVersion phyVersion, FiraProtocolVersion macVersion, Optional<Integer> deviceRole, Optional<Integer> rangingMethod, Optional<Integer> stsConfig, Optional<Integer> multiNodeMode, Optional<Byte> rangingTimeStruct, Optional<Integer> scheduleMode, Optional<Boolean> hoppingMode, Optional<Boolean> blockStriding, Optional<Boolean> uwbInitiationTime, Optional<Integer> channel, Optional<Integer> rframeConfig, Optional<Integer> ccConstraintLength, Optional<Integer> prfMode, Optional<Integer> sp0PhyParameterSet, Optional<Integer> sp1PhyParameterSet, Optional<Integer> sp3PhyParameterSet, Optional<Integer> preambleCodeIndex, Optional<EnumSet<FiraParams.AoaCapabilityFlag>> resultReportConfig, Optional<Integer> macAddressMode, Optional<UwbAddress> controleeShortMacAddress, Optional<UwbAddress> controllerMacAddress, Optional<Integer> slotsPerRangingRound, Optional<Integer> maxContentionPhaseLength, Optional<Integer> slotDuration, Optional<Integer> rangingIntervalMs, Optional<Integer> keyRotationRate, Optional<Integer> macFcsType, Optional<Integer> maxRangingRoundRetry)107     public ConfigurationParams(
108             FiraProtocolVersion phyVersion,
109             FiraProtocolVersion macVersion,
110             Optional<Integer> deviceRole,
111             Optional<Integer> rangingMethod,
112             Optional<Integer> stsConfig,
113             Optional<Integer> multiNodeMode,
114             Optional<Byte> rangingTimeStruct, Optional<Integer> scheduleMode,
115             Optional<Boolean> hoppingMode, Optional<Boolean> blockStriding,
116             Optional<Boolean> uwbInitiationTime,
117             Optional<Integer> channel,
118             Optional<Integer> rframeConfig,
119             Optional<Integer> ccConstraintLength,
120             Optional<Integer> prfMode,
121             Optional<Integer> sp0PhyParameterSet,
122             Optional<Integer> sp1PhyParameterSet,
123             Optional<Integer> sp3PhyParameterSet,
124             Optional<Integer> preambleCodeIndex,
125             Optional<EnumSet<FiraParams.AoaCapabilityFlag>> resultReportConfig,
126             Optional<Integer> macAddressMode,
127             Optional<UwbAddress> controleeShortMacAddress,
128             Optional<UwbAddress> controllerMacAddress,
129             Optional<Integer> slotsPerRangingRound,
130             Optional<Integer> maxContentionPhaseLength,
131             Optional<Integer> slotDuration,
132             Optional<Integer> rangingIntervalMs,
133             Optional<Integer> keyRotationRate,
134             Optional<Integer> macFcsType,
135             Optional<Integer> maxRangingRoundRetry) {
136         mPhyVersion = phyVersion;
137         mMacVersion = macVersion;
138         mDeviceRole = deviceRole;
139         mRangingMethod = rangingMethod;
140         mStsConfig = stsConfig;
141         mMultiNodeMode = multiNodeMode;
142         mRangingTimeStruct = rangingTimeStruct;
143         mScheduleMode = scheduleMode;
144         mHoppingMode = hoppingMode;
145         mBlockStriding = blockStriding;
146         mUwbInitiationTime = uwbInitiationTime;
147         mChannel = channel;
148         mRframeConfig = rframeConfig;
149         mCcConstraintLength = ccConstraintLength;
150         mPrfMode = prfMode;
151         mSp0PhyParameterSet = sp0PhyParameterSet;
152         mSp1PhyParameterSet = sp1PhyParameterSet;
153         mSp3PhyParameterSet = sp3PhyParameterSet;
154         mPreambleCodeIndex = preambleCodeIndex;
155         mResultReportConfig = resultReportConfig;
156         mMacAddressMode = macAddressMode;
157         mControleeShortMacAddress = controleeShortMacAddress;
158         mControllerMacAddress = controllerMacAddress;
159         mSlotsPerRangingRound = slotsPerRangingRound;
160         mMaxContentionPhaseLength = maxContentionPhaseLength;
161         mSlotDuration = slotDuration;
162         mRangingIntervalMs = rangingIntervalMs;
163         mKeyRotationRate = keyRotationRate;
164         mMacFcsType = macFcsType;
165         mMaxRangingRoundRetry = maxRangingRoundRetry;
166     }
167 
168     /**
169      * Converts the UwbCapabilities to the bytes which are combined per the TLV of CSML 8.5.3.2.
170      */
171     @NonNull
toBytes()172     byte[] toBytes() {
173         TlvBuffer.Builder configParamsBuilder = new TlvBuffer.Builder()
174                 .putByteArray(FIRA_PHY_VERSION, new byte[]{
175                         (byte) mPhyVersion.getMajor(),
176                         (byte) mPhyVersion.getMinor(),
177                 })
178                 .putByteArray(FIRA_MAC_VERSION, new byte[]{
179                         (byte) mMacVersion.getMajor(),
180                         (byte) mMacVersion.getMinor(),
181                 });
182 
183         mDeviceRole.ifPresent(integer -> configParamsBuilder.putByte(DEVICE_ROLES,
184                 integer.byteValue()));
185 
186         mRangingMethod.ifPresent(integer -> configParamsBuilder.putByte(RANGING_METHOD,
187                 integer.byteValue()));
188 
189         //configParamsBuilder.putByte(RANGING_METHOD,(byte) HAS_DS_TWR_SUPPORT.getValue());
190 
191         mStsConfig.ifPresent(
192                 integer -> configParamsBuilder.putByte(STS_CONFIG, integer.byteValue()));
193 
194         mMultiNodeMode.ifPresent(
195                 integer -> configParamsBuilder.putByte(MULTI_NODE_MODE, integer.byteValue()));
196 
197         mRangingTimeStruct.ifPresent(
198                 aByte -> configParamsBuilder.putByte(RANGING_TIME_STRUCT, aByte));
199 
200         mScheduleMode.ifPresent(
201                 integer -> configParamsBuilder.putByte(SCHEDULED_MODE, integer.byteValue()));
202 
203         mHoppingMode.ifPresent(aBoolean -> configParamsBuilder.putByte(HOPPING_MODE,
204                 (byte) (aBoolean ? 1 : 0)));
205 
206         mBlockStriding.ifPresent(aBoolean -> configParamsBuilder.putByte(BLOCK_STRIDING,
207                 (byte) (aBoolean ? 1 : 0)));
208 
209         mUwbInitiationTime.ifPresent(aBoolean -> configParamsBuilder.putByte(UWB_INITIATION_TIME,
210                 (byte) (aBoolean ? 1 : 0)));
211 
212         mChannel.ifPresent(integer -> configParamsBuilder.putByte(CHANNEL, integer.byteValue()));
213 
214         mRframeConfig.ifPresent(integer -> configParamsBuilder.putByte(RFRAME_CONFIG,
215                 integer.byteValue()));
216 
217         mCcConstraintLength.ifPresent(
218                 cccLen -> configParamsBuilder.putByte(CC_CONSTRAINT_LENGTH, cccLen.byteValue()));
219 
220         mPrfMode.ifPresent(integer -> configParamsBuilder.putByte(PRF_MODE, integer.byteValue()));
221 
222         mSp0PhyParameterSet.ifPresent(integer -> configParamsBuilder.putByte(SP0_PHY_SET,
223                 integer.byteValue()));
224 
225         mSp1PhyParameterSet.ifPresent(integer -> configParamsBuilder.putByte(SP1_PHY_SET,
226                 integer.byteValue()));
227 
228         mSp3PhyParameterSet.ifPresent(integer -> configParamsBuilder.putByte(SP3_PHY_SET,
229                 integer.byteValue()));
230 
231         mPreambleCodeIndex.ifPresent(
232                 integer -> configParamsBuilder.putByte(PREAMBLE_CODE_INDEX, integer.byteValue()));
233 
234         mPreambleCodeIndex.ifPresent(
235                 integer -> configParamsBuilder.putByte(PREAMBLE_CODE_INDEX, integer.byteValue()));
236 
237         if (mResultReportConfig.isPresent()) {
238             byte resultReportConfig = 0;
239             if (mResultReportConfig.get().contains(
240                     FiraParams.AoaCapabilityFlag.HAS_AZIMUTH_SUPPORT)) {
241                 resultReportConfig = (byte) (resultReportConfig | AOA_AZIMUTH_90);
242             }
243             if (mResultReportConfig.get().contains(
244                     FiraParams.AoaCapabilityFlag.HAS_FULL_AZIMUTH_SUPPORT)) {
245                 resultReportConfig = (byte) (resultReportConfig | AOA_AZIMUTH_180);
246             }
247             if (mResultReportConfig.get().contains(
248                     FiraParams.AoaCapabilityFlag.HAS_ELEVATION_SUPPORT)) {
249                 resultReportConfig = (byte) (resultReportConfig | AOA_ELEVATION);
250             }
251             if (mResultReportConfig.get().contains(FiraParams.AoaCapabilityFlag.HAS_FOM_SUPPORT)) {
252                 resultReportConfig = (byte) (resultReportConfig | AOA_FOM);
253             }
254             configParamsBuilder.putByte(RESULT_REPORT_CONFIG, resultReportConfig);
255         }
256 
257         mMacAddressMode.ifPresent(
258                 integer -> configParamsBuilder.putByte(MAC_ADDRESS_MODE, integer.byteValue()));
259 
260         mControleeShortMacAddress.ifPresent(
261                 uwbAddress -> configParamsBuilder.putByteArray(CONTROLEE_SHORT_MAC_ADDRESS,
262                         uwbAddress.toBytes()));
263 
264         mControllerMacAddress.ifPresent(
265                 uwbAddress -> configParamsBuilder.putByteArray(CONTROLLER_MAC_ADDRESS,
266                         uwbAddress.toBytes()));
267 
268         mSlotsPerRangingRound.ifPresent(
269                 integer -> configParamsBuilder.putByte(SLOTS_PER_RR, integer.byteValue()));
270 
271         mMaxContentionPhaseLength.ifPresent(
272                 integer -> configParamsBuilder.putByte(MAX_CONTENTION_PHASE_LENGTH,
273                         integer.byteValue()));
274 
275         mSlotDuration.ifPresent(
276                 integer -> configParamsBuilder.putByteArray(SLOT_DURATION, ByteBuffer.allocate(
277                         2).putInt(
278                         integer).array()));
279 
280         mRangingIntervalMs.ifPresent(
281                 integer -> configParamsBuilder.putByteArray(RANGING_INTERVAL, ByteBuffer.allocate(
282                         2).putInt(
283                         integer).array()));
284 
285         mKeyRotationRate.ifPresent(
286                 integer -> configParamsBuilder.putByte(KEY_ROTATION_RATE,
287                         mKeyRotationRate.get().byteValue()));
288 
289         mMacFcsType.ifPresent(
290                 integer -> configParamsBuilder.putByte(MAC_ADDRESS_MODE,
291                         mMacFcsType.get().byteValue()));
292 
293         mMaxRangingRoundRetry.ifPresent(
294                 integer -> configParamsBuilder.putByteArray(MAX_RR_RETRY, ByteBuffer.allocate(
295                         2).putInt(
296                         integer).array()));
297 
298         return configParamsBuilder.build().getByteArray();
299     }
300 
301 
isBitSet(int flags, int mask)302     private static boolean isBitSet(int flags, int mask) {
303         return (flags & mask) != 0;
304     }
305 
isPresent(TlvDecoderBuffer tlvDecoderBuffer, int tagType)306     private static boolean isPresent(TlvDecoderBuffer tlvDecoderBuffer, int tagType) {
307         try {
308             tlvDecoderBuffer.getByte(tagType);
309         } catch (IllegalArgumentException e) {
310             try {
311                 tlvDecoderBuffer.getByteArray(tagType);
312             } catch (IllegalArgumentException e1) {
313                 return false;
314             }
315         }
316         return true;
317     }
318 
319     /**
320      * Converts the UwbCapabilities from the data stream, which is encoded per the CSML 8.5.3.2.
321      *
322      * @return null if the data cannot be decoded per spec.
323      */
324     @Nullable
fromBytes(@onNull byte[] data)325     static ConfigurationParams fromBytes(@NonNull byte[] data) {
326         TlvDecoderBuffer configParamsTlv = new TlvDecoderBuffer(data,
327                 CONFIGURATION_PARAMS_MAX_COUNT);
328         configParamsTlv.parse();
329         ConfigurationParams.Builder configParamsBuilder = new ConfigurationParams.Builder();
330 
331         if (isPresent(configParamsTlv, FIRA_PHY_VERSION)) {
332             byte[] firaPhyVersion = configParamsTlv.getByteArray(FIRA_PHY_VERSION);
333             if (firaPhyVersion.length == 2) {
334                 FiraProtocolVersion version = new FiraProtocolVersion(firaPhyVersion[0],
335                         firaPhyVersion[1]);
336                 configParamsBuilder.setPhyVersion(version);
337             }
338         }
339         if (isPresent(configParamsTlv, FIRA_MAC_VERSION)) {
340             byte[] firaMacVersion = configParamsTlv.getByteArray(FIRA_MAC_VERSION);
341             if (firaMacVersion.length == 2) {
342                 FiraProtocolVersion version = new FiraProtocolVersion(firaMacVersion[0],
343                         firaMacVersion[1]);
344                 configParamsBuilder.setMacVersion(version);
345             }
346         }
347         if (isPresent(configParamsTlv, DEVICE_ROLES)) {
348             configParamsBuilder.setDeviceRole(configParamsTlv.getByte(DEVICE_ROLES));
349         }
350         if (isPresent(configParamsTlv, RANGING_METHOD)) {
351             configParamsBuilder.setRangingMethod(
352                     configParamsTlv.getByte(RANGING_METHOD).intValue());
353         }
354         if (isPresent(configParamsTlv, STS_CONFIG)) {
355             configParamsBuilder.setStsConfig(configParamsTlv.getByte(STS_CONFIG).intValue());
356         }
357         if (isPresent(configParamsTlv, MULTI_NODE_MODE)) {
358             configParamsBuilder.setMultiNodeMode(
359                     configParamsTlv.getByte(MULTI_NODE_MODE).intValue());
360         }
361         if (isPresent(configParamsTlv, RANGING_TIME_STRUCT)) {
362             configParamsBuilder.setRangingTimeStruct(configParamsTlv.getByte(RANGING_TIME_STRUCT));
363         }
364         if (isPresent(configParamsTlv, SCHEDULED_MODE)) {
365             configParamsBuilder.setScheduleMode(configParamsTlv.getByte(SCHEDULED_MODE).intValue());
366         }
367         if (isPresent(configParamsTlv, HOPPING_MODE)) {
368             configParamsBuilder.setHoppingMode(configParamsTlv.getByte(HOPPING_MODE) == 1);
369         }
370         if (isPresent(configParamsTlv, BLOCK_STRIDING)) {
371             configParamsBuilder.setBlockStriding(configParamsTlv.getByte(BLOCK_STRIDING) == 1);
372         }
373         if (isPresent(configParamsTlv, UWB_INITIATION_TIME)) {
374             configParamsBuilder.setUwbInitiationTime(
375                     configParamsTlv.getByte(UWB_INITIATION_TIME) == 1);
376         }
377         if (isPresent(configParamsTlv, CHANNEL)) {
378             configParamsBuilder.setChannel(configParamsTlv.getByte(CHANNEL).intValue());
379         }
380         if (isPresent(configParamsTlv, RFRAME_CONFIG)) {
381             configParamsBuilder.setRframeConfig(configParamsTlv.getByte(RFRAME_CONFIG).intValue());
382         }
383         if (isPresent(configParamsTlv, CC_CONSTRAINT_LENGTH)) {
384             configParamsBuilder.setCcConstraintLength(
385                     configParamsTlv.getByte(CC_CONSTRAINT_LENGTH).intValue());
386         }
387         if (isPresent(configParamsTlv, PRF_MODE)) {
388             configParamsBuilder.setPrfMode(configParamsTlv.getByte(PRF_MODE).intValue());
389         }
390         if (isPresent(configParamsTlv, SP0_PHY_SET)) {
391             configParamsBuilder.setSp0PhyParameterSet(
392                     configParamsTlv.getByte(SP0_PHY_SET).intValue());
393         }
394         if (isPresent(configParamsTlv, SP1_PHY_SET)) {
395             configParamsBuilder.setSp1PhyParameterSet(
396                     configParamsTlv.getByte(SP1_PHY_SET).intValue());
397         }
398         if (isPresent(configParamsTlv, SP3_PHY_SET)) {
399             configParamsBuilder.setSp3PhyParameterSet(
400                     configParamsTlv.getByte(SP3_PHY_SET).intValue());
401         }
402         if (isPresent(configParamsTlv, PREAMBLE_CODE_INDEX)) {
403             configParamsBuilder.setPreambleCodeIndex(
404                     configParamsTlv.getByte(PREAMBLE_CODE_INDEX).intValue());
405         }
406         if (isPresent(configParamsTlv, PREAMBLE_CODE_INDEX)) {
407             configParamsBuilder.setPreambleCodeIndex(
408                     configParamsTlv.getByte(PREAMBLE_CODE_INDEX).intValue());
409         }
410         if (isPresent(configParamsTlv, RESULT_REPORT_CONFIG)) {
411             EnumSet<FiraParams.AoaCapabilityFlag> aoaSupport = EnumSet.noneOf(
412                     FiraParams.AoaCapabilityFlag.class);
413             byte aoaSupportRaw = configParamsTlv.getByte(RESULT_REPORT_CONFIG);
414             if (isBitSet(aoaSupportRaw, AOA_AZIMUTH_90)) {
415                 aoaSupport.add(FiraParams.AoaCapabilityFlag.HAS_AZIMUTH_SUPPORT);
416             }
417             if (isBitSet(aoaSupportRaw, AOA_AZIMUTH_180)) {
418                 aoaSupport.add(FiraParams.AoaCapabilityFlag.HAS_FULL_AZIMUTH_SUPPORT);
419             }
420             if (isBitSet(aoaSupportRaw, AOA_ELEVATION)) {
421                 aoaSupport.add(FiraParams.AoaCapabilityFlag.HAS_ELEVATION_SUPPORT);
422             }
423             if (isBitSet(aoaSupportRaw, AOA_FOM)) {
424                 aoaSupport.add(FiraParams.AoaCapabilityFlag.HAS_FOM_SUPPORT);
425             }
426             configParamsBuilder.setResultReportConfig(aoaSupport);
427         }
428         if (isPresent(configParamsTlv, MAC_ADDRESS_MODE)) {
429             configParamsBuilder.setMacAddressMode(
430                     configParamsTlv.getByte(MAC_ADDRESS_MODE).intValue());
431         }
432         if (isPresent(configParamsTlv, CONTROLEE_SHORT_MAC_ADDRESS)) {
433             UwbAddress controleeAddress = UwbAddress.fromBytes(
434                     configParamsTlv.getByteArray(CONTROLEE_SHORT_MAC_ADDRESS));
435             configParamsBuilder.setControleeShortMacAddress(controleeAddress);
436         }
437         if (isPresent(configParamsTlv, CONTROLLER_MAC_ADDRESS)) {
438             UwbAddress controllerAddress = UwbAddress.fromBytes(
439                     configParamsTlv.getByteArray(CONTROLLER_MAC_ADDRESS));
440             configParamsBuilder.setControllerMacAddress(controllerAddress);
441         }
442         if (isPresent(configParamsTlv, SLOTS_PER_RR)) {
443             configParamsBuilder.setSlotsPerRangingRound(
444                     configParamsTlv.getByte(SLOTS_PER_RR).intValue());
445         }
446         if (isPresent(configParamsTlv, MAX_CONTENTION_PHASE_LENGTH)) {
447             configParamsBuilder.setMaxContentionPhaseLength(
448                     configParamsTlv.getByte(MAX_CONTENTION_PHASE_LENGTH).intValue());
449         }
450         if (isPresent(configParamsTlv, SLOT_DURATION)) {
451             configParamsBuilder.setSlotDuration(
452                     ByteBuffer.wrap(configParamsTlv.getByteArray(SLOT_DURATION)).getInt());
453         }
454         if (isPresent(configParamsTlv, RANGING_INTERVAL)) {
455             configParamsBuilder.setRangingIntervalMs(
456                     ByteBuffer.wrap(
457                             configParamsTlv.getByteArray(RANGING_INTERVAL)).getInt());
458         }
459         if (isPresent(configParamsTlv, KEY_ROTATION_RATE)) {
460             configParamsBuilder.setKeyRotationRate(
461                     configParamsTlv.getByte(KEY_ROTATION_RATE).intValue());
462         }
463         if (isPresent(configParamsTlv, MAC_FCS_TYPE)) {
464             configParamsBuilder.setMaxContentionPhaseLength(
465                     configParamsTlv.getByte(MAC_FCS_TYPE).intValue());
466         }
467         if (isPresent(configParamsTlv, MAX_RR_RETRY)) {
468             configParamsBuilder.setMaxRangingRoundRetry(
469                     ByteBuffer.wrap(configParamsTlv.getByteArray(MAX_RR_RETRY)).getInt());
470         }
471         return configParamsBuilder.build();
472     }
473 
474     /** Builder for CONFIGURATION_PARAMS */
475     static class Builder {
476         // Set all default protocol version to FiRa 1.1
477         private FiraProtocolVersion mPhyVersion = new FiraProtocolVersion(1, 1);
478         private FiraProtocolVersion mMacVersion = new FiraProtocolVersion(1, 1);
479         private Optional<Integer> mDeviceRole =
480                 Optional.empty();
481         private Optional<Integer> mRangingMethod =
482                 Optional.empty();
483         private Optional<Integer> mStsConfig = Optional.empty();
484         private Optional<Integer> mMultiNodeMode =
485                 Optional.empty();
486         private Optional<Byte> mRangingTimeStruct = Optional.empty();
487         private Optional<Integer> mScheduleMode = Optional.empty();
488         private Optional<Boolean> mHoppingMode = Optional.empty();
489         private Optional<Boolean> mBlockStriding = Optional.empty();
490         private Optional<Boolean> mUwbInitiationTime = Optional.empty();
491         private Optional<Integer> mChannel = Optional.empty();
492         private Optional<Integer> mRframeConfig = Optional.empty();
493         private Optional<Integer> mCcConstraintLength =
494                 Optional.empty();
495         private Optional<Integer> mPrfMode = Optional.empty();
496         private Optional<Integer> mSp0PhyParameterSet = Optional.empty();
497         private Optional<Integer> mSp1PhyParameterSet = Optional.empty();
498         private Optional<Integer> mSp3PhyParameterSet = Optional.empty();
499         private Optional<Integer> mPreambleCodeIndex = Optional.empty();
500         private Optional<EnumSet<FiraParams.AoaCapabilityFlag>> mResultReportConfig =
501                 Optional.empty();
502         private Optional<Integer> mMacAddressMode = Optional.empty();
503         private Optional<UwbAddress> mControleeShortMacAddress = Optional.empty();
504         private Optional<UwbAddress> mControllerMacAddress = Optional.empty();
505         private Optional<Integer> mSlotsPerRangingRound = Optional.empty();
506         private Optional<Integer> mMaxContentionPhaseLength = Optional.empty();
507         private Optional<Integer> mSlotDuration = Optional.empty();
508         private Optional<Integer> mRangingIntervalMs = Optional.empty();
509         private Optional<Integer> mKeyRotationRate = Optional.empty();
510         private Optional<Integer> mMacFcsType = Optional.empty();
511         private Optional<Integer> mMaxRangingRoundRetry = Optional.empty();
512 
setPhyVersion( FiraProtocolVersion phyVersion)513         ConfigurationParams.Builder setPhyVersion(
514                 FiraProtocolVersion phyVersion) {
515             mPhyVersion = phyVersion;
516             return this;
517         }
518 
setMacVersion( FiraProtocolVersion macVersion)519         ConfigurationParams.Builder setMacVersion(
520                 FiraProtocolVersion macVersion) {
521             mMacVersion = macVersion;
522             return this;
523         }
524 
setDeviceRole( int deviceRole)525         ConfigurationParams.Builder setDeviceRole(
526                 int deviceRole) {
527             mDeviceRole = Optional.of(deviceRole);
528             return this;
529         }
530 
setRangingMethod( @iraParams.RangingRoundUsage int rangingMethod)531         ConfigurationParams.Builder setRangingMethod(
532                 @FiraParams.RangingRoundUsage int rangingMethod) {
533             mRangingMethod = Optional.of(rangingMethod);
534             return this;
535         }
536 
setStsConfig(@iraParams.StsConfig int stsConfig)537         ConfigurationParams.Builder setStsConfig(@FiraParams.StsConfig int stsConfig) {
538             mStsConfig = Optional.of(stsConfig);
539             return this;
540         }
541 
setMultiNodeMode( @iraParams.MultiNodeMode int multiNodeMode)542         ConfigurationParams.Builder setMultiNodeMode(
543                 @FiraParams.MultiNodeMode int multiNodeMode) {
544             mMultiNodeMode = Optional.of(multiNodeMode);
545             return this;
546         }
547 
setRangingTimeStruct(Byte rangingTimeStruct)548         ConfigurationParams.Builder setRangingTimeStruct(Byte rangingTimeStruct) {
549             mRangingTimeStruct = Optional.of(rangingTimeStruct);
550             return this;
551         }
552 
setScheduleMode(@iraParams.SchedulingMode int scheduleMode)553         ConfigurationParams.Builder setScheduleMode(@FiraParams.SchedulingMode int scheduleMode) {
554             mScheduleMode = Optional.of(scheduleMode);
555             return this;
556         }
557 
setHoppingMode(Boolean hoppingMode)558         ConfigurationParams.Builder setHoppingMode(Boolean hoppingMode) {
559             mHoppingMode = Optional.of(hoppingMode);
560             return this;
561         }
562 
setBlockStriding(Boolean blockStriding)563         ConfigurationParams.Builder setBlockStriding(Boolean blockStriding) {
564             mBlockStriding = Optional.of(blockStriding);
565             return this;
566         }
567 
setUwbInitiationTime( Boolean uwbInitiationTime)568         ConfigurationParams.Builder setUwbInitiationTime(
569                 Boolean uwbInitiationTime) {
570             mUwbInitiationTime = Optional.of(uwbInitiationTime);
571             return this;
572         }
573 
setChannel(Integer channel)574         ConfigurationParams.Builder setChannel(Integer channel) {
575             mChannel = Optional.of(channel);
576             return this;
577         }
578 
setRframeConfig( @iraParams.RframeConfig int rframeConfig)579         ConfigurationParams.Builder setRframeConfig(
580                  @FiraParams.RframeConfig int rframeConfig) {
581             mRframeConfig = Optional.of(rframeConfig);
582             return this;
583         }
584 
setCcConstraintLength( @iraParams.CcConstraintLength int ccConstraintLength)585         ConfigurationParams.Builder setCcConstraintLength(
586                 @FiraParams.CcConstraintLength int ccConstraintLength) {
587             mCcConstraintLength = Optional.of(ccConstraintLength);
588             return this;
589         }
590 
setPrfMode(Integer prfMode)591         ConfigurationParams.Builder setPrfMode(Integer prfMode) {
592             mPrfMode = Optional.of(prfMode);
593             return this;
594         }
595 
setSp0PhyParameterSet( Integer sp0PhyParameterSet)596         ConfigurationParams.Builder setSp0PhyParameterSet(
597                 Integer sp0PhyParameterSet) {
598             mSp0PhyParameterSet = Optional.of(sp0PhyParameterSet);
599             return this;
600         }
601 
setSp1PhyParameterSet( Integer sp1PhyParameterSet)602         ConfigurationParams.Builder setSp1PhyParameterSet(
603                 Integer sp1PhyParameterSet) {
604             mSp1PhyParameterSet = Optional.of(sp1PhyParameterSet);
605             return this;
606         }
607 
setSp3PhyParameterSet( Integer sp3PhyParameterSet)608         ConfigurationParams.Builder setSp3PhyParameterSet(
609                 Integer sp3PhyParameterSet) {
610             mSp3PhyParameterSet = Optional.of(sp3PhyParameterSet);
611             return this;
612         }
613 
setPreambleCodeIndex( Integer preambleCodeIndex)614         ConfigurationParams.Builder setPreambleCodeIndex(
615                 Integer preambleCodeIndex) {
616             mPreambleCodeIndex = Optional.of(preambleCodeIndex);
617             return this;
618         }
619 
setResultReportConfig( EnumSet<FiraParams.AoaCapabilityFlag> resultReportConfig)620         ConfigurationParams.Builder setResultReportConfig(
621                 EnumSet<FiraParams.AoaCapabilityFlag> resultReportConfig) {
622             mResultReportConfig = Optional.of(resultReportConfig);
623             return this;
624         }
625 
setMacAddressMode( Integer macAddressMode)626         ConfigurationParams.Builder setMacAddressMode(
627                 Integer macAddressMode) {
628             mMacAddressMode = Optional.of(macAddressMode);
629             return this;
630         }
631 
setControleeShortMacAddress( UwbAddress controleeShortMacAddress)632         ConfigurationParams.Builder setControleeShortMacAddress(
633                 UwbAddress controleeShortMacAddress) {
634             mControleeShortMacAddress = Optional.of(controleeShortMacAddress);
635             return this;
636         }
637 
setControllerMacAddress( UwbAddress controllerMacAddress)638         ConfigurationParams.Builder setControllerMacAddress(
639                 UwbAddress controllerMacAddress) {
640             mControllerMacAddress = Optional.of(controllerMacAddress);
641             return this;
642         }
643 
setSlotsPerRangingRound( Integer slotsPerRangingRound)644         ConfigurationParams.Builder setSlotsPerRangingRound(
645                 Integer slotsPerRangingRound) {
646             mSlotsPerRangingRound = Optional.of(slotsPerRangingRound);
647             return this;
648         }
649 
setMaxContentionPhaseLength( Integer maxContentionPhaseLength)650         ConfigurationParams.Builder setMaxContentionPhaseLength(
651                 Integer maxContentionPhaseLength) {
652             mMaxContentionPhaseLength = Optional.of((maxContentionPhaseLength));
653             return this;
654         }
655 
setSlotDuration(Integer slotDuration)656         ConfigurationParams.Builder setSlotDuration(Integer slotDuration) {
657             mSlotDuration = Optional.of(slotDuration);
658             return this;
659         }
660 
setRangingIntervalMs( Integer rangingIntervalMs)661         ConfigurationParams.Builder setRangingIntervalMs(
662                 Integer rangingIntervalMs) {
663             mRangingIntervalMs = Optional.of(rangingIntervalMs);
664             return this;
665         }
666 
setKeyRotationRate(Integer keyRotationRate)667         ConfigurationParams.Builder setKeyRotationRate(Integer keyRotationRate) {
668             mKeyRotationRate = Optional.of(keyRotationRate);
669             return this;
670         }
671 
setMacFcsType(Integer macFcsType)672         ConfigurationParams.Builder setMacFcsType(Integer macFcsType) {
673             mMacFcsType = Optional.of(macFcsType);
674             return this;
675         }
676 
setMaxRangingRoundRetry( Integer maxRangingRoundRetry)677         ConfigurationParams.Builder setMaxRangingRoundRetry(
678                 Integer maxRangingRoundRetry) {
679             mMaxRangingRoundRetry = Optional.of(maxRangingRoundRetry);
680             return this;
681         }
682 
build()683         ConfigurationParams build() {
684             return new ConfigurationParams(
685                     mPhyVersion,
686                     mMacVersion,
687                     mDeviceRole,
688                     mRangingMethod,
689                     mStsConfig,
690                     mMultiNodeMode,
691                     mRangingTimeStruct,
692                     mScheduleMode,
693                     mHoppingMode,
694                     mBlockStriding,
695                     mUwbInitiationTime,
696                     mChannel,
697                     mRframeConfig,
698                     mCcConstraintLength,
699                     mPrfMode,
700                     mSp0PhyParameterSet,
701                     mSp1PhyParameterSet,
702                     mSp3PhyParameterSet,
703                     mPreambleCodeIndex,
704                     mResultReportConfig,
705                     mMacAddressMode,
706                     mControleeShortMacAddress,
707                     mControllerMacAddress,
708                     mSlotsPerRangingRound,
709                     mMaxContentionPhaseLength,
710                     mSlotDuration,
711                     mRangingIntervalMs,
712                     mKeyRotationRate,
713                     mMacFcsType,
714                     mMaxRangingRoundRetry
715             );
716         }
717     }
718 }
719