• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static com.google.uwb.support.radar.RadarParams.BITS_PER_SAMPLES_48;
27 import static com.google.uwb.support.radar.RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES;
28 
29 import android.os.PersistableBundle;
30 import android.util.Pair;
31 import android.uwb.AngleMeasurement;
32 import android.uwb.AngleOfArrivalMeasurement;
33 import android.uwb.DistanceMeasurement;
34 import android.uwb.RangingMeasurement;
35 import android.uwb.RangingReport;
36 import android.uwb.UwbAddress;
37 
38 import com.android.modules.utils.build.SdkLevel;
39 import com.android.server.uwb.data.UwbDlTDoAMeasurement;
40 import com.android.server.uwb.data.UwbOwrAoaMeasurement;
41 import com.android.server.uwb.data.UwbRadarData;
42 import com.android.server.uwb.data.UwbRadarSweepData;
43 import com.android.server.uwb.data.UwbRangingData;
44 import com.android.server.uwb.data.UwbTwoWayMeasurement;
45 import com.android.server.uwb.params.TlvUtil;
46 
47 import com.google.uwb.support.dltdoa.DlTDoAMeasurement;
48 import com.google.uwb.support.fira.FiraParams;
49 import com.google.uwb.support.oemextension.RangingReportMetadata;
50 import com.google.uwb.support.radar.RadarData;
51 import com.google.uwb.support.radar.RadarParams;
52 import com.google.uwb.support.radar.RadarSweepData;
53 
54 public class UwbTestUtils {
55     public static final int TEST_SESSION_ID = 7;
56     public static final int TEST_SESSION_ID_2 = 8;
57     public static final byte TEST_SESSION_TYPE = FiraParams.SESSION_TYPE_RANGING;
58     public static final byte[] PEER_SHORT_MAC_ADDRESS = {0x35, 0x37};
59     public static final long PEER_SHORT_MAC_ADDRESS_LONG = 0x3735L;
60     public static final byte[] PEER_EXTENDED_SHORT_MAC_ADDRESS =
61             {0x35, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
62     public static final long PEER_EXTENDED_SHORT_MAC_ADDRESS_LONG = 0x3735L;
63     public static final byte[] PEER_EXTENDED_MAC_ADDRESS =
64             {0x12, 0x14, 0x16, 0x18, 0x31, 0x33, 0x35, 0x37};
65     public static final long PEER_EXTENDED_MAC_ADDRESS_LONG = 0x3735333118161412L;
66     public static final byte[] PEER_EXTENDED_MAC_ADDRESS_2 =
67             {0x2, 0x4, 0x6, 0x8, 0x1, 0x3, 0x5, 0x7};
68     public static final long  PEER_EXTENDED_MAC_ADDRESS_2_LONG = 0x0705030108060402L;
69     public static final byte[] PEER_BAD_MAC_ADDRESS = {0x12, 0x14, 0x16, 0x18};
70     public static final UwbAddress PEER_EXTENDED_UWB_ADDRESS = UwbAddress.fromBytes(
71             PEER_EXTENDED_MAC_ADDRESS);
72     public static final UwbAddress PEER_EXTENDED_UWB_ADDRESS_2 = UwbAddress.fromBytes(
73             PEER_EXTENDED_MAC_ADDRESS_2);
74     public static final UwbAddress PEER_SHORT_UWB_ADDRESS = UwbAddress.fromBytes(
75             PEER_SHORT_MAC_ADDRESS);
76     public static final UwbAddress PEER_EXTENDED_SHORT_UWB_ADDRESS = UwbAddress.fromBytes(
77             PEER_EXTENDED_SHORT_MAC_ADDRESS);
78 
79     public static final PersistableBundle PERSISTABLE_BUNDLE = new PersistableBundle();
80     public static final byte[] DATA_PAYLOAD = new byte[] {0x13, 0x15, 0x18};
81     public static final int RANGING_MEASUREMENT_TYPE_UNDEFINED = 0; // RFU in spec
82     public static final int MAX_DATA_SIZE = 100;
83 
84     private static final byte[] TEST_RAW_NTF_DATA = {0x10, 0x01, 0x05};
85     private static final long TEST_SEQ_COUNTER = 5;
86     private static final long TEST_SEQ_COUNTER2 = 6;
87     private static final int TEST_RCR_INDICATION = 7;
88     private static final long TEST_CURR_RANGING_INTERVAL = 100;
89     private static final int TEST_RANGING_MEASURES_TYPE = RANGING_MEASUREMENT_TYPE_TWO_WAY;
90     private static final long TEST_HUS_PRIMARY_SESSION_ID = 0;
91     private static final int TEST_MAC_ADDRESS_MODE = 1;
92     public static final int TEST_STATUS = FiraParams.STATUS_CODE_OK;
93     private static final int TEST_LOS = 0;
94     private static final int TEST_DISTANCE = 101;
95     private static final float TEST_AOA_AZIMUTH = 67;
96     private static final int TEST_AOA_AZIMUTH_FOM = 50;
97     private static final int TEST_BAD_AOA_AZIMUTH_FOM = 150;
98     private static final float TEST_AOA_ELEVATION = 37;
99     private static final int TEST_AOA_ELEVATION_FOM = 90;
100     private static final float TEST_AOA_DEST_AZIMUTH = 67;
101     private static final int TEST_AOA_DEST_AZIMUTH_FOM = 50;
102     private static final float TEST_AOA_DEST_ELEVATION = 37;
103     private static final int TEST_AOA_DEST_ELEVATION_FOM = 90;
104     private static final int TEST_FRAME_SEQUENCE_NUMBER = 1;
105     private static final int TEST_BLOCK_IDX = 100;
106     private static final int TEST_SLOT_IDX = 10;
107     private static final int TEST_MESSAGE_TYPE = 1;
108     private static final int TEST_MESSAGE_CONTROL = 1331;
109     private static final int TEST_BLOCK_INDEX = 5;
110     private static final int TEST_ROUND_INDEX = 1;
111     private static final long TEST_TIMESTAMP = 500_000L;
112     private static final long TEST_TIMESTAMP2 = 600_000L;
113     private static final float TEST_ANCHOR_CFO = 12.50f;
114     private static final float TEST_CFO = 15.50f;
115     private static final long TEST_INTIATOR_REPLY_TIME = 500_000L;
116     private static final long TEST_RESPONDER_REPLY_TIME = 300_000L;
117     private static final int TEST_INITIATOR_RESPONDER_TOF = 500;
118     private static final byte[] TEST_ANCHOR_LOCATION = {0x01, 0x02, 0x03, 0x04,
119             0x05, 0x06, 0x07, 0x08, 0x09, 0x10};
120     private static final byte[] TEST_ACTIVE_RANGING_ROUNDS = {0x02, 0x08};
121     private static final int TEST_RSSI = 150;
122 
123     private static final int TEST_SAMPLES_PER_SWEEP = 64;
124     private static final int TEST_BITS_PER_SAMPLE = BITS_PER_SAMPLES_48;
125     private static final int TEST_SWEEP_OFFSET = -10;
126     private static final byte[] TEST_VENDOR_SPECIFIC_DATA = {0x04, 0x07};
127     private static final byte[] TEST_SAMPLE_DATA = {0x06, 0x08, (byte) 0Xff};
128 
UwbTestUtils()129     private UwbTestUtils() {}
130 
131     /** Build UwbRangingData for all Ranging Measurement Type(s). */
generateRangingData( int rangingMeasurementType, int macAddressingMode, int rangingStatus)132     public static UwbRangingData generateRangingData(
133             int rangingMeasurementType, int macAddressingMode, int rangingStatus) {
134         byte[] macAddress = (macAddressingMode == MAC_ADDRESSING_MODE_SHORT)
135                 ? PEER_SHORT_MAC_ADDRESS : PEER_EXTENDED_MAC_ADDRESS;
136         return generateRangingData(
137                 rangingMeasurementType, macAddressingMode, macAddress, rangingStatus);
138     }
139 
140     /** Build UwbRangingData for all Ranging Measurement Type(s). */
generateRangingData( int rangingMeasurementType, int macAddressingMode, byte[] macAddress, int rangingStatus)141     public static UwbRangingData generateRangingData(
142             int rangingMeasurementType, int macAddressingMode, byte[] macAddress,
143             int rangingStatus) {
144         switch (rangingMeasurementType) {
145             case RANGING_MEASUREMENT_TYPE_TWO_WAY:
146                 return generateTwoWayMeasurementRangingData(rangingStatus);
147             case RANGING_MEASUREMENT_TYPE_OWR_AOA:
148                 return generateOwrAoaMeasurementRangingData(
149                         macAddressingMode, macAddress, rangingStatus);
150             case RANGING_MEASUREMENT_TYPE_DL_TDOA:
151                 return generateDlTDoAMeasurementRangingData(macAddressingMode, rangingStatus);
152             default:
153                 return generateDefaultRangingData();
154         }
155     }
156 
generateTwoWayMeasurementRangingData(int rangingStatus)157     private static UwbRangingData generateTwoWayMeasurementRangingData(int rangingStatus) {
158         final int noOfRangingMeasures = 1;
159         final UwbTwoWayMeasurement[] uwbTwoWayMeasurements =
160                 new UwbTwoWayMeasurement[noOfRangingMeasures];
161         uwbTwoWayMeasurements[0] = new UwbTwoWayMeasurement(PEER_SHORT_MAC_ADDRESS, rangingStatus,
162                 TEST_LOS, TEST_DISTANCE, convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7),
163                 TEST_AOA_AZIMUTH_FOM, convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7),
164                 TEST_AOA_ELEVATION_FOM, convertFloatToQFormat(TEST_AOA_DEST_AZIMUTH, 9, 7),
165                 TEST_AOA_DEST_AZIMUTH_FOM, convertFloatToQFormat(TEST_AOA_DEST_ELEVATION, 9, 7),
166                 TEST_AOA_DEST_ELEVATION_FOM, TEST_SLOT_IDX, TEST_RSSI);
167         return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID,
168                 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_TWO_WAY,
169                 TEST_HUS_PRIMARY_SESSION_ID, TEST_MAC_ADDRESS_MODE, noOfRangingMeasures,
170                 uwbTwoWayMeasurements, TEST_RAW_NTF_DATA);
171     }
172 
generateOwrAoaMeasurementRangingData( int macAddressingMode, byte[] macAddress, int rangingStatus)173     private static UwbRangingData generateOwrAoaMeasurementRangingData(
174             int macAddressingMode, byte[] macAddress, int rangingStatus) {
175         final int noOfRangingMeasures = 1;
176         final UwbOwrAoaMeasurement uwbOwrAoaMeasurement  = new UwbOwrAoaMeasurement(
177                 macAddress, rangingStatus, TEST_LOS,
178                 TEST_FRAME_SEQUENCE_NUMBER, TEST_BLOCK_IDX,
179                 convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7), TEST_AOA_AZIMUTH_FOM,
180                 convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7), TEST_AOA_ELEVATION_FOM);
181         return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID,
182                 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_OWR_AOA,
183                 TEST_HUS_PRIMARY_SESSION_ID, macAddressingMode, noOfRangingMeasures,
184                 uwbOwrAoaMeasurement, TEST_RAW_NTF_DATA);
185     }
186 
187     /** Generate an OWR ranging data with a bad AoA Azimuth FOM */
generateBadOwrAoaMeasurementRangingData( int macAddressingMode, byte[] macAddress)188     public static UwbRangingData generateBadOwrAoaMeasurementRangingData(
189             int macAddressingMode, byte[] macAddress) {
190         final int noOfRangingMeasures = 1;
191         final UwbOwrAoaMeasurement uwbOwrAoaMeasurement  = new UwbOwrAoaMeasurement(
192                 macAddress, TEST_STATUS, TEST_LOS,
193                 TEST_FRAME_SEQUENCE_NUMBER, TEST_BLOCK_IDX,
194                 convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7), TEST_BAD_AOA_AZIMUTH_FOM,
195                 convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7), TEST_AOA_ELEVATION_FOM);
196         return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID,
197                 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_OWR_AOA,
198                 TEST_HUS_PRIMARY_SESSION_ID, macAddressingMode, noOfRangingMeasures,
199                 uwbOwrAoaMeasurement, TEST_RAW_NTF_DATA);
200     }
201 
generateDlTDoAMeasurementRangingData( int macAddressingMode, int rangingStatus)202     private static UwbRangingData generateDlTDoAMeasurementRangingData(
203             int macAddressingMode, int rangingStatus) {
204         final int noOfRangingMeasures = 1;
205         byte[] macAddress = (macAddressingMode == MAC_ADDRESSING_MODE_SHORT)
206                 ? PEER_SHORT_MAC_ADDRESS : PEER_EXTENDED_MAC_ADDRESS;
207         final UwbDlTDoAMeasurement[] uwbDlTDoAMeasurements =
208                 new UwbDlTDoAMeasurement[noOfRangingMeasures];
209         uwbDlTDoAMeasurements[0] = new UwbDlTDoAMeasurement(macAddress, rangingStatus,
210                 TEST_MESSAGE_TYPE, TEST_MESSAGE_CONTROL, TEST_BLOCK_INDEX, TEST_ROUND_INDEX,
211                 TEST_LOS, convertFloatToQFormat(TEST_AOA_AZIMUTH, 9, 7),
212                 TEST_AOA_AZIMUTH_FOM, convertFloatToQFormat(TEST_AOA_ELEVATION, 9, 7),
213                 TEST_AOA_ELEVATION_FOM, TEST_RSSI, TEST_TIMESTAMP, TEST_TIMESTAMP,
214                 convertFloatToQFormat(TEST_ANCHOR_CFO, 6, 10),
215                 convertFloatToQFormat(TEST_CFO, 6, 10), TEST_INTIATOR_REPLY_TIME,
216                 TEST_RESPONDER_REPLY_TIME, TEST_INITIATOR_RESPONDER_TOF, TEST_ANCHOR_LOCATION,
217                 TEST_ACTIVE_RANGING_ROUNDS);
218 
219         return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID,
220                 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_DL_TDOA,
221                 TEST_HUS_PRIMARY_SESSION_ID, macAddressingMode, noOfRangingMeasures,
222                 uwbDlTDoAMeasurements, TEST_RAW_NTF_DATA);
223     }
224 
225     // Create a UwbRangingData with no measurements, for negative test cases (example: incorrect
226     // ranging measurement type).
generateDefaultRangingData()227     private static UwbRangingData generateDefaultRangingData() {
228         final int noOfRangingMeasures = 0;
229         final UwbTwoWayMeasurement[] uwbEmptyTwoWayMeasurements =
230                 new UwbTwoWayMeasurement[noOfRangingMeasures];
231         return new UwbRangingData(TEST_SEQ_COUNTER, TEST_SESSION_ID,
232                 TEST_RCR_INDICATION, TEST_CURR_RANGING_INTERVAL, RANGING_MEASUREMENT_TYPE_UNDEFINED,
233                 TEST_HUS_PRIMARY_SESSION_ID, TEST_MAC_ADDRESS_MODE, noOfRangingMeasures,
234                 uwbEmptyTwoWayMeasurements, TEST_RAW_NTF_DATA);
235     }
236 
237     // 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)238     public static Pair<UwbRangingData, RangingReport> generateRangingDataAndRangingReport(
239             byte[] macAddress, int macAddressingMode, int rangingMeasurementType,
240             boolean isAoaAzimuthEnabled, boolean isAoaElevationEnabled,
241             boolean isDestAoaAzimuthEnabled, boolean isDestAoaElevationEnabled,
242             long elapsedRealtimeNanos) {
243         UwbRangingData uwbRangingData = generateRangingData(rangingMeasurementType,
244                 macAddressingMode, TEST_STATUS);
245 
246         PersistableBundle rangingReportMetadata = new RangingReportMetadata.Builder()
247                 .setSessionId(0)
248                 .setRawNtfData(new byte[] {0x10, 0x01, 0x05})
249                 .build()
250                 .toBundle();
251 
252         AngleOfArrivalMeasurement aoaMeasurement = null;
253         AngleOfArrivalMeasurement aoaDestMeasurement = null;
254         if (isAoaAzimuthEnabled || isAoaElevationEnabled) {
255             AngleMeasurement aoaAzimuth = isAoaAzimuthEnabled
256                     ? new AngleMeasurement(degreeToRadian(TEST_AOA_AZIMUTH), 0,
257                     TEST_AOA_AZIMUTH_FOM / (double) 100)
258                     : new AngleMeasurement(0, 0, 0);
259             AngleOfArrivalMeasurement.Builder aoaBuilder =
260                     new AngleOfArrivalMeasurement.Builder(aoaAzimuth);
261 
262             if (isAoaElevationEnabled) {
263                 AngleMeasurement aoaElevation = new AngleMeasurement(
264                         degreeToRadian(TEST_AOA_ELEVATION), 0,
265                         TEST_AOA_ELEVATION_FOM / (double) 100);
266                 aoaBuilder.setAltitude(aoaElevation);
267             }
268 
269             aoaMeasurement = aoaBuilder.build();
270         }
271         if (isDestAoaAzimuthEnabled || isDestAoaElevationEnabled) {
272             AngleMeasurement aoaAzimuth = isDestAoaAzimuthEnabled
273                     ? new AngleMeasurement(degreeToRadian(TEST_AOA_DEST_AZIMUTH), 0,
274                     TEST_AOA_DEST_AZIMUTH_FOM / (double) 100)
275                     : new AngleMeasurement(0, 0, 0);
276             AngleOfArrivalMeasurement.Builder aoaBuilder =
277                     new AngleOfArrivalMeasurement.Builder(aoaAzimuth);
278 
279             if (isDestAoaElevationEnabled) {
280                 AngleMeasurement aoaElevation = new AngleMeasurement(
281                         degreeToRadian(TEST_AOA_DEST_ELEVATION), 0,
282                         TEST_AOA_DEST_ELEVATION_FOM / (double) 100);
283                 aoaBuilder.setAltitude(aoaElevation);
284             }
285 
286             aoaDestMeasurement = aoaBuilder.build();
287         }
288 
289         RangingReport rangingReport = buildRangingReport(macAddress, rangingMeasurementType,
290                 aoaMeasurement, aoaDestMeasurement, elapsedRealtimeNanos, rangingReportMetadata);
291         return Pair.create(uwbRangingData, rangingReport);
292     }
293 
getComputedMacAddress(byte[] address)294     private static UwbAddress getComputedMacAddress(byte[] address) {
295         if (!SdkLevel.isAtLeastU()) {
296             return UwbAddress.fromBytes(TlvUtil.getReverseBytes(address));
297         }
298         return UwbAddress.fromBytes(address);
299     }
300 
buildRangingReport(byte[] macAddress, int rangingMeasurementType, AngleOfArrivalMeasurement aoaMeasurement, AngleOfArrivalMeasurement aoaDestMeasurement, long elapsedRealtimeNanos, PersistableBundle rangingReportMetadata)301     private static RangingReport buildRangingReport(byte[] macAddress, int rangingMeasurementType,
302             AngleOfArrivalMeasurement aoaMeasurement, AngleOfArrivalMeasurement aoaDestMeasurement,
303             long elapsedRealtimeNanos, PersistableBundle rangingReportMetadata) {
304 
305         PersistableBundle rangingMeasurementMetadata = new PersistableBundle();
306 
307         RangingMeasurement.Builder rangingMeasurementBuilder = new RangingMeasurement.Builder()
308                 .setRemoteDeviceAddress(getComputedMacAddress(macAddress))
309                 .setStatus(TEST_STATUS)
310                 .setElapsedRealtimeNanos(elapsedRealtimeNanos)
311                 .setAngleOfArrivalMeasurement(aoaMeasurement)
312                 .setLineOfSight(TEST_LOS);
313 
314         if (rangingMeasurementType == RANGING_MEASUREMENT_TYPE_TWO_WAY) {
315             rangingMeasurementBuilder
316                     .setDistanceMeasurement(
317                             new DistanceMeasurement.Builder()
318                                     .setMeters(TEST_DISTANCE / (double) 100)
319                                     .setErrorMeters(0)
320                                     .setConfidenceLevel(1.0)
321                                     .build())
322                     .setDestinationAngleOfArrivalMeasurement(aoaDestMeasurement)
323                     .setRssiDbm(-TEST_RSSI / 2)
324                     .setRangingMeasurementMetadata(rangingMeasurementMetadata);
325         }
326 
327         if (rangingMeasurementType == RANGING_MEASUREMENT_TYPE_DL_TDOA) {
328             DlTDoAMeasurement dlTDoAMeasurement = new DlTDoAMeasurement.Builder()
329                     .setMessageType(TEST_MESSAGE_TYPE)
330                     .setMessageControl(TEST_MESSAGE_CONTROL)
331                     .setBlockIndex(TEST_BLOCK_INDEX)
332                     .setNLoS(TEST_LOS)
333                     .setTxTimestamp(TEST_TIMESTAMP)
334                     .setRxTimestamp(TEST_TIMESTAMP)
335                     .setAnchorCfo(TEST_ANCHOR_CFO)
336                     .setCfo(TEST_CFO)
337                     .setInitiatorReplyTime(TEST_INTIATOR_REPLY_TIME)
338                     .setResponderReplyTime(TEST_RESPONDER_REPLY_TIME)
339                     .setInitiatorResponderTof(TEST_INITIATOR_RESPONDER_TOF)
340                     .setAnchorLocation(TEST_ANCHOR_LOCATION)
341                     .setActiveRangingRounds(TEST_ACTIVE_RANGING_ROUNDS)
342                     .setRoundIndex(TEST_ROUND_INDEX)
343                     .build();
344             rangingMeasurementBuilder.setRssiDbm(-TEST_RSSI / 2);
345             rangingMeasurementBuilder.setRangingMeasurementMetadata(dlTDoAMeasurement.toBundle());
346         }
347 
348         return new RangingReport.Builder()
349                 .addMeasurement(rangingMeasurementBuilder.build())
350                 .addRangingReportMetadata(rangingReportMetadata)
351                 .build();
352     }
353 
354     /** Build UwbRadarData for all Radar Data Type(s). */
generateUwbRadarData(int radarDataType, int rangingStatus)355     public static UwbRadarData generateUwbRadarData(int radarDataType, int rangingStatus) {
356         switch (radarDataType) {
357             case RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES:
358                 return generateRadarSweepSamplesUwbRadarData(rangingStatus);
359             default:
360                 return generateDefaultUwbRadarData();
361         }
362     }
363 
364     /** Build UwbRadarData for Radar Sweep Samples Radar Data Type. */
generateRadarSweepSamplesUwbRadarData(int rangingStatus)365     public static UwbRadarData generateRadarSweepSamplesUwbRadarData(int rangingStatus) {
366         final int noOfRadarSweeps = 2;
367         final UwbRadarSweepData[] uwbRadarSweepData = new UwbRadarSweepData[noOfRadarSweeps];
368         uwbRadarSweepData[0] =
369                 new UwbRadarSweepData(
370                         TEST_SEQ_COUNTER,
371                         TEST_TIMESTAMP,
372                         TEST_VENDOR_SPECIFIC_DATA,
373                         TEST_SAMPLE_DATA);
374         uwbRadarSweepData[1] =
375                 new UwbRadarSweepData(
376                         TEST_SEQ_COUNTER2,
377                         TEST_TIMESTAMP2,
378                         TEST_VENDOR_SPECIFIC_DATA,
379                         TEST_SAMPLE_DATA);
380         return new UwbRadarData(
381                 TEST_SESSION_ID,
382                 rangingStatus,
383                 RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES,
384                 TEST_SAMPLES_PER_SWEEP,
385                 TEST_BITS_PER_SAMPLE,
386                 TEST_SWEEP_OFFSET,
387                 uwbRadarSweepData);
388     }
389 
390     /* Create a UwbRadarData with no measurements */
generateDefaultUwbRadarData()391     private static UwbRadarData generateDefaultUwbRadarData() {
392         final int noOfRadarSweeps = 0;
393         final UwbRadarSweepData[] uwbEmptyRadarSweepData = new UwbRadarSweepData[noOfRadarSweeps];
394         return new UwbRadarData(
395                 TEST_SESSION_ID,
396                 TEST_STATUS,
397                 RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES,
398                 TEST_SAMPLES_PER_SWEEP,
399                 TEST_BITS_PER_SAMPLE,
400                 TEST_SWEEP_OFFSET,
401                 uwbEmptyRadarSweepData);
402     }
403 
404     /** Build RadarData for all Radar Data Type(s). */
generateRadarData(UwbRadarData uwbRadarData)405     public static RadarData generateRadarData(UwbRadarData uwbRadarData) {
406         RadarData.Builder radarDataBuilder =
407                 new RadarData.Builder()
408                         .setStatusCode(uwbRadarData.statusCode)
409                         .setRadarDataType(uwbRadarData.radarDataType)
410                         .setSamplesPerSweep(uwbRadarData.samplesPerSweep)
411                         .setBitsPerSample(uwbRadarData.bitsPerSample)
412                         .setSweepOffset(uwbRadarData.sweepOffset);
413         if (uwbRadarData.radarDataType == RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES) {
414             for (UwbRadarSweepData sweepData : uwbRadarData.radarSweepData) {
415                 radarDataBuilder.addSweepData(
416                         new RadarSweepData.Builder()
417                                 .setSequenceNumber(sweepData.sequenceNumber)
418                                 .setTimestamp(sweepData.timestamp)
419                                 .setVendorSpecificData(sweepData.vendorSpecificData)
420                                 .setSampleData(sweepData.sampleData)
421                                 .build());
422             }
423         }
424         return radarDataBuilder.build();
425     }
426 
427     /**
428      * Helper method to generate a {@link UwbRadarData} instance and a corresponding
429      * {@link RadarData}.
430      */
generateUwbRadarDataAndRadarData( int radarDataType)431     public static Pair<UwbRadarData, RadarData> generateUwbRadarDataAndRadarData(
432             int radarDataType) {
433         UwbRadarData uwbRadarData = generateUwbRadarData(radarDataType, TEST_STATUS);
434         RadarData radarData = generateRadarData(uwbRadarData);
435         return Pair.create(uwbRadarData, radarData);
436     }
437 }
438