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 .putShort(ConfigParam.MAX_NUMBER_OF_MEASUREMENTS, 124 (short) params.getMaxNumberOfMeasurements()) 125 .putByte(ConfigParam.STS_LENGTH, (byte) params.getStsLength()); 126 if (params.getPrfMode() == FiraParams.PRF_MODE_BPRF) { 127 tlvBufferBuilder.putByte( 128 ConfigParam.BPRF_PHR_DATA_RATE, (byte) params.getBprfPhrDataRate()); 129 } 130 if (params.getDeviceRole() != FiraParams.RANGING_DEVICE_UT_TAG) { 131 tlvBufferBuilder.putInt(ConfigParam.RANGING_INTERVAL, params.getRangingIntervalMs()); 132 } 133 if (deviceRole != FiraParams.RANGING_DEVICE_DT_TAG) { 134 tlvBufferBuilder.putByte(ConfigParam.DEVICE_TYPE, (byte) params.getDeviceType()); 135 } 136 137 if (isTimeScheduledTwrSession( 138 params.getScheduledMode(), params.getRangingRoundUsage())) { 139 if (params.getDestAddressList().size() > 0) { 140 ByteBuffer dstAddressList = ByteBuffer.allocate(1024); 141 for (UwbAddress address : params.getDestAddressList()) { 142 dstAddressList.put(getComputedMacAddress(address)); 143 } 144 tlvBufferBuilder 145 .putByte(ConfigParam.NUMBER_OF_CONTROLEES, 146 (byte) params.getDestAddressList().size()) 147 .putByteArray( 148 ConfigParam.DST_MAC_ADDRESS, dstAddressList.position(), 149 Arrays.copyOf(dstAddressList.array(), dstAddressList.position())); 150 } 151 } 152 153 if (uwbsFiraProtocolVersion.getMajor() >= 2) { 154 // Initiation time Changed from 4 byte field to 8 byte field in version 2. 155 if (deviceRole != FiraParams.RANGING_DEVICE_DT_TAG) { 156 // For FiRa 2.0+ device, prefer to set the Absolute UWB Initiation time. 157 if (params.getAbsoluteInitiationTime() > 0) { 158 tlvBufferBuilder.putLong(ConfigParam.UWB_INITIATION_TIME, 159 params.getAbsoluteInitiationTime()); 160 } else { 161 tlvBufferBuilder.putLong(ConfigParam.UWB_INITIATION_TIME, 162 params.getInitiationTime()); 163 } 164 } else { 165 tlvBufferBuilder.putByte(ConfigParam.DL_TDOA_BLOCK_STRIDING, 166 (byte) params.getDlTdoaBlockStriding()); 167 } 168 tlvBufferBuilder.putByte(ConfigParam.LINK_LAYER_MODE, (byte) params.getLinkLayerMode()) 169 .putByte(ConfigParam.DATA_REPETITION_COUNT, 170 (byte) params.getDataRepetitionCount()) 171 .putByte(ConfigParam.SESSION_DATA_TRANSFER_STATUS_NTF_CONFIG, 172 params.getSessionDataTransferStatusNtfConfig() ? (byte) 1 : (byte) 0) 173 .putByte(ConfigParam.APPLICATION_DATA_ENDPOINT, 174 (byte) params.getApplicationDataEndpoint()); 175 if (deviceType == FiraParams.RANGING_DEVICE_TYPE_CONTROLLER && UwbUtil.isBitSet( 176 params.getReferenceTimeBase(), 177 FiraParams.SESSION_TIME_BASE_REFERENCE_FEATURE_ENABLED)) { 178 tlvBufferBuilder.putByteArray(ConfigParam.SESSION_TIME_BASE, 179 getSessionTimeBase(params)); 180 } 181 } else { 182 if (deviceRole != FiraParams.RANGING_DEVICE_DT_TAG) { 183 tlvBufferBuilder 184 .putInt(ConfigParam.UWB_INITIATION_TIME, 185 Math.toIntExact(params.getInitiationTime())); 186 } 187 tlvBufferBuilder.putByte(ConfigParam.TX_ADAPTIVE_PAYLOAD_POWER, 188 params.isTxAdaptivePayloadPowerEnabled() ? (byte) 1 : (byte) 0); 189 } 190 191 configureStsParameters(tlvBufferBuilder, params); 192 193 if (params.getAoaResultRequest() 194 == FiraParams.AOA_RESULT_REQUEST_MODE_REQ_AOA_RESULTS_INTERLEAVED) { 195 tlvBufferBuilder.putByte(ConfigParam.NUM_RANGE_MEASUREMENTS, 196 (byte) params.getNumOfMsrmtFocusOnRange()) 197 .putByte(ConfigParam.NUM_AOA_AZIMUTH_MEASUREMENTS, 198 (byte) params.getNumOfMsrmtFocusOnAoaAzimuth()) 199 .putByte(ConfigParam.NUM_AOA_ELEVATION_MEASUREMENTS, 200 (byte) params.getNumOfMsrmtFocusOnAoaElevation()); 201 } 202 if (hasAoaBoundInRangeDataNtfConfig(params.getRangeDataNtfConfig())) { 203 tlvBufferBuilder.putShortArray(ConfigParam.RANGE_DATA_NTF_AOA_BOUND, new short[]{ 204 // TODO (b/235355249): Verify this conversion. This is using AOA value 205 // in UwbTwoWayMeasurement to external RangingMeasurement conversion as 206 // reference. 207 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 208 UwbUtil.radianTodegree( 209 params.getRangeDataNtfAoaAzimuthLower()), 9, 7), 16), 210 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 211 UwbUtil.radianTodegree( 212 params.getRangeDataNtfAoaAzimuthUpper()), 9, 7), 16), 213 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 214 UwbUtil.radianTodegree( 215 params.getRangeDataNtfAoaElevationLower()), 9, 7), 16), 216 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 217 UwbUtil.radianTodegree( 218 params.getRangeDataNtfAoaElevationUpper()), 9, 7), 16), 219 }); 220 } 221 if (params.isDiagnosticsEnabled()) { 222 tlvBufferBuilder.putByte(ConfigParam.ENABLE_DIAGNOSTICS_RSSI, (byte) 1); 223 if (SdkLevel.isAtLeastU()) { 224 // Fixed bug to be compliant with HAL interface. 225 tlvBufferBuilder.putByte(ConfigParam.ENABLE_DIAGRAMS_FRAME_REPORTS_FIELDS, 226 params.getDiagramsFrameReportsFieldsFlags()); 227 } else { 228 tlvBufferBuilder.putInt(ConfigParam.ENABLE_DIAGRAMS_FRAME_REPORTS_FIELDS, 229 params.getDiagramsFrameReportsFieldsFlags()); 230 } 231 } 232 if (params.getScheduledMode() == FiraParams.CONTENTION_BASED_RANGING) { 233 tlvBufferBuilder.putByteArray(ConfigParam.CAP_SIZE_RANGE, params.getCapSize()); 234 } 235 if (params.getDeviceRole() == FiraParams.RANGING_DEVICE_UT_TAG) { 236 tlvBufferBuilder.putInt(ConfigParam.UL_TDOA_TX_INTERVAL, 237 params.getUlTdoaTxIntervalMs()); 238 tlvBufferBuilder.putInt(ConfigParam.UL_TDOA_RANDOM_WINDOW, 239 params.getUlTdoaRandomWindowMs()); 240 tlvBufferBuilder.putByteArray(ConfigParam.UL_TDOA_DEVICE_ID, getUlTdoaDeviceId( 241 params.getUlTdoaDeviceIdType(), params.getUlTdoaDeviceId())); 242 tlvBufferBuilder.putByte(ConfigParam.UL_TDOA_TX_TIMESTAMP, 243 (byte) params.getUlTdoaTxTimestampType()); 244 } 245 if (params.getDeviceRole() == FiraParams.RANGING_DEVICE_ROLE_ADVERTISER || 246 params.getDeviceRole() == FiraParams.RANGING_DEVICE_ROLE_OBSERVER) { 247 tlvBufferBuilder 248 .putByte(ConfigParam.MIN_FRAMES_PER_RR, (byte) params.getMinFramesPerRr()) 249 .putShort(ConfigParam.MTU_SIZE, (short) params.getMtuSize()) 250 .putByte(ConfigParam.INTER_FRAME_INTERVAL, 251 (byte) params.getInterFrameInterval()); 252 } 253 254 if (mUwbInjector.getDeviceConfigFacade().isAntennaModeConfigSupported()) { 255 tlvBufferBuilder.putByte(ConfigParam.ANTENNA_MODE, params.getAntennaMode()); 256 } 257 return tlvBufferBuilder.build(); 258 } 259 isTimeScheduledTwrSession(int scheduledMode, int rangingUsage)260 private boolean isTimeScheduledTwrSession(int scheduledMode, int rangingUsage) { 261 if (scheduledMode == FiraParams.TIME_SCHEDULED_RANGING) { 262 if (rangingUsage == FiraParams.RANGING_ROUND_USAGE_SS_TWR_DEFERRED_MODE 263 || rangingUsage == FiraParams.RANGING_ROUND_USAGE_DS_TWR_DEFERRED_MODE 264 || rangingUsage == FiraParams.RANGING_ROUND_USAGE_SS_TWR_NON_DEFERRED_MODE 265 || rangingUsage == FiraParams.RANGING_ROUND_USAGE_DS_TWR_NON_DEFERRED_MODE) { 266 return true; 267 } 268 } 269 return false; 270 } 271 configureStsParameters(TlvBuffer.Builder tlvBufferBuilder, FiraOpenSessionParams params)272 private void configureStsParameters(TlvBuffer.Builder tlvBufferBuilder, 273 FiraOpenSessionParams params) { 274 int stsConfig = params.getStsConfig(); 275 276 if (stsConfig == FiraParams.STS_CONFIG_STATIC) { 277 tlvBufferBuilder 278 .putByteArray(ConfigParam.VENDOR_ID, params.getVendorId() != null 279 ? getComputedVendorId(params.getVendorId()): null) 280 .putByteArray(ConfigParam.STATIC_STS_IV, params.getStaticStsIV()); 281 } else if (stsConfig == FiraParams.STS_CONFIG_DYNAMIC_FOR_CONTROLEE_INDIVIDUAL_KEY) { 282 if (params.getDeviceType() == FiraParams.RANGING_DEVICE_TYPE_CONTROLEE) { 283 tlvBufferBuilder.putInt(ConfigParam.SUB_SESSION_ID, params.getSubSessionId()); 284 } 285 } else if (stsConfig == FiraParams.STS_CONFIG_PROVISIONED) { 286 if (params.getSessionKey() != null ) { 287 tlvBufferBuilder.putByteArray(ConfigParam.SESSION_KEY, params.getSessionKey()); 288 } 289 } else if (stsConfig == FiraParams.STS_CONFIG_PROVISIONED_FOR_CONTROLEE_INDIVIDUAL_KEY) { 290 if (params.getDeviceType() == FiraParams.RANGING_DEVICE_TYPE_CONTROLEE) { 291 tlvBufferBuilder.putInt(ConfigParam.SUB_SESSION_ID, params.getSubSessionId()); 292 if (params.getSubsessionKey() != null ) { 293 tlvBufferBuilder. 294 putByteArray(ConfigParam.SUBSESSION_KEY, params.getSubsessionKey()); 295 } 296 } 297 if (params.getSessionKey() != null ) { 298 tlvBufferBuilder.putByteArray(ConfigParam.SESSION_KEY, params.getSessionKey()); 299 } 300 } 301 } 302 getUlTdoaDeviceId(int ulTdoaDeviceIdType, byte[] ulTdoaDeviceId)303 private byte[] getUlTdoaDeviceId(int ulTdoaDeviceIdType, byte[] ulTdoaDeviceId) { 304 if (ulTdoaDeviceIdType == FiraParams.UL_TDOA_DEVICE_ID_NONE) { 305 // Device ID not included 306 return new byte[]{0}; 307 } 308 ByteBuffer buffer = ByteBuffer.allocate(ulTdoaDeviceId.length + 1); 309 buffer.put((byte) ulTdoaDeviceIdType); 310 buffer.put(ulTdoaDeviceId); 311 return buffer.array(); 312 } 313 getTlvBufferFromFiraRangingReconfigureParams(Params baseParam)314 private TlvBuffer getTlvBufferFromFiraRangingReconfigureParams(Params baseParam) { 315 FiraRangingReconfigureParams params = (FiraRangingReconfigureParams) baseParam; 316 TlvBuffer.Builder tlvBuilder = new TlvBuffer.Builder(); 317 Integer blockStrideLength = params.getBlockStrideLength(); 318 Integer rangeDataNtfConfig = params.getRangeDataNtfConfig(); 319 Integer rangeDataProximityNear = params.getRangeDataProximityNear(); 320 Integer rangeDataProximityFar = params.getRangeDataProximityFar(); 321 Double rangeDataAoaAzimuthLower = params.getRangeDataAoaAzimuthLower(); 322 Double rangeDataAoaAzimuthUpper = params.getRangeDataAoaAzimuthUpper(); 323 Double rangeDataAoaElevationLower = params.getRangeDataAoaElevationLower(); 324 Double rangeDataAoaElevationUpper = params.getRangeDataAoaElevationUpper(); 325 Integer suspendRangingRounds = params.getSuspendRangingRounds(); 326 327 if (blockStrideLength != null) { 328 tlvBuilder.putByte(ConfigParam.BLOCK_STRIDE_LENGTH, 329 (byte) blockStrideLength.intValue()); 330 } 331 332 if (rangeDataNtfConfig != null) { 333 tlvBuilder.putByte(ConfigParam.RANGE_DATA_NTF_CONFIG, 334 (byte) rangeDataNtfConfig.intValue()); 335 } 336 337 if (rangeDataProximityNear != null) { 338 tlvBuilder.putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_NEAR, 339 (short) rangeDataProximityNear.intValue()); 340 } 341 342 if (rangeDataProximityFar != null) { 343 tlvBuilder.putShort(ConfigParam.RANGE_DATA_NTF_PROXIMITY_FAR, 344 (short) rangeDataProximityFar.intValue()); 345 } 346 347 if (rangeDataNtfConfig != null && hasAoaBoundInRangeDataNtfConfig(rangeDataNtfConfig)) { 348 if ((rangeDataAoaAzimuthLower != null && rangeDataAoaAzimuthUpper != null) 349 || (rangeDataAoaElevationLower != null && rangeDataAoaElevationUpper != null)) { 350 rangeDataAoaAzimuthLower = rangeDataAoaAzimuthLower != null 351 ? rangeDataAoaAzimuthLower 352 : FiraParams.RANGE_DATA_NTF_AOA_AZIMUTH_LOWER_DEFAULT; 353 rangeDataAoaAzimuthUpper = rangeDataAoaAzimuthUpper != null 354 ? rangeDataAoaAzimuthUpper 355 : FiraParams.RANGE_DATA_NTF_AOA_AZIMUTH_UPPER_DEFAULT; 356 rangeDataAoaElevationLower = rangeDataAoaElevationLower != null 357 ? rangeDataAoaElevationLower 358 : FiraParams.RANGE_DATA_NTF_AOA_ELEVATION_LOWER_DEFAULT; 359 rangeDataAoaElevationUpper = rangeDataAoaElevationUpper != null 360 ? rangeDataAoaElevationUpper 361 : FiraParams.RANGE_DATA_NTF_AOA_ELEVATION_UPPER_DEFAULT; 362 tlvBuilder.putShortArray(ConfigParam.RANGE_DATA_NTF_AOA_BOUND, new short[]{ 363 // TODO (b/235355249): Verify this conversion. This is using AOA value 364 // in UwbTwoWayMeasurement to external RangingMeasurement conversion as 365 // reference. 366 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 367 UwbUtil.radianTodegree( 368 rangeDataAoaAzimuthLower.floatValue()), 9, 7), 16), 369 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 370 UwbUtil.radianTodegree( 371 rangeDataAoaAzimuthUpper.floatValue()), 9, 7), 16), 372 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 373 UwbUtil.radianTodegree( 374 rangeDataAoaElevationLower.floatValue()), 9, 7), 16), 375 (short) UwbUtil.twos_compliment(UwbUtil.convertFloatToQFormat( 376 UwbUtil.radianTodegree( 377 rangeDataAoaElevationUpper.floatValue()), 9, 7), 16), 378 }); 379 } 380 } 381 if (suspendRangingRounds != null) { 382 tlvBuilder.putByte(ConfigParam.SUSPEND_RANGING_ROUNDS, 383 (byte) suspendRangingRounds.intValue()); 384 } 385 return tlvBuilder.build(); 386 } 387 388 // Merged data from other parameter values getResultReportConfig(FiraOpenSessionParams params)389 private int getResultReportConfig(FiraOpenSessionParams params) { 390 int resultReportConfig = 0x00; 391 resultReportConfig |= params.hasTimeOfFlightReport() ? 0x01 : 0x00; 392 resultReportConfig |= params.hasAngleOfArrivalAzimuthReport() ? 0x02 : 0x00; 393 resultReportConfig |= params.hasAngleOfArrivalElevationReport() ? 0x04 : 0x00; 394 resultReportConfig |= params.hasAngleOfArrivalFigureOfMeritReport() ? 0x08 : 0x00; 395 return resultReportConfig; 396 } 397 getRangingRoundControl(FiraOpenSessionParams params)398 private int getRangingRoundControl(FiraOpenSessionParams params) { 399 // RANGING_ROUND_CONTROL 400 byte rangingRoundControl = 0x00; 401 402 // b0 : Ranging Result Report Message 403 rangingRoundControl |= (byte) (params.hasRangingResultReportMessage() ? 0x01 : 0x00); 404 405 // b1 : Control Message 406 rangingRoundControl |= (byte) (params.hasControlMessage() ? 0x02 : 0x00); 407 408 // b2 : Ranging Control Phase 409 rangingRoundControl |= (byte) (params.hasRangingControlPhase() ? 0x04 : 0x00); 410 411 // b6 : Measurement Report Message 412 if (params.getScheduledMode() == FiraParams.CONTENTION_BASED_RANGING) { 413 if (params.getMeasurementReportPhase() == FiraParams.MEASUREMENT_REPORT_PHASE_SET) { 414 rangingRoundControl |= (byte) 0x40; 415 } 416 } 417 418 // b7 : Measurement Report Message 419 if (params.getMeasurementReportType() 420 == FiraParams.MEASUREMENT_REPORT_TYPE_RESPONDER_TO_INITIATOR) { 421 rangingRoundControl |= (byte) 0x80; 422 } 423 return rangingRoundControl; 424 } 425 getComputedMacAddress(UwbAddress address)426 private static byte[] getComputedMacAddress(UwbAddress address) { 427 if (!SdkLevel.isAtLeastU()) { 428 return TlvUtil.getReverseBytes(address.toBytes()); 429 } 430 return address.toBytes(); 431 } 432 getComputedVendorId(byte[] data)433 private static byte[] getComputedVendorId(byte[] data) { 434 if (!SdkLevel.isAtLeastU()) { 435 return TlvUtil.getReverseBytes(data); 436 } 437 return data; 438 } 439 getSessionTimeBase(FiraOpenSessionParams params)440 private byte[] getSessionTimeBase(FiraOpenSessionParams params) { 441 byte[] sessionTimeBaseParam = new byte[FiraParams.SESSION_TIME_BASE_PARAM_LEN]; 442 int offset = 0; 443 sessionTimeBaseParam[offset++] = (byte) params.getReferenceTimeBase(); 444 byte[] sessionHandleValue = TlvUtil.getBytes(params.getReferenceSessionHandle()); 445 for (int index = FiraParams.SESSION_HANDLE_LEN - 1; index >= 0; index--) { 446 sessionTimeBaseParam[offset++] = (byte) sessionHandleValue[index]; 447 } 448 byte[] sessionOffsetInMicroSecondValue = 449 TlvUtil.getBytes(params.getSessionOffsetInMicroSeconds()); 450 for (int index = FiraParams.SESSION_OFFSET_TIME_LEN - 1; index >= 0; index--) { 451 sessionTimeBaseParam[offset++] = (byte) sessionOffsetInMicroSecondValue[index]; 452 } 453 return sessionTimeBaseParam; 454 } 455 } 456