1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.uwb; 18 19 import static com.android.server.uwb.data.UwbUciConstants.MAC_ADDRESSING_MODE_SHORT; 20 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_DL_TDOA; 21 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_OWR_AOA; 22 import static com.android.server.uwb.data.UwbUciConstants.RANGING_MEASUREMENT_TYPE_TWO_WAY; 23 import static com.android.server.uwb.util.UwbUtil.convertFloatToQFormat; 24 import static com.android.server.uwb.util.UwbUtil.degreeToRadian; 25 26 import android.os.PersistableBundle; 27 import android.util.Pair; 28 import android.uwb.AngleMeasurement; 29 import android.uwb.AngleOfArrivalMeasurement; 30 import android.uwb.DistanceMeasurement; 31 import android.uwb.RangingMeasurement; 32 import android.uwb.RangingReport; 33 import android.uwb.UwbAddress; 34 35 import com.android.modules.utils.build.SdkLevel; 36 import com.android.server.uwb.data.UwbDlTDoAMeasurement; 37 import com.android.server.uwb.data.UwbOwrAoaMeasurement; 38 import com.android.server.uwb.data.UwbRangingData; 39 import com.android.server.uwb.data.UwbTwoWayMeasurement; 40 import com.android.server.uwb.params.TlvUtil; 41 42 import com.google.uwb.support.dltdoa.DlTDoAMeasurement; 43 import com.google.uwb.support.fira.FiraParams; 44 import com.google.uwb.support.oemextension.RangingReportMetadata; 45 46 public class UwbTestUtils { 47 public static final int TEST_SESSION_ID = 7; 48 public static final int TEST_SESSION_ID_2 = 8; 49 public static final byte TEST_SESSION_TYPE = FiraParams.SESSION_TYPE_RANGING; 50 public static final byte[] PEER_SHORT_MAC_ADDRESS = {0x35, 0x37}; 51 public static final long PEER_SHORT_MAC_ADDRESS_LONG = 0x3735L; 52 public static final byte[] PEER_EXTENDED_SHORT_MAC_ADDRESS = 53 {0x35, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 54 public static final long PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG = 0x3735L; 55 public static final byte[] PEER_EXTENDED_MAC_ADDRESS = 56 {0x12, 0x14, 0x16, 0x18, 0x31, 0x33, 0x35, 0x37}; 57 public static final long PEER_EXTENDED_MAC_ADDRESS_LONG = 0x3735333118161412L; 58 public static final byte[] PEER_EXTENDED_MAC_ADDRESS_2 = 59 {0x2, 0x4, 0x6, 0x8, 0x1, 0x3, 0x5, 0x7}; 60 public static final long PEER_EXTENDED_MAC_ADDRESS_2_LONG = 0x0705030108060402L; 61 public static final byte[] PEER_BAD_MAC_ADDRESS = {0x12, 0x14, 0x16, 0x18}; 62 public static final UwbAddress PEER_EXTENDED_UWB_ADDRESS = UwbAddress.fromBytes( 63 PEER_EXTENDED_MAC_ADDRESS); 64 public static final UwbAddress PEER_EXTENDED_UWB_ADDRESS_2 = UwbAddress.fromBytes( 65 PEER_EXTENDED_MAC_ADDRESS_2); 66 public static final UwbAddress PEER_SHORT_UWB_ADDRESS = UwbAddress.fromBytes( 67 PEER_SHORT_MAC_ADDRESS); 68 public static final UwbAddress PEER_EXTENDED_SHORT_UWB_ADDRESS = UwbAddress.fromBytes( 69 PEER_EXTENDED_SHORT_MAC_ADDRESS); 70 71 public static final PersistableBundle PERSISTABLE_BUNDLE = new PersistableBundle(); 72 public static final byte[] DATA_PAYLOAD = new byte[] {0x13, 0x15, 0x18}; 73 public static final int RANGING_MEASUREMENT_TYPE_UNDEFINED = 0; // RFU in spec 74 public static final int MAX_DATA_SIZE = 100; 75 76 private static final byte[] TEST_RAW_NTF_DATA = {0x10, 0x01, 0x05}; 77 private static final long TEST_SEQ_COUNTER = 5; 78 private static final int TEST_RCR_INDICATION = 7; 79 private static final long TEST_CURR_RANGING_INTERVAL = 100; 80 private static final int TEST_RANGING_MEASURES_TYPE = RANGING_MEASUREMENT_TYPE_TWO_WAY; 81 private static final int TEST_MAC_ADDRESS_MODE = 1; 82 private static final int TEST_STATUS = FiraParams.STATUS_CODE_OK; 83 private static final int TEST_LOS = 0; 84 private static final int TEST_DISTANCE = 101; 85 private static final float TEST_AOA_AZIMUTH = 67; 86 private static final int TEST_AOA_AZIMUTH_FOM = 50; 87 private static final int TEST_BAD_AOA_AZIMUTH_FOM = 150; 88 private static final float TEST_AOA_ELEVATION = 37; 89 private static final int TEST_AOA_ELEVATION_FOM = 90; 90 private static final float TEST_AOA_DEST_AZIMUTH = 67; 91 private static final int TEST_AOA_DEST_AZIMUTH_FOM = 50; 92 private static final float TEST_AOA_DEST_ELEVATION = 37; 93 private static final int TEST_AOA_DEST_ELEVATION_FOM = 90; 94 private static final int TEST_FRAME_SEQUENCE_NUMBER = 1; 95 private static final int TEST_BLOCK_IDX = 100; 96 private static final int TEST_SLOT_IDX = 10; 97 private static final int TEST_MESSAGE_TYPE = 1; 98 private static final int TEST_MESSAGE_CONTROL = 1331; 99 private static final int TEST_BLOCK_INDEX = 5; 100 private static final int TEST_ROUND_INDEX = 1; 101 private static final long TEST_TIMESTAMP = 500_000L; 102 private static final float TEST_ANCHOR_CFO = 100.0f; 103 private static final float TEST_CFO = 200.50f; 104 private static final long TEST_INTIATOR_REPLY_TIME = 500_000L; 105 private static final long TEST_RESPONDER_REPLY_TIME = 300_000L; 106 private static final int TEST_INITIATOR_RESPONDER_TOF = 500; 107 private static final byte[] TEST_ANCHOR_LOCATION = {0x01, 0x02, 0x03, 0x04, 108 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}; 109 private static final byte[] TEST_ACTIVE_RANGING_ROUNDS = {0x02, 0x08}; 110 private static final int TEST_RSSI = 150; 111 UwbTestUtils()112 private UwbTestUtils() {} 113 114 /** Build UwbRangingData for all Ranging Measurement Type(s). */ generateRangingData( int rangingMeasurementType, int macAddressingMode, int rangingStatus)115 public static UwbRangingData generateRangingData( 116 int rangingMeasurementType, int macAddressingMode, int rangingStatus) { 117 byte[] macAddress = (macAddressingMode == MAC_ADDRESSING_MODE_SHORT) 118 ? PEER_SHORT_MAC_ADDRESS : PEER_EXTENDED_MAC_ADDRESS; 119 return generateRangingData( 120 rangingMeasurementType, macAddressingMode, macAddress, rangingStatus); 121 } 122 123 /** Build UwbRangingData for all Ranging Measurement Type(s). */ generateRangingData( int rangingMeasurementType, int macAddressingMode, byte[] macAddress, int rangingStatus)124 public static UwbRangingData generateRangingData( 125 int rangingMeasurementType, int macAddressingMode, byte[] macAddress, 126 int rangingStatus) { 127 switch (rangingMeasurementType) { 128 case RANGING_MEASUREMENT_TYPE_TWO_WAY: 129 return generateTwoWayMeasurementRangingData(rangingStatus); 130 case RANGING_MEASUREMENT_TYPE_OWR_AOA: 131 return generateOwrAoaMeasurementRangingData( 132 macAddressingMode, macAddress, rangingStatus); 133 case RANGING_MEASUREMENT_TYPE_DL_TDOA: 134 return generateDlTDoAMeasurementRangingData(macAddressingMode, rangingStatus); 135 default: 136 return generateDefaultRangingData(); 137 } 138 } 139 generateTwoWayMeasurementRangingData(int rangingStatus)140 private static UwbRangingData generateTwoWayMeasurementRangingData(int rangingStatus) { 141 final int noOfRangingMeasures = 1; 142 final UwbTwoWayMeasurement[] uwbTwoWayMeasurements = 143 new UwbTwoWayMeasurement[noOfRangingMeasures]; 144 uwbTwoWayMeasurements[0] = new UwbTwoWayMeasurement(PEER_SHORT_MAC_ADDRESS, rangingStatus, 145 TEST_LOS, TEST_DISTANCE, convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7), 146 TEST_AOA_AZIMUTH_FOM, convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7), 147 TEST_AOA_ELEVATION_FOM, convertFloatToQFormat(TEST_AOA_DEST_AZIMUTH, 9, 7), 148 TEST_AOA_DEST_AZIMUTH_FOM, convertFloatToQFormat(TEST_AOA_DEST_ELEVATION, 9, 7), 149 TEST_AOA_DEST_ELEVATION_FOM, TEST_SLOT_IDX, TEST_RSSI); 150 return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID, 151 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_TWO_WAY, 152 TEST_MAC_ADDRESS_MODE, noOfRangingMeasures, uwbTwoWayMeasurements, 153 TEST_RAW_NTF_DATA); 154 } 155 generateOwrAoaMeasurementRangingData( int macAddressingMode, byte[] macAddress, int rangingStatus)156 private static UwbRangingData generateOwrAoaMeasurementRangingData( 157 int macAddressingMode, byte[] macAddress, int rangingStatus) { 158 final int noOfRangingMeasures = 1; 159 final UwbOwrAoaMeasurement uwbOwrAoaMeasurement = new UwbOwrAoaMeasurement( 160 macAddress, rangingStatus, TEST_LOS, 161 TEST_FRAME_SEQUENCE_NUMBER, TEST_BLOCK_IDX, 162 convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7), TEST_AOA_AZIMUTH_FOM, 163 convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7), TEST_AOA_ELEVATION_FOM); 164 return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID, 165 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_OWR_AOA, 166 macAddressingMode, noOfRangingMeasures, uwbOwrAoaMeasurement, 167 TEST_RAW_NTF_DATA); 168 } 169 170 /** Generate an OWR ranging data with a bad AoA Azimuth FOM */ generateBadOwrAoaMeasurementRangingData( int macAddressingMode, byte[] macAddress)171 public static UwbRangingData generateBadOwrAoaMeasurementRangingData( 172 int macAddressingMode, byte[] macAddress) { 173 final int noOfRangingMeasures = 1; 174 final UwbOwrAoaMeasurement uwbOwrAoaMeasurement = new UwbOwrAoaMeasurement( 175 macAddress, TEST_STATUS, TEST_LOS, 176 TEST_FRAME_SEQUENCE_NUMBER, TEST_BLOCK_IDX, 177 convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7), TEST_BAD_AOA_AZIMUTH_FOM, 178 convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7), TEST_AOA_ELEVATION_FOM); 179 return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID, 180 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_OWR_AOA, 181 macAddressingMode, noOfRangingMeasures, uwbOwrAoaMeasurement, 182 TEST_RAW_NTF_DATA); 183 } 184 generateDlTDoAMeasurementRangingData( int macAddressingMode, int rangingStatus)185 private static UwbRangingData generateDlTDoAMeasurementRangingData( 186 int macAddressingMode, int rangingStatus) { 187 final int noOfRangingMeasures = 1; 188 byte[] macAddress = (macAddressingMode == MAC_ADDRESSING_MODE_SHORT) 189 ? PEER_SHORT_MAC_ADDRESS : PEER_EXTENDED_MAC_ADDRESS; 190 final UwbDlTDoAMeasurement[] uwbDlTDoAMeasurements = 191 new UwbDlTDoAMeasurement[noOfRangingMeasures]; 192 uwbDlTDoAMeasurements[0] = new UwbDlTDoAMeasurement(macAddress, rangingStatus, 193 TEST_MESSAGE_TYPE, TEST_MESSAGE_CONTROL, TEST_BLOCK_INDEX, TEST_ROUND_INDEX, 194 TEST_LOS, convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7), 195 TEST_AOA_AZIMUTH_FOM, convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7), 196 TEST_AOA_ELEVATION_FOM, TEST_RSSI, TEST_TIMESTAMP, TEST_TIMESTAMP, 197 convertFloatToQFormat(TEST_ANCHOR_CFO, 5, 11), 198 convertFloatToQFormat(TEST_CFO, 5, 11), TEST_INTIATOR_REPLY_TIME, 199 TEST_RESPONDER_REPLY_TIME, TEST_INITIATOR_RESPONDER_TOF, TEST_ANCHOR_LOCATION, 200 TEST_ACTIVE_RANGING_ROUNDS); 201 202 return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID, 203 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_DL_TDOA, 204 macAddressingMode, noOfRangingMeasures, uwbDlTDoAMeasurements, 205 TEST_RAW_NTF_DATA); 206 } 207 208 // Create a UwbRangingData with no measurements, for negative test cases (example: incorrect 209 // ranging measurement type). generateDefaultRangingData()210 private static UwbRangingData generateDefaultRangingData() { 211 final int noOfRangingMeasures = 0; 212 final UwbTwoWayMeasurement[] uwbEmptyTwoWayMeasurements = 213 new UwbTwoWayMeasurement[noOfRangingMeasures]; 214 return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID, 215 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_UNDEFINED, 216 TEST_MAC_ADDRESS_MODE, noOfRangingMeasures, uwbEmptyTwoWayMeasurements, 217 TEST_RAW_NTF_DATA); 218 } 219 220 // Helper method to generate a UwbRangingData instance and corresponding RangingMeasurement generateRangingDataAndRangingReport( byte[] macAddress, int macAddressingMode, int rangingMeasurementType, boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled, boolean isDestAoaAzimuthEnabled, boolean isDestAoaElevationEnabled, long elapsedRealtimeNanos)221 public static Pair<UwbRangingData, RangingReport> generateRangingDataAndRangingReport( 222 byte[] macAddress, int macAddressingMode, int rangingMeasurementType, 223 boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled, 224 boolean isDestAoaAzimuthEnabled, boolean isDestAoaElevationEnabled, 225 long elapsedRealtimeNanos) { 226 UwbRangingData uwbRangingData = generateRangingData(rangingMeasurementType, 227 macAddressingMode, TEST_STATUS); 228 229 PersistableBundle rangingReportMetadata = new RangingReportMetadata.Builder() 230 .setSessionId(0) 231 .setRawNtfData(new byte[] {0x10, 0x01, 0x05}) 232 .build() 233 .toBundle(); 234 235 AngleOfArrivalMeasurement aoaMeasurement = null; 236 AngleOfArrivalMeasurement aoaDestMeasurement = null; 237 if (isAoaAzimuthEnabled || isAoaElevationEnabled) { 238 AngleMeasurement aoaAzimuth = null; 239 AngleMeasurement aoaElevation = null; 240 AngleOfArrivalMeasurement.Builder aoaBuilder = null; 241 242 if (isAoaAzimuthEnabled) { 243 aoaAzimuth = new AngleMeasurement( 244 degreeToRadian(TEST_AOA_AZIMUTH), 0, 245 TEST_AOA_AZIMUTH_FOM / (double) 100); 246 aoaBuilder = new AngleOfArrivalMeasurement.Builder(aoaAzimuth); 247 } 248 if (isAoaElevationEnabled && aoaBuilder != null) { 249 aoaElevation = new AngleMeasurement( 250 degreeToRadian(TEST_AOA_ELEVATION), 0, 251 TEST_AOA_ELEVATION_FOM / (double) 100); 252 aoaBuilder.setAltitude(aoaElevation); 253 } 254 255 aoaMeasurement = (aoaBuilder != null) ? aoaBuilder.build() : null; 256 } 257 if (isDestAoaAzimuthEnabled || isDestAoaElevationEnabled) { 258 AngleMeasurement aoaDestAzimuth = null; 259 AngleMeasurement aoaDestElevation = null; 260 AngleOfArrivalMeasurement.Builder aoaBuilder = null; 261 262 if (isDestAoaAzimuthEnabled) { 263 aoaDestAzimuth = 264 new AngleMeasurement( 265 degreeToRadian(TEST_AOA_DEST_AZIMUTH), 0, 266 TEST_AOA_DEST_AZIMUTH_FOM / (double) 100); 267 aoaBuilder = new AngleOfArrivalMeasurement.Builder(aoaDestAzimuth); 268 } 269 if (isDestAoaElevationEnabled && aoaBuilder != null) { 270 aoaDestElevation = 271 new AngleMeasurement( 272 degreeToRadian(TEST_AOA_DEST_ELEVATION), 0, 273 TEST_AOA_DEST_ELEVATION_FOM / (double) 100); 274 aoaBuilder.setAltitude(aoaDestElevation); 275 } 276 aoaDestMeasurement = (aoaBuilder != null) ? aoaBuilder.build() : null; 277 } 278 279 RangingReport rangingReport = buildRangingReport(macAddress, rangingMeasurementType, 280 aoaMeasurement, aoaDestMeasurement, elapsedRealtimeNanos, rangingReportMetadata); 281 return Pair.create(uwbRangingData, rangingReport); 282 } 283 getComputedMacAddress(byte[] address)284 private static UwbAddress getComputedMacAddress(byte[] address) { 285 if (!SdkLevel.isAtLeastU()) { 286 return UwbAddress.fromBytes(TlvUtil.getReverseBytes(address)); 287 } 288 return UwbAddress.fromBytes(address); 289 } 290 buildRangingReport(byte[] macAddress, int rangingMeasurementType, AngleOfArrivalMeasurement aoaMeasurement, AngleOfArrivalMeasurement aoaDestMeasurement, long elapsedRealtimeNanos, PersistableBundle rangingReportMetadata)291 private static RangingReport buildRangingReport(byte[] macAddress, int rangingMeasurementType, 292 AngleOfArrivalMeasurement aoaMeasurement, AngleOfArrivalMeasurement aoaDestMeasurement, 293 long elapsedRealtimeNanos, PersistableBundle rangingReportMetadata) { 294 295 PersistableBundle rangingMeasurementMetadata = new PersistableBundle(); 296 297 RangingMeasurement.Builder rangingMeasurementBuilder = new RangingMeasurement.Builder() 298 .setRemoteDeviceAddress(getComputedMacAddress(macAddress)) 299 .setStatus(TEST_STATUS) 300 .setElapsedRealtimeNanos(elapsedRealtimeNanos) 301 .setAngleOfArrivalMeasurement(aoaMeasurement) 302 .setLineOfSight(TEST_LOS); 303 304 if (rangingMeasurementType == RANGING_MEASUREMENT_TYPE_TWO_WAY) { 305 rangingMeasurementBuilder 306 .setDistanceMeasurement( 307 new DistanceMeasurement.Builder() 308 .setMeters(TEST_DISTANCE / (double) 100) 309 .setErrorMeters(0) 310 .setConfidenceLevel(0) 311 .build()) 312 .setDestinationAngleOfArrivalMeasurement(aoaDestMeasurement) 313 .setRssiDbm(-TEST_RSSI / 2) 314 .setRangingMeasurementMetadata(rangingMeasurementMetadata); 315 } 316 317 if (rangingMeasurementType == RANGING_MEASUREMENT_TYPE_DL_TDOA) { 318 DlTDoAMeasurement dlTDoAMeasurement = new DlTDoAMeasurement.Builder() 319 .setMessageType(TEST_MESSAGE_TYPE) 320 .setMessageControl(TEST_MESSAGE_CONTROL) 321 .setBlockIndex(TEST_BLOCK_INDEX) 322 .setNLoS(TEST_LOS) 323 .setTxTimestamp(TEST_TIMESTAMP) 324 .setRxTimestamp(TEST_TIMESTAMP) 325 .setAnchorCfo(TEST_ANCHOR_CFO) 326 .setCfo(TEST_CFO) 327 .setInitiatorReplyTime(TEST_INTIATOR_REPLY_TIME) 328 .setResponderReplyTime(TEST_RESPONDER_REPLY_TIME) 329 .setInitiatorResponderTof(TEST_INITIATOR_RESPONDER_TOF) 330 .setAnchorLocation(TEST_ANCHOR_LOCATION) 331 .setActiveRangingRounds(TEST_ACTIVE_RANGING_ROUNDS) 332 .setRoundIndex(TEST_ROUND_INDEX) 333 .build(); 334 rangingMeasurementBuilder.setRangingMeasurementMetadata(dlTDoAMeasurement.toBundle()); 335 } 336 337 return new RangingReport.Builder() 338 .addMeasurement(rangingMeasurementBuilder.build()) 339 .addRangingReportMetadata(rangingReportMetadata) 340 .build(); 341 } 342 } 343