blob: 724de48f6b8ad03d01499c5945685687dd92a3ba [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.uwb.params;
import static com.android.server.uwb.config.CapabilityParam.ADS_TWR;
import static com.android.server.uwb.config.CapabilityParam.ADVERTISER;
import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_180;
import static com.android.server.uwb.config.CapabilityParam.AOA_AZIMUTH_90;
import static com.android.server.uwb.config.CapabilityParam.AOA_ELEVATION;
import static com.android.server.uwb.config.CapabilityParam.AOA_FOM;
import static com.android.server.uwb.config.CapabilityParam.AOA_RESULT_REQ_INTERLEAVING;
import static com.android.server.uwb.config.CapabilityParam.BLOCK_BASED_SCHEDULING;
import static com.android.server.uwb.config.CapabilityParam.BLOCK_STRIDING;
import static com.android.server.uwb.config.CapabilityParam.CC_CONSTRAINT_LENGTH_K3;
import static com.android.server.uwb.config.CapabilityParam.CC_CONSTRAINT_LENGTH_K7;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_10;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_12;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_13;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_14;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_5;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_6;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_8;
import static com.android.server.uwb.config.CapabilityParam.CHANNEL_9;
import static com.android.server.uwb.config.CapabilityParam.CONSTRAINT_LENGTH_3;
import static com.android.server.uwb.config.CapabilityParam.CONSTRAINT_LENGTH_7;
import static com.android.server.uwb.config.CapabilityParam.CONTENTION_BASED_RANGING;
import static com.android.server.uwb.config.CapabilityParam.DIAGNOSTICS;
import static com.android.server.uwb.config.CapabilityParam.DS_TWR_DEFERRED;
import static com.android.server.uwb.config.CapabilityParam.DS_TWR_NON_DEFERRED;
import static com.android.server.uwb.config.CapabilityParam.DT_ANCHOR;
import static com.android.server.uwb.config.CapabilityParam.DT_TAG;
import static com.android.server.uwb.config.CapabilityParam.DT_TAG_BLOCK_SKIPPING;
import static com.android.server.uwb.config.CapabilityParam.DYNAMIC_STS;
import static com.android.server.uwb.config.CapabilityParam.DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY;
import static com.android.server.uwb.config.CapabilityParam.ESS_TWR_NON_DEFERRED;
import static com.android.server.uwb.config.CapabilityParam.EXTENDED_MAC_ADDRESS;
import static com.android.server.uwb.config.CapabilityParam.HOPPING_MODE;
import static com.android.server.uwb.config.CapabilityParam.INITIATOR;
import static com.android.server.uwb.config.CapabilityParam.INTERVAL_BASED_SCHEDULING;
import static com.android.server.uwb.config.CapabilityParam.MANY_TO_MANY;
import static com.android.server.uwb.config.CapabilityParam.OBSERVER;
import static com.android.server.uwb.config.CapabilityParam.ONE_TO_MANY;
import static com.android.server.uwb.config.CapabilityParam.OWR_AOA;
import static com.android.server.uwb.config.CapabilityParam.OWR_DL_TDOA;
import static com.android.server.uwb.config.CapabilityParam.OWR_UL_TDOA;
import static com.android.server.uwb.config.CapabilityParam.PROVISIONED_STS;
import static com.android.server.uwb.config.CapabilityParam.PROVISIONED_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY;
import static com.android.server.uwb.config.CapabilityParam.PSDU_LENGTH_SUPPORT;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_DISABLE;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG;
import static com.android.server.uwb.config.CapabilityParam.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG;
import static com.android.server.uwb.config.CapabilityParam.RESPONDER;
import static com.android.server.uwb.config.CapabilityParam.RSSI_REPORTING;
import static com.android.server.uwb.config.CapabilityParam.SP0;
import static com.android.server.uwb.config.CapabilityParam.SP1;
import static com.android.server.uwb.config.CapabilityParam.SP3;
import static com.android.server.uwb.config.CapabilityParam.SS_TWR_DEFERRED;
import static com.android.server.uwb.config.CapabilityParam.SS_TWR_NON_DEFERRED;
import static com.android.server.uwb.config.CapabilityParam.STATIC_STS;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA_RESULT_REQ_INTERLEAVING;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_AOA_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BLOCK_STRIDING_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BLOCK_STRIDING_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BPRF_PARAMETER_SETS_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_BPRF_PARAMETER_SETS_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CC_CONSTRAINT_LENGTH_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CC_CONSTRAINT_LENGTH_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CHANNELS_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_CHANNELS_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DEVICE_ROLES_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DEVICE_ROLES_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DEVICE_TYPE_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DIAGNOSTICS;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DT_TAG_BLOCK_SKIPPING_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_DT_TAG_MAX_ACTIVE_RR_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_EXTENDED_MAC_ADDRESS_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_EXTENDED_MAC_ADDRESS_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HOPPING_MODE_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HOPPING_MODE_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HPRF_PARAMETER_SETS_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_HPRF_PARAMETER_SETS_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_MESSAGE_SIZE_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_MESSAGE_SIZE_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MAX_RANGING_SESSION_NUMBER;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MIN_RANGING_INTERVAL_MS;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MIN_SLOT_DURATION_RSTU;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MULTI_NODE_MODES_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_MULTI_NODE_MODES_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_PSDU_LENGTH_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGE_DATA_NTF_CONFIG;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_METHOD_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_METHOD_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_TIME_STRUCT_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RANGING_TIME_STRUCT_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RFRAME_CONFIG_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RFRAME_CONFIG_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_RSSI_REPORTING;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SCHEDULED_MODE_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SCHEDULED_MODE_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SESSION_KEY_LENGTH_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_STS_CONFIG_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_STS_CONFIG_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_SUSPEND_RANGING_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_UWB_INITIATION_TIME_VER_1_0;
import static com.android.server.uwb.config.CapabilityParam.SUPPORTED_UWB_INITIATION_TIME_VER_2_0;
import static com.android.server.uwb.config.CapabilityParam.TIME_SCHEDULED_RANGING;
import static com.android.server.uwb.config.CapabilityParam.UNICAST;
import static com.android.server.uwb.config.CapabilityParam.UT_ANCHOR;
import static com.android.server.uwb.config.CapabilityParam.UT_SYNCHRONIZATION_ANCHOR;
import static com.android.server.uwb.config.CapabilityParam.UT_TAG;
import static com.android.server.uwb.config.CapabilityParam.UWB_INITIATION_TIME;
import android.util.Log;
import com.android.server.uwb.UwbInjector;
import com.google.uwb.support.base.FlagEnum;
import com.google.uwb.support.base.Params;
import com.google.uwb.support.base.ProtocolVersion;
import com.google.uwb.support.fira.FiraParams;
import com.google.uwb.support.fira.FiraParams.BprfParameterSetCapabilityFlag;
import com.google.uwb.support.fira.FiraParams.CcConstraintLengthCapabilitiesFlag;
import com.google.uwb.support.fira.FiraParams.DeviceRoleCapabilityFlag;
import com.google.uwb.support.fira.FiraParams.HprfParameterSetCapabilityFlag;
import com.google.uwb.support.fira.FiraParams.MultiNodeCapabilityFlag;
import com.google.uwb.support.fira.FiraParams.PsduDataRateCapabilityFlag;
import com.google.uwb.support.fira.FiraParams.RangingRoundCapabilityFlag;
import com.google.uwb.support.fira.FiraParams.RangingTimeStructCapabilitiesFlag;
import com.google.uwb.support.fira.FiraParams.RframeCapabilityFlag;
import com.google.uwb.support.fira.FiraParams.SchedulingModeCapabilitiesFlag;
import com.google.uwb.support.fira.FiraParams.StsCapabilityFlag;
import com.google.uwb.support.fira.FiraProtocolVersion;
import com.google.uwb.support.fira.FiraSpecificationParams;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.stream.IntStream;
public class FiraDecoder extends TlvDecoder {
private static final String TAG = "FiraDecoder";
private final UwbInjector mUwbInjector;
public FiraDecoder(UwbInjector uwbInjector) {
mUwbInjector = uwbInjector;
}
@Override
public <T extends Params> T getParams(TlvDecoderBuffer tlvs, Class<T> paramType,
ProtocolVersion protocolVersion) {
if (FiraSpecificationParams.class.equals(paramType)) {
// The "protocolVersion" is always expected to be of type "FiraProtocolVersion" here,
// but in case it's not, we use a backup value of "PROTOCOL_VERSION_1_1".
FiraProtocolVersion uwbsFiraProtocolVersion =
(protocolVersion instanceof FiraProtocolVersion)
? (FiraProtocolVersion) protocolVersion : FiraParams.PROTOCOL_VERSION_1_1;
return (T) getFiraSpecificationParamsFromTlvBuffer(tlvs, uwbsFiraProtocolVersion);
}
return null;
}
private static boolean isBitSet(int flags, int mask) {
return (flags & mask) != 0;
}
private FiraSpecificationParams getFiraSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs,
ProtocolVersion protocolVersion) {
FiraSpecificationParams.Builder builder = new FiraSpecificationParams.Builder();
byte[] versionCheck = tlvs.getByteArray(SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_2_0);
if (versionCheck.length == 1) {
// FiRa Version 1.0
byte[] phyVersions = tlvs.getByteArray(SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_1_0);
builder.setMinPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 0));
builder.setMaxPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 2));
byte[] macVersions = tlvs.getByteArray(SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_1_0);
builder.setMinMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 0));
builder.setMaxMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 2));
byte deviceRolesUci = tlvs.getByte(SUPPORTED_DEVICE_ROLES_VER_1_0);
EnumSet<DeviceRoleCapabilityFlag> deviceRoles =
EnumSet.noneOf(DeviceRoleCapabilityFlag.class);
if (isBitSet(deviceRolesUci, INITIATOR)) {
// This assumes both controller + controlee is supported.
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_INITIATOR_SUPPORT);
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_INITIATOR_SUPPORT);
}
if (isBitSet(deviceRolesUci, RESPONDER)) {
// This assumes both controller + controlee is supported.
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_RESPONDER_SUPPORT);
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_RESPONDER_SUPPORT);
}
builder.setDeviceRoleCapabilities(deviceRoles);
byte rangingMethodUci = tlvs.getByte(SUPPORTED_RANGING_METHOD_VER_1_0);
EnumSet<RangingRoundCapabilityFlag> rangingRoundFlag = EnumSet.noneOf(
RangingRoundCapabilityFlag.class);
if (isBitSet(rangingMethodUci, DS_TWR_DEFERRED)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_DS_TWR_SUPPORT);
}
if (isBitSet(rangingMethodUci, SS_TWR_DEFERRED)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_SS_TWR_SUPPORT);
}
builder.setRangingRoundCapabilities(rangingRoundFlag);
// TODO(b/209053358): This does not align with UCI spec.
if (isBitSet(rangingMethodUci, DS_TWR_NON_DEFERRED)
|| isBitSet(rangingMethodUci, SS_TWR_NON_DEFERRED)) {
builder.hasNonDeferredModeSupport(true);
}
byte stsConfigUci = tlvs.getByte(SUPPORTED_STS_CONFIG_VER_1_0);
EnumSet<StsCapabilityFlag> stsCapabilityFlag = EnumSet.noneOf(StsCapabilityFlag.class);
if (isBitSet(stsConfigUci, STATIC_STS)) {
stsCapabilityFlag.add(StsCapabilityFlag.HAS_STATIC_STS_SUPPORT);
}
if (isBitSet(stsConfigUci, DYNAMIC_STS)) {
stsCapabilityFlag.add(StsCapabilityFlag.HAS_DYNAMIC_STS_SUPPORT);
}
if (isBitSet(stsConfigUci, DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) {
stsCapabilityFlag.add(
StsCapabilityFlag.HAS_DYNAMIC_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT);
}
if (isBitSet(stsConfigUci, PROVISIONED_STS)) {
stsCapabilityFlag.add(StsCapabilityFlag.HAS_PROVISIONED_STS_SUPPORT);
}
if (isBitSet(stsConfigUci, PROVISIONED_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) {
stsCapabilityFlag.add(
StsCapabilityFlag.HAS_PROVISIONED_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT);
}
builder.setStsCapabilities(stsCapabilityFlag);
byte multiNodeUci = tlvs.getByte(SUPPORTED_MULTI_NODE_MODES_VER_1_0);
EnumSet<MultiNodeCapabilityFlag> multiNodeFlag =
EnumSet.noneOf(MultiNodeCapabilityFlag.class);
if (isBitSet(multiNodeUci, UNICAST)) {
multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_UNICAST_SUPPORT);
}
if (isBitSet(multiNodeUci, ONE_TO_MANY)) {
multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_ONE_TO_MANY_SUPPORT);
}
if (isBitSet(multiNodeUci, MANY_TO_MANY)) {
multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_MANY_TO_MANY_SUPPORT);
}
builder.setMultiNodeCapabilities(multiNodeFlag);
byte rangingTimeStructUci = tlvs.getByte(SUPPORTED_RANGING_TIME_STRUCT_VER_1_0);
EnumSet<RangingTimeStructCapabilitiesFlag> rangingTimeStructFlag =
EnumSet.noneOf(RangingTimeStructCapabilitiesFlag.class);
if (protocolVersion.getMajor() <= 2
&& isBitSet(rangingTimeStructUci, INTERVAL_BASED_SCHEDULING)) {
rangingTimeStructFlag.add(
RangingTimeStructCapabilitiesFlag.HAS_INTERVAL_BASED_SCHEDULING_SUPPORT);
}
if (isBitSet(rangingTimeStructUci, BLOCK_BASED_SCHEDULING)) {
rangingTimeStructFlag.add(
RangingTimeStructCapabilitiesFlag.HAS_BLOCK_BASED_SCHEDULING_SUPPORT);
}
builder.setRangingTimeStructCapabilities(rangingTimeStructFlag);
byte schedulingModeUci = tlvs.getByte(SUPPORTED_SCHEDULED_MODE_VER_1_0);
EnumSet<SchedulingModeCapabilitiesFlag> schedulingModeFlag =
EnumSet.noneOf(SchedulingModeCapabilitiesFlag.class);
if (isBitSet(schedulingModeUci, CONTENTION_BASED_RANGING)) {
schedulingModeFlag.add(
SchedulingModeCapabilitiesFlag.HAS_CONTENTION_BASED_RANGING_SUPPORT);
}
if (isBitSet(schedulingModeUci, TIME_SCHEDULED_RANGING)) {
schedulingModeFlag.add(
SchedulingModeCapabilitiesFlag.HAS_TIME_SCHEDULED_RANGING_SUPPORT);
}
builder.setSchedulingModeCapabilities(schedulingModeFlag);
byte ccConstraintLengthUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_1_0);
EnumSet<CcConstraintLengthCapabilitiesFlag> ccConstraintLengthFlag =
EnumSet.noneOf(CcConstraintLengthCapabilitiesFlag.class);
if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_3)) {
ccConstraintLengthFlag.add(
CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_3_SUPPORT);
}
if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_7)) {
ccConstraintLengthFlag.add(
CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_7_SUPPORT);
}
builder.setCcConstraintLengthCapabilities(ccConstraintLengthFlag);
byte blockStridingUci = tlvs.getByte(SUPPORTED_BLOCK_STRIDING_VER_1_0);
if (isBitSet(blockStridingUci, BLOCK_STRIDING)) {
builder.hasBlockStridingSupport(true);
}
byte hoppingPreferenceUci = tlvs.getByte(SUPPORTED_HOPPING_MODE_VER_1_0);
if (isBitSet(hoppingPreferenceUci, HOPPING_MODE)) {
builder.hasHoppingPreferenceSupport(true);
}
byte extendedMacAddressUci = tlvs.getByte(SUPPORTED_EXTENDED_MAC_ADDRESS_VER_1_0);
if (isBitSet(extendedMacAddressUci, EXTENDED_MAC_ADDRESS)) {
builder.hasExtendedMacAddressSupport(true);
}
byte initiationTimeUci = tlvs.getByte(SUPPORTED_UWB_INITIATION_TIME_VER_1_0);
if (isBitSet(initiationTimeUci, UWB_INITIATION_TIME)) {
builder.hasInitiationTimeSupport(true);
}
byte channelsUci = tlvs.getByte(SUPPORTED_CHANNELS_VER_1_0);
List<Integer> channels = new ArrayList<>();
if (isBitSet(channelsUci, CHANNEL_5)) {
channels.add(5);
}
if (isBitSet(channelsUci, CHANNEL_6)) {
channels.add(6);
}
if (isBitSet(channelsUci, CHANNEL_8)) {
channels.add(8);
}
if (isBitSet(channelsUci, CHANNEL_9)) {
channels.add(9);
}
if (isBitSet(channelsUci, CHANNEL_10)) {
channels.add(10);
}
if (isBitSet(channelsUci, CHANNEL_12)) {
channels.add(12);
}
if (isBitSet(channelsUci, CHANNEL_13)) {
channels.add(13);
}
if (isBitSet(channelsUci, CHANNEL_14)) {
channels.add(14);
}
builder.setSupportedChannels(channels);
byte rframeConfigUci = tlvs.getByte(SUPPORTED_RFRAME_CONFIG_VER_1_0);
EnumSet<RframeCapabilityFlag> rframeConfigFlag =
EnumSet.noneOf(RframeCapabilityFlag.class);
if (isBitSet(rframeConfigUci, SP0)) {
rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP0_RFRAME_SUPPORT);
}
if (isBitSet(rframeConfigUci, SP1)) {
rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP1_RFRAME_SUPPORT);
}
if (isBitSet(rframeConfigUci, SP3)) {
rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP3_RFRAME_SUPPORT);
}
builder.setRframeCapabilities(rframeConfigFlag);
byte bprfSets = tlvs.getByte(SUPPORTED_BPRF_PARAMETER_SETS_VER_1_0);
int bprfSetsValue = Integer.valueOf(bprfSets);
EnumSet<BprfParameterSetCapabilityFlag> bprfFlag;
bprfFlag = FlagEnum.toEnumSet(bprfSetsValue, BprfParameterSetCapabilityFlag.values());
builder.setBprfParameterSetCapabilities(bprfFlag);
byte[] hprfSets = tlvs.getByteArray(SUPPORTED_HPRF_PARAMETER_SETS_VER_1_0);
// Extend the 5 bytes from HAL to 8 bytes for long.
long hprfSetsValue = new BigInteger(TlvUtil.getReverseBytes(hprfSets)).longValue();
EnumSet<HprfParameterSetCapabilityFlag> hprfFlag;
hprfFlag = FlagEnum.longToEnumSet(
hprfSetsValue, HprfParameterSetCapabilityFlag.values());
builder.setHprfParameterSetCapabilities(hprfFlag);
EnumSet<FiraParams.PrfCapabilityFlag> prfFlag =
EnumSet.noneOf(FiraParams.PrfCapabilityFlag.class);
boolean hasBprfSupport = bprfSets != 0;
if (hasBprfSupport) {
prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_BPRF_SUPPORT);
}
boolean hasHprfSupport =
IntStream.range(0, hprfSets.length).parallel().anyMatch(i -> hprfSets[i] != 0);
if (hasHprfSupport) {
prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_HPRF_SUPPORT);
}
builder.setPrfCapabilities(prfFlag);
byte ccConstraintUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_1_0);
EnumSet<PsduDataRateCapabilityFlag> psduRateFlag =
EnumSet.noneOf(PsduDataRateCapabilityFlag.class);
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasBprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_6M81_SUPPORT);
}
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasBprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_7M80_SUPPORT);
}
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasHprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_27M2_SUPPORT);
}
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasHprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_31M2_SUPPORT);
}
builder.setPsduDataRateCapabilities(psduRateFlag);
byte aoaUci = tlvs.getByte(SUPPORTED_AOA_VER_1_0);
EnumSet<FiraParams.AoaCapabilityFlag> aoaFlag =
EnumSet.noneOf(FiraParams.AoaCapabilityFlag.class);
if (isBitSet(aoaUci, AOA_AZIMUTH_90)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_AZIMUTH_SUPPORT);
}
if (isBitSet(aoaUci, AOA_AZIMUTH_180)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FULL_AZIMUTH_SUPPORT);
}
if (isBitSet(aoaUci, AOA_ELEVATION)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_ELEVATION_SUPPORT);
}
if (isBitSet(aoaUci, AOA_FOM)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FOM_SUPPORT);
}
byte aoaInterleavingUci = tlvs.getByte(SUPPORTED_AOA_RESULT_REQ_INTERLEAVING);
if (isBitSet(aoaInterleavingUci, AOA_RESULT_REQ_INTERLEAVING)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_INTERLEAVING_SUPPORT);
}
builder.setAoaCapabilities(aoaFlag);
try {
int maxMessageSizeUci = tlvs.getShort(SUPPORTED_MAX_MESSAGE_SIZE_VER_1_0);
builder.setMaxMessageSize(Integer.valueOf(maxMessageSizeUci));
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_MAX_MESSAGE_SIZE not found.");
}
try {
int maxDataPacketPayloadSizeUci = tlvs.getShort(
SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_1_0);
builder.setMaxDataPacketPayloadSize(Integer.valueOf(maxDataPacketPayloadSizeUci));
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE not found.");
}
} else if (versionCheck.length == 4) {
// FiRa Version 2.0
byte[] phyVersions = tlvs.getByteArray(SUPPORTED_FIRA_PHY_VERSION_RANGE_VER_2_0);
builder.setMinPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 0));
builder.setMaxPhyVersionSupported(FiraProtocolVersion.fromBytes(phyVersions, 2));
byte[] macVersions = tlvs.getByteArray(SUPPORTED_FIRA_MAC_VERSION_RANGE_VER_2_0);
builder.setMinMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 0));
builder.setMaxMacVersionSupported(FiraProtocolVersion.fromBytes(macVersions, 2));
byte[] deviceRolesUci = tlvs.getByteArray(SUPPORTED_DEVICE_ROLES_VER_2_0);
EnumSet<DeviceRoleCapabilityFlag> deviceRoles =
EnumSet.noneOf(DeviceRoleCapabilityFlag.class);
if (isBitSet(deviceRolesUci[0], INITIATOR)) {
// This assumes both controller + controlee is supported.
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_INITIATOR_SUPPORT);
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_INITIATOR_SUPPORT);
}
if (isBitSet(deviceRolesUci[0], RESPONDER)) {
// This assumes both controller + controlee is supported.
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLLER_RESPONDER_SUPPORT);
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_CONTROLEE_RESPONDER_SUPPORT);
}
if (isBitSet(deviceRolesUci[0], UT_SYNCHRONIZATION_ANCHOR)) {
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_UT_SYNCHRONIZATION_SUPPORT);
}
if (isBitSet(deviceRolesUci[0], UT_ANCHOR)) {
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_UT_ANCHOR_SUPPORT);
}
if (isBitSet(deviceRolesUci[0], UT_TAG)) {
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_UT_TAG_SUPPORT);
}
if (isBitSet(deviceRolesUci[0], ADVERTISER)) {
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_ADVERTISER_SUPPORT);
}
if (isBitSet(deviceRolesUci[0], OBSERVER)) {
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_OBSERVER_SUPPORT);
}
if (isBitSet(deviceRolesUci[0], DT_ANCHOR)) {
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_DT_ANCHOR_SUPPORT);
}
if (isBitSet(deviceRolesUci[1], DT_TAG)) {
deviceRoles.add(DeviceRoleCapabilityFlag.HAS_DT_TAG_SUPPORT);
}
builder.setDeviceRoleCapabilities(deviceRoles);
byte[] rangingMethodUci = tlvs.getByteArray(SUPPORTED_RANGING_METHOD_VER_2_0);
EnumSet<RangingRoundCapabilityFlag> rangingRoundFlag = EnumSet.noneOf(
RangingRoundCapabilityFlag.class);
if (isBitSet(rangingMethodUci[0], DS_TWR_DEFERRED)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_DS_TWR_SUPPORT);
}
if (isBitSet(rangingMethodUci[0], SS_TWR_DEFERRED)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_SS_TWR_SUPPORT);
}
if (isBitSet(rangingMethodUci[0], OWR_UL_TDOA)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_OWR_UL_TDOA_SUPPORT);
}
if (isBitSet(rangingMethodUci[0], OWR_DL_TDOA)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_OWR_DL_TDOA_SUPPORT);
}
if (isBitSet(rangingMethodUci[0], OWR_AOA)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_OWR_AOA_SUPPORT);
}
if (isBitSet(rangingMethodUci[0], ESS_TWR_NON_DEFERRED)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_ESS_TWR_SUPPORT);
}
if (isBitSet(rangingMethodUci[1], ADS_TWR)) {
rangingRoundFlag.add(RangingRoundCapabilityFlag.HAS_ADS_TWR_SUPPORT);
}
builder.setRangingRoundCapabilities(rangingRoundFlag);
// TODO(b/209053358): This does not align with UCI spec.
if (isBitSet(rangingMethodUci[0], DS_TWR_NON_DEFERRED)
|| isBitSet(rangingMethodUci[0], SS_TWR_NON_DEFERRED)) {
builder.hasNonDeferredModeSupport(true);
}
byte stsConfigUci = tlvs.getByte(SUPPORTED_STS_CONFIG_VER_2_0);
EnumSet<StsCapabilityFlag> stsCapabilityFlag = EnumSet.noneOf(StsCapabilityFlag.class);
if (isBitSet(stsConfigUci, STATIC_STS)) {
stsCapabilityFlag.add(StsCapabilityFlag.HAS_STATIC_STS_SUPPORT);
}
if (isBitSet(stsConfigUci, DYNAMIC_STS)) {
stsCapabilityFlag.add(StsCapabilityFlag.HAS_DYNAMIC_STS_SUPPORT);
}
if (isBitSet(stsConfigUci, DYNAMIC_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) {
stsCapabilityFlag.add(
StsCapabilityFlag.HAS_DYNAMIC_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT);
}
if (isBitSet(stsConfigUci, PROVISIONED_STS)) {
stsCapabilityFlag.add(StsCapabilityFlag.HAS_PROVISIONED_STS_SUPPORT);
}
if (isBitSet(stsConfigUci, PROVISIONED_STS_RESPONDER_SPECIFIC_SUBSESSION_KEY)) {
stsCapabilityFlag.add(
StsCapabilityFlag.HAS_PROVISIONED_STS_INDIVIDUAL_CONTROLEE_KEY_SUPPORT);
}
builder.setStsCapabilities(stsCapabilityFlag);
byte multiNodeUci = tlvs.getByte(SUPPORTED_MULTI_NODE_MODES_VER_2_0);
EnumSet<MultiNodeCapabilityFlag> multiNodeFlag =
EnumSet.noneOf(MultiNodeCapabilityFlag.class);
if (isBitSet(multiNodeUci, UNICAST)) {
multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_UNICAST_SUPPORT);
}
if (isBitSet(multiNodeUci, ONE_TO_MANY)) {
multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_ONE_TO_MANY_SUPPORT);
}
if (isBitSet(multiNodeUci, MANY_TO_MANY)) {
multiNodeFlag.add(MultiNodeCapabilityFlag.HAS_MANY_TO_MANY_SUPPORT);
}
builder.setMultiNodeCapabilities(multiNodeFlag);
byte rangingTimeStructUci = tlvs.getByte(SUPPORTED_RANGING_TIME_STRUCT_VER_2_0);
EnumSet<RangingTimeStructCapabilitiesFlag> rangingTimeStructFlag =
EnumSet.noneOf(RangingTimeStructCapabilitiesFlag.class);
// When CR-423 is implemented, do not parse for the "INTERVAL_BASED_SCHEDULING" bit.
if (!mUwbInjector.getFeatureFlags().cr423CleanupIntervalScheduling()) {
if (isBitSet(rangingTimeStructUci, INTERVAL_BASED_SCHEDULING)) {
rangingTimeStructFlag.add(
RangingTimeStructCapabilitiesFlag.HAS_INTERVAL_BASED_SCHEDULING_SUPPORT);
}
}
if (isBitSet(rangingTimeStructUci, BLOCK_BASED_SCHEDULING)) {
rangingTimeStructFlag.add(
RangingTimeStructCapabilitiesFlag.HAS_BLOCK_BASED_SCHEDULING_SUPPORT);
}
builder.setRangingTimeStructCapabilities(rangingTimeStructFlag);
byte schedulingModeUci = tlvs.getByte(SUPPORTED_SCHEDULED_MODE_VER_2_0);
EnumSet<SchedulingModeCapabilitiesFlag> schedulingModeFlag =
EnumSet.noneOf(SchedulingModeCapabilitiesFlag.class);
if (isBitSet(schedulingModeUci, CONTENTION_BASED_RANGING)) {
schedulingModeFlag.add(
SchedulingModeCapabilitiesFlag.HAS_CONTENTION_BASED_RANGING_SUPPORT);
}
if (isBitSet(schedulingModeUci, TIME_SCHEDULED_RANGING)) {
schedulingModeFlag.add(
SchedulingModeCapabilitiesFlag.HAS_TIME_SCHEDULED_RANGING_SUPPORT);
}
builder.setSchedulingModeCapabilities(schedulingModeFlag);
byte ccConstraintLengthUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_2_0);
EnumSet<CcConstraintLengthCapabilitiesFlag> ccConstraintLengthFlag =
EnumSet.noneOf(CcConstraintLengthCapabilitiesFlag.class);
if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_3)) {
ccConstraintLengthFlag.add(
CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_3_SUPPORT);
}
if (isBitSet(ccConstraintLengthUci, CONSTRAINT_LENGTH_7)) {
ccConstraintLengthFlag.add(
CcConstraintLengthCapabilitiesFlag.HAS_CONSTRAINT_LENGTH_7_SUPPORT);
}
builder.setCcConstraintLengthCapabilities(ccConstraintLengthFlag);
byte blockStridingUci = tlvs.getByte(SUPPORTED_BLOCK_STRIDING_VER_2_0);
if (isBitSet(blockStridingUci, BLOCK_STRIDING)) {
builder.hasBlockStridingSupport(true);
}
byte hoppingPreferenceUci = tlvs.getByte(SUPPORTED_HOPPING_MODE_VER_2_0);
if (isBitSet(hoppingPreferenceUci, HOPPING_MODE)) {
builder.hasHoppingPreferenceSupport(true);
}
byte extendedMacAddressUci = tlvs.getByte(SUPPORTED_EXTENDED_MAC_ADDRESS_VER_2_0);
if (isBitSet(extendedMacAddressUci, EXTENDED_MAC_ADDRESS)) {
builder.hasExtendedMacAddressSupport(true);
}
byte initiationTimeUci = tlvs.getByte(SUPPORTED_UWB_INITIATION_TIME_VER_2_0);
if (isBitSet(initiationTimeUci, UWB_INITIATION_TIME)) {
builder.hasInitiationTimeSupport(true);
}
byte channelsUci = tlvs.getByte(SUPPORTED_CHANNELS_VER_2_0);
List<Integer> channels = new ArrayList<>();
if (isBitSet(channelsUci, CHANNEL_5)) {
channels.add(5);
}
if (isBitSet(channelsUci, CHANNEL_6)) {
channels.add(6);
}
if (isBitSet(channelsUci, CHANNEL_8)) {
channels.add(8);
}
if (isBitSet(channelsUci, CHANNEL_9)) {
channels.add(9);
}
if (isBitSet(channelsUci, CHANNEL_10)) {
channels.add(10);
}
if (isBitSet(channelsUci, CHANNEL_12)) {
channels.add(12);
}
if (isBitSet(channelsUci, CHANNEL_13)) {
channels.add(13);
}
if (isBitSet(channelsUci, CHANNEL_14)) {
channels.add(14);
}
builder.setSupportedChannels(channels);
byte rframeConfigUci = tlvs.getByte(SUPPORTED_RFRAME_CONFIG_VER_2_0);
EnumSet<RframeCapabilityFlag> rframeConfigFlag =
EnumSet.noneOf(RframeCapabilityFlag.class);
if (isBitSet(rframeConfigUci, SP0)) {
rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP0_RFRAME_SUPPORT);
}
if (isBitSet(rframeConfigUci, SP1)) {
rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP1_RFRAME_SUPPORT);
}
if (isBitSet(rframeConfigUci, SP3)) {
rframeConfigFlag.add(RframeCapabilityFlag.HAS_SP3_RFRAME_SUPPORT);
}
builder.setRframeCapabilities(rframeConfigFlag);
byte bprfSets = tlvs.getByte(SUPPORTED_BPRF_PARAMETER_SETS_VER_2_0);
int bprfSetsValue = Integer.valueOf(bprfSets);
EnumSet<BprfParameterSetCapabilityFlag> bprfFlag;
bprfFlag = FlagEnum.toEnumSet(bprfSetsValue, BprfParameterSetCapabilityFlag.values());
builder.setBprfParameterSetCapabilities(bprfFlag);
byte[] hprfSets = tlvs.getByteArray(SUPPORTED_HPRF_PARAMETER_SETS_VER_2_0);
// Extend the 5 bytes from HAL to 8 bytes for long.
long hprfSetsValue = new BigInteger(TlvUtil.getReverseBytes(hprfSets)).longValue();
EnumSet<HprfParameterSetCapabilityFlag> hprfFlag;
hprfFlag = FlagEnum.longToEnumSet(
hprfSetsValue, HprfParameterSetCapabilityFlag.values());
builder.setHprfParameterSetCapabilities(hprfFlag);
EnumSet<FiraParams.PrfCapabilityFlag> prfFlag =
EnumSet.noneOf(FiraParams.PrfCapabilityFlag.class);
boolean hasBprfSupport = bprfSets != 0;
if (hasBprfSupport) {
prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_BPRF_SUPPORT);
}
boolean hasHprfSupport =
IntStream.range(0, hprfSets.length).parallel().anyMatch(i -> hprfSets[i] != 0);
if (hasHprfSupport) {
prfFlag.add(FiraParams.PrfCapabilityFlag.HAS_HPRF_SUPPORT);
}
builder.setPrfCapabilities(prfFlag);
byte ccConstraintUci = tlvs.getByte(SUPPORTED_CC_CONSTRAINT_LENGTH_VER_2_0);
EnumSet<PsduDataRateCapabilityFlag> psduRateFlag =
EnumSet.noneOf(PsduDataRateCapabilityFlag.class);
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasBprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_6M81_SUPPORT);
}
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasBprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_7M80_SUPPORT);
}
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K3) && hasHprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_27M2_SUPPORT);
}
if (isBitSet(ccConstraintUci, CC_CONSTRAINT_LENGTH_K7) && hasHprfSupport) {
psduRateFlag.add(PsduDataRateCapabilityFlag.HAS_31M2_SUPPORT);
}
builder.setPsduDataRateCapabilities(psduRateFlag);
byte aoaUci = tlvs.getByte(SUPPORTED_AOA_VER_2_0);
EnumSet<FiraParams.AoaCapabilityFlag> aoaFlag =
EnumSet.noneOf(FiraParams.AoaCapabilityFlag.class);
if (isBitSet(aoaUci, AOA_AZIMUTH_90)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_AZIMUTH_SUPPORT);
}
if (isBitSet(aoaUci, AOA_AZIMUTH_180)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FULL_AZIMUTH_SUPPORT);
}
if (isBitSet(aoaUci, AOA_ELEVATION)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_ELEVATION_SUPPORT);
}
if (isBitSet(aoaUci, AOA_FOM)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_FOM_SUPPORT);
}
byte aoaInterleavingUci = tlvs.getByte(SUPPORTED_AOA_RESULT_REQ_INTERLEAVING);
if (isBitSet(aoaInterleavingUci, AOA_RESULT_REQ_INTERLEAVING)) {
aoaFlag.add(FiraParams.AoaCapabilityFlag.HAS_INTERLEAVING_SUPPORT);
}
builder.setAoaCapabilities(aoaFlag);
try {
int maxMessageSizeUci = tlvs.getShort(SUPPORTED_MAX_MESSAGE_SIZE_VER_2_0);
builder.setMaxMessageSize(Integer.valueOf(maxMessageSizeUci));
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_MAX_MESSAGE_SIZE not found.");
}
try {
int maxDataPacketPayloadSizeUci = tlvs.getShort(
SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE_VER_2_0);
builder.setMaxDataPacketPayloadSize(Integer.valueOf(maxDataPacketPayloadSizeUci));
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_MAX_DATA_PACKET_PAYLOAD_SIZE not found.");
}
int deviceType = tlvs.getByte(SUPPORTED_DEVICE_TYPE_VER_2_0);
builder.setDeviceType(deviceType);
int supportedSuspendSupport = tlvs.getByte(SUPPORTED_SUSPEND_RANGING_VER_2_0);
builder.setSuspendRangingSupport(supportedSuspendSupport != 0);
int sessionKeyLength = tlvs.getByte(SUPPORTED_SESSION_KEY_LENGTH_VER_2_0);
builder.setSessionKeyLength(sessionKeyLength);
try {
int dtTagMaxActiveRr = tlvs.getByte(SUPPORTED_DT_TAG_MAX_ACTIVE_RR_2_0);
builder.setDtTagMaxActiveRr(dtTagMaxActiveRr);
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_DT_TAG_MAX_ACTIVE_RR not found.");
}
try {
byte dtTagBlockSkippingUci = tlvs.getByte(SUPPORTED_DT_TAG_BLOCK_SKIPPING_2_0);
if (isBitSet(dtTagBlockSkippingUci, DT_TAG_BLOCK_SKIPPING)) {
builder.setDtTagBlockSkippingSupport(true);
}
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_DT_TAG_BLOCK_SKIPPING_2_0 not found.");
}
try {
byte psduLengthUci = tlvs.getByte(SUPPORTED_PSDU_LENGTH_2_0);
if (isBitSet(psduLengthUci, PSDU_LENGTH_SUPPORT)) {
builder.setPsduLengthSupport(true);
}
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_PSDU_LENGTH_2_0 not found.");
}
} else {
// This FiRa version is not supported yet.
return null;
}
try {
int minRangingInterval = tlvs.getInt(SUPPORTED_MIN_RANGING_INTERVAL_MS);
builder.setMinRangingIntervalSupported(minRangingInterval);
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_MIN_RANGING_INTERVAL_MS not found.");
}
try {
int minSlotDurationUs = TlvUtil.rstuToUs(tlvs.getInt(SUPPORTED_MIN_SLOT_DURATION_RSTU));
builder.setMinSlotDurationSupportedUs(minSlotDurationUs);
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_MIN_SLOT_DURATION not found.");
}
try {
int maxRangingSessionNumber = tlvs.getInt(SUPPORTED_MAX_RANGING_SESSION_NUMBER);
builder.setMaxRangingSessionNumberSupported(maxRangingSessionNumber);
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_MAX_RANGING_SESSION_NUMBER not found");
}
try {
byte rssiReporting = tlvs.getByte(SUPPORTED_RSSI_REPORTING);
if (isBitSet(rssiReporting, RSSI_REPORTING)) {
builder.hasRssiReportingSupport(true);
}
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_RSSI_REPORTING not found.");
}
try {
byte diagnostics = tlvs.getByte(SUPPORTED_DIAGNOSTICS);
if (isBitSet(diagnostics, DIAGNOSTICS)) {
builder.hasDiagnosticsSupport(true);
}
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_DIAGNOSTICS not found.");
}
try {
byte[] rangeDataNtfConfigUciBytes = tlvs.getByteArray(SUPPORTED_RANGE_DATA_NTF_CONFIG);
int rangeDataNtfConfigUci =
new BigInteger(TlvUtil.getReverseBytes(rangeDataNtfConfigUciBytes)).intValue();
EnumSet<FiraParams.RangeDataNtfConfigCapabilityFlag> rangeDataNtfConfigCapabilityFlag =
EnumSet.noneOf(FiraParams.RangeDataNtfConfigCapabilityFlag.class);
if (isBitSet(rangeDataNtfConfigUci, RANGE_DATA_NTF_CONFIG_ENABLE)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_ENABLE);
}
if (isBitSet(rangeDataNtfConfigUci, RANGE_DATA_NTF_CONFIG_DISABLE)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_DISABLE);
}
if (isBitSet(rangeDataNtfConfigUci,
RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_LEVEL_TRIG);
}
if (isBitSet(rangeDataNtfConfigUci,
RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG);
}
if (isBitSet(rangeDataNtfConfigUci,
RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG);
}
if (isBitSet(rangeDataNtfConfigUci,
RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_EDGE_TRIG);
}
if (isBitSet(rangeDataNtfConfigUci,
RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG);
}
if (isBitSet(rangeDataNtfConfigUci,
RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG)) {
rangeDataNtfConfigCapabilityFlag.add(
FiraParams.RangeDataNtfConfigCapabilityFlag
.HAS_RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG);
}
builder.setRangeDataNtfConfigCapabilities(rangeDataNtfConfigCapabilityFlag);
} catch (IllegalArgumentException e) {
Log.w(TAG, "SUPPORTED_RANGE_DATA_NTF_CONFIG not found.");
}
return builder.build();
}
}