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