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.google.uwb.support.fira.FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG; 20 import static com.google.uwb.support.fira.FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG; 21 import static com.google.uwb.support.fira.FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG; 22 import static com.google.uwb.support.fira.FiraParams.RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG; 23 24 import android.uwb.UwbAddress; 25 26 import com.android.modules.utils.build.SdkLevel; 27 import com.android.server.uwb.UwbInjector; 28 import com.android.server.uwb.config.ConfigParam; 29 import com.android.server.uwb.util.UwbUtil; 30 31 import com.google.uwb.support.base.Params; 32 import com.google.uwb.support.base.ProtocolVersion; 33 import com.google.uwb.support.fira.FiraOpenSessionParams; 34 import com.google.uwb.support.fira.FiraParams; 35 import com.google.uwb.support.fira.FiraProtocolVersion; 36 import com.google.uwb.support.fira.FiraRangingReconfigureParams; 37 38 import java.nio.ByteBuffer; 39 import java.util.Arrays; 40 41 public class FiraEncoder extends TlvEncoder { 42 private final UwbInjector mUwbInjector; 43 FiraEncoder(UwbInjector uwbInjector)44 public FiraEncoder(UwbInjector uwbInjector) { 45 mUwbInjector = uwbInjector; 46 } 47 48 @Override getTlvBuffer(Params param, ProtocolVersion protocolVersion)49 public TlvBuffer getTlvBuffer(Params param, ProtocolVersion protocolVersion) { 50 // The "protocolVersion" is always expected to be of type "FiraProtocolVersion" here, but 51 // in case it's not, we use a backup value of "PROTOCOL_VERSION_1_1". 52 FiraProtocolVersion uwbsFiraProtocolVersion = 53 (protocolVersion instanceof FiraProtocolVersion) 54 ? (FiraProtocolVersion) protocolVersion : FiraParams.PROTOCOL_VERSION_1_1; 55 if (param instanceof FiraOpenSessionParams) { 56 return getTlvBufferFromFiraOpenSessionParams(param, uwbsFiraProtocolVersion); 57 } 58 59 if (param instanceof FiraRangingReconfigureParams) { 60 return getTlvBufferFromFiraRangingReconfigureParams(param); 61 } 62 return null; 63 } 64 hasAoaBoundInRangeDataNtfConfig(int rangeDataNtfConfig)65 private static boolean hasAoaBoundInRangeDataNtfConfig(int rangeDataNtfConfig) { 66 return rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_AOA_LEVEL_TRIG 67 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_LEVEL_TRIG 68 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_AOA_EDGE_TRIG 69 || rangeDataNtfConfig == RANGE_DATA_NTF_CONFIG_ENABLE_PROXIMITY_AOA_EDGE_TRIG; 70 } 71 getTlvBufferFromFiraOpenSessionParams( Params baseParam, FiraProtocolVersion uwbsFiraProtocolVersion)72 private TlvBuffer getTlvBufferFromFiraOpenSessionParams( 73 Params baseParam, FiraProtocolVersion uwbsFiraProtocolVersion) { 74 FiraOpenSessionParams params = (FiraOpenSessionParams) baseParam; 75 int deviceType = params.getDeviceType(); 76 int resultReportConfig = getResultReportConfig(params); 77 int rangingRoundControl = getRangingRoundControl(params); 78 int deviceRole = params.getDeviceRole(); 79 80 TlvBuffer.Builder tlvBufferBuilder = new TlvBuffer.Builder() 81 .putByte(ConfigParam.RANGING_ROUND_USAGE, (byte) params.getRangingRoundUsage()) 82 .putByte(ConfigParam.STS_CONFIG, (byte) params.getStsConfig()) 83 .putByte(ConfigParam.MULTI_NODE_MODE, (byte) params.getMultiNodeMode()) 84 .putByte(ConfigParam.CHANNEL_NUMBER, (byte) params.getChannelNumber()) 85 .putByteArray(ConfigParam.DEVICE_MAC_ADDRESS, params.getDeviceAddress().size(), 86 getComputedMacAddress(params.getDeviceAddress())) 87 .putShort(ConfigParam.SLOT_DURATION, (short) params.getSlotDurationRstu()) 88 .putByte(ConfigParam.MAC_FCS_TYPE, (byte) params.getFcsType()) 89 .putByte(ConfigParam.RANGING_ROUND_CONTROL, 90 (byte) rangingRoundControl/* params.getMeasurementReportType()*/) 91 .putByte(ConfigParam.AOA_RESULT_REQ, (byte) params.getAoaResultRequest()) 92 .putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, (byte) params.getRangeDataNtfConfig()) 93 .putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_NEAR, 94 (short) params.getRangeDataNtfProximityNear()) 95 .putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_FAR, 96 (short) params.getRangeDataNtfProximityFar()) 97 .putByte(ConfigParam.DEVICE_ROLE, (byte) params.getDeviceRole()) 98 .putByte(ConfigParam.RFRAME_CONFIG, (byte) params.getRframeConfig()) 99 .putByte(ConfigParam.RSSI_REPORTING, 100 (byte) (params.isRssiReportingEnabled() ? 1 : 0)) 101 .putByte(ConfigParam.PREAMBLE_CODE_INDEX, (byte) params.getPreambleCodeIndex()) 102 .putByte(ConfigParam.SFD_ID, (byte) params.getSfdId()) 103 .putByte(ConfigParam.PSDU_DATA_RATE, (byte) params.getPsduDataRate()) 104 .putByte(ConfigParam.PREAMBLE_DURATION, (byte) params.getPreambleDuration()) 105 // n.a. for OWR UL-TDoA and 0x01 for all other RangingRoundUsage values. 106 .putByte(ConfigParam.RANGING_TIME_STRUCT, (byte) params.getRangingTimeStruct()) 107 .putByte(ConfigParam.SLOTS_PER_RR, (byte) params.getSlotsPerRangingRound()) 108 .putByte(ConfigParam.PRF_MODE, (byte) params.getPrfMode()) 109 .putByte(ConfigParam.SCHEDULED_MODE, (byte) params.getScheduledMode()) 110 .putByte(ConfigParam.KEY_ROTATION, 111 params.isKeyRotationEnabled() ? (byte) 1 : (byte) 0) 112 .putByte(ConfigParam.KEY_ROTATION_RATE, (byte) params.getKeyRotationRate()) 113 .putByte(ConfigParam.SESSION_PRIORITY, (byte) params.getSessionPriority()) 114 .putByte(ConfigParam.MAC_ADDRESS_MODE, (byte) params.getMacAddressMode()) 115 .putByte(ConfigParam.NUMBER_OF_STS_SEGMENTS, (byte) params.getStsSegmentCount()) 116 .putShort(ConfigParam.MAX_RR_RETRY, (short) params.getMaxRangingRoundRetries()) 117 .putByte(ConfigParam.HOPPING_MODE, 118 (byte) params.getHoppingMode()) 119 .putByte(ConfigParam.BLOCK_STRIDE_LENGTH, (byte) params.getBlockStrideLength()) 120 .putByte(ConfigParam.RESULT_REPORT_CONFIG, (byte) resultReportConfig) 121 .putByte(ConfigParam.IN_BAND_TERMINATION_ATTEMPT_COUNT, 122 (byte) params.getInBandTerminationAttemptCount()) 123 .putByte(ConfigParam.BPRF_PHR_DATA_RATE, 124 (byte) params.getBprfPhrDataRate()) 125 .putShort(ConfigParam.MAX_NUMBER_OF_MEASUREMENTS, 126 (short) params.getMaxNumberOfMeasurements()) 127 .putByte(ConfigParam.STS_LENGTH, (byte) params.getStsLength()); 128 if (params.getDeviceRole() != FiraParams.RANGING_DEVICE_UT_TAG) { 129 tlvBufferBuilder.putInt(ConfigParam.RANGING_INTERVAL, params.getRangingIntervalMs()); 130 } 131 if (deviceRole != FiraParams.RANGING_DEVICE_DT_TAG) { 132 tlvBufferBuilder.putByte(ConfigParam.DEVICE_TYPE, (byte) params.getDeviceType()); 133 } 134 135 if (isTimeScheduledTwrSession( 136 params.getScheduledMode(), params.getRangingRoundUsage())) { 137 if (params.getDestAddressList().size() > 0) { 138 ByteBuffer dstAddressList = ByteBuffer.allocate(1024); 139 for (UwbAddress address : params.getDestAddressList()) { 140 dstAddressList.put(getComputedMacAddress(address)); 141 } 142 tlvBufferBuilder 143 .putByte(ConfigParam.NUMBER_OF_CONTROLEES, 144 (byte) params.getDestAddressList().size()) 145 .putByteArray( 146 ConfigParam.DST_MAC_ADDRESS, dstAddressList.position(), 147 Arrays.copyOf(dstAddressList.array(), dstAddressList.position())); 148 } 149 } 150 151 if (uwbsFiraProtocolVersion.getMajor() >= 2) { 152 // Initiation time Changed from 4 byte field to 8 byte field in version 2. 153 if (deviceRole != FiraParams.RANGING_DEVICE_DT_TAG) { 154 // For FiRa 2.0+ device, prefer to set the Absolute UWB Initiation time. 155 if (params.getAbsoluteInitiationTime() > 0) { 156 tlvBufferBuilder.putLong(ConfigParam.UWB_INITIATION_TIME, 157 params.getAbsoluteInitiationTime()); 158 } else { 159 tlvBufferBuilder.putLong(ConfigParam.UWB_INITIATION_TIME, 160 params.getInitiationTime()); 161 } 162 } else { 163 tlvBufferBuilder.putByte(ConfigParam.DL_TDOA_BLOCK_STRIDING, 164 (byte) params.getDlTdoaBlockStriding()); 165 } 166 tlvBufferBuilder.putByte(ConfigParam.LINK_LAYER_MODE, (byte) params.getLinkLayerMode()) 167 .putByte(ConfigParam.DATA_REPETITION_COUNT, 168 (byte) params.getDataRepetitionCount()) 169 .putByte(ConfigParam.SESSION_DATA_TRANSFER_STATUS_NTF_CONFIG, 170 params.getSessionDataTransferStatusNtfConfig() ? (byte) 1 : (byte) 0) 171 .putByte(ConfigParam.APPLICATION_DATA_ENDPOINT, 172 (byte) params.getApplicationDataEndpoint()); 173 if (deviceType == FiraParams.RANGING_DEVICE_TYPE_CONTROLLER && UwbUtil.isBitSet( 174 params.getReferenceTimeBase(), 175 FiraParams.SESSION_TIME_BASE_REFERENCE_FEATURE_ENABLED)) { 176 tlvBufferBuilder.putByteArray(ConfigParam.SESSION_TIME_BASE, 177 getSessionTimeBase(params)); 178 } 179 } else { 180 if (deviceRole != FiraParams.RANGING_DEVICE_DT_TAG) { 181 tlvBufferBuilder 182 .putInt(ConfigParam.UWB_INITIATION_TIME, 183 Math.toIntExact(params.getInitiationTime())); 184 } 185 tlvBufferBuilder.putByte(ConfigParam.TX_ADAPTIVE_PAYLOAD_POWER, 186 params.isTxAdaptivePayloadPowerEnabled() ? (byte) 1 : (byte) 0); 187 } 188 189 configureStsParameters(tlvBufferBuilder, params); 190 191 if (params.getAoaResultRequest() 192 == FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_INTERLEAVED) { 193 tlvBufferBuilder.putByte(ConfigParam.NUM_RANGE_MEASUREMENTS, 194 (byte) params.getNumOfMsrmtFocusOnRange()) 195 .putByte(ConfigParam.NUM_AOA_AZIMUTH_MEASUREMENTS, 196 (byte) params.getNumOfMsrmtFocusOnAoaAzimuth()) 197 .putByte(ConfigParam.NUM_AOA_ELEVATION_MEASUREMENTS, 198 (byte) params.getNumOfMsrmtFocusOnAoaElevation()); 199 } 200 if (hasAoaBoundInRangeDataNtfConfig(params.getRangeDataNtfConfig())) { 201 tlvBufferBuilder.putShortArray(ConfigParam.RANGE_DATA_NTF_AOA_BOUND, new short[]{ 202 // TODO (b/235355249): Verify this conversion. This is using AOA value 203 // in UwbTwoWayMeasurement to external RangingMeasurement conversion as 204 // reference. 205 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 206 UwbUtil.radianTodegree( 207 params.getRangeDataNtfAoaAzimuthLower()), 9, 7), 16), 208 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 209 UwbUtil.radianTodegree( 210 params.getRangeDataNtfAoaAzimuthUpper()), 9, 7), 16), 211 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 212 UwbUtil.radianTodegree( 213 params.getRangeDataNtfAoaElevationLower()), 9, 7), 16), 214 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 215 UwbUtil.radianTodegree( 216 params.getRangeDataNtfAoaElevationUpper()), 9, 7), 16), 217 }); 218 } 219 if (params.isDiagnosticsEnabled()) { 220 tlvBufferBuilder.putByte(ConfigParam.ENABLE_DIAGNOSTICS_RSSI, (byte) 1); 221 if (SdkLevel.isAtLeastU()) { 222 // Fixed bug to be compliant with HAL interface. 223 tlvBufferBuilder.putByte(ConfigParam.ENABLE_DIAGRAMS_FRAME_REPORTS_FIELDS, 224 params.getDiagramsFrameReportsFieldsFlags()); 225 } else { 226 tlvBufferBuilder.putInt(ConfigParam.ENABLE_DIAGRAMS_FRAME_REPORTS_FIELDS, 227 params.getDiagramsFrameReportsFieldsFlags()); 228 } 229 } 230 if (params.getScheduledMode() == FiraParams.CONTENTION_BASED_RANGING) { 231 tlvBufferBuilder.putByteArray(ConfigParam.CAP_SIZE_RANGE, params.getCapSize()); 232 } 233 if (params.getDeviceRole() == FiraParams.RANGING_DEVICE_UT_TAG) { 234 tlvBufferBuilder.putInt(ConfigParam.UL_TDOA_TX_INTERVAL, 235 params.getUlTdoaTxIntervalMs()); 236 tlvBufferBuilder.putInt(ConfigParam.UL_TDOA_RANDOM_WINDOW, 237 params.getUlTdoaRandomWindowMs()); 238 tlvBufferBuilder.putByteArray(ConfigParam.UL_TDOA_DEVICE_ID, getUlTdoaDeviceId( 239 params.getUlTdoaDeviceIdType(), params.getUlTdoaDeviceId())); 240 tlvBufferBuilder.putByte(ConfigParam.UL_TDOA_TX_TIMESTAMP, 241 (byte) params.getUlTdoaTxTimestampType()); 242 } 243 if (params.getDeviceRole() == FiraParams.RANGING_DEVICE_ROLE_ADVERTISER || 244 params.getDeviceRole() == FiraParams.RANGING_DEVICE_ROLE_OBSERVER) { 245 tlvBufferBuilder 246 .putByte(ConfigParam.MIN_FRAMES_PER_RR, (byte) params.getMinFramesPerRr()) 247 .putShort(ConfigParam.MTU_SIZE, (short) params.getMtuSize()) 248 .putByte(ConfigParam.INTER_FRAME_INTERVAL, 249 (byte) params.getInterFrameInterval()); 250 } 251 252 if (mUwbInjector.getDeviceConfigFacade().isAntennaModeConfigSupported()) { 253 tlvBufferBuilder.putByte(ConfigParam.ANTENNA_MODE, params.getAntennaMode()); 254 } 255 return tlvBufferBuilder.build(); 256 } 257 isTimeScheduledTwrSession(int scheduledMode, int rangingUsage)258 private boolean isTimeScheduledTwrSession(int scheduledMode, int rangingUsage) { 259 if (scheduledMode == FiraParams.TIME_SCHEDULED_RANGING) { 260 if (rangingUsage == FiraParams.RANGING_ROUND_USAGE_SS_TWR_DEFERRED_MODE 261 || rangingUsage == FiraParams.RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE 262 || rangingUsage == FiraParams.RANGING_ROUND_USAGE_SS_TWR_NON_DEFERRED_MODE 263 || rangingUsage == FiraParams.RANGING_ROUND_USAGE_DS_TWR_NON_DEFERRED_MODE) { 264 return true; 265 } 266 } 267 return false; 268 } 269 configureStsParameters(TlvBuffer.Builder tlvBufferBuilder, FiraOpenSessionParams params)270 private void configureStsParameters(TlvBuffer.Builder tlvBufferBuilder, 271 FiraOpenSessionParams params) { 272 int stsConfig = params.getStsConfig(); 273 274 if (stsConfig == FiraParams.STS_CONFIG_STATIC) { 275 tlvBufferBuilder 276 .putByteArray(ConfigParam.VENDOR_ID, params.getVendorId() != null 277 ? getComputedVendorId(params.getVendorId()): null) 278 .putByteArray(ConfigParam.STATIC_STS_IV, params.getStaticStsIV()); 279 } else if (stsConfig == FiraParams.STS_CONFIG_DYNAMIC_FOR_CONTROLEE_INDIVIDUAL_KEY) { 280 if (params.getDeviceType() == FiraParams.RANGING_DEVICE_TYPE_CONTROLEE) { 281 tlvBufferBuilder.putInt(ConfigParam.SUB_SESSION_ID, params.getSubSessionId()); 282 } 283 } else if (stsConfig == FiraParams.STS_CONFIG_PROVISIONED) { 284 if (params.getSessionKey() != null ) { 285 tlvBufferBuilder.putByteArray(ConfigParam.SESSION_KEY, params.getSessionKey()); 286 } 287 } else if (stsConfig == FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY) { 288 if (params.getDeviceType() == FiraParams.RANGING_DEVICE_TYPE_CONTROLEE) { 289 tlvBufferBuilder.putInt(ConfigParam.SUB_SESSION_ID, params.getSubSessionId()); 290 if (params.getSubsessionKey() != null ) { 291 tlvBufferBuilder. 292 putByteArray(ConfigParam.SUBSESSION_KEY, params.getSubsessionKey()); 293 } 294 } 295 if (params.getSessionKey() != null ) { 296 tlvBufferBuilder.putByteArray(ConfigParam.SESSION_KEY, params.getSessionKey()); 297 } 298 } 299 } 300 getUlTdoaDeviceId(int ulTdoaDeviceIdType, byte[] ulTdoaDeviceId)301 private byte[] getUlTdoaDeviceId(int ulTdoaDeviceIdType, byte[] ulTdoaDeviceId) { 302 if (ulTdoaDeviceIdType == FiraParams.UL_TDOA_DEVICE_ID_NONE) { 303 // Device ID not included 304 return new byte[]{0}; 305 } 306 ByteBuffer buffer = ByteBuffer.allocate(ulTdoaDeviceId.length + 1); 307 buffer.put((byte) ulTdoaDeviceIdType); 308 buffer.put(ulTdoaDeviceId); 309 return buffer.array(); 310 } 311 getTlvBufferFromFiraRangingReconfigureParams(Params baseParam)312 private TlvBuffer getTlvBufferFromFiraRangingReconfigureParams(Params baseParam) { 313 FiraRangingReconfigureParams params = (FiraRangingReconfigureParams) baseParam; 314 TlvBuffer.Builder tlvBuilder = new TlvBuffer.Builder(); 315 Integer blockStrideLength = params.getBlockStrideLength(); 316 Integer rangeDataNtfConfig = params.getRangeDataNtfConfig(); 317 Integer rangeDataProximityNear = params.getRangeDataProximityNear(); 318 Integer rangeDataProximityFar = params.getRangeDataProximityFar(); 319 Double rangeDataAoaAzimuthLower = params.getRangeDataAoaAzimuthLower(); 320 Double rangeDataAoaAzimuthUpper = params.getRangeDataAoaAzimuthUpper(); 321 Double rangeDataAoaElevationLower = params.getRangeDataAoaElevationLower(); 322 Double rangeDataAoaElevationUpper = params.getRangeDataAoaElevationUpper(); 323 Integer suspendRangingRounds = params.getSuspendRangingRounds(); 324 325 if (blockStrideLength != null) { 326 tlvBuilder.putByte(ConfigParam.BLOCK_STRIDE_LENGTH, 327 (byte) blockStrideLength.intValue()); 328 } 329 330 if (rangeDataNtfConfig != null) { 331 tlvBuilder.putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, 332 (byte) rangeDataNtfConfig.intValue()); 333 } 334 335 if (rangeDataProximityNear != null) { 336 tlvBuilder.putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_NEAR, 337 (short) rangeDataProximityNear.intValue()); 338 } 339 340 if (rangeDataProximityFar != null) { 341 tlvBuilder.putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_FAR, 342 (short) rangeDataProximityFar.intValue()); 343 } 344 345 if (rangeDataNtfConfig != null && hasAoaBoundInRangeDataNtfConfig(rangeDataNtfConfig)) { 346 if ((rangeDataAoaAzimuthLower != null && rangeDataAoaAzimuthUpper != null) 347 || (rangeDataAoaElevationLower != null && rangeDataAoaElevationUpper != null)) { 348 rangeDataAoaAzimuthLower = rangeDataAoaAzimuthLower != null 349 ? rangeDataAoaAzimuthLower 350 : FiraParams.RANGE_DATA_NTF_AOA_AZIMUTH_LOWER_DEFAULT; 351 rangeDataAoaAzimuthUpper = rangeDataAoaAzimuthUpper != null 352 ? rangeDataAoaAzimuthUpper 353 : FiraParams.RANGE_DATA_NTF_AOA_AZIMUTH_UPPER_DEFAULT; 354 rangeDataAoaElevationLower = rangeDataAoaElevationLower != null 355 ? rangeDataAoaElevationLower 356 : FiraParams.RANGE_DATA_NTF_AOA_ELEVATION_LOWER_DEFAULT; 357 rangeDataAoaElevationUpper = rangeDataAoaElevationUpper != null 358 ? rangeDataAoaElevationUpper 359 : FiraParams.RANGE_DATA_NTF_AOA_ELEVATION_UPPER_DEFAULT; 360 tlvBuilder.putShortArray(ConfigParam.RANGE_DATA_NTF_AOA_BOUND, new short[]{ 361 // TODO (b/235355249): Verify this conversion. This is using AOA value 362 // in UwbTwoWayMeasurement to external RangingMeasurement conversion as 363 // reference. 364 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 365 UwbUtil.radianTodegree( 366 rangeDataAoaAzimuthLower.floatValue()), 9, 7), 16), 367 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 368 UwbUtil.radianTodegree( 369 rangeDataAoaAzimuthUpper.floatValue()), 9, 7), 16), 370 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 371 UwbUtil.radianTodegree( 372 rangeDataAoaElevationLower.floatValue()), 9, 7), 16), 373 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 374 UwbUtil.radianTodegree( 375 rangeDataAoaElevationUpper.floatValue()), 9, 7), 16), 376 }); 377 } 378 } 379 if (suspendRangingRounds != null) { 380 tlvBuilder.putByte(ConfigParam.SUSPEND_RANGING_ROUNDS, 381 (byte) suspendRangingRounds.intValue()); 382 } 383 return tlvBuilder.build(); 384 } 385 386 // Merged data from other parameter values getResultReportConfig(FiraOpenSessionParams params)387 private int getResultReportConfig(FiraOpenSessionParams params) { 388 int resultReportConfig = 0x00; 389 resultReportConfig |= params.hasTimeOfFlightReport() ? 0x01 : 0x00; 390 resultReportConfig |= params.hasAngleOfArrivalAzimuthReport() ? 0x02 : 0x00; 391 resultReportConfig |= params.hasAngleOfArrivalElevationReport() ? 0x04 : 0x00; 392 resultReportConfig |= params.hasAngleOfArrivalFigureOfMeritReport() ? 0x08 : 0x00; 393 return resultReportConfig; 394 } 395 getRangingRoundControl(FiraOpenSessionParams params)396 private int getRangingRoundControl(FiraOpenSessionParams params) { 397 // RANGING_ROUND_CONTROL 398 byte rangingRoundControl = 0x00; 399 400 // b0 : Ranging Result Report Message 401 rangingRoundControl |= (byte) (params.hasRangingResultReportMessage() ? 0x01 : 0x00); 402 403 // b1 : Control Message 404 rangingRoundControl |= (byte) (params.hasControlMessage() ? 0x02 : 0x00); 405 406 // b2 : Ranging Control Phase 407 rangingRoundControl |= (byte) (params.hasRangingControlPhase() ? 0x04 : 0x00); 408 409 // b6 : Measurement Report Message 410 if (params.getScheduledMode() == FiraParams.CONTENTION_BASED_RANGING) { 411 if (params.getMeasurementReportPhase() == FiraParams.MEASUREMENT_REPORT_PHASE_SET) { 412 rangingRoundControl |= (byte) 0x40; 413 } 414 } 415 416 // b7 : Measurement Report Message 417 if (params.getMeasurementReportType() 418 == FiraParams.MEASUREMENT_REPORT_TYPE_RESPONDER_TO_INITIATOR) { 419 rangingRoundControl |= (byte) 0x80; 420 } 421 return rangingRoundControl; 422 } 423 getComputedMacAddress(UwbAddress address)424 private static byte[] getComputedMacAddress(UwbAddress address) { 425 if (!SdkLevel.isAtLeastU()) { 426 return TlvUtil.getReverseBytes(address.toBytes()); 427 } 428 return address.toBytes(); 429 } 430 getComputedVendorId(byte[] data)431 private static byte[] getComputedVendorId(byte[] data) { 432 if (!SdkLevel.isAtLeastU()) { 433 return TlvUtil.getReverseBytes(data); 434 } 435 return data; 436 } 437 getSessionTimeBase(FiraOpenSessionParams params)438 private byte[] getSessionTimeBase(FiraOpenSessionParams params) { 439 byte[] sessionTimeBaseParam = new byte[FiraParams.SESSION_TIME_BASE_PARAM_LEN]; 440 int offset = 0; 441 sessionTimeBaseParam[offset++] = (byte) params.getReferenceTimeBase(); 442 byte[] sessionHandleValue = TlvUtil.getBytes(params.getReferenceSessionHandle()); 443 for (int index = FiraParams.SESSION_HANDLE_LEN - 1; index >= 0; index--) { 444 sessionTimeBaseParam[offset++] = (byte) sessionHandleValue[index]; 445 } 446 byte[] sessionOffsetInMicroSecondValue = 447 TlvUtil.getBytes(params.getSessionOffsetInMicroSeconds()); 448 for (int index = FiraParams.SESSION_OFFSET_TIME_LEN - 1; index >= 0; index--) { 449 sessionTimeBaseParam[offset++] = (byte) sessionOffsetInMicroSecondValue[index]; 450 } 451 return sessionTimeBaseParam; 452 } 453 } 454