1 /*
2  * Copyright (C) 2023 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.google.uwb.support;
18 
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertThrows;
22 
23 import android.os.PersistableBundle;
24 
25 import androidx.test.ext.junit.runners.AndroidJUnit4;
26 import androidx.test.filters.SmallTest;
27 
28 import com.google.uwb.support.fira.FiraParams;
29 import com.google.uwb.support.fira.FiraSpecificationParams;
30 import com.google.uwb.support.radar.RadarData;
31 import com.google.uwb.support.radar.RadarOpenSessionParams;
32 import com.google.uwb.support.radar.RadarParams;
33 import com.google.uwb.support.radar.RadarParams.RadarCapabilityFlag;
34 import com.google.uwb.support.radar.RadarSpecificationParams;
35 import com.google.uwb.support.radar.RadarSweepData;
36 
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.util.ArrayList;
41 import java.util.EnumSet;
42 import java.util.List;
43 
44 @SmallTest
45 @RunWith(AndroidJUnit4.class)
46 public class RadarTests {
47     private static final int SESSION_ID = 77;
48     private static final long SEQUENCE_NUMBER = 10;
49     private static final long TIMESTAMP = 1000;
50     private static final byte[] VENDOR_SPECIFIC_DATA = new byte[] {0x01, 0x02, 0x03, 0x04, 0x05};
51     private static final byte[] SAMPLE_DATA = new byte[] {0x05, 0x04, 0x03, 0x02, 0x01};
52     private static final PersistableBundle INVALID_BUNDLE =
53             new FiraSpecificationParams.Builder().build().toBundle();
54 
55     @Test
testOpenSessionParams_missingRequiredParams()56     public void testOpenSessionParams_missingRequiredParams() {
57         assertThrows(
58                 IllegalStateException.class, () -> new RadarOpenSessionParams.Builder().build());
59     }
60 
61     @Test
testOpenSessionParams_fromBundleWithInvalidProtocol()62     public void testOpenSessionParams_fromBundleWithInvalidProtocol() {
63         assertThrows(
64                 IllegalArgumentException.class,
65                 () -> RadarOpenSessionParams.fromBundle(INVALID_BUNDLE));
66     }
67 
68     @Test
testOpenSessionParams()69     public void testOpenSessionParams() {
70         @RadarParams.BurstPeriod int burstPeriod = 100;
71         @RadarParams.SweepPeriod int sweepPeriod = 40;
72         @RadarParams.SweepsPerBurst int sweepsPerBurst = 16;
73         @RadarParams.SamplesPerSweep int samplesPerSweep = 128;
74         @FiraParams.UwbChannel int channelNumber = FiraParams.UWB_CHANNEL_9;
75         @RadarParams.SweepOffset int sweepOffset = -1;
76         @FiraParams.RframeConfig int rframeConfig = FiraParams.RFRAME_CONFIG_SP0;
77         @RadarParams.PreambleDuration
78         int preambleDuration = RadarParams.PREAMBLE_DURATION_T1024_SYMBOLS;
79         @RadarParams.PreambleCodeIndex int preambleCodeIndex = 90;
80         @RadarParams.SessionPriority int sessionPriority = 255;
81         @RadarParams.BitsPerSample int bitsPerSample = RadarParams.BITS_PER_SAMPLES_64;
82         @FiraParams.PrfMode int prfMode = FiraParams.PRF_MODE_HPRF;
83         @RadarParams.NumberOfBursts int numberOfBursts = 1000;
84         @RadarParams.RadarDataType
85         int radarDataType = RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES;
86 
87         RadarOpenSessionParams params =
88                 new RadarOpenSessionParams.Builder()
89                         .setSessionId(SESSION_ID)
90                         .setBurstPeriod(burstPeriod)
91                         .setSweepPeriod(sweepPeriod)
92                         .setSweepsPerBurst(sweepsPerBurst)
93                         .setSamplesPerSweep(samplesPerSweep)
94                         .setChannelNumber(channelNumber)
95                         .setSweepOffset(sweepOffset)
96                         .setRframeConfig(rframeConfig)
97                         .setPreambleDuration(preambleDuration)
98                         .setPreambleCodeIndex(preambleCodeIndex)
99                         .setSessionPriority(sessionPriority)
100                         .setBitsPerSample(bitsPerSample)
101                         .setPrfMode(prfMode)
102                         .setNumberOfBursts(numberOfBursts)
103                         .setRadarDataType(radarDataType)
104                         .build();
105 
106         assertEquals(params.getSessionId(), SESSION_ID);
107         assertEquals(params.getSessionType(), RadarParams.SESSION_TYPE_RADAR);
108         assertEquals(params.getBurstPeriod(), burstPeriod);
109         assertEquals(params.getSweepPeriod(), sweepPeriod);
110         assertEquals(params.getSweepsPerBurst(), sweepsPerBurst);
111         assertEquals(params.getSamplesPerSweep(), samplesPerSweep);
112         assertEquals(params.getChannelNumber(), channelNumber);
113         assertEquals(params.getSweepOffset(), sweepOffset);
114         assertEquals(params.getRframeConfig(), rframeConfig);
115         assertEquals(params.getPreambleDuration(), preambleDuration);
116         assertEquals(params.getPreambleCodeIndex(), preambleCodeIndex);
117         assertEquals(params.getSessionPriority(), sessionPriority);
118         assertEquals(params.getBitsPerSample(), bitsPerSample);
119         assertEquals(params.getPrfMode(), prfMode);
120         assertEquals(params.getNumberOfBursts(), numberOfBursts);
121         assertEquals(params.getRadarDataType(), radarDataType);
122 
123         RadarOpenSessionParams fromBundle = RadarOpenSessionParams.fromBundle(params.toBundle());
124 
125         assertEquals(fromBundle.getSessionId(), SESSION_ID);
126         assertEquals(fromBundle.getSessionType(), RadarParams.SESSION_TYPE_RADAR);
127         assertEquals(fromBundle.getBurstPeriod(), burstPeriod);
128         assertEquals(fromBundle.getSweepPeriod(), sweepPeriod);
129         assertEquals(fromBundle.getSweepsPerBurst(), sweepsPerBurst);
130         assertEquals(fromBundle.getSamplesPerSweep(), samplesPerSweep);
131         assertEquals(fromBundle.getChannelNumber(), channelNumber);
132         assertEquals(fromBundle.getSweepOffset(), sweepOffset);
133         assertEquals(fromBundle.getRframeConfig(), rframeConfig);
134         assertEquals(fromBundle.getPreambleDuration(), preambleDuration);
135         assertEquals(fromBundle.getPreambleCodeIndex(), preambleCodeIndex);
136         assertEquals(fromBundle.getSessionPriority(), sessionPriority);
137         assertEquals(fromBundle.getBitsPerSample(), bitsPerSample);
138         assertEquals(fromBundle.getPrfMode(), prfMode);
139         assertEquals(fromBundle.getNumberOfBursts(), numberOfBursts);
140         assertEquals(fromBundle.getRadarDataType(), radarDataType);
141         assertEquals(params, fromBundle);
142 
143         RadarOpenSessionParams.Builder builder = new RadarOpenSessionParams.Builder(params);
144         RadarOpenSessionParams fromBuilder = builder.build();
145 
146         assertEquals(params, fromBuilder);
147 
148         fromBuilder = new RadarOpenSessionParams.Builder(builder).build();
149 
150         assertEquals(params, fromBuilder);
151     }
152 
153     @Test
testSpecificationParams_fromBundleWithInvalidProtocol()154     public void testSpecificationParams_fromBundleWithInvalidProtocol() {
155         assertThrows(
156                 IllegalArgumentException.class,
157                 () -> RadarSpecificationParams.fromBundle(INVALID_BUNDLE));
158     }
159 
160     @Test
testSpecificationParams()161     public void testSpecificationParams() {
162         EnumSet<RadarCapabilityFlag> radarCapabilities =
163                 EnumSet.of(RadarCapabilityFlag.HAS_RADAR_SWEEP_SAMPLES_SUPPORT);
164         RadarSpecificationParams.Builder paramsBuilder = new RadarSpecificationParams.Builder();
165         paramsBuilder.setRadarCapabilities(radarCapabilities);
166         paramsBuilder.addRadarCapability(RadarCapabilityFlag.HAS_RADAR_SWEEP_SAMPLES_SUPPORT);
167 
168         RadarSpecificationParams params = paramsBuilder.build();
169 
170         assertEquals(radarCapabilities, params.getRadarCapabilities());
171 
172         RadarSpecificationParams fromBundle =
173                 RadarSpecificationParams.fromBundle(params.toBundle());
174 
175         assertEquals(radarCapabilities, fromBundle.getRadarCapabilities());
176         assertEquals(params, fromBundle);
177     }
178 
179     @Test
testSpecificationParams_emptyCapabilities()180     public void testSpecificationParams_emptyCapabilities() {
181         RadarSpecificationParams params = new RadarSpecificationParams.Builder().build();
182         assertEquals(EnumSet.noneOf(RadarCapabilityFlag.class), params.getRadarCapabilities());
183 
184         RadarSpecificationParams fromBundle =
185                 RadarSpecificationParams.fromBundle(params.toBundle());
186         assertEquals(EnumSet.noneOf(RadarCapabilityFlag.class), fromBundle.getRadarCapabilities());
187     }
188 
189     @Test
testRadarSweepData_missingRequiredParams()190     public void testRadarSweepData_missingRequiredParams() {
191         assertThrows(IllegalStateException.class, () -> new RadarSweepData.Builder().build());
192     }
193 
194     @Test
testRadarSweepData_fromBundleWithInvalidProtocol()195     public void testRadarSweepData_fromBundleWithInvalidProtocol() {
196         assertThrows(
197                 IllegalArgumentException.class, () -> RadarSweepData.fromBundle(INVALID_BUNDLE));
198     }
199 
200     @Test
testRadarSweepData_invalidParamsSequenceNumber()201     public void testRadarSweepData_invalidParamsSequenceNumber() {
202         RadarSweepData.Builder builder =
203                 new RadarSweepData.Builder()
204                         .setSequenceNumber(-1) // Invalid as timestamp must be greater than 0.
205                         .setTimestamp(10)
206                         .setSampleData(new byte[] {0x01});
207         assertThrows(IllegalArgumentException.class, () -> builder.build());
208     }
209 
210     @Test
testRadarSweepData_invalidParamsTimestamp()211     public void testRadarSweepData_invalidParamsTimestamp() {
212         RadarSweepData.Builder builder =
213                 new RadarSweepData.Builder()
214                         .setSequenceNumber(1)
215                         .setTimestamp(-10) // Invalid as timestamp must be greater than 0.
216                         .setSampleData(new byte[] {0x01});
217         assertThrows(IllegalArgumentException.class, () -> builder.build());
218     }
219 
220     @Test
testRadarSweepData_invalidParamsSampleData()221     public void testRadarSweepData_invalidParamsSampleData() {
222         RadarSweepData.Builder builder =
223                 new RadarSweepData.Builder()
224                         .setSequenceNumber(1)
225                         .setTimestamp(10)
226                         .setSampleData(new byte[] {}); // Empty sampleData.
227         assertThrows(IllegalArgumentException.class, () -> builder.build());
228     }
229 
230     @Test
testRadarSweepData()231     public void testRadarSweepData() {
232         RadarSweepData data =
233                 new RadarSweepData.Builder()
234                         .setSequenceNumber(SEQUENCE_NUMBER)
235                         .setTimestamp(TIMESTAMP)
236                         .setVendorSpecificData(VENDOR_SPECIFIC_DATA)
237                         .setSampleData(SAMPLE_DATA)
238                         .build();
239 
240         assertEquals(data.getSequenceNumber(), SEQUENCE_NUMBER);
241         assertEquals(data.getTimestamp(), TIMESTAMP);
242         assertArrayEquals(data.getVendorSpecificData(), VENDOR_SPECIFIC_DATA);
243         assertArrayEquals(data.getSampleData(), SAMPLE_DATA);
244 
245         RadarSweepData fromBundle = RadarSweepData.fromBundle(data.toBundle());
246 
247         assertEquals(fromBundle.getSequenceNumber(), SEQUENCE_NUMBER);
248         assertEquals(fromBundle.getTimestamp(), TIMESTAMP);
249         assertArrayEquals(fromBundle.getVendorSpecificData(), VENDOR_SPECIFIC_DATA);
250         assertArrayEquals(fromBundle.getSampleData(), SAMPLE_DATA);
251         assertEquals(data, fromBundle);
252 
253         data =
254                 new RadarSweepData.Builder()
255                         .setSequenceNumber(SEQUENCE_NUMBER)
256                         .setTimestamp(TIMESTAMP)
257                         .setSampleData(SAMPLE_DATA)
258                         .build();
259 
260         assertEquals(data.getVendorSpecificData(), null);
261 
262         fromBundle = RadarSweepData.fromBundle(data.toBundle());
263 
264         assertEquals(fromBundle.getVendorSpecificData(), null);
265         assertEquals(data, fromBundle);
266     }
267 
268     @Test
testRadarData_missingRequiredParams()269     public void testRadarData_missingRequiredParams() {
270         assertThrows(IllegalStateException.class, () -> new RadarData.Builder().build());
271     }
272 
273     @Test
testRadarData_fromBundleWithInvalidProtocol()274     public void testRadarData_fromBundleWithInvalidProtocol() {
275         assertThrows(IllegalArgumentException.class, () -> RadarData.fromBundle(INVALID_BUNDLE));
276     }
277 
278     @Test
testRadarData_invalidParams()279     public void testRadarData_invalidParams() {
280         RadarData.Builder builder =
281                 new RadarData.Builder()
282                         .setStatusCode(FiraParams.STATUS_CODE_OK)
283                         .setRadarDataType(RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES)
284                         .setSamplesPerSweep(5)
285                         .setBitsPerSample(RadarParams.BITS_PER_SAMPLES_64)
286                         .setSweepOffset(-1); // Empty SweepData
287         assertThrows(IllegalArgumentException.class, () -> builder.build());
288     }
289 
290     @Test
testRadarData()291     public void testRadarData() {
292         @FiraParams.StatusCode int statusCode = FiraParams.STATUS_CODE_OK;
293         @RadarParams.RadarDataType
294         int radarDataType = RadarParams.RADAR_DATA_TYPE_RADAR_SWEEP_SAMPLES;
295         @RadarParams.SamplesPerSweep int samplesPerSweep = 5;
296         @RadarParams.BitsPerSample int bitsPerSample = RadarParams.BITS_PER_SAMPLES_32;
297         @RadarParams.SweepOffset int sweepOffset = -1;
298 
299         RadarSweepData sweepData1 =
300                 new RadarSweepData.Builder()
301                         .setSequenceNumber(SEQUENCE_NUMBER)
302                         .setTimestamp(TIMESTAMP)
303                         .setVendorSpecificData(VENDOR_SPECIFIC_DATA)
304                         .setSampleData(SAMPLE_DATA)
305                         .build();
306         RadarSweepData sweepData2 =
307                 new RadarSweepData.Builder()
308                         .setSequenceNumber(SEQUENCE_NUMBER)
309                         .setTimestamp(TIMESTAMP)
310                         .setVendorSpecificData(VENDOR_SPECIFIC_DATA)
311                         .setSampleData(SAMPLE_DATA)
312                         .build();
313 
314         List<RadarSweepData> sweepDataList = new ArrayList<>();
315         sweepDataList.add(sweepData1);
316         sweepDataList.add(sweepData2);
317 
318         RadarData data =
319                 new RadarData.Builder()
320                         .setStatusCode(statusCode)
321                         .setRadarDataType(radarDataType)
322                         .setSamplesPerSweep(5)
323                         .setBitsPerSample(RadarParams.BITS_PER_SAMPLES_32)
324                         .setSweepOffset(-1)
325                         .setSweepData(sweepDataList)
326                         .build();
327 
328         assertEquals(data.getStatusCode(), statusCode);
329         assertEquals(data.getRadarDataType(), radarDataType);
330         assertEquals(data.getSamplesPerSweep(), samplesPerSweep);
331         assertEquals(data.getBitsPerSample(), bitsPerSample);
332         assertEquals(data.getSweepOffset(), sweepOffset);
333         assertEquals(data.getSweepData().get(0), sweepData1);
334         assertEquals(data.getSweepData().get(1), sweepData2);
335 
336         RadarData fromBundle = RadarData.fromBundle(data.toBundle());
337 
338         assertEquals(fromBundle.getStatusCode(), statusCode);
339         assertEquals(fromBundle.getRadarDataType(), radarDataType);
340         assertEquals(fromBundle.getSamplesPerSweep(), samplesPerSweep);
341         assertEquals(fromBundle.getBitsPerSample(), bitsPerSample);
342         assertEquals(fromBundle.getSweepOffset(), sweepOffset);
343         assertEquals(fromBundle.getSweepData().get(0), sweepData1);
344         assertEquals(fromBundle.getSweepData().get(1), sweepData2);
345         assertEquals(data, fromBundle);
346     }
347 }
348