blob: 9efb6428ae97d3fc9c5441c2ede3e17c93236eee [file] [log] [blame]
Roy Wantb1772f92019-01-20 00:18:31 -08001/*
2 * Copyright (C) 2018 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
17package android.net.wifi.rtt;
18
19import android.location.Address;
20import android.net.MacAddress;
21import android.os.Parcel;
22
23import static junit.framework.Assert.assertEquals;
24import static junit.framework.Assert.assertFalse;
25import static junit.framework.Assert.assertTrue;
26
27import org.junit.Test;
28import org.junit.runner.RunWith;
29import org.junit.runners.JUnit4;
30
31import java.util.List;
32
33/**
34 * Tests for {@link ResponderLocation}.
35 */
36@RunWith(JUnit4.class)
37public class ResponderLocationTest {
38 private static final double LATLNG_TOLERANCE_DEGREES = 0.001;
39 private static final double ALT_TOLERANCE_METERS = 0.01;
40 private static final double HEIGHT_TOLERANCE_METERS = 0.01;
41 private static final int INDEX_ELEMENT_TYPE = 2;
42 private static final int INDEX_SUBELEMENT_TYPE = 0;
43 private static final int INDEX_SUBELEMENT_LENGTH = 1;
44
45 /* Test Buffers */
46
47 private static final byte[] sTestLciIeHeader = {
48 (byte) 0x01, (byte) 0x00, (byte) 0x08 // LCI Information Element (IE)
49 };
50
51 private static final byte[] sTestLciShortBuffer = {
52 (byte) 0x00
53 };
54
55 private static final byte[] sTestLciSE = {
56 (byte) 0x00, // Subelement LCI
57 (byte) 16, // Subelement LCI length always = 16
58 (byte) 0x52,
59 (byte) 0x83,
60 (byte) 0x4d,
61 (byte) 0x12,
62 (byte) 0xef,
63 (byte) 0xd2,
64 (byte) 0xb0,
65 (byte) 0x8b,
66 (byte) 0x9b,
67 (byte) 0x4b,
68 (byte) 0xf1,
69 (byte) 0xcc,
70 (byte) 0x2c,
71 (byte) 0x00,
72 (byte) 0x00,
73 (byte) 0x41
74 };
75
76 private static final byte[] sTestZHeightSE = {
77 (byte) 0x04, // Subelement Z
78 (byte) 6, // Length always 6
79 (byte) 0x00, // LSB STA Floor Info (2 bytes)
80 (byte) 0x01, // MSB
81 (byte) 0xcd, // LSB Height(m) (3 bytes)
82 (byte) 0x2c,
83 (byte) 0x00, // MSB Height(m)
84 (byte) 0x0e, // STA Height Uncertainty
85 };
86
87 private static final byte[] sTestUsageSE1 = {
88 (byte) 0x06, // Subelement Usage Rights
89 (byte) 1, // Length 1 (with no retention limit)
90 (byte) 0x01, // Retransmit ok, No expiration, no extra info available
91 };
92
93 private static final byte[] sTestUsageSE2 = {
94 (byte) 0x06, // Subelement Usage Rights
95 (byte) 3, // Length 3 (including retention limit)
96 (byte) 0x06, // Retransmit not ok, Expiration, extra info available
97 (byte) 0x00, // LSB expiration time (0x8000 = 32768 hrs)
98 (byte) 0x80 // MSB expiration time
99 };
100
101 private static final byte[] sTestBssidListSE = {
102 (byte) 0x07, // Subelement BSSID list
103 (byte) 13, // length dependent on number of BSSIDs in list
104 (byte) 0x02, // Number of BSSIDs in list
105 (byte) 0x01, // BSSID #1 (MSB)
106 (byte) 0x02,
107 (byte) 0x03,
108 (byte) 0x04,
109 (byte) 0x05,
110 (byte) 0x06, // (LSB)
111 (byte) 0xf1, // BSSID #2 (MSB)
112 (byte) 0xf2,
113 (byte) 0xf3,
114 (byte) 0xf4,
115 (byte) 0xf5,
116 (byte) 0xf6 // (LSB)
117 };
118
119 private static final byte[] sTestLcrBufferHeader = {
120 (byte) 0x01, (byte) 0x00, (byte) 0x0b,
121 };
122
123 private static final byte[] sEmptyBuffer = {};
124
125 private static final byte[] sTestCivicLocationSEWithAddress = {
126 (byte) 0, // Civic Location Subelement
127 (byte) 39, // Length of subelement value
128 (byte) 'U', // CountryCodeChar1
129 (byte) 'S', // CountryCodeChar2
130 (byte) CivicLocationKeys.HNO,
131 (byte) 2,
132 (byte) '1',
133 (byte) '5',
134 (byte) CivicLocationKeys.PRIMARY_ROAD_NAME,
135 (byte) 4,
136 (byte) 'A',
137 (byte) 'l',
138 (byte) 't',
139 (byte) 'o',
140 (byte) CivicLocationKeys.STREET_NAME_POST_MODIFIER,
141 (byte) 4,
142 (byte) 'R',
143 (byte) 'o',
144 (byte) 'a',
145 (byte) 'd',
146 (byte) CivicLocationKeys.CITY,
147 (byte) 8,
148 (byte) 'M',
149 (byte) 't',
150 (byte) 'n',
151 (byte) ' ',
152 (byte) 'V',
153 (byte) 'i',
154 (byte) 'e',
155 (byte) 'w',
156 (byte) CivicLocationKeys.STATE,
157 (byte) 2,
158 (byte) 'C',
159 (byte) 'A',
160 (byte) CivicLocationKeys.POSTAL_CODE,
161 (byte) 5,
162 (byte) '9',
163 (byte) '4',
164 (byte) '0',
165 (byte) '4',
166 (byte) '3'
167 };
168
169 // Buffer representing: "https://map.com/mall.jpg"
170 private static final byte[] sTestMapUrlSE = {
171 (byte) 5, // Map URL Subelement
172 (byte) 25,
173 (byte) ResponderLocation.MAP_TYPE_URL_DEFINED,
174 (byte) 'h',
175 (byte) 't',
176 (byte) 't',
177 (byte) 'p',
178 (byte) 's',
179 (byte) ':',
180 (byte) '/',
181 (byte) '/',
182 (byte) 'm',
183 (byte) 'a',
184 (byte) 'p',
185 (byte) '.',
186 (byte) 'c',
187 (byte) 'o',
188 (byte) 'm',
189 (byte) '/',
190 (byte) 'm',
191 (byte) 'a',
192 (byte) 'l',
193 (byte) 'l',
194 (byte) '.',
195 (byte) 'j',
196 (byte) 'p',
197 (byte) 'g'
198 };
199
200 /**
201 * Test if the lci and lcr buffers are null.
202 */
203 @Test
204 public void testIfLciOrLcrIsNull() {
205 ResponderLocation responderLocation = new ResponderLocation(null, null);
206
207 boolean valid = responderLocation.isValid();
208 boolean lciValid = responderLocation.isLciSubelementValid();
209 boolean zValid = responderLocation.isZsubelementValid();
210
211 assertFalse(valid);
212 assertFalse(lciValid);
213 assertFalse(zValid);
214 }
215
216 /**
217 * Test if the lci and lcr buffers are empty.
218 */
219 @Test
220 public void testIfLciOrLcrIsEmpty() {
221 ResponderLocation responderLocation = new ResponderLocation(sEmptyBuffer, sEmptyBuffer);
222
223 boolean valid = responderLocation.isValid();
224 boolean lciValid = responderLocation.isLciSubelementValid();
225 boolean zValid = responderLocation.isZsubelementValid();
226
227 assertFalse(valid);
228 assertFalse(lciValid);
229 assertFalse(zValid);
230 }
231
232 /**
233 * Test if the lci subelement only has one byte
234 */
235 @Test
236 public void testIfLciShortBuffer() {
237 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciShortBuffer);
238 ResponderLocation responderLocation =
239 new ResponderLocation(testLciBuffer, sTestLcrBufferHeader);
240
241 boolean valid = responderLocation.isValid();
242 boolean lciValid = responderLocation.isLciSubelementValid();
243 boolean zValid = responderLocation.isZsubelementValid();
244
245 assertFalse(valid);
246 assertFalse(lciValid);
247 assertFalse(zValid);
248 }
249
250 /**
251 * Test that the example buffer contains a valid LCI Subelement.
252 */
253 @Test
254 public void testLciValidSubelement() {
255 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
256 ResponderLocation responderLocation =
257 new ResponderLocation(testLciBuffer, sTestLcrBufferHeader);
258
259 boolean valid = responderLocation.isValid();
260 boolean lciValid = responderLocation.isLciSubelementValid();
261 boolean zValid = responderLocation.isZsubelementValid();
262
263 assertTrue(valid);
264 assertTrue(lciValid);
265 assertFalse(zValid);
266 assertEquals(0.0009765625, responderLocation.getLatitudeUncertainty());
267 assertEquals(-33.857009, responderLocation.getLatitude(),
268 LATLNG_TOLERANCE_DEGREES);
269 assertEquals(0.0009765625, responderLocation.getLongitudeUncertainty());
270 assertEquals(151.215200, responderLocation.getLongitude(),
271 LATLNG_TOLERANCE_DEGREES);
272 assertEquals(1, responderLocation.getAltitudeType());
273 assertEquals(64.0, responderLocation.getAltitudeUncertainty());
274 assertEquals(11.2, responderLocation.getAltitude(), ALT_TOLERANCE_METERS);
275 assertEquals(1, responderLocation.getDatum()); // WGS84
276 int lciFlags = responderLocation.getLciFlags();
277 assertEquals(0, lciFlags & ResponderLocation.LCI_FLAGS_MASK_REGLOC_AGREEMENT);
278 assertEquals(0, lciFlags & ResponderLocation.LCI_FLAGS_MASK_REGLOC_DSE);
279 assertEquals(0, lciFlags & ResponderLocation.LCI_FLAGS_MASK_DEPENDENT_STA);
280 assertEquals(1, lciFlags & ResponderLocation.LCI_FLAGS_MASK_VERSION);
281 }
282
283 /**
284 * Test for an invalid LCI element.
285 */
286 @Test
287 public void testLciInvalidElement() {
288 byte[] testBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
289 testBuffer[INDEX_ELEMENT_TYPE] = (byte) 0xFF;
290 ResponderLocation responderLocation =
291 new ResponderLocation(testBuffer, sTestLcrBufferHeader);
292
293 boolean valid = responderLocation.isValid();
294 boolean lciValid = responderLocation.isLciSubelementValid();
295 boolean zValid = responderLocation.isZsubelementValid();
296
297 assertFalse(valid);
298 assertFalse(lciValid);
299 assertFalse(zValid);
300 }
301
302 /**
303 * Test for an invalid subelement type.
304 */
305 @Test
306 public void testSkipLciSubElementUnusedOrUnknown() {
307 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
308 // Corrupt the subelement type to an unknown type.
309 testLciBuffer[sTestLciIeHeader.length + INDEX_SUBELEMENT_TYPE] = (byte) 0x77;
310 ResponderLocation responderLocation =
311 new ResponderLocation(testLciBuffer, sTestLcrBufferHeader);
312
313 boolean valid = responderLocation.isValid();
314 boolean lciValid = responderLocation.isLciSubelementValid();
315 boolean zValid = responderLocation.isZsubelementValid();
316
317 assertFalse(valid);
318 assertFalse(lciValid);
319 assertFalse(zValid);
320 }
321
322 /**
323 * Test for a subelement LCI length too small.
324 */
325 @Test
326 public void testInvalidLciSubElementLengthTooSmall() {
327 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
328 // Corrupt the length making it too small.
329 testLciBuffer[sTestLciIeHeader.length + INDEX_SUBELEMENT_LENGTH] = (byte) 0x01;
330 ResponderLocation responderLocation =
331 new ResponderLocation(testLciBuffer, sTestLcrBufferHeader);
332
333 boolean valid = responderLocation.isValid();
334 boolean lciValid = responderLocation.isLciSubelementValid();
335 boolean zValid = responderLocation.isZsubelementValid();
336
337 assertFalse(valid);
338 assertFalse(lciValid);
339 assertFalse(zValid);
340 }
341
342 /**
343 * Test for a subelement LCI length too big.
344 */
345 @Test
346 public void testInvalidLciSubElementLengthTooBig() {
347 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
348 // Corrupt the length making it too big.
349 testLciBuffer[sTestLciIeHeader.length + INDEX_SUBELEMENT_TYPE] = (byte) 0x11;
350 ResponderLocation responderLocation =
351 new ResponderLocation(testLciBuffer, sTestLcrBufferHeader);
352
353 boolean valid = responderLocation.isValid();
354 boolean lciValid = responderLocation.isLciSubelementValid();
355 boolean zValid = responderLocation.isZsubelementValid();
356
357 assertFalse(valid);
358 assertFalse(lciValid);
359 assertFalse(zValid);
360 }
361
362 /**
363 * Test for a valid Z (Height) subelement following an LCI subelement.
364 */
365 @Test
366 public void testLciValidZBufferSEAfterLci() {
367 byte[] testBufferTmp = concatenateArrays(sTestLciIeHeader, sTestLciSE);
368 byte[] testBuffer = concatenateArrays(testBufferTmp, sTestZHeightSE);
369 ResponderLocation responderLocation =
370 new ResponderLocation(testBuffer, sTestLcrBufferHeader);
371
372 boolean isValid = responderLocation.isValid();
373 boolean isZValid = responderLocation.isZsubelementValid();
374 boolean isLciValid = responderLocation.isLciSubelementValid();
375 double staFloorNumber = responderLocation.getStaFloorNumber();
376 double staHeightAboveFloorMeters = responderLocation.getStaHeightAboveFloorMeters();
377 double staHeightAboveFloorUncertaintyMeters =
378 responderLocation.getStaHeightAboveFloorUncertaintyMeters();
379
380 assertTrue(isValid);
381 assertTrue(isZValid);
382 assertTrue(isLciValid);
383 assertEquals(4.0, staFloorNumber);
384 assertEquals(2.8, staHeightAboveFloorMeters, HEIGHT_TOLERANCE_METERS);
385 assertEquals(0.125, staHeightAboveFloorUncertaintyMeters);
386 }
387
388 /**
389 * Test for a valid Usage Policy that is unrestrictive
390 */
391 @Test
392 public void testLciOpenUsagePolicy() {
393 byte[] testBufferTmp = concatenateArrays(sTestLciIeHeader, sTestLciSE);
394 byte[] testBuffer = concatenateArrays(testBufferTmp, sTestUsageSE1);
395 ResponderLocation responderLocation =
396 new ResponderLocation(testBuffer, sTestLcrBufferHeader);
397
398 boolean valid = responderLocation.isValid();
399 boolean retransmit = responderLocation.getRetransmitPolicyIndication();
400 boolean expiration = responderLocation.getRetentionExpiresIndication();
401 boolean extraInfo = responderLocation.getExtraInfoOnAssociationIndication();
402
403 assertTrue(valid);
404 assertTrue(retransmit);
405 assertFalse(expiration);
406 assertFalse(extraInfo);
407 }
408
409 /**
410 * Test for a valid Usage Policy that is restrictive
411 */
412 @Test
413 public void testLciRestrictiveUsagePolicy() {
414 byte[] testBufferTmp = concatenateArrays(sTestLciIeHeader, sTestLciSE);
415 byte[] testBuffer = concatenateArrays(testBufferTmp, sTestUsageSE2);
416 ResponderLocation responderLocation =
417 new ResponderLocation(testBuffer, sTestLcrBufferHeader);
418
419 boolean valid = responderLocation.isValid();
420 boolean retransmit = responderLocation.getRetransmitPolicyIndication();
421 boolean expiration = responderLocation.getRetentionExpiresIndication();
422 boolean extraInfo = responderLocation.getExtraInfoOnAssociationIndication();
423
424 assertFalse(valid);
425 assertFalse(retransmit);
426 assertTrue(expiration);
427 assertTrue(extraInfo);
428 }
429
430 /**
431 * Test for a valid BSSID element following an LCI subelement.
432 */
433 @Test
434 public void testLciBssidListSEAfterLci() {
435 byte[] testBufferTmp = concatenateArrays(sTestLciIeHeader, sTestLciSE);
436 byte[] testBuffer = concatenateArrays(testBufferTmp, sTestBssidListSE);
437 ResponderLocation responderLocation =
438 new ResponderLocation(testBuffer, sTestLcrBufferHeader);
439
440 boolean valid = responderLocation.isValid();
441 List<MacAddress> bssidList = responderLocation.getColocatedBssids();
442
443 assertTrue(valid);
444 assertEquals(2, bssidList.size());
445 MacAddress macAddress1 = bssidList.get(0);
446 assertEquals("01:02:03:04:05:06", macAddress1.toString());
447 MacAddress macAddress2 = bssidList.get(1);
448 assertEquals("f1:f2:f3:f4:f5:f6", macAddress2.toString());
449 }
450
451 /**
452 * Test for a valid BSSID element before and LCI element
453 */
454 @Test
455 public void testLciBssidListSEBeforeLci() {
456 byte[] testBufferTmp = concatenateArrays(sTestLciIeHeader, sTestBssidListSE);
457 byte[] testBuffer = concatenateArrays(testBufferTmp, sTestLciSE);
458 ResponderLocation responderLocation =
459 new ResponderLocation(testBuffer, sTestLcrBufferHeader);
460
461 boolean valid = responderLocation.isValid();
462 List<MacAddress> bssidList = responderLocation.getColocatedBssids();
463
464 assertTrue(valid);
465 assertEquals(2, bssidList.size());
466 MacAddress macAddress1 = bssidList.get(0);
467 assertEquals("01:02:03:04:05:06", macAddress1.toString());
468 MacAddress macAddress2 = bssidList.get(1);
469 assertEquals("f1:f2:f3:f4:f5:f6", macAddress2.toString());
470 }
471
472 /**
473 * Test that a valid address can be extracted from a valid lcr buffer with Civic Location.
474 */
475 @Test
476 public void testLcrTestCivicLocationAddress() {
477 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
478 byte[] testLcrBuffer =
479 concatenateArrays(sTestLcrBufferHeader, sTestCivicLocationSEWithAddress);
480 ResponderLocation responderLocation = new ResponderLocation(testLciBuffer, testLcrBuffer);
481
482 boolean valid = responderLocation.isValid();
483 String countryCode = responderLocation.getCivicLocationCountryCode();
484 Address address = responderLocation.toCivicLocationAddress();
485
486 assertTrue(valid);
487 assertEquals("US", countryCode);
488 assertEquals("", address.getAddressLine(0));
489 assertEquals("15 Alto", address.getAddressLine(1));
490 assertEquals("Mtn View", address.getAddressLine(2));
491 assertEquals("CA 94043", address.getAddressLine(3));
492 assertEquals("US", address.getAddressLine(4));
493 }
494
495 /**
496 * Test that a URL can be extracted from a valid lcr buffer with a map image subelement.
497 */
498 @Test
499 public void testLcrCheckMapUrlIsValid() {
500 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
501 byte[] testLcrBuffer = concatenateArrays(sTestLcrBufferHeader, sTestMapUrlSE);
502 ResponderLocation responderLocation = new ResponderLocation(testLciBuffer, testLcrBuffer);
503
504 boolean valid = responderLocation.isValid();
505 int mapImageType = responderLocation.getMapImageType();
506 String urlString = "";
507 if (responderLocation.getMapImageUrl() != null) {
508 urlString = responderLocation.getMapImageUrl().toString();
509 }
510
511 assertTrue(valid);
512 assertEquals(ResponderLocation.MAP_TYPE_URL_DEFINED, mapImageType);
513 assertEquals("https://map.com/mall.jpg", urlString);
514 }
515
516 /**
517 * Test the object is parcelable
518 */
519 @Test
520 public void testResponderLocationParcelable() {
521 byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
522 ResponderLocation responderLocation =
523 new ResponderLocation(testLciBuffer, sTestLcrBufferHeader);
524
525 Parcel parcel = Parcel.obtain();
526 responderLocation.writeToParcel(parcel, 0);
527 parcel.setDataPosition(0);
528 ResponderLocation responderLocationFromParcel =
529 ResponderLocation.CREATOR.createFromParcel(parcel);
530
531 assertEquals(responderLocationFromParcel, responderLocation);
532 }
533
534 /* Helper Method */
535
536 /**
537 * Concatenate two arrays.
538 *
539 * @param a first array
540 * @param b second array
541 * @return a third array which is the concatenation of the two array params
542 */
543 private byte[] concatenateArrays(byte[] a, byte[] b) {
544 int aLen = a.length;
545 int bLen = b.length;
546 byte[] c = new byte[aLen + bLen];
547 System.arraycopy(a, 0, c, 0, aLen);
548 System.arraycopy(b, 0, c, aLen, bLen);
549 return c;
550 }
551}