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 androidx.core.uwb.backend.impl.internal;
18 
19 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_DL_TDOA_DT_TAG;
20 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_MULTICAST_DS_TWR;
21 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_MULTICAST_DS_TWR_NO_AOA;
22 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR;
23 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_MULTICAST_DS_TWR;
24 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_UNICAST_DS_TWR;
25 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_AOA;
26 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_UNICAST_DS_TWR;
27 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_UNICAST_DS_TWR_NO_AOA;
28 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE;
29 import static androidx.core.uwb.backend.impl.internal.Utils.CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE_HPRF;
30 import static androidx.core.uwb.backend.impl.internal.Utils.STATIC_STS_SESSION_KEY_INFO_SIZE;
31 import static androidx.core.uwb.backend.impl.internal.Utils.VENDOR_ID_SIZE;
32 import static androidx.core.uwb.backend.impl.internal.Utils.getRangingTimingParams;
33 
34 import static com.google.uwb.support.fira.FiraParams.AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT;
35 import static com.google.uwb.support.fira.FiraParams.FILTER_TYPE_NONE;
36 import static com.google.uwb.support.fira.FiraParams.HOPPING_MODE_FIRA_HOPPING_ENABLE;
37 import static com.google.uwb.support.fira.FiraParams.MAC_ADDRESS_MODE_2_BYTES;
38 import static com.google.uwb.support.fira.FiraParams.MULTI_NODE_MODE_ONE_TO_MANY;
39 import static com.google.uwb.support.fira.FiraParams.MULTI_NODE_MODE_UNICAST;
40 import static com.google.uwb.support.fira.FiraParams.PRF_MODE_HPRF;
41 import static com.google.uwb.support.fira.FiraParams.PROTOCOL_VERSION_1_1;
42 import static com.google.uwb.support.fira.FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG;
43 import static com.google.uwb.support.fira.FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG;
44 import static com.google.uwb.support.fira.FiraParams.RANGING_DEVICE_DT_TAG;
45 import static com.google.uwb.support.fira.FiraParams.RANGING_DEVICE_ROLE_INITIATOR;
46 import static com.google.uwb.support.fira.FiraParams.RANGING_DEVICE_ROLE_RESPONDER;
47 import static com.google.uwb.support.fira.FiraParams.RANGING_DEVICE_TYPE_CONTROLEE;
48 import static com.google.uwb.support.fira.FiraParams.RANGING_DEVICE_TYPE_CONTROLLER;
49 import static com.google.uwb.support.fira.FiraParams.RANGING_DEVICE_TYPE_DT_TAG;
50 import static com.google.uwb.support.fira.FiraParams.RANGING_ROUND_USAGE_DL_TDOA;
51 import static com.google.uwb.support.fira.FiraParams.RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
52 import static com.google.uwb.support.fira.FiraParams.RFRAME_CONFIG_SP1;
53 import static com.google.uwb.support.fira.FiraParams.STS_CONFIG_PROVISIONED;
54 import static com.google.uwb.support.fira.FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY;
55 
56 import android.util.ArrayMap;
57 
58 import androidx.annotation.Nullable;
59 
60 import com.google.uwb.support.fira.FiraControleeParams;
61 import com.google.uwb.support.fira.FiraOpenSessionParams;
62 import com.google.uwb.support.fira.FiraParams;
63 import com.google.uwb.support.fira.FiraRangingReconfigureParams;
64 
65 import java.util.Arrays;
66 import java.util.Map;
67 
68 /**
69  * Creates the session-opening bundles for a FiRa session. The default parameters are
70  * profile-dependent.
71  */
72 public final class ConfigurationManager {
73 
74     private static final Map<Integer, UwbConfiguration> sConfigs = new ArrayMap<>();
75 
76     static {
77         // ID_1 properties.
sConfigs.put( CONFIG_UNICAST_DS_TWR, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_UNICAST_DS_TWR; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_UNICAST; } @Override public int getStsConfig() { return FiraParams.STS_CONFIG_STATIC; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })78         sConfigs.put(
79                 CONFIG_UNICAST_DS_TWR,
80                 new UwbConfiguration() {
81 
82                     @Override
83                     public int getConfigId() {
84                         return CONFIG_UNICAST_DS_TWR;
85                     }
86 
87                     @Override
88                     public int getMultiNodeMode() {
89                         return MULTI_NODE_MODE_UNICAST;
90                     }
91 
92                     @Override
93                     public int getStsConfig() {
94                         return FiraParams.STS_CONFIG_STATIC;
95                     }
96 
97                     @Override
98                     public int getAoaResultRequestMode() {
99                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
100                     }
101 
102                     @Override
103                     public boolean isControllerTheInitiator() {
104                         return true;
105                     }
106 
107                     @Override
108                     public int getRangingRoundUsage() {
109                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
110                     }
111                 });
112 
113         // ID_2 properties.
sConfigs.put( CONFIG_MULTICAST_DS_TWR, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_MULTICAST_DS_TWR; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_ONE_TO_MANY; } @Override public int getStsConfig() { return FiraParams.STS_CONFIG_STATIC; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })114         sConfigs.put(
115                 CONFIG_MULTICAST_DS_TWR,
116                 new UwbConfiguration() {
117 
118                     @Override
119                     public int getConfigId() {
120                         return CONFIG_MULTICAST_DS_TWR;
121                     }
122 
123                     @Override
124                     public int getMultiNodeMode() {
125                         return MULTI_NODE_MODE_ONE_TO_MANY;
126                     }
127 
128                     @Override
129                     public int getStsConfig() {
130                         return FiraParams.STS_CONFIG_STATIC;
131                     }
132 
133                     @Override
134                     public int getAoaResultRequestMode() {
135                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
136                     }
137 
138                     @Override
139                     public boolean isControllerTheInitiator() {
140                         return true;
141                     }
142 
143                     @Override
144                     public int getRangingRoundUsage() {
145                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
146                     }
147                 });
148 
149         // ID_3 properties.
sConfigs.put( CONFIG_UNICAST_DS_TWR_NO_AOA, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_UNICAST_DS_TWR_NO_AOA; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_UNICAST; } @Override public int getStsConfig() { return FiraParams.STS_CONFIG_STATIC; } @Override public int getAoaResultRequestMode() { return AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })150         sConfigs.put(
151                 CONFIG_UNICAST_DS_TWR_NO_AOA,
152                 new UwbConfiguration() {
153 
154                     @Override
155                     public int getConfigId() {
156                         return CONFIG_UNICAST_DS_TWR_NO_AOA;
157                     }
158 
159                     @Override
160                     public int getMultiNodeMode() {
161                         return MULTI_NODE_MODE_UNICAST;
162                     }
163 
164                     @Override
165                     public int getStsConfig() {
166                         return FiraParams.STS_CONFIG_STATIC;
167                     }
168 
169                     @Override
170                     public int getAoaResultRequestMode() {
171                         return AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT;
172                     }
173 
174                     @Override
175                     public boolean isControllerTheInitiator() {
176                         return true;
177                     }
178 
179                     @Override
180                     public int getRangingRoundUsage() {
181                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
182                     }
183                 });
184 
185         // ID_4 properties.
sConfigs.put( CONFIG_PROVISIONED_UNICAST_DS_TWR, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_PROVISIONED_UNICAST_DS_TWR; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_UNICAST; } @Override public int getStsConfig() { return STS_CONFIG_PROVISIONED; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })186         sConfigs.put(
187                 CONFIG_PROVISIONED_UNICAST_DS_TWR,
188                 new UwbConfiguration() {
189 
190                     @Override
191                     public int getConfigId() {
192                         return CONFIG_PROVISIONED_UNICAST_DS_TWR;
193                     }
194 
195                     @Override
196                     public int getMultiNodeMode() {
197                         return MULTI_NODE_MODE_UNICAST;
198                     }
199 
200                     @Override
201                     public int getStsConfig() {
202                         return STS_CONFIG_PROVISIONED;
203                     }
204 
205                     @Override
206                     public int getAoaResultRequestMode() {
207                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
208                     }
209 
210                     @Override
211                     public boolean isControllerTheInitiator() {
212                         return true;
213                     }
214 
215                     @Override
216                     public int getRangingRoundUsage() {
217                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
218                     }
219                 });
220 
221         // ID_5 properties.
sConfigs.put( CONFIG_PROVISIONED_MULTICAST_DS_TWR, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_PROVISIONED_MULTICAST_DS_TWR; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_ONE_TO_MANY; } @Override public int getStsConfig() { return STS_CONFIG_PROVISIONED; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })222         sConfigs.put(
223                 CONFIG_PROVISIONED_MULTICAST_DS_TWR,
224                 new UwbConfiguration() {
225 
226                     @Override
227                     public int getConfigId() {
228                         return CONFIG_PROVISIONED_MULTICAST_DS_TWR;
229                     }
230 
231                     @Override
232                     public int getMultiNodeMode() {
233                         return MULTI_NODE_MODE_ONE_TO_MANY;
234                     }
235 
236                     @Override
237                     public int getStsConfig() {
238                         return STS_CONFIG_PROVISIONED;
239                     }
240 
241                     @Override
242                     public int getAoaResultRequestMode() {
243                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
244                     }
245 
246                     @Override
247                     public boolean isControllerTheInitiator() {
248                         return true;
249                     }
250 
251                     @Override
252                     public int getRangingRoundUsage() {
253                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
254                     }
255                 });
256 
257         // ID_6 properties.
sConfigs.put( CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_AOA, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_AOA; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_UNICAST; } @Override public int getStsConfig() { return STS_CONFIG_PROVISIONED; } @Override public int getAoaResultRequestMode() { return AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })258         sConfigs.put(
259                 CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_AOA,
260                 new UwbConfiguration() {
261                     @Override
262                     public int getConfigId() {
263                         return CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_AOA;
264                     }
265 
266                     @Override
267                     public int getMultiNodeMode() {
268                         return MULTI_NODE_MODE_UNICAST;
269                     }
270 
271                     @Override
272                     public int getStsConfig() {
273                         return STS_CONFIG_PROVISIONED;
274                     }
275 
276                     @Override
277                     public int getAoaResultRequestMode() {
278                         return AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT;
279                     }
280 
281                     @Override
282                     public boolean isControllerTheInitiator() {
283                         return true;
284                     }
285 
286                     @Override
287                     public int getRangingRoundUsage() {
288                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
289                     }
290                 });
291 
292         // ID_7 properties.
sConfigs.put( CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_ONE_TO_MANY; } @Override public int getStsConfig() { return FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })293         sConfigs.put(
294                 CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR,
295                 new UwbConfiguration() {
296 
297                     @Override
298                     public int getConfigId() {
299                         return CONFIG_PROVISIONED_INDIVIDUAL_MULTICAST_DS_TWR;
300                     }
301 
302                     @Override
303                     public int getMultiNodeMode() {
304                         return MULTI_NODE_MODE_ONE_TO_MANY;
305                     }
306 
307                     @Override
308                     public int getStsConfig() {
309                         return FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY;
310                     }
311 
312                     @Override
313                     public int getAoaResultRequestMode() {
314                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
315                     }
316 
317                     @Override
318                     public boolean isControllerTheInitiator() {
319                         return true;
320                     }
321 
322                     @Override
323                     public int getRangingRoundUsage() {
324                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
325                     }
326                 });
327 
328         // ID_1001 properties.
sConfigs.put( CONFIG_DL_TDOA_DT_TAG, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_DL_TDOA_DT_TAG; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_ONE_TO_MANY; } @Override public int getStsConfig() { return FiraParams.STS_CONFIG_STATIC; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DL_TDOA; } })329         sConfigs.put(
330                 CONFIG_DL_TDOA_DT_TAG,
331                 new UwbConfiguration() {
332 
333                     @Override
334                     public int getConfigId() {
335                         return CONFIG_DL_TDOA_DT_TAG;
336                     }
337 
338                     @Override
339                     public int getMultiNodeMode() {
340                         return MULTI_NODE_MODE_ONE_TO_MANY;
341                     }
342 
343                     @Override
344                     public int getStsConfig() {
345                         return FiraParams.STS_CONFIG_STATIC;
346                     }
347 
348                     @Override
349                     public int getAoaResultRequestMode() {
350                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
351                     }
352 
353                     @Override
354                     public boolean isControllerTheInitiator() {
355                         return true;
356                     }
357 
358                     @Override
359                     public int getRangingRoundUsage() {
360                         return RANGING_ROUND_USAGE_DL_TDOA;
361                     }
362                 });
363 
364         // ID_1000 properties.
sConfigs.put( CONFIG_MULTICAST_DS_TWR_NO_AOA, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_UNICAST_DS_TWR_NO_AOA; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_ONE_TO_MANY; } @Override public int getStsConfig() { return FiraParams.STS_CONFIG_STATIC; } @Override public int getAoaResultRequestMode() { return AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })365         sConfigs.put(
366                 CONFIG_MULTICAST_DS_TWR_NO_AOA,
367                 new UwbConfiguration() {
368 
369                     @Override
370                     public int getConfigId() {
371                         return CONFIG_UNICAST_DS_TWR_NO_AOA;
372                     }
373 
374                     @Override
375                     public int getMultiNodeMode() {
376                         return MULTI_NODE_MODE_ONE_TO_MANY;
377                     }
378 
379                     @Override
380                     public int getStsConfig() {
381                         return FiraParams.STS_CONFIG_STATIC;
382                     }
383 
384                     @Override
385                     public int getAoaResultRequestMode() {
386                         return AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT;
387                     }
388 
389                     @Override
390                     public boolean isControllerTheInitiator() {
391                         return true;
392                     }
393 
394                     @Override
395                     public int getRangingRoundUsage() {
396                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
397                     }
398                 });
399 
400         // ID_1002 properties.
sConfigs.put( CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_UNICAST; } @Override public int getStsConfig() { return STS_CONFIG_PROVISIONED; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })401         sConfigs.put(
402                 CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE,
403                 new UwbConfiguration() {
404 
405                     @Override
406                     public int getConfigId() {
407                         return CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE;
408                     }
409 
410                     @Override
411                     public int getMultiNodeMode() {
412                         return MULTI_NODE_MODE_UNICAST;
413                     }
414 
415                     @Override
416                     public int getStsConfig() {
417                         return STS_CONFIG_PROVISIONED;
418                     }
419 
420                     @Override
421                     public int getAoaResultRequestMode() {
422                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
423                     }
424 
425                     @Override
426                     public boolean isControllerTheInitiator() {
427                         return true;
428                     }
429 
430                     @Override
431                     public int getRangingRoundUsage() {
432                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
433                     }
434                 });
435 
436         // ID_1003 properties.
sConfigs.put( CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE_HPRF, new UwbConfiguration() { @Override public int getConfigId() { return CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE_HPRF; } @Override public int getMultiNodeMode() { return MULTI_NODE_MODE_UNICAST; } @Override public int getStsConfig() { return STS_CONFIG_PROVISIONED; } @Override public int getAoaResultRequestMode() { return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS; } @Override public boolean isControllerTheInitiator() { return true; } @Override public int getRangingRoundUsage() { return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE; } })437         sConfigs.put(
438                 CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE_HPRF,
439                 new UwbConfiguration() {
440 
441                     @Override
442                     public int getConfigId() {
443                         return CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE_HPRF;
444                     }
445 
446                     @Override
447                     public int getMultiNodeMode() {
448                         return MULTI_NODE_MODE_UNICAST;
449                     }
450 
451                     @Override
452                     public int getStsConfig() {
453                         return STS_CONFIG_PROVISIONED;
454                     }
455 
456                     @Override
457                     public int getAoaResultRequestMode() {
458                         return FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS;
459                     }
460 
461                     @Override
462                     public boolean isControllerTheInitiator() {
463                         return true;
464                     }
465 
466                     @Override
467                     public int getRangingRoundUsage() {
468                         return RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE;
469                     }
470                 });
471     }
472 
ConfigurationManager()473     private ConfigurationManager() {
474     }
475 
476     /** Creates a {@link FiraOpenSessionParams}. */
createOpenSessionParams( @iraParams.RangingDeviceType int deviceType, UwbAddress localAddress, RangingParameters rangingParameters, UwbFeatureFlags featureFlags)477     public static FiraOpenSessionParams createOpenSessionParams(
478             @FiraParams.RangingDeviceType int deviceType,
479             UwbAddress localAddress,
480             RangingParameters rangingParameters,
481             UwbFeatureFlags featureFlags) {
482         RangingTimingParams timingParams =
483                 getRangingTimingParams(rangingParameters.getUwbConfigId());
484         UwbConfiguration configuration = sConfigs.get(rangingParameters.getUwbConfigId());
485         int deviceRole;
486         switch (deviceType) {
487             case RANGING_DEVICE_TYPE_CONTROLLER:
488                 deviceRole =
489                         configuration.isControllerTheInitiator()
490                                 ? RANGING_DEVICE_ROLE_INITIATOR
491                                 : RANGING_DEVICE_ROLE_RESPONDER;
492                 break;
493             case RANGING_DEVICE_TYPE_CONTROLEE:
494                 deviceRole =
495                         configuration.isControllerTheInitiator()
496                                 ? RANGING_DEVICE_ROLE_RESPONDER
497                                 : RANGING_DEVICE_ROLE_INITIATOR;
498                 break;
499             case RANGING_DEVICE_TYPE_DT_TAG:
500                 deviceRole = RANGING_DEVICE_DT_TAG;
501                 break;
502             default:
503                 deviceRole = RANGING_DEVICE_ROLE_RESPONDER;
504                 break;
505         }
506 
507         // Remove this when we add support for ranging device type Dt-TAG.
508         if (configuration.getConfigId() == CONFIG_DL_TDOA_DT_TAG) {
509             deviceRole = RANGING_DEVICE_DT_TAG;
510         }
511 
512         FiraOpenSessionParams.Builder builder =
513                 new FiraOpenSessionParams.Builder()
514                         .setProtocolVersion(PROTOCOL_VERSION_1_1)
515                         .setRangingRoundUsage(configuration.getRangingRoundUsage())
516                         .setMultiNodeMode(configuration.getMultiNodeMode())
517                         .setMacAddressMode(MAC_ADDRESS_MODE_2_BYTES)
518                         .setDeviceType(deviceType)
519                         .setDeviceRole(deviceRole)
520                         .setSessionId(rangingParameters.getSessionId())
521                         .setDeviceAddress(Conversions.convertUwbAddress(localAddress,
522                                 featureFlags.isReversedByteOrderFiraParams()))
523                         .setAoaResultRequest(rangingParameters.isAoaDisabled()
524                                 ? AOA_RESULT_REQUEST_MODE_NO_AOA_REPORT :
525                                 configuration.getAoaResultRequestMode())
526                         .setChannelNumber(rangingParameters.getComplexChannel().getChannel())
527                         .setPreambleCodeIndex(
528                                 rangingParameters.getComplexChannel().getPreambleIndex())
529                         .setInitiationTime(timingParams.getInitiationTimeMs())
530                         .setSlotDurationRstu(
531                                 Utils.convertMsToRstu(rangingParameters.getSlotDuration()))
532                         .setSlotsPerRangingRound(timingParams.getSlotPerRangingRound())
533                         .setRangingIntervalMs(
534                                 timingParams.getRangingInterval(
535                                         rangingParameters.getRangingUpdateRate()))
536                         .setRangeDataNtfConfig(
537                                 Utils.convertToFiraNtfConfig(
538                                         rangingParameters
539                                                 .getUwbRangeDataNtfConfig()
540                                                 .getRangeDataNtfConfigType()))
541                         .setRangeDataNtfProximityNear(
542                                 rangingParameters.getUwbRangeDataNtfConfig().getNtfProximityNear())
543                         .setRangeDataNtfProximityFar(
544                                 rangingParameters.getUwbRangeDataNtfConfig().getNtfProximityFar())
545                         .setInBandTerminationAttemptCount(3)
546                         .setStsConfig(configuration.getStsConfig())
547                         .setRangingErrorStreakTimeoutMs(10_000L);
548 
549         if (configuration.getStsConfig() == FiraParams.STS_CONFIG_STATIC) {
550             byte[] staticStsIv =
551                     Arrays.copyOfRange(
552                             rangingParameters.getSessionKeyInfo(),
553                             VENDOR_ID_SIZE,
554                             STATIC_STS_SESSION_KEY_INFO_SIZE);
555             builder.setVendorId(
556                             featureFlags.isReversedByteOrderFiraParams()
557                                     ? Conversions.getReverseBytes(
558                                     Arrays.copyOf(rangingParameters.getSessionKeyInfo(),
559                                             VENDOR_ID_SIZE)) :
560                                     Arrays.copyOf(rangingParameters.getSessionKeyInfo(),
561                                             VENDOR_ID_SIZE))
562                     .setStaticStsIV(staticStsIv);
563         } else if (configuration.getStsConfig() == STS_CONFIG_PROVISIONED) {
564             builder.setSessionKey(rangingParameters.getSessionKeyInfo())
565                     .setIsKeyRotationEnabled(true)
566                     .setKeyRotationRate(0);
567         } else if (configuration.getStsConfig()
568                 == STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY) {
569             builder.setSessionKey(rangingParameters.getSessionKeyInfo())
570                     .setSubSessionId(rangingParameters.getSubSessionId())
571                     .setSubsessionKey(rangingParameters.getSubSessionKeyInfo());
572         }
573 
574         if (timingParams.isHoppingEnabled()) {
575             builder.setHoppingMode(HOPPING_MODE_FIRA_HOPPING_ENABLE);
576         }
577 
578         if (deviceRole != RANGING_DEVICE_DT_TAG) {
579             builder.setDestAddressList(Conversions.convertUwbAddressList(
580                     rangingParameters.getPeerAddresses().toArray(new UwbAddress[0]),
581                     featureFlags.isReversedByteOrderFiraParams()));
582         } else {
583             builder.setRframeConfig(RFRAME_CONFIG_SP1);
584         }
585 
586         if (configuration.getConfigId()
587                 == CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE_HPRF) {
588             builder.setPrfMode(PRF_MODE_HPRF);
589         }
590 
591         if (configuration.getConfigId() == CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE
592                 || configuration.getConfigId()
593                     == CONFIG_PROVISIONED_UNICAST_DS_TWR_NO_RESULT_REPORT_PHASE_HPRF) {
594             builder.setHasRangingResultReportMessage(false);
595             builder.setFilterType(FILTER_TYPE_NONE);
596         }
597 
598         return builder.build();
599     }
600 
601     /** Creates a {@link FiraRangingReconfigureParams}. */
createReconfigureParams( @tils.UwbConfigId int configId, @FiraParams.MulticastListUpdateAction int action, UwbAddress[] peerAddresses, @Nullable int[] subSessionIdList, @Nullable byte[] subSessionKey, UwbFeatureFlags uwbFeatureFlags)602     public static FiraRangingReconfigureParams createReconfigureParams(
603             @Utils.UwbConfigId int configId,
604             @FiraParams.MulticastListUpdateAction int action,
605             UwbAddress[] peerAddresses,
606             @Nullable int[] subSessionIdList,
607             @Nullable byte[] subSessionKey,
608             UwbFeatureFlags uwbFeatureFlags) {
609         UwbConfiguration configuration = sConfigs.get(configId);
610         FiraRangingReconfigureParams.Builder builder =
611                 new FiraRangingReconfigureParams.Builder()
612                         .setAction(action)
613                         .setAddressList(
614                                 Conversions.convertUwbAddressList(peerAddresses,
615                                                 uwbFeatureFlags.isReversedByteOrderFiraParams())
616                                         .toArray(new android.uwb.UwbAddress[0]));
617         if (configuration.getStsConfig()
618                 == FiraParams.STS_CONFIG_DYNAMIC_FOR_CONTROLEE_INDIVIDUAL_KEY) {
619             builder.setSubSessionIdList(subSessionIdList).setSubSessionKeyList(subSessionKey);
620         }
621         return builder.build();
622     }
623 
624     /** Creates a {@link FiraControleeParams}. */
createControleeParams( @tils.UwbConfigId int configId, @FiraParams.MulticastListUpdateAction int action, UwbAddress[] peerAddresses, @Nullable int[] subSessionIdList, @Nullable byte[] subSessionKey, UwbFeatureFlags uwbFeatureFlags)625     public static FiraControleeParams createControleeParams(
626             @Utils.UwbConfigId int configId,
627             @FiraParams.MulticastListUpdateAction int action,
628             UwbAddress[] peerAddresses,
629             @Nullable int[] subSessionIdList,
630             @Nullable byte[] subSessionKey,
631             UwbFeatureFlags uwbFeatureFlags) {
632         UwbConfiguration configuration = sConfigs.get(configId);
633         FiraControleeParams.Builder builder = new FiraControleeParams.Builder();
634         builder.setAction(action);
635         builder.setAddressList(
636                 Conversions.convertUwbAddressList(
637                                 peerAddresses, uwbFeatureFlags.isReversedByteOrderFiraParams())
638                         .toArray(new android.uwb.UwbAddress[0]));
639         if (configuration.getStsConfig()
640                 == FiraParams.STS_CONFIG_DYNAMIC_FOR_CONTROLEE_INDIVIDUAL_KEY) {
641             builder.setSubSessionIdList(subSessionIdList).setSubSessionKeyList(subSessionKey);
642         }
643         return builder.build();
644     }
645 
646     /** Creates a {@link FiraRangingReconfigureParams} with block striding set. */
createReconfigureParamsBlockStriding( int blockStridingLength)647     public static FiraRangingReconfigureParams createReconfigureParamsBlockStriding(
648             int blockStridingLength) {
649         return new FiraRangingReconfigureParams.Builder()
650                 .setBlockStrideLength(blockStridingLength)
651                 .build();
652     }
653 
654     /** Creates a {@link FiraRangingReconfigureParams} with range data notification configured. */
createReconfigureParamsRangeDataNtf( UwbRangeDataNtfConfig rangeDataNtfConfig)655     public static FiraRangingReconfigureParams createReconfigureParamsRangeDataNtf(
656             UwbRangeDataNtfConfig rangeDataNtfConfig) {
657         int configType = Utils.convertToFiraNtfConfig(
658                 rangeDataNtfConfig.getRangeDataNtfConfigType());
659         FiraRangingReconfigureParams.Builder builder =
660                 new FiraRangingReconfigureParams.Builder().setRangeDataNtfConfig(configType);
661 
662         if (configType == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG
663                 || configType == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG) {
664             builder
665                     .setRangeDataProximityNear(rangeDataNtfConfig.getNtfProximityNear())
666                     .setRangeDataProximityFar(rangeDataNtfConfig.getNtfProximityFar());
667         }
668         return builder.build();
669     }
670 
671     /** Indicates if the ID presents an unicast configuration. */
isUnicast(@tils.UwbConfigId int configId)672     public static boolean isUnicast(@Utils.UwbConfigId int configId) {
673         return sConfigs.get(configId).getMultiNodeMode() == MULTI_NODE_MODE_UNICAST;
674     }
675 }
676