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.android.server.uwb.params; 18 19 import static com.android.server.uwb.config.CapabilityParam.ADS_TWR; 20 import static com.android.server.uwb.config.CapabilityParam.ADVERTISER; 21 import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_180; 22 import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_90; 23 import static com.android.server.uwb.config.CapabilityParam.AOA_ELEVATION; 24 import static com.android.server.uwb.config.CapabilityParam.AOA_FOM; 25 import static com.android.server.uwb.config.CapabilityParam.AOA_RESULT_REQ_INTERLEAVING; 26 import static com.android.server.uwb.config.CapabilityParam.BLOCK_BASED_SCHEDULING; 27 import static com.android.server.uwb.config.CapabilityParam.BLOCK_STRIDING; 28 import static com.android.server.uwb.config.CapabilityParam.CC_CONSTRAINT_LENGTH_K3; 29 import static com.android.server.uwb.config.CapabilityParam.CC_CONSTRAINT_LENGTH_K7; 30 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_10; 31 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_12; 32 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_13; 33 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_14; 34 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_5; 35 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_6; 36 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_8; 37 import static com.android.server.uwb.config.CapabilityParam.CHANNEL_9; 38 import static com.android.server.uwb.config.CapabilityParam.CONSTRAINT_LENGTH_3; 39 import static com.android.server.uwb.config.CapabilityParam.CONSTRAINT_LENGTH_7; 40 import static com.android.server.uwb.config.CapabilityParam.CONTENTION_BASED_RANGING; 41 import static com.android.server.uwb.config.CapabilityParam.DIAGNOSTICS; 42 import static com.android.server.uwb.config.CapabilityParam.DS_TWR_DEFERRED; 43 import static com.android.server.uwb.config.CapabilityParam.DS_TWR_NON_DEFERRED; 44 import static com.android.server.uwb.config.CapabilityParam.DT_ANCHOR; 45 import static com.android.server.uwb.config.CapabilityParam.DT_TAG; 46 import static com.android.server.uwb.config.CapabilityParam.DYNAMIC_STS; 47 import static com.android.server.uwb.config.CapabilityParam.DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY; 48 import static com.android.server.uwb.config.CapabilityParam.ESS_TWR_NON_DEFERRED; 49 import static com.android.server.uwb.config.CapabilityParam.EXTENDED_MAC_ADDRESS; 50 import static com.android.server.uwb.config.CapabilityParam.HOPPING_MODE; 51 import static com.android.server.uwb.config.CapabilityParam.INITIATOR; 52 import static com.android.server.uwb.config.CapabilityParam.INTERVAL_BASED_SCHEDULING; 53 import static com.android.server.uwb.config.CapabilityParam.MANY_TO_MANY; 54 import static com.android.server.uwb.config.CapabilityParam.OBSERVER; 55 import static com.android.server.uwb.config.CapabilityParam.ONE_TO_MANY; 56 import static com.android.server.uwb.config.CapabilityParam.OWR_AOA; 57 import static com.android.server.uwb.config.CapabilityParam.OWR_DL_TDOA; 58 import static com.android.server.uwb.config.CapabilityParam.OWR_UL_TDOA; 59 import static com.android.server.uwb.config.CapabilityParam.PROVISIONED_STS; 60 import static com.android.server.uwb.config.CapabilityParam.PROVISIONED_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY; 61 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_DISABLE; 62 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE; 63 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG; 64 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG; 65 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG; 66 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG; 67 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG; 68 import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG; 69 import static com.android.server.uwb.config.CapabilityParam.RESPONDER; 70 import static com.android.server.uwb.config.CapabilityParam.RSSI_REPORTING; 71 import static com.android.server.uwb.config.CapabilityParam.SP0; 72 import static com.android.server.uwb.config.CapabilityParam.SP1; 73 import static com.android.server.uwb.config.CapabilityParam.SP3; 74 import static com.android.server.uwb.config.CapabilityParam.SS_TWR_DEFERRED; 75 import static com.android.server.uwb.config.CapabilityParam.SS_TWR_NON_DEFERRED; 76 import static com.android.server.uwb.config.CapabilityParam.STATIC_STS; 77 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA_RESULT_REQ_INTERLEAVING; 78 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA_VER_1_0; 79 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA_VER_2_0; 80 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BLOCK_STRIDING_VER_1_0; 81 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BLOCK_STRIDING_VER_2_0; 82 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BPRF_PARAMETER_SETS_VER_1_0; 83 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BPRF_PARAMETER_SETS_VER_2_0; 84 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CC_CONSTRAINT_LENGTH_VER_1_0; 85 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CC_CONSTRAINT_LENGTH_VER_2_0; 86 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CHANNELS_VER_1_0; 87 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CHANNELS_VER_2_0; 88 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DEVICE_ROLES_VER_1_0; 89 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DEVICE_ROLES_VER_2_0; 90 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DEVICE_TYPE_VER_2_0; 91 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DIAGNOSTICS; 92 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DT_TAG_MAX_ACTIVE_RR_2_0; 93 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_EXTENDED_MAC_ADDRESS_VER_1_0; 94 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_EXTENDED_MAC_ADDRESS_VER_2_0; 95 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_1_0; 96 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_2_0; 97 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_1_0; 98 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_2_0; 99 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HOPPING_MODE_VER_1_0; 100 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HOPPING_MODE_VER_2_0; 101 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HPRF_PARAMETER_SETS_VER_1_0; 102 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HPRF_PARAMETER_SETS_VER_2_0; 103 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_1_0; 104 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_2_0; 105 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_MESSAGE_SIZE_VER_1_0; 106 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_MESSAGE_SIZE_VER_2_0; 107 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_RANGING_SESSION_NUMBER; 108 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MIN_RANGING_INTERVAL_MS; 109 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MIN_SLOT_DURATION_RSTU; 110 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MULTI_NODE_MODES_VER_1_0; 111 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MULTI_NODE_MODES_VER_2_0; 112 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGE_DATA_NTF_CONFIG; 113 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_METHOD_VER_1_0; 114 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_METHOD_VER_2_0; 115 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_TIME_STRUCT_VER_1_0; 116 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_TIME_STRUCT_VER_2_0; 117 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RFRAME_CONFIG_VER_1_0; 118 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RFRAME_CONFIG_VER_2_0; 119 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RSSI_REPORTING; 120 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SCHEDULED_MODE_VER_1_0; 121 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SCHEDULED_MODE_VER_2_0; 122 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SESSION_KEY_LENGTH_VER_2_0; 123 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_STS_CONFIG_VER_1_0; 124 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_STS_CONFIG_VER_2_0; 125 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SUSPEND_RANGING_VER_2_0; 126 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_UWB_INITIATION_TIME_VER_1_0; 127 import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_UWB_INITIATION_TIME_VER_2_0; 128 import static com.android.server.uwb.config.CapabilityParam.TIME_SCHEDULED_RANGING; 129 import static com.android.server.uwb.config.CapabilityParam.UNICAST; 130 import static com.android.server.uwb.config.CapabilityParam.UT_ANCHOR; 131 import static com.android.server.uwb.config.CapabilityParam.UT_SYNCHRONIZATION_ANCHOR; 132 import static com.android.server.uwb.config.CapabilityParam.UT_TAG; 133 import static com.android.server.uwb.config.CapabilityParam.UWB_INITIATION_TIME; 134 135 import android.util.Log; 136 137 import com.google.uwb.support.base.FlagEnum; 138 import com.google.uwb.support.base.Params; 139 import com.google.uwb.support.fira.FiraParams; 140 import com.google.uwb.support.fira.FiraParams.BprfParameterSetCapabilityFlag; 141 import com.google.uwb.support.fira.FiraParams.CcConstraintLengthCapabilitiesFlag; 142 import com.google.uwb.support.fira.FiraParams.DeviceRoleCapabilityFlag; 143 import com.google.uwb.support.fira.FiraParams.HprfParameterSetCapabilityFlag; 144 import com.google.uwb.support.fira.FiraParams.MultiNodeCapabilityFlag; 145 import com.google.uwb.support.fira.FiraParams.PsduDataRateCapabilityFlag; 146 import com.google.uwb.support.fira.FiraParams.RangingRoundCapabilityFlag; 147 import com.google.uwb.support.fira.FiraParams.RangingTimeStructCapabilitiesFlag; 148 import com.google.uwb.support.fira.FiraParams.RframeCapabilityFlag; 149 import com.google.uwb.support.fira.FiraParams.SchedulingModeCapabilitiesFlag; 150 import com.google.uwb.support.fira.FiraParams.StsCapabilityFlag; 151 import com.google.uwb.support.fira.FiraProtocolVersion; 152 import com.google.uwb.support.fira.FiraSpecificationParams; 153 154 import java.math.BigInteger; 155 import java.util.ArrayList; 156 import java.util.EnumSet; 157 import java.util.List; 158 import java.util.stream.IntStream; 159 160 public class FiraDecoder extends TlvDecoder { 161 private static final String TAG = "FiraDecoder"; 162 163 @Override getParams(TlvDecoderBuffer tlvs, Class<T> paramType)164 public <T extends Params> T getParams(TlvDecoderBuffer tlvs, Class<T> paramType) { 165 if (FiraSpecificationParams.class.equals(paramType)) { 166 return (T) getFiraSpecificationParamsFromTlvBuffer(tlvs); 167 } 168 return null; 169 } 170 isBitSet(int flags, int mask)171 private static boolean isBitSet(int flags, int mask) { 172 return (flags & mask) != 0; 173 } 174 getFiraSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs)175 private FiraSpecificationParams getFiraSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs) { 176 FiraSpecificationParams.Builder builder = new FiraSpecificationParams.Builder(); 177 byte[] versionCheck = tlvs.getByteArray(SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_2_0); 178 if (versionCheck.length == 1) { 179 // FiRa Version 1.0 180 byte[] phyVersions = tlvs.getByteArray(SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_1_0); 181 builder.setMinPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 0)); 182 builder.setMaxPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 2)); 183 byte[] macVersions = tlvs.getByteArray(SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_1_0); 184 builder.setMinMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 0)); 185 builder.setMaxMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 2)); 186 187 byte deviceRolesUci = tlvs.getByte(SUPPORTED_DEVICE_ROLES_VER_1_0); 188 EnumSet<DeviceRoleCapabilityFlag> deviceRoles = 189 EnumSet.noneOf(DeviceRoleCapabilityFlag.class); 190 if (isBitSet(deviceRolesUci, INITIATOR)) { 191 // This assumes both controller + controlee is supported. 192 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_INITIATOR_SUPPORT); 193 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_INITIATOR_SUPPORT); 194 } 195 if (isBitSet(deviceRolesUci, RESPONDER)) { 196 // This assumes both controller + controlee is supported. 197 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_RESPONDER_SUPPORT); 198 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_RESPONDER_SUPPORT); 199 } 200 builder.setDeviceRoleCapabilities(deviceRoles); 201 202 byte rangingMethodUci = tlvs.getByte(SUPPORTED_RANGING_METHOD_VER_1_0); 203 EnumSet<RangingRoundCapabilityFlag> rangingRoundFlag = EnumSet.noneOf( 204 RangingRoundCapabilityFlag.class); 205 if (isBitSet(rangingMethodUci, DS_TWR_DEFERRED)) { 206 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_DS_TWR_SUPPORT); 207 } 208 if (isBitSet(rangingMethodUci, SS_TWR_DEFERRED)) { 209 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_SS_TWR_SUPPORT); 210 } 211 builder.setRangingRoundCapabilities(rangingRoundFlag); 212 213 // TODO(b/209053358): This does not align with UCI spec. 214 if (isBitSet(rangingMethodUci, DS_TWR_NON_DEFERRED) 215 || isBitSet(rangingMethodUci, SS_TWR_NON_DEFERRED)) { 216 builder.hasNonDeferredModeSupport(true); 217 } 218 219 byte stsConfigUci = tlvs.getByte(SUPPORTED_STS_CONFIG_VER_1_0); 220 EnumSet<StsCapabilityFlag> stsCapabilityFlag = EnumSet.noneOf(StsCapabilityFlag.class); 221 if (isBitSet(stsConfigUci, STATIC_STS)) { 222 stsCapabilityFlag.add(StsCapabilityFlag.HAS_STATIC_STS_SUPPORT); 223 } 224 if (isBitSet(stsConfigUci, DYNAMIC_STS)) { 225 stsCapabilityFlag.add(StsCapabilityFlag.HAS_DYNAMIC_STS_SUPPORT); 226 } 227 if (isBitSet(stsConfigUci, DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) { 228 stsCapabilityFlag.add( 229 StsCapabilityFlag.HAS_DYNAMIC_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT); 230 } 231 if (isBitSet(stsConfigUci, PROVISIONED_STS)) { 232 stsCapabilityFlag.add(StsCapabilityFlag.HAS_PROVISIONED_STS_SUPPORT); 233 } 234 if (isBitSet(stsConfigUci, PROVISIONED_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) { 235 stsCapabilityFlag.add( 236 StsCapabilityFlag.HAS_PROVISIONED_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT); 237 } 238 builder.setStsCapabilities(stsCapabilityFlag); 239 240 byte multiNodeUci = tlvs.getByte(SUPPORTED_MULTI_NODE_MODES_VER_1_0); 241 EnumSet<MultiNodeCapabilityFlag> multiNodeFlag = 242 EnumSet.noneOf(MultiNodeCapabilityFlag.class); 243 if (isBitSet(multiNodeUci, UNICAST)) { 244 multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_UNICAST_SUPPORT); 245 } 246 if (isBitSet(multiNodeUci, ONE_TO_MANY)) { 247 multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_ONE_TO_MANY_SUPPORT); 248 } 249 if (isBitSet(multiNodeUci, MANY_TO_MANY)) { 250 multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_MANY_TO_MANY_SUPPORT); 251 } 252 builder.setMultiNodeCapabilities(multiNodeFlag); 253 254 byte rangingTimeStructUci = tlvs.getByte(SUPPORTED_RANGING_TIME_STRUCT_VER_1_0); 255 EnumSet<RangingTimeStructCapabilitiesFlag> rangingTimeStructFlag = 256 EnumSet.noneOf(RangingTimeStructCapabilitiesFlag.class); 257 if (isBitSet(rangingTimeStructUci, INTERVAL_BASED_SCHEDULING)) { 258 rangingTimeStructFlag.add( 259 RangingTimeStructCapabilitiesFlag.HAS_INTERVAL_BASED_SCHEDULING_SUPPORT); 260 } 261 if (isBitSet(rangingTimeStructUci, BLOCK_BASED_SCHEDULING)) { 262 rangingTimeStructFlag.add( 263 RangingTimeStructCapabilitiesFlag.HAS_BLOCK_BASED_SCHEDULING_SUPPORT); 264 } 265 builder.setRangingTimeStructCapabilities(rangingTimeStructFlag); 266 267 byte schedulingModeUci = tlvs.getByte(SUPPORTED_SCHEDULED_MODE_VER_1_0); 268 EnumSet<SchedulingModeCapabilitiesFlag> schedulingModeFlag = 269 EnumSet.noneOf(SchedulingModeCapabilitiesFlag.class); 270 if (isBitSet(schedulingModeUci, CONTENTION_BASED_RANGING)) { 271 schedulingModeFlag.add( 272 SchedulingModeCapabilitiesFlag.HAS_CONTENTION_BASED_RANGING_SUPPORT); 273 } 274 if (isBitSet(schedulingModeUci, TIME_SCHEDULED_RANGING)) { 275 schedulingModeFlag.add( 276 SchedulingModeCapabilitiesFlag.HAS_TIME_SCHEDULED_RANGING_SUPPORT); 277 } 278 builder.setSchedulingModeCapabilities(schedulingModeFlag); 279 280 byte ccConstraintLengthUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_1_0); 281 EnumSet<CcConstraintLengthCapabilitiesFlag> ccConstraintLengthFlag = 282 EnumSet.noneOf(CcConstraintLengthCapabilitiesFlag.class); 283 if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_3)) { 284 ccConstraintLengthFlag.add( 285 CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_3_SUPPORT); 286 } 287 if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_7)) { 288 ccConstraintLengthFlag.add( 289 CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_7_SUPPORT); 290 } 291 builder.setCcConstraintLengthCapabilities(ccConstraintLengthFlag); 292 293 byte blockStridingUci = tlvs.getByte(SUPPORTED_BLOCK_STRIDING_VER_1_0); 294 if (isBitSet(blockStridingUci, BLOCK_STRIDING)) { 295 builder.hasBlockStridingSupport(true); 296 } 297 298 byte hoppingPreferenceUci = tlvs.getByte(SUPPORTED_HOPPING_MODE_VER_1_0); 299 if (isBitSet(hoppingPreferenceUci, HOPPING_MODE)) { 300 builder.hasHoppingPreferenceSupport(true); 301 } 302 303 byte extendedMacAddressUci = tlvs.getByte(SUPPORTED_EXTENDED_MAC_ADDRESS_VER_1_0); 304 if (isBitSet(extendedMacAddressUci, EXTENDED_MAC_ADDRESS)) { 305 builder.hasExtendedMacAddressSupport(true); 306 } 307 308 byte initiationTimeUci = tlvs.getByte(SUPPORTED_UWB_INITIATION_TIME_VER_1_0); 309 if (isBitSet(initiationTimeUci, UWB_INITIATION_TIME)) { 310 builder.hasInitiationTimeSupport(true); 311 } 312 313 byte channelsUci = tlvs.getByte(SUPPORTED_CHANNELS_VER_1_0); 314 List<Integer> channels = new ArrayList<>(); 315 if (isBitSet(channelsUci, CHANNEL_5)) { 316 channels.add(5); 317 } 318 if (isBitSet(channelsUci, CHANNEL_6)) { 319 channels.add(6); 320 } 321 if (isBitSet(channelsUci, CHANNEL_8)) { 322 channels.add(8); 323 } 324 if (isBitSet(channelsUci, CHANNEL_9)) { 325 channels.add(9); 326 } 327 if (isBitSet(channelsUci, CHANNEL_10)) { 328 channels.add(10); 329 } 330 if (isBitSet(channelsUci, CHANNEL_12)) { 331 channels.add(12); 332 } 333 if (isBitSet(channelsUci, CHANNEL_13)) { 334 channels.add(13); 335 } 336 if (isBitSet(channelsUci, CHANNEL_14)) { 337 channels.add(14); 338 } 339 builder.setSupportedChannels(channels); 340 341 byte rframeConfigUci = tlvs.getByte(SUPPORTED_RFRAME_CONFIG_VER_1_0); 342 EnumSet<RframeCapabilityFlag> rframeConfigFlag = 343 EnumSet.noneOf(RframeCapabilityFlag.class); 344 if (isBitSet(rframeConfigUci, SP0)) { 345 rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP0_RFRAME_SUPPORT); 346 } 347 if (isBitSet(rframeConfigUci, SP1)) { 348 rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP1_RFRAME_SUPPORT); 349 } 350 if (isBitSet(rframeConfigUci, SP3)) { 351 rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP3_RFRAME_SUPPORT); 352 } 353 builder.setRframeCapabilities(rframeConfigFlag); 354 355 byte bprfSets = tlvs.getByte(SUPPORTED_BPRF_PARAMETER_SETS_VER_1_0); 356 int bprfSetsValue = Integer.valueOf(bprfSets); 357 EnumSet<BprfParameterSetCapabilityFlag> bprfFlag; 358 bprfFlag = FlagEnum.toEnumSet(bprfSetsValue, BprfParameterSetCapabilityFlag.values()); 359 builder.setBprfParameterSetCapabilities(bprfFlag); 360 361 byte[] hprfSets = tlvs.getByteArray(SUPPORTED_HPRF_PARAMETER_SETS_VER_1_0); 362 // Extend the 5 bytes from HAL to 8 bytes for long. 363 long hprfSetsValue = new BigInteger(TlvUtil.getReverseBytes(hprfSets)).longValue(); 364 EnumSet<HprfParameterSetCapabilityFlag> hprfFlag; 365 hprfFlag = FlagEnum.longToEnumSet( 366 hprfSetsValue, HprfParameterSetCapabilityFlag.values()); 367 builder.setHprfParameterSetCapabilities(hprfFlag); 368 369 EnumSet<FiraParams.PrfCapabilityFlag> prfFlag = 370 EnumSet.noneOf(FiraParams.PrfCapabilityFlag.class); 371 boolean hasBprfSupport = bprfSets != 0; 372 if (hasBprfSupport) { 373 prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_BPRF_SUPPORT); 374 } 375 boolean hasHprfSupport = 376 IntStream.range(0, hprfSets.length).parallel().anyMatch(i -> hprfSets[i] != 0); 377 if (hasHprfSupport) { 378 prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_HPRF_SUPPORT); 379 } 380 builder.setPrfCapabilities(prfFlag); 381 382 byte ccConstraintUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_1_0); 383 EnumSet<PsduDataRateCapabilityFlag> psduRateFlag = 384 EnumSet.noneOf(PsduDataRateCapabilityFlag.class); 385 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasBprfSupport) { 386 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_6M81_SUPPORT); 387 } 388 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasBprfSupport) { 389 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_7M80_SUPPORT); 390 } 391 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasHprfSupport) { 392 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_27M2_SUPPORT); 393 } 394 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasHprfSupport) { 395 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_31M2_SUPPORT); 396 } 397 builder.setPsduDataRateCapabilities(psduRateFlag); 398 399 byte aoaUci = tlvs.getByte(SUPPORTED_AOA_VER_1_0); 400 EnumSet<FiraParams.AoaCapabilityFlag> aoaFlag = 401 EnumSet.noneOf(FiraParams.AoaCapabilityFlag.class); 402 if (isBitSet(aoaUci, AOA_AZIMUTH_90)) { 403 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_AZIMUTH_SUPPORT); 404 } 405 if (isBitSet(aoaUci, AOA_AZIMUTH_180)) { 406 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FULL_AZIMUTH_SUPPORT); 407 } 408 if (isBitSet(aoaUci, AOA_ELEVATION)) { 409 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_ELEVATION_SUPPORT); 410 } 411 if (isBitSet(aoaUci, AOA_FOM)) { 412 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FOM_SUPPORT); 413 } 414 byte aoaInterleavingUci = tlvs.getByte(SUPPORTED_AOA_RESULT_REQ_INTERLEAVING); 415 if (isBitSet(aoaInterleavingUci, AOA_RESULT_REQ_INTERLEAVING)) { 416 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_INTERLEAVING_SUPPORT); 417 } 418 builder.setAoaCapabilities(aoaFlag); 419 420 try { 421 int maxMessageSizeUci = tlvs.getShort(SUPPORTED_MAX_MESSAGE_SIZE_VER_1_0); 422 builder.setMaxMessageSize(Integer.valueOf(maxMessageSizeUci)); 423 } catch (IllegalArgumentException e) { 424 Log.w(TAG, "SUPPORTED_MAX_MESSAGE_SIZE not found."); 425 } 426 try { 427 int maxDataPacketPayloadSizeUci = tlvs.getShort( 428 SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_1_0); 429 builder.setMaxDataPacketPayloadSize(Integer.valueOf(maxDataPacketPayloadSizeUci)); 430 } catch (IllegalArgumentException e) { 431 Log.w(TAG, "SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE not found."); 432 } 433 } else if (versionCheck.length == 4) { 434 // FiRa Version 2.0 435 byte[] phyVersions = tlvs.getByteArray(SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_2_0); 436 builder.setMinPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 0)); 437 builder.setMaxPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 2)); 438 byte[] macVersions = tlvs.getByteArray(SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_2_0); 439 builder.setMinMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 0)); 440 builder.setMaxMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 2)); 441 442 byte[] deviceRolesUci = tlvs.getByteArray(SUPPORTED_DEVICE_ROLES_VER_2_0); 443 EnumSet<DeviceRoleCapabilityFlag> deviceRoles = 444 EnumSet.noneOf(DeviceRoleCapabilityFlag.class); 445 if (isBitSet(deviceRolesUci[0], INITIATOR)) { 446 // This assumes both controller + controlee is supported. 447 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_INITIATOR_SUPPORT); 448 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_INITIATOR_SUPPORT); 449 } 450 if (isBitSet(deviceRolesUci[0], RESPONDER)) { 451 // This assumes both controller + controlee is supported. 452 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_RESPONDER_SUPPORT); 453 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_RESPONDER_SUPPORT); 454 } 455 if (isBitSet(deviceRolesUci[0], UT_SYNCHRONIZATION_ANCHOR)) { 456 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_UT_SYNCHRONIZATION_SUPPORT); 457 } 458 if (isBitSet(deviceRolesUci[0], UT_ANCHOR)) { 459 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_UT_ANCHOR_SUPPORT); 460 } 461 if (isBitSet(deviceRolesUci[0], UT_TAG)) { 462 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_UT_TAG_SUPPORT); 463 } 464 if (isBitSet(deviceRolesUci[0], ADVERTISER)) { 465 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_ADVERTISER_SUPPORT); 466 } 467 if (isBitSet(deviceRolesUci[0], OBSERVER)) { 468 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_OBSERVER_SUPPORT); 469 } 470 if (isBitSet(deviceRolesUci[0], DT_ANCHOR)) { 471 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_DT_ANCHOR_SUPPORT); 472 } 473 if (isBitSet(deviceRolesUci[1], DT_TAG)) { 474 deviceRoles.add(DeviceRoleCapabilityFlag.HAS_DT_TAG_SUPPORT); 475 } 476 builder.setDeviceRoleCapabilities(deviceRoles); 477 478 byte[] rangingMethodUci = tlvs.getByteArray(SUPPORTED_RANGING_METHOD_VER_2_0); 479 EnumSet<RangingRoundCapabilityFlag> rangingRoundFlag = EnumSet.noneOf( 480 RangingRoundCapabilityFlag.class); 481 if (isBitSet(rangingMethodUci[0], DS_TWR_DEFERRED)) { 482 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_DS_TWR_SUPPORT); 483 } 484 if (isBitSet(rangingMethodUci[0], SS_TWR_DEFERRED)) { 485 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_SS_TWR_SUPPORT); 486 } 487 if (isBitSet(rangingMethodUci[0], OWR_UL_TDOA)) { 488 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_OWR_UL_TDOA_SUPPORT); 489 } 490 if (isBitSet(rangingMethodUci[0], OWR_DL_TDOA)) { 491 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_OWR_DL_TDOA_SUPPORT); 492 } 493 if (isBitSet(rangingMethodUci[0], OWR_AOA)) { 494 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_OWR_AOA_SUPPORT); 495 } 496 if (isBitSet(rangingMethodUci[0], ESS_TWR_NON_DEFERRED)) { 497 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_ESS_TWR_SUPPORT); 498 } 499 if (isBitSet(rangingMethodUci[1], ADS_TWR)) { 500 rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_ADS_TWR_SUPPORT); 501 } 502 builder.setRangingRoundCapabilities(rangingRoundFlag); 503 504 // TODO(b/209053358): This does not align with UCI spec. 505 if (isBitSet(rangingMethodUci[0], DS_TWR_NON_DEFERRED) 506 || isBitSet(rangingMethodUci[0], SS_TWR_NON_DEFERRED)) { 507 builder.hasNonDeferredModeSupport(true); 508 } 509 510 byte stsConfigUci = tlvs.getByte(SUPPORTED_STS_CONFIG_VER_2_0); 511 EnumSet<StsCapabilityFlag> stsCapabilityFlag = EnumSet.noneOf(StsCapabilityFlag.class); 512 if (isBitSet(stsConfigUci, STATIC_STS)) { 513 stsCapabilityFlag.add(StsCapabilityFlag.HAS_STATIC_STS_SUPPORT); 514 } 515 if (isBitSet(stsConfigUci, DYNAMIC_STS)) { 516 stsCapabilityFlag.add(StsCapabilityFlag.HAS_DYNAMIC_STS_SUPPORT); 517 } 518 if (isBitSet(stsConfigUci, DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) { 519 stsCapabilityFlag.add( 520 StsCapabilityFlag.HAS_DYNAMIC_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT); 521 } 522 if (isBitSet(stsConfigUci, PROVISIONED_STS)) { 523 stsCapabilityFlag.add(StsCapabilityFlag.HAS_PROVISIONED_STS_SUPPORT); 524 } 525 if (isBitSet(stsConfigUci, PROVISIONED_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) { 526 stsCapabilityFlag.add( 527 StsCapabilityFlag.HAS_PROVISIONED_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT); 528 } 529 builder.setStsCapabilities(stsCapabilityFlag); 530 531 byte multiNodeUci = tlvs.getByte(SUPPORTED_MULTI_NODE_MODES_VER_2_0); 532 EnumSet<MultiNodeCapabilityFlag> multiNodeFlag = 533 EnumSet.noneOf(MultiNodeCapabilityFlag.class); 534 if (isBitSet(multiNodeUci, UNICAST)) { 535 multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_UNICAST_SUPPORT); 536 } 537 if (isBitSet(multiNodeUci, ONE_TO_MANY)) { 538 multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_ONE_TO_MANY_SUPPORT); 539 } 540 if (isBitSet(multiNodeUci, MANY_TO_MANY)) { 541 multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_MANY_TO_MANY_SUPPORT); 542 } 543 builder.setMultiNodeCapabilities(multiNodeFlag); 544 545 byte rangingTimeStructUci = tlvs.getByte(SUPPORTED_RANGING_TIME_STRUCT_VER_2_0); 546 EnumSet<RangingTimeStructCapabilitiesFlag> rangingTimeStructFlag = 547 EnumSet.noneOf(RangingTimeStructCapabilitiesFlag.class); 548 if (isBitSet(rangingTimeStructUci, INTERVAL_BASED_SCHEDULING)) { 549 rangingTimeStructFlag.add( 550 RangingTimeStructCapabilitiesFlag.HAS_INTERVAL_BASED_SCHEDULING_SUPPORT); 551 } 552 if (isBitSet(rangingTimeStructUci, BLOCK_BASED_SCHEDULING)) { 553 rangingTimeStructFlag.add( 554 RangingTimeStructCapabilitiesFlag.HAS_BLOCK_BASED_SCHEDULING_SUPPORT); 555 } 556 builder.setRangingTimeStructCapabilities(rangingTimeStructFlag); 557 558 byte schedulingModeUci = tlvs.getByte(SUPPORTED_SCHEDULED_MODE_VER_2_0); 559 EnumSet<SchedulingModeCapabilitiesFlag> schedulingModeFlag = 560 EnumSet.noneOf(SchedulingModeCapabilitiesFlag.class); 561 if (isBitSet(schedulingModeUci, CONTENTION_BASED_RANGING)) { 562 schedulingModeFlag.add( 563 SchedulingModeCapabilitiesFlag.HAS_CONTENTION_BASED_RANGING_SUPPORT); 564 } 565 if (isBitSet(schedulingModeUci, TIME_SCHEDULED_RANGING)) { 566 schedulingModeFlag.add( 567 SchedulingModeCapabilitiesFlag.HAS_TIME_SCHEDULED_RANGING_SUPPORT); 568 } 569 builder.setSchedulingModeCapabilities(schedulingModeFlag); 570 571 byte ccConstraintLengthUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_2_0); 572 EnumSet<CcConstraintLengthCapabilitiesFlag> ccConstraintLengthFlag = 573 EnumSet.noneOf(CcConstraintLengthCapabilitiesFlag.class); 574 if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_3)) { 575 ccConstraintLengthFlag.add( 576 CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_3_SUPPORT); 577 } 578 if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_7)) { 579 ccConstraintLengthFlag.add( 580 CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_7_SUPPORT); 581 } 582 builder.setCcConstraintLengthCapabilities(ccConstraintLengthFlag); 583 584 byte blockStridingUci = tlvs.getByte(SUPPORTED_BLOCK_STRIDING_VER_2_0); 585 if (isBitSet(blockStridingUci, BLOCK_STRIDING)) { 586 builder.hasBlockStridingSupport(true); 587 } 588 589 byte hoppingPreferenceUci = tlvs.getByte(SUPPORTED_HOPPING_MODE_VER_2_0); 590 if (isBitSet(hoppingPreferenceUci, HOPPING_MODE)) { 591 builder.hasHoppingPreferenceSupport(true); 592 } 593 594 byte extendedMacAddressUci = tlvs.getByte(SUPPORTED_EXTENDED_MAC_ADDRESS_VER_2_0); 595 if (isBitSet(extendedMacAddressUci, EXTENDED_MAC_ADDRESS)) { 596 builder.hasExtendedMacAddressSupport(true); 597 } 598 599 byte initiationTimeUci = tlvs.getByte(SUPPORTED_UWB_INITIATION_TIME_VER_2_0); 600 if (isBitSet(initiationTimeUci, UWB_INITIATION_TIME)) { 601 builder.hasInitiationTimeSupport(true); 602 } 603 604 byte channelsUci = tlvs.getByte(SUPPORTED_CHANNELS_VER_2_0); 605 List<Integer> channels = new ArrayList<>(); 606 if (isBitSet(channelsUci, CHANNEL_5)) { 607 channels.add(5); 608 } 609 if (isBitSet(channelsUci, CHANNEL_6)) { 610 channels.add(6); 611 } 612 if (isBitSet(channelsUci, CHANNEL_8)) { 613 channels.add(8); 614 } 615 if (isBitSet(channelsUci, CHANNEL_9)) { 616 channels.add(9); 617 } 618 if (isBitSet(channelsUci, CHANNEL_10)) { 619 channels.add(10); 620 } 621 if (isBitSet(channelsUci, CHANNEL_12)) { 622 channels.add(12); 623 } 624 if (isBitSet(channelsUci, CHANNEL_13)) { 625 channels.add(13); 626 } 627 if (isBitSet(channelsUci, CHANNEL_14)) { 628 channels.add(14); 629 } 630 builder.setSupportedChannels(channels); 631 632 byte rframeConfigUci = tlvs.getByte(SUPPORTED_RFRAME_CONFIG_VER_2_0); 633 EnumSet<RframeCapabilityFlag> rframeConfigFlag = 634 EnumSet.noneOf(RframeCapabilityFlag.class); 635 if (isBitSet(rframeConfigUci, SP0)) { 636 rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP0_RFRAME_SUPPORT); 637 } 638 if (isBitSet(rframeConfigUci, SP1)) { 639 rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP1_RFRAME_SUPPORT); 640 } 641 if (isBitSet(rframeConfigUci, SP3)) { 642 rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP3_RFRAME_SUPPORT); 643 } 644 builder.setRframeCapabilities(rframeConfigFlag); 645 646 byte bprfSets = tlvs.getByte(SUPPORTED_BPRF_PARAMETER_SETS_VER_2_0); 647 int bprfSetsValue = Integer.valueOf(bprfSets); 648 EnumSet<BprfParameterSetCapabilityFlag> bprfFlag; 649 bprfFlag = FlagEnum.toEnumSet(bprfSetsValue, BprfParameterSetCapabilityFlag.values()); 650 builder.setBprfParameterSetCapabilities(bprfFlag); 651 652 byte[] hprfSets = tlvs.getByteArray(SUPPORTED_HPRF_PARAMETER_SETS_VER_2_0); 653 // Extend the 5 bytes from HAL to 8 bytes for long. 654 long hprfSetsValue = new BigInteger(TlvUtil.getReverseBytes(hprfSets)).longValue(); 655 EnumSet<HprfParameterSetCapabilityFlag> hprfFlag; 656 hprfFlag = FlagEnum.longToEnumSet( 657 hprfSetsValue, HprfParameterSetCapabilityFlag.values()); 658 builder.setHprfParameterSetCapabilities(hprfFlag); 659 660 EnumSet<FiraParams.PrfCapabilityFlag> prfFlag = 661 EnumSet.noneOf(FiraParams.PrfCapabilityFlag.class); 662 boolean hasBprfSupport = bprfSets != 0; 663 if (hasBprfSupport) { 664 prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_BPRF_SUPPORT); 665 } 666 boolean hasHprfSupport = 667 IntStream.range(0, hprfSets.length).parallel().anyMatch(i -> hprfSets[i] != 0); 668 if (hasHprfSupport) { 669 prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_HPRF_SUPPORT); 670 } 671 builder.setPrfCapabilities(prfFlag); 672 673 byte ccConstraintUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_2_0); 674 EnumSet<PsduDataRateCapabilityFlag> psduRateFlag = 675 EnumSet.noneOf(PsduDataRateCapabilityFlag.class); 676 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasBprfSupport) { 677 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_6M81_SUPPORT); 678 } 679 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasBprfSupport) { 680 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_7M80_SUPPORT); 681 } 682 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasHprfSupport) { 683 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_27M2_SUPPORT); 684 } 685 if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasHprfSupport) { 686 psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_31M2_SUPPORT); 687 } 688 builder.setPsduDataRateCapabilities(psduRateFlag); 689 690 byte aoaUci = tlvs.getByte(SUPPORTED_AOA_VER_2_0); 691 EnumSet<FiraParams.AoaCapabilityFlag> aoaFlag = 692 EnumSet.noneOf(FiraParams.AoaCapabilityFlag.class); 693 if (isBitSet(aoaUci, AOA_AZIMUTH_90)) { 694 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_AZIMUTH_SUPPORT); 695 } 696 if (isBitSet(aoaUci, AOA_AZIMUTH_180)) { 697 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FULL_AZIMUTH_SUPPORT); 698 } 699 if (isBitSet(aoaUci, AOA_ELEVATION)) { 700 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_ELEVATION_SUPPORT); 701 } 702 if (isBitSet(aoaUci, AOA_FOM)) { 703 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FOM_SUPPORT); 704 } 705 byte aoaInterleavingUci = tlvs.getByte(SUPPORTED_AOA_RESULT_REQ_INTERLEAVING); 706 if (isBitSet(aoaInterleavingUci, AOA_RESULT_REQ_INTERLEAVING)) { 707 aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_INTERLEAVING_SUPPORT); 708 } 709 builder.setAoaCapabilities(aoaFlag); 710 711 try { 712 int maxMessageSizeUci = tlvs.getShort(SUPPORTED_MAX_MESSAGE_SIZE_VER_2_0); 713 builder.setMaxMessageSize(Integer.valueOf(maxMessageSizeUci)); 714 } catch (IllegalArgumentException e) { 715 Log.w(TAG, "SUPPORTED_MAX_MESSAGE_SIZE not found."); 716 } 717 try { 718 int maxDataPacketPayloadSizeUci = tlvs.getShort( 719 SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_2_0); 720 builder.setMaxDataPacketPayloadSize(Integer.valueOf(maxDataPacketPayloadSizeUci)); 721 } catch (IllegalArgumentException e) { 722 Log.w(TAG, "SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE not found."); 723 } 724 725 int deviceType = tlvs.getByte(SUPPORTED_DEVICE_TYPE_VER_2_0); 726 builder.setDeviceType(deviceType); 727 728 int supportedSuspendSupport = tlvs.getByte(SUPPORTED_SUSPEND_RANGING_VER_2_0); 729 builder.setSuspendRangingSupport(supportedSuspendSupport != 0); 730 731 int sessionKeyLength = tlvs.getByte(SUPPORTED_SESSION_KEY_LENGTH_VER_2_0); 732 builder.setSessionKeyLength(sessionKeyLength); 733 734 try { 735 int dtTagMaxActiveRr = tlvs.getByte(SUPPORTED_DT_TAG_MAX_ACTIVE_RR_2_0); 736 builder.setDtTagMaxActiveRr(dtTagMaxActiveRr); 737 } catch (IllegalArgumentException e) { 738 Log.w(TAG, "SUPPORTED_DT_TAG_MAX_ACTIVE_RR not found."); 739 } 740 } else { 741 // This FiRa version is not supported yet. 742 return null; 743 } 744 try { 745 int minRangingInterval = tlvs.getInt(SUPPORTED_MIN_RANGING_INTERVAL_MS); 746 builder.setMinRangingIntervalSupported(minRangingInterval); 747 } catch (IllegalArgumentException e) { 748 Log.w(TAG, "SUPPORTED_MIN_RANGING_INTERVAL_MS not found."); 749 } 750 751 try { 752 int minSlotDurationUs = TlvUtil.rstuToUs(tlvs.getInt(SUPPORTED_MIN_SLOT_DURATION_RSTU)); 753 builder.setMinSlotDurationSupportedUs(minSlotDurationUs); 754 } catch (IllegalArgumentException e) { 755 Log.w(TAG, "SUPPORTED_MIN_SLOT_DURATION not found."); 756 } 757 758 try { 759 int maxRangingSessionNumber = tlvs.getInt(SUPPORTED_MAX_RANGING_SESSION_NUMBER); 760 builder.setMaxRangingSessionNumberSupported(maxRangingSessionNumber); 761 } catch (IllegalArgumentException e) { 762 Log.w(TAG, "SUPPORTED_MAX_RANGING_SESSION_NUMBER not found"); 763 } 764 765 try { 766 byte rssiReporting = tlvs.getByte(SUPPORTED_RSSI_REPORTING); 767 if (isBitSet(rssiReporting, RSSI_REPORTING)) { 768 builder.hasRssiReportingSupport(true); 769 } 770 } catch (IllegalArgumentException e) { 771 Log.w(TAG, "SUPPORTED_RSSI_REPORTING not found."); 772 } 773 774 try { 775 byte diagnostics = tlvs.getByte(SUPPORTED_DIAGNOSTICS); 776 if (isBitSet(diagnostics, DIAGNOSTICS)) { 777 builder.hasDiagnosticsSupport(true); 778 } 779 } catch (IllegalArgumentException e) { 780 Log.w(TAG, "SUPPORTED_DIAGNOSTICS not found."); 781 } 782 783 try { 784 byte[] rangeDataNtfConfigUciBytes = tlvs.getByteArray(SUPPORTED_RANGE_DATA_NTF_CONFIG); 785 int rangeDataNtfConfigUci = 786 new BigInteger(TlvUtil.getReverseBytes(rangeDataNtfConfigUciBytes)).intValue(); 787 EnumSet<FiraParams.RangeDataNtfConfigCapabilityFlag> rangeDataNtfConfigCapabilityFlag = 788 EnumSet.noneOf(FiraParams.RangeDataNtfConfigCapabilityFlag.class); 789 if (isBitSet(rangeDataNtfConfigUci, RANGE_DATA_NTF_CONFIG_ENABLE)) { 790 rangeDataNtfConfigCapabilityFlag.add( 791 FiraParams.RangeDataNtfConfigCapabilityFlag 792 .HAS_RANGE_DATA_NTF_CONFIG_ENABLE); 793 } 794 if (isBitSet(rangeDataNtfConfigUci, RANGE_DATA_NTF_CONFIG_DISABLE)) { 795 rangeDataNtfConfigCapabilityFlag.add( 796 FiraParams.RangeDataNtfConfigCapabilityFlag 797 .HAS_RANGE_DATA_NTF_CONFIG_DISABLE); 798 } 799 if (isBitSet(rangeDataNtfConfigUci, 800 RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG)) { 801 rangeDataNtfConfigCapabilityFlag.add( 802 FiraParams.RangeDataNtfConfigCapabilityFlag 803 .HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG); 804 } 805 if (isBitSet(rangeDataNtfConfigUci, 806 RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG)) { 807 rangeDataNtfConfigCapabilityFlag.add( 808 FiraParams.RangeDataNtfConfigCapabilityFlag 809 .HAS_RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG); 810 } 811 if (isBitSet(rangeDataNtfConfigUci, 812 RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG)) { 813 rangeDataNtfConfigCapabilityFlag.add( 814 FiraParams.RangeDataNtfConfigCapabilityFlag 815 .HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG); 816 } 817 if (isBitSet(rangeDataNtfConfigUci, 818 RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG)) { 819 rangeDataNtfConfigCapabilityFlag.add( 820 FiraParams.RangeDataNtfConfigCapabilityFlag 821 .HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG); 822 } 823 if (isBitSet(rangeDataNtfConfigUci, 824 RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG)) { 825 rangeDataNtfConfigCapabilityFlag.add( 826 FiraParams.RangeDataNtfConfigCapabilityFlag 827 .HAS_RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG); 828 } 829 if (isBitSet(rangeDataNtfConfigUci, 830 RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG)) { 831 rangeDataNtfConfigCapabilityFlag.add( 832 FiraParams.RangeDataNtfConfigCapabilityFlag 833 .HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG); 834 } 835 builder.setRangeDataNtfConfigCapabilities(rangeDataNtfConfigCapabilityFlag); 836 } catch (IllegalArgumentException e) { 837 Log.w(TAG, "SUPPORTED_RANGE_DATA_NTF_CONFIG not found."); 838 } 839 return builder.build(); 840 } 841 } 842