1 /*
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 
17 package android.net.wifi;
18 
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNotEquals;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNotSame;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertThrows;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29 import static org.junit.Assume.assumeTrue;
30 
31 import android.net.MacAddress;
32 import android.net.NetworkCapabilities;
33 import android.net.wifi.util.HexEncoding;
34 import android.os.Parcel;
35 import android.telephony.SubscriptionManager;
36 
37 import androidx.test.filters.SmallTest;
38 
39 import com.android.modules.utils.build.SdkLevel;
40 
41 import org.junit.Test;
42 
43 import java.nio.charset.Charset;
44 import java.nio.charset.StandardCharsets;
45 import java.util.ArrayList;
46 import java.util.List;
47 
48 /**
49  * Unit tests for {@link android.net.wifi.WifiInfo}.
50  */
51 @SmallTest
52 public class WifiInfoTest {
53     private static final long TEST_TX_SUCCESS = 1;
54     private static final long TEST_TX_RETRIES = 2;
55     private static final long TEST_TX_BAD = 3;
56     private static final long TEST_RX_SUCCESS = 4;
57     private static final String TEST_PACKAGE_NAME = "com.test.example";
58     private static final String TEST_FQDN = "test.com";
59     private static final String TEST_PROVIDER_NAME = "test";
60     private static final int TEST_WIFI_STANDARD = ScanResult.WIFI_STANDARD_11AC;
61     private static final int TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS = 866;
62     private static final int TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS = 1200;
63     private static final String TEST_SSID = "Test123";
64     private static final String TEST_BSSID = "12:12:12:12:12:12";
65     private static final int TEST_RSSI = -60;
66     private static final int TEST_NETWORK_ID = 5;
67     private static final int TEST_NETWORK_ID2 = 6;
68     private static final int TEST_SUB_ID = 1;
69     private static final String TEST_NETWORK_KEY = "TestNetworkKey";
70     private static final String AP_MLD_MAC_ADDRESS = "22:33:44:55:66:77";
71     private static final String MLO_LINK_STA_MAC_ADDRESS = "12:34:56:78:9a:bc";
72     private static final String MLO_LINK_AP_MAC_ADDRESS = "bc:9a:78:56:34:12";
73     private static final int TEST_MLO_LINK_ID = 3;
74     private static final int TEST_CHANNEL = 36;
75     private static final int TEST_LINK_SPEED = 300;
76     private static final List<OuiKeyedData> TEST_VENDOR_DATA =
77             OuiKeyedDataUtil.createTestOuiKeyedDataList(5);
78 
addMloInfo(WifiInfo info)79     private void addMloInfo(WifiInfo info) {
80         info.setApMldMacAddress(MacAddress.fromString(AP_MLD_MAC_ADDRESS));
81         info.enableApTidToLinkMappingNegotiationSupport(true);
82         List<MloLink> links = new ArrayList<>();
83         MloLink link = new MloLink();
84         link.setStaMacAddress(MacAddress.fromString(MLO_LINK_STA_MAC_ADDRESS));
85         link.setApMacAddress(MacAddress.fromString(MLO_LINK_AP_MAC_ADDRESS));
86         links.add(link);
87         info.setAffiliatedMloLinks(links);
88         link.setRssi(TEST_RSSI);
89         link.setLinkId(TEST_MLO_LINK_ID);
90         link.setBand(WifiScanner.WIFI_BAND_5_GHZ);
91         link.setChannel(TEST_CHANNEL);
92         link.setRxLinkSpeedMbps(TEST_LINK_SPEED);
93         link.setTxLinkSpeedMbps(TEST_LINK_SPEED);
94         link.setState(MloLink.MLO_LINK_STATE_UNASSOCIATED);
95     }
96 
assertMloNoRedaction(WifiInfo info)97     private void assertMloNoRedaction(WifiInfo info) {
98         assertTrue(info.isApTidToLinkMappingNegotiationSupported());
99         assertNotNull(info.getApMldMacAddress());
100         assertEquals(AP_MLD_MAC_ADDRESS, info.getApMldMacAddress().toString());
101         List<MloLink> links = info.getAffiliatedMloLinks();
102         assertEquals(1, links.size());
103         for (MloLink link : links) {
104             assertNotNull(link.getApMacAddress());
105             assertEquals(MLO_LINK_AP_MAC_ADDRESS, link.getApMacAddress().toString());
106             assertNotNull(link.getStaMacAddress());
107             assertEquals(MLO_LINK_STA_MAC_ADDRESS, link.getStaMacAddress().toString());
108             assertEquals(TEST_RSSI, link.getRssi());
109             assertEquals(TEST_CHANNEL, link.getChannel());
110             assertEquals(TEST_LINK_SPEED, link.getRxLinkSpeedMbps());
111             assertEquals(TEST_LINK_SPEED, link.getTxLinkSpeedMbps());
112             assertEquals(TEST_MLO_LINK_ID, link.getLinkId());
113             assertEquals(WifiScanner.WIFI_BAND_5_GHZ, link.getBand());
114             assertEquals(MloLink.MLO_LINK_STATE_UNASSOCIATED, link.getState());
115         }
116     }
117 
assertMloLocalMacRedaction(WifiInfo info)118     private void assertMloLocalMacRedaction(WifiInfo info) {
119         assertNotNull(info.getApMldMacAddress());
120         assertEquals(AP_MLD_MAC_ADDRESS, info.getApMldMacAddress().toString());
121         List<MloLink> links = info.getAffiliatedMloLinks();
122         assertEquals(1, links.size());
123         for (MloLink link : links) {
124             assertNotNull(link.getApMacAddress());
125             assertEquals(MLO_LINK_AP_MAC_ADDRESS, link.getApMacAddress().toString());
126             assertNull(link.getStaMacAddress());
127         }
128     }
129 
assertMloSensitiveLocationRedaction(WifiInfo info)130     private void assertMloSensitiveLocationRedaction(WifiInfo info) {
131         assertNull(info.getApMldMacAddress());
132         List<MloLink> links = info.getAffiliatedMloLinks();
133         assertEquals(1, links.size());
134         for (MloLink link : links) {
135             assertNull(link.getApMacAddress());
136             assertNotNull(link.getStaMacAddress());
137             assertEquals(MLO_LINK_STA_MAC_ADDRESS, link.getStaMacAddress().toString());
138         }
139     }
140 
makeWifiInfoForRedactionTest( List<ScanResult.InformationElement> informationElements)141     private WifiInfo makeWifiInfoForRedactionTest(
142             List<ScanResult.InformationElement> informationElements) {
143         WifiInfo info = new WifiInfo();
144         info.txSuccess = TEST_TX_SUCCESS;
145         info.txRetries = TEST_TX_RETRIES;
146         info.txBad = TEST_TX_BAD;
147         info.rxSuccess = TEST_RX_SUCCESS;
148         info.setSSID(WifiSsid.fromUtf8Text(TEST_SSID));
149         info.setBSSID(TEST_BSSID);
150         info.setNetworkId(TEST_NETWORK_ID);
151         info.setTrusted(true);
152         info.setOemPaid(true);
153         info.setOemPrivate(true);
154         info.setCarrierMerged(true);
155         info.setOsuAp(true);
156         info.setFQDN(TEST_FQDN);
157         info.setProviderFriendlyName(TEST_PROVIDER_NAME);
158         info.setRequestingPackageName(TEST_PACKAGE_NAME);
159         info.setWifiStandard(TEST_WIFI_STANDARD);
160         info.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
161         info.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
162         info.setSubscriptionId(TEST_SUB_ID);
163         info.setInformationElements(informationElements);
164         info.setIsPrimary(true);
165         info.setMacAddress(TEST_BSSID);
166         if (SdkLevel.isAtLeastT()) {
167             addMloInfo(info);
168         }
169         if (SdkLevel.isAtLeastV()) {
170             info.setVendorData(TEST_VENDOR_DATA);
171         }
172 
173         return info;
174     }
175 
assertNoRedaction(WifiInfo info, List<ScanResult.InformationElement> informationElements)176     private void assertNoRedaction(WifiInfo info,
177             List<ScanResult.InformationElement> informationElements) {
178         assertEquals(TEST_TX_SUCCESS, info.txSuccess);
179         assertEquals(TEST_TX_RETRIES, info.txRetries);
180         assertEquals(TEST_TX_BAD, info.txBad);
181         assertEquals(TEST_RX_SUCCESS, info.rxSuccess);
182         assertEquals("\"" + TEST_SSID + "\"", info.getSSID());
183         assertEquals(TEST_BSSID, info.getBSSID());
184         assertEquals(TEST_NETWORK_ID, info.getNetworkId());
185         assertTrue(info.isTrusted());
186         assertFalse((info.isRestricted()));
187         assertTrue(info.isOsuAp());
188         assertTrue(info.isPasspointAp());
189         assertEquals(TEST_PACKAGE_NAME, info.getRequestingPackageName());
190         assertEquals(TEST_FQDN, info.getPasspointFqdn());
191         assertEquals(TEST_PROVIDER_NAME, info.getPasspointProviderFriendlyName());
192         assertEquals(TEST_WIFI_STANDARD, info.getWifiStandard());
193         assertEquals(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS, info.getMaxSupportedTxLinkSpeedMbps());
194         assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS, info.getMaxSupportedRxLinkSpeedMbps());
195         assertEquals(TEST_BSSID, info.getMacAddress());
196         assertEquals(2, info.getInformationElements().size());
197         assertEquals(informationElements.get(0).id,
198                 info.getInformationElements().get(0).id);
199         assertEquals(informationElements.get(0).idExt,
200                 info.getInformationElements().get(0).idExt);
201         assertArrayEquals(informationElements.get(0).bytes,
202                 info.getInformationElements().get(0).bytes);
203         assertEquals(informationElements.get(1).id,
204                 info.getInformationElements().get(1).id);
205         assertEquals(informationElements.get(1).idExt,
206                 info.getInformationElements().get(1).idExt);
207         assertArrayEquals(informationElements.get(1).bytes,
208                 info.getInformationElements().get(1).bytes);
209         if (SdkLevel.isAtLeastS()) {
210             assertTrue(info.isOemPaid());
211             assertTrue(info.isOemPrivate());
212             assertTrue(info.isCarrierMerged());
213             assertEquals(TEST_SUB_ID, info.getSubscriptionId());
214             assertTrue(info.isPrimary());
215         }
216         if (SdkLevel.isAtLeastT()) {
217             assertMloNoRedaction(info);
218         }
219         if (SdkLevel.isAtLeastV()) {
220             assertTrue(TEST_VENDOR_DATA.equals(info.getVendorData()));
221         }
222     }
223 
224     /**
225      *  Verify redaction of WifiInfo with REDACT_NONE.
226      */
227     @Test
testWifiInfoRedactNoRedactions()228     public void testWifiInfoRedactNoRedactions() throws Exception {
229         List<ScanResult.InformationElement> informationElements = generateIes();
230         WifiInfo writeWifiInfo = makeWifiInfoForRedactionTest(informationElements);
231 
232         // Make a copy which allows parcelling of location sensitive data.
233         WifiInfo redactedWifiInfo = writeWifiInfo.makeCopy(NetworkCapabilities.REDACT_NONE);
234 
235         Parcel parcel = Parcel.obtain();
236         redactedWifiInfo.writeToParcel(parcel, 0);
237         // Rewind the pointer to the head of the parcel.
238         parcel.setDataPosition(0);
239         WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
240 
241         // Verify that redaction did not affect the original WifiInfo
242         assertNoRedaction(writeWifiInfo, informationElements);
243 
244         assertNoRedaction(redactedWifiInfo, informationElements);
245         assertNoRedaction(readWifiInfo, informationElements);
246 
247         if (SdkLevel.isAtLeastS()) {
248             // equals() was only introduced in S.
249             assertEquals(readWifiInfo, redactedWifiInfo);
250         }
251     }
252 
assertLocationSensitiveRedaction(WifiInfo info)253     private void assertLocationSensitiveRedaction(WifiInfo info) {
254         assertNotNull(info);
255         assertEquals(TEST_TX_SUCCESS, info.txSuccess);
256         assertEquals(TEST_TX_RETRIES, info.txRetries);
257         assertEquals(TEST_TX_BAD, info.txBad);
258         assertEquals(TEST_RX_SUCCESS, info.rxSuccess);
259         assertEquals(WifiManager.UNKNOWN_SSID, info.getSSID());
260         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, info.getBSSID());
261         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, info.getNetworkId());
262         assertTrue(info.isTrusted());
263         assertFalse(info.isRestricted());
264         assertTrue(info.isOsuAp());
265         assertFalse(info.isPasspointAp()); // fqdn & friendly name is masked.
266         assertEquals(TEST_PACKAGE_NAME, info.getRequestingPackageName());
267         assertNull(info.getPasspointFqdn());
268         assertNull(info.getPasspointProviderFriendlyName());
269         assertEquals(TEST_WIFI_STANDARD, info.getWifiStandard());
270         assertEquals(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS, info.getMaxSupportedTxLinkSpeedMbps());
271         assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS, info.getMaxSupportedRxLinkSpeedMbps());
272         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, info.getMacAddress());
273         assertNull(info.getInformationElements());
274         if (SdkLevel.isAtLeastS()) {
275             assertTrue(info.isOemPaid());
276             assertTrue(info.isOemPrivate());
277             assertTrue(info.isCarrierMerged());
278             assertEquals(TEST_SUB_ID, info.getSubscriptionId());
279             assertTrue(info.isPrimary());
280         }
281         assertEquals(null, info.getNetworkKey());
282         if (SdkLevel.isAtLeastT()) {
283             assertMloSensitiveLocationRedaction(info);
284         }
285     }
286 
287     /**
288      *  Verify redaction of WifiInfo with REDACT_FOR_ACCESS_FINE_LOCATION.
289      */
290     @Test
testWifiInfoRedactLocationSensitiveInfo()291     public void testWifiInfoRedactLocationSensitiveInfo() throws Exception {
292         List<ScanResult.InformationElement> informationElements = generateIes();
293         WifiInfo writeWifiInfo = makeWifiInfoForRedactionTest(informationElements);
294 
295         WifiInfo redactedWifiInfo =
296                 writeWifiInfo.makeCopy(NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION);
297 
298         Parcel parcel = Parcel.obtain();
299         redactedWifiInfo.writeToParcel(parcel, 0);
300         // Rewind the pointer to the head of the parcel.
301         parcel.setDataPosition(0);
302         WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
303 
304         // Verify that redaction did not affect the original WifiInfo
305         assertNoRedaction(writeWifiInfo, informationElements);
306 
307         assertLocationSensitiveRedaction(redactedWifiInfo);
308         assertLocationSensitiveRedaction(readWifiInfo);
309 
310         if (SdkLevel.isAtLeastS()) {
311             // equals() was only introduced in S.
312             assertEquals(redactedWifiInfo, readWifiInfo);
313         }
314     }
315 
assertLocalMacAddressInfoRedaction(WifiInfo info)316     private void assertLocalMacAddressInfoRedaction(WifiInfo info) {
317         assertNotNull(info);
318         assertEquals(TEST_TX_SUCCESS, info.txSuccess);
319         assertEquals(TEST_TX_RETRIES, info.txRetries);
320         assertEquals(TEST_TX_BAD, info.txBad);
321         assertEquals(TEST_RX_SUCCESS, info.rxSuccess);
322         assertEquals("\"" + TEST_SSID + "\"", info.getSSID());
323         assertEquals(TEST_BSSID, info.getBSSID());
324         assertEquals(TEST_NETWORK_ID, info.getNetworkId());
325         assertTrue(info.isTrusted());
326         assertFalse(info.isRestricted());
327         assertTrue(info.isOsuAp());
328         assertTrue(info.isPasspointAp());
329         assertEquals(TEST_PACKAGE_NAME, info.getRequestingPackageName());
330 
331         assertEquals(TEST_FQDN, info.getPasspointFqdn());
332         assertEquals(TEST_PROVIDER_NAME, info.getPasspointProviderFriendlyName());
333         assertEquals(TEST_WIFI_STANDARD, info.getWifiStandard());
334         assertEquals(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS, info.getMaxSupportedTxLinkSpeedMbps());
335         assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS, info.getMaxSupportedRxLinkSpeedMbps());
336         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, info.getMacAddress());
337         if (SdkLevel.isAtLeastS()) {
338             assertTrue(info.isOemPaid());
339             assertTrue(info.isOemPrivate());
340             assertTrue(info.isCarrierMerged());
341             assertEquals(TEST_SUB_ID, info.getSubscriptionId());
342             assertTrue(info.isPrimary());
343         }
344         assertEquals(null, info.getNetworkKey());
345         if (SdkLevel.isAtLeastT()) {
346             assertMloLocalMacRedaction(info);
347         }
348     }
349 
350     /**
351      *  Verify redaction of WifiInfo with REDACT_FOR_LOCAL_MAC_ADDRESS.
352      */
353     @Test
testWifiInfoRedactLocalMacAddressInfo()354     public void testWifiInfoRedactLocalMacAddressInfo() throws Exception {
355         List<ScanResult.InformationElement> informationElements = generateIes();
356         WifiInfo writeWifiInfo = makeWifiInfoForRedactionTest(informationElements);
357 
358         WifiInfo redactedWifiInfo =
359                 writeWifiInfo.makeCopy(NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS);
360 
361         Parcel parcel = Parcel.obtain();
362         redactedWifiInfo.writeToParcel(parcel, 0);
363         // Rewind the pointer to the head of the parcel.
364         parcel.setDataPosition(0);
365         WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
366 
367         // Verify that redaction did not affect the original WifiInfo
368         assertNoRedaction(writeWifiInfo, informationElements);
369 
370         assertLocalMacAddressInfoRedaction(redactedWifiInfo);
371         assertLocalMacAddressInfoRedaction(readWifiInfo);
372         if (SdkLevel.isAtLeastS()) {
373             // equals() was only introduced in S.
374             assertEquals(redactedWifiInfo, readWifiInfo);
375         }
376     }
377 
assertIsPrimaryThrowsSecurityException(WifiInfo info)378     private void assertIsPrimaryThrowsSecurityException(WifiInfo info) {
379         try {
380             // Should generate a security exception if caller does not have network settings
381             // permission.
382             info.isPrimary();
383             fail();
384         } catch (SecurityException e) { /* pass */ }
385     }
386 
387     /**
388      *  Verify redaction of WifiInfo with REDACT_FOR_NETWORK_SETTINGS.
389      */
390     @Test
testWifiInfoRedactNetworkSettingsInfo()391     public void testWifiInfoRedactNetworkSettingsInfo() throws Exception {
392         assumeTrue(SdkLevel.isAtLeastS());
393 
394         WifiInfo writeWifiInfo = new WifiInfo();
395         writeWifiInfo.setIsPrimary(true);
396         writeWifiInfo.setRequestingPackageName(TEST_PACKAGE_NAME);
397         writeWifiInfo.setIsPrimary(true);
398         assertTrue(writeWifiInfo.isPrimary());
399 
400         WifiInfo redactedWifiInfo =
401                 writeWifiInfo.makeCopy(NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS);
402         assertNull(redactedWifiInfo.getRequestingPackageName());
403         assertThrows(SecurityException.class, () -> redactedWifiInfo.isPrimary());
404 
405         Parcel parcel = Parcel.obtain();
406         redactedWifiInfo.writeToParcel(parcel, 0);
407         // Rewind the pointer to the head of the parcel.
408         parcel.setDataPosition(0);
409         WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
410 
411         assertNotNull(redactedWifiInfo);
412         assertIsPrimaryThrowsSecurityException(redactedWifiInfo);
413         assertNotNull(readWifiInfo);
414         assertIsPrimaryThrowsSecurityException(readWifiInfo);
415 
416         if (SdkLevel.isAtLeastS()) {
417             // equals() was only introduced in S.
418             assertEquals(redactedWifiInfo, readWifiInfo);
419         }
420     }
421 
422     @Test
testWifiInfoGetApplicableRedactions()423     public void testWifiInfoGetApplicableRedactions() throws Exception {
424         long redactions = new WifiInfo().getApplicableRedactions();
425         assertEquals(NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION
426                 | NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS
427                 | NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS, redactions);
428     }
429 
assertLocationSensitiveAndLocalMacAddressRedaction(WifiInfo info)430     private void assertLocationSensitiveAndLocalMacAddressRedaction(WifiInfo info) {
431         assertNotNull(info);
432         assertEquals(WifiManager.UNKNOWN_SSID, info.getSSID());
433         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, info.getBSSID());
434         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, info.getNetworkId());
435         assertNull(info.getPasspointFqdn());
436         assertNull(info.getPasspointProviderFriendlyName());
437         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, info.getMacAddress());
438         assertNull(info.getInformationElements());
439         assertNull(info.getNetworkKey());
440     }
441 
442     @Test
testWifiInfoRedactLocationAndLocalMacAddressSensitiveInfo()443     public void testWifiInfoRedactLocationAndLocalMacAddressSensitiveInfo()
444             throws Exception {
445         assumeTrue(SdkLevel.isAtLeastS());
446         List<ScanResult.InformationElement> informationElements = generateIes();
447         WifiInfo writeWifiInfo = makeWifiInfoForRedactionTest(informationElements);
448 
449         WifiInfo redactedWifiInfo =
450                 writeWifiInfo.makeCopy(NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION
451                         | NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS);
452 
453         Parcel parcel = Parcel.obtain();
454         redactedWifiInfo.writeToParcel(parcel, 0);
455         // Rewind the pointer to the head of the parcel.
456         parcel.setDataPosition(0);
457         WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
458 
459         assertLocationSensitiveAndLocalMacAddressRedaction(redactedWifiInfo);
460         assertLocationSensitiveAndLocalMacAddressRedaction(readWifiInfo);
461 
462         if (SdkLevel.isAtLeastS()) {
463             // equals() was only introduced in S.
464             assertEquals(redactedWifiInfo, readWifiInfo);
465         }
466     }
467 
468     /**
469      *  Verify parcel write/read with null information elements.
470      */
471     @Test
testWifiInfoParcelWriteReadWithNullInfoElements()472     public void testWifiInfoParcelWriteReadWithNullInfoElements() throws Exception {
473         assumeTrue(SdkLevel.isAtLeastS());
474 
475         WifiInfo writeWifiInfo = new WifiInfo();
476         writeWifiInfo.setInformationElements(null);
477 
478         // Make a copy which allows parcelling of location sensitive data.
479         WifiInfo writeWifiInfoCopy = writeWifiInfo.makeCopy(NetworkCapabilities.REDACT_NONE);
480 
481         Parcel parcel = Parcel.obtain();
482         writeWifiInfoCopy.writeToParcel(parcel, 0);
483         // Rewind the pointer to the head of the parcel.
484         parcel.setDataPosition(0);
485         WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
486         assertNull(readWifiInfo.getInformationElements());
487     }
488 
489     /**
490      *  Verify parcel write/read with empty information elements.
491      */
492     @Test
testWifiInfoParcelWriteReadWithEmptyInfoElements()493     public void testWifiInfoParcelWriteReadWithEmptyInfoElements() throws Exception {
494         assumeTrue(SdkLevel.isAtLeastS());
495 
496         WifiInfo writeWifiInfo = new WifiInfo();
497         writeWifiInfo.setInformationElements(new ArrayList<>());
498 
499         // Make a copy which allows parcelling of location sensitive data.
500         WifiInfo writeWifiInfoCopy = writeWifiInfo.makeCopy(NetworkCapabilities.REDACT_NONE);
501 
502         Parcel parcel = Parcel.obtain();
503         writeWifiInfoCopy.writeToParcel(parcel, 0);
504         // Rewind the pointer to the head of the parcel.
505         parcel.setDataPosition(0);
506         WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
507         assertTrue(readWifiInfo.getInformationElements().isEmpty());
508     }
509 
510     @Test
testWifiInfoCopyConstructor()511     public void testWifiInfoCopyConstructor() throws Exception {
512         WifiInfo writeWifiInfo = new WifiInfo();
513         writeWifiInfo.txSuccess = TEST_TX_SUCCESS;
514         writeWifiInfo.txRetries = TEST_TX_RETRIES;
515         writeWifiInfo.txBad = TEST_TX_BAD;
516         writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
517         writeWifiInfo.setTrusted(true);
518         writeWifiInfo.setOemPaid(true);
519         writeWifiInfo.setOemPrivate(true);
520         writeWifiInfo.setCarrierMerged(true);
521         writeWifiInfo.setOsuAp(true);
522         writeWifiInfo.setFQDN(TEST_FQDN);
523         writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
524         writeWifiInfo.setRequestingPackageName(TEST_PACKAGE_NAME);
525         writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
526         writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
527         writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
528         writeWifiInfo.setSubscriptionId(TEST_SUB_ID);
529         writeWifiInfo.setIsPrimary(true);
530         writeWifiInfo.setRestricted(true);
531         writeWifiInfo.enableApTidToLinkMappingNegotiationSupport(true);
532         if (SdkLevel.isAtLeastV()) {
533             writeWifiInfo.setVendorData(TEST_VENDOR_DATA);
534         }
535 
536         WifiInfo readWifiInfo = new WifiInfo(writeWifiInfo);
537 
538         assertEquals(TEST_TX_SUCCESS, readWifiInfo.txSuccess);
539         assertEquals(TEST_TX_RETRIES, readWifiInfo.txRetries);
540         assertEquals(TEST_TX_BAD, readWifiInfo.txBad);
541         assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
542         assertTrue(readWifiInfo.isTrusted());
543         assertTrue(readWifiInfo.isOsuAp());
544         assertTrue(readWifiInfo.isPasspointAp());
545         assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
546         assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
547         assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
548         assertEquals(TEST_WIFI_STANDARD, readWifiInfo.getWifiStandard());
549         assertEquals(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS,
550                 readWifiInfo.getMaxSupportedTxLinkSpeedMbps());
551         assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS,
552                 readWifiInfo.getMaxSupportedRxLinkSpeedMbps());
553         assertTrue(readWifiInfo.isRestricted());
554         if (SdkLevel.isAtLeastS()) {
555             assertTrue(readWifiInfo.isOemPaid());
556             assertTrue(readWifiInfo.isOemPrivate());
557             assertTrue(readWifiInfo.isCarrierMerged());
558             assertEquals(TEST_SUB_ID, readWifiInfo.getSubscriptionId());
559             assertTrue(readWifiInfo.isPrimary());
560         }
561         assertTrue(readWifiInfo.isApTidToLinkMappingNegotiationSupported());
562         if (SdkLevel.isAtLeastV()) {
563             assertTrue(TEST_VENDOR_DATA.equals(readWifiInfo.getVendorData()));
564         }
565     }
566 
567     /**
568      *  Verify values after reset()
569      */
570     @Test
testWifiInfoResetValue()571     public void testWifiInfoResetValue() throws Exception {
572         WifiInfo wifiInfo = new WifiInfo();
573         wifiInfo.reset();
574         assertEquals(WifiInfo.LINK_SPEED_UNKNOWN, wifiInfo.getMaxSupportedTxLinkSpeedMbps());
575         assertEquals(WifiInfo.LINK_SPEED_UNKNOWN, wifiInfo.getMaxSupportedRxLinkSpeedMbps());
576         assertEquals(WifiInfo.LINK_SPEED_UNKNOWN, wifiInfo.getTxLinkSpeedMbps());
577         assertEquals(WifiInfo.LINK_SPEED_UNKNOWN, wifiInfo.getRxLinkSpeedMbps());
578         assertEquals(WifiInfo.INVALID_RSSI, wifiInfo.getRssi());
579         assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID());
580         assertNull(wifiInfo.getBSSID());
581         assertEquals(-1, wifiInfo.getNetworkId());
582         if (SdkLevel.isAtLeastS()) {
583             assertFalse(wifiInfo.isOemPaid());
584             assertFalse(wifiInfo.isOemPrivate());
585             assertFalse(wifiInfo.isCarrierMerged());
586             assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, wifiInfo.getSubscriptionId());
587             assertFalse(wifiInfo.isPrimary());
588         }
589         assertNull(wifiInfo.getNetworkKey());
590         assertEquals(MloLink.INVALID_MLO_LINK_ID, wifiInfo.getApMloLinkId());
591         assertNull(wifiInfo.getApMldMacAddress());
592         assertEquals(0, wifiInfo.getAffiliatedMloLinks().size());
593         assertFalse(wifiInfo.isApTidToLinkMappingNegotiationSupported());
594         if (SdkLevel.isAtLeastV()) {
595             assertNotNull(wifiInfo.getVendorData());
596             assertTrue(wifiInfo.getVendorData().isEmpty());
597         }
598     }
599 
600     /**
601      * Test that the WifiInfo Builder returns the same values that was set, and that
602      * calling build multiple times returns different instances.
603      */
604     @Test
testWifiInfoBuilder()605     public void testWifiInfoBuilder() throws Exception {
606         WifiInfo.Builder builder = new WifiInfo.Builder()
607                 .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8))
608                 .setBssid(TEST_BSSID)
609                 .setRssi(TEST_RSSI)
610                 .setNetworkId(TEST_NETWORK_ID);
611 
612         WifiInfo info1 = builder.build();
613 
614         assertEquals("\"" + TEST_SSID + "\"", info1.getSSID());
615         assertEquals(TEST_BSSID, info1.getBSSID());
616         assertEquals(TEST_RSSI, info1.getRssi());
617         assertEquals(TEST_NETWORK_ID, info1.getNetworkId());
618 
619         WifiInfo info2 = builder
620                 .setNetworkId(TEST_NETWORK_ID2)
621                 .build();
622 
623         // different instances
624         assertNotSame(info1, info2);
625 
626         // assert that info1 didn't change
627         assertEquals("\"" + TEST_SSID + "\"", info1.getSSID());
628         assertEquals(TEST_BSSID, info1.getBSSID());
629         assertEquals(TEST_RSSI, info1.getRssi());
630         assertEquals(TEST_NETWORK_ID, info1.getNetworkId());
631 
632         // assert that info2 changed
633         assertEquals("\"" + TEST_SSID + "\"", info2.getSSID());
634         assertEquals(TEST_BSSID, info2.getBSSID());
635         assertEquals(TEST_RSSI, info2.getRssi());
636         assertEquals(TEST_NETWORK_ID2, info2.getNetworkId());
637     }
638 
639     @Test
testSetSsid()640     public void testSetSsid() throws Exception {
641         WifiInfo.Builder builder = new WifiInfo.Builder();
642 
643         // Null
644         assertEquals(WifiManager.UNKNOWN_SSID, builder.build().getSSID());
645 
646         // Empty
647         builder.setSsid(new byte[0]);
648         assertEquals(WifiManager.UNKNOWN_SSID, builder.build().getSSID());
649 
650         // UTF-8
651         builder.setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8));
652         assertEquals("\"" + TEST_SSID + "\"", builder.build().getSSID());
653 
654         // Non-UTF-8
655         byte[] gbkBytes = "服務集識別碼".getBytes(Charset.forName("GBK"));
656         builder.setSsid(gbkBytes);
657         assertEquals(HexEncoding.encodeToString(gbkBytes, false), builder.build().getSSID());
658     }
659 
660     @Test
testWifiInfoEquals()661     public void testWifiInfoEquals() throws Exception {
662         WifiInfo.Builder builder = new WifiInfo.Builder()
663                 .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8))
664                 .setBssid(TEST_BSSID)
665                 .setRssi(TEST_RSSI)
666                 .setNetworkId(TEST_NETWORK_ID);
667 
668         WifiInfo info1 = builder.build();
669         WifiInfo info2 = builder.build();
670         if (SdkLevel.isAtLeastS()) {
671             assertEquals(info1, info2);
672         } else {
673             // On R devices, reference equality.
674             assertNotEquals(info1, info2);
675         }
676 
677         info1.setSubscriptionId(TEST_SUB_ID);
678         assertNotEquals(info1, info2);
679 
680         info2.setSubscriptionId(TEST_SUB_ID);
681         if (SdkLevel.isAtLeastS()) {
682             assertEquals(info1, info2);
683         } else {
684             // On R devices, reference equality.
685             assertNotEquals(info1, info2);
686         }
687 
688         info1.setSSID(WifiSsid.fromBytes(null));
689         assertNotEquals(info1, info2);
690 
691         info2.setSSID(WifiSsid.fromBytes(null));
692         if (SdkLevel.isAtLeastS()) {
693             assertEquals(info1, info2);
694         } else {
695             // On R devices, reference equality.
696             assertNotEquals(info1, info2);
697         }
698     }
699 
700     @Test
testWifiInfoEqualsWithInfoElements()701     public void testWifiInfoEqualsWithInfoElements() throws Exception {
702         WifiInfo.Builder builder = new WifiInfo.Builder()
703                 .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8))
704                 .setBssid(TEST_BSSID)
705                 .setRssi(TEST_RSSI)
706                 .setNetworkId(TEST_NETWORK_ID);
707 
708         WifiInfo info1 = builder.build();
709         WifiInfo info2 = builder.build();
710         if (SdkLevel.isAtLeastS()) {
711             assertEquals(info1, info2);
712         } else {
713             // On R devices, reference equality.
714             assertNotEquals(info1, info2);
715         }
716 
717         info1.setInformationElements(generateIes());
718         info2.setInformationElements(generateIes());
719 
720         if (SdkLevel.isAtLeastS()) {
721             assertEquals(info1, info2);
722         } else {
723             // On R devices, reference equality.
724             assertNotEquals(info1, info2);
725         }
726     }
727 
728     @Test
testWifiInfoHashcode()729     public void testWifiInfoHashcode() throws Exception {
730         WifiInfo.Builder builder = new WifiInfo.Builder()
731                 .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8))
732                 .setBssid(TEST_BSSID)
733                 .setRssi(TEST_RSSI)
734                 .setNetworkId(TEST_NETWORK_ID);
735 
736         WifiInfo info1 = builder.build();
737         WifiInfo info2 = builder.build();
738         if (SdkLevel.isAtLeastS()) {
739             assertEquals(info1.hashCode(), info2.hashCode());
740         } else {
741             // On R devices, system generated hashcode.
742             assertNotEquals(info1.hashCode(), info2.hashCode());
743         }
744 
745         info1.setSubscriptionId(TEST_SUB_ID);
746         assertNotEquals(info1.hashCode(), info2.hashCode());
747 
748         info2.setSubscriptionId(TEST_SUB_ID);
749         if (SdkLevel.isAtLeastS()) {
750             assertEquals(info1.hashCode(), info2.hashCode());
751         } else {
752             // On R devices, system generated hashcode.
753             assertNotEquals(info1.hashCode(), info2.hashCode());
754         }
755 
756         info1.setSSID(WifiSsid.fromBytes(null));
757         assertNotEquals(info1.hashCode(), info2.hashCode());
758 
759         info2.setSSID(WifiSsid.fromBytes(null));
760         if (SdkLevel.isAtLeastS()) {
761             assertEquals(info1.hashCode(), info2.hashCode());
762         } else {
763             // On R devices, system generated hashcode.
764             assertNotEquals(info1.hashCode(), info2.hashCode());
765         }
766     }
767 
768     @Test
testWifiInfoCurrentSecurityType()769     public void testWifiInfoCurrentSecurityType() throws Exception {
770         WifiInfo.Builder builder = new WifiInfo.Builder()
771                 .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8))
772                 .setBssid(TEST_BSSID)
773                 .setRssi(TEST_RSSI)
774                 .setNetworkId(TEST_NETWORK_ID)
775                 .setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_SAE);
776 
777         WifiInfo info = new WifiInfo();
778         assertEquals(WifiInfo.SECURITY_TYPE_UNKNOWN, info.getCurrentSecurityType());
779 
780         info = builder.build();
781         assertEquals(WifiInfo.SECURITY_TYPE_SAE, info.getCurrentSecurityType());
782 
783         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN).build();
784         assertEquals(WifiInfo.SECURITY_TYPE_OPEN, info.getCurrentSecurityType());
785 
786         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_WEP).build();
787         assertEquals(WifiInfo.SECURITY_TYPE_WEP, info.getCurrentSecurityType());
788 
789         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_PSK).build();
790         assertEquals(WifiInfo.SECURITY_TYPE_PSK, info.getCurrentSecurityType());
791 
792         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_EAP).build();
793         assertEquals(WifiInfo.SECURITY_TYPE_EAP, info.getCurrentSecurityType());
794 
795         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_OWE).build();
796         assertEquals(WifiInfo.SECURITY_TYPE_OWE, info.getCurrentSecurityType());
797 
798         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_WAPI_PSK).build();
799         assertEquals(WifiInfo.SECURITY_TYPE_WAPI_PSK, info.getCurrentSecurityType());
800 
801         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_WAPI_CERT).build();
802         assertEquals(WifiInfo.SECURITY_TYPE_WAPI_CERT, info.getCurrentSecurityType());
803 
804         info = builder.setCurrentSecurityType(
805                 WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE).build();
806         assertEquals(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE, info.getCurrentSecurityType());
807 
808         info = builder.setCurrentSecurityType(
809                 WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT).build();
810         assertEquals(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
811                 info.getCurrentSecurityType());
812 
813         info = builder.setCurrentSecurityType(
814                 WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2).build();
815         assertEquals(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2, info.getCurrentSecurityType());
816 
817         info = builder.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3).build();
818         assertEquals(WifiInfo.SECURITY_TYPE_PASSPOINT_R3, info.getCurrentSecurityType());
819 
820         info.clearCurrentSecurityType();
821         assertEquals(WifiInfo.SECURITY_TYPE_UNKNOWN, info.getCurrentSecurityType());
822     }
823 
generateIes()824     private static List<ScanResult.InformationElement> generateIes() {
825         List<ScanResult.InformationElement> informationElements = new ArrayList<>();
826         ScanResult.InformationElement informationElement = new ScanResult.InformationElement();
827         informationElement.id = ScanResult.InformationElement.EID_HT_OPERATION;
828         informationElement.idExt = 0;
829         informationElement.bytes = new byte[]{0x11, 0x22, 0x33};
830         informationElements.add(informationElement);
831 
832         informationElement = new ScanResult.InformationElement();
833         informationElement.id = ScanResult.InformationElement.EID_EXTENSION_PRESENT;
834         informationElement.idExt = ScanResult.InformationElement.EID_EXT_HE_OPERATION;
835         informationElement.bytes = new byte[]{0x44, 0x55, 0x66};
836         informationElements.add(informationElement);
837 
838         return informationElements;
839     }
840 
841     @Test
testMloLink()842     public void testMloLink() throws Exception {
843         // Create an MLO link and set parameters.
844         MloLink link1 = new MloLink();
845         link1.setStaMacAddress(MacAddress.fromString(MLO_LINK_STA_MAC_ADDRESS));
846         link1.setApMacAddress(MacAddress.fromString(MLO_LINK_AP_MAC_ADDRESS));
847         link1.setRssi(TEST_RSSI);
848         link1.setLinkId(TEST_MLO_LINK_ID);
849         link1.setBand(WifiScanner.WIFI_BAND_5_GHZ);
850         link1.setChannel(TEST_CHANNEL);
851         link1.setRxLinkSpeedMbps(TEST_LINK_SPEED);
852         link1.setTxLinkSpeedMbps(TEST_LINK_SPEED);
853         link1.setState(MloLink.MLO_LINK_STATE_UNASSOCIATED);
854         link1.setLostTxPacketsPerSecond(10);
855         link1.setRetriedTxPacketsRate(20);
856         link1.setSuccessfulTxPacketsPerSecond(30);
857         link1.setSuccessfulRxPacketsPerSecond(40);
858 
859         // Make sure all parameters are set.
860         assertNotNull(link1.getApMacAddress());
861         assertEquals(MLO_LINK_AP_MAC_ADDRESS, link1.getApMacAddress().toString());
862         assertNotNull(link1.getStaMacAddress());
863         assertEquals(MLO_LINK_STA_MAC_ADDRESS, link1.getStaMacAddress().toString());
864         assertEquals(TEST_RSSI, link1.getRssi());
865         assertEquals(TEST_CHANNEL, link1.getChannel());
866         assertEquals(TEST_LINK_SPEED, link1.getRxLinkSpeedMbps());
867         assertEquals(TEST_LINK_SPEED, link1.getTxLinkSpeedMbps());
868         assertEquals(TEST_MLO_LINK_ID, link1.getLinkId());
869         assertEquals(WifiScanner.WIFI_BAND_5_GHZ, link1.getBand());
870         assertEquals(MloLink.MLO_LINK_STATE_UNASSOCIATED, link1.getState());
871         assertEquals(10, link1.getLostTxPacketsPerSecond(), 0);
872         assertEquals(20, link1.getRetriedTxPacketsPerSecond(), 0);
873         assertEquals(30, link1.getSuccessfulTxPacketsPerSecond(), 0);
874         assertEquals(40, link1.getSuccessfulRxPacketsPerSecond(), 0);
875         // Check default values
876         assertEquals(0, link1.txBad);
877         assertEquals(0, link1.txRetries);
878         assertEquals(0, link1.txSuccess);
879         assertEquals(0, link1.rxSuccess);
880 
881         // Test RSSI range.
882         link1.setRssi(WifiInfo.INVALID_RSSI - 1);
883         assertEquals(WifiInfo.INVALID_RSSI, link1.getRssi());
884         link1.setRssi(WifiInfo.MAX_RSSI + 1);
885         assertEquals(WifiInfo.MAX_RSSI, link1.getRssi());
886 
887         // Copy link
888         MloLink link2 = new MloLink(link1, 0);
889 
890         // Check links are equal.
891         assertTrue(link1.equals(link2));
892         assertEquals(link2.hashCode(), link1.hashCode());
893         assertEquals(link2.toString(), link1.toString());
894 
895         // Change one parameter and check the links are not equal.
896         link1.setState(MloLink.MLO_LINK_STATE_INVALID);
897         assertFalse(link1.equals(link2));
898         assertNotEquals(link2.hashCode(), link1.hashCode());
899         assertNotEquals(link2.toString(), link1.toString());
900 
901         // Validate states.
902         assertTrue(MloLink.isValidState(MloLink.MLO_LINK_STATE_INVALID));
903         assertTrue(MloLink.isValidState(MloLink.MLO_LINK_STATE_UNASSOCIATED));
904         assertTrue(MloLink.isValidState(MloLink.MLO_LINK_STATE_ACTIVE));
905         assertTrue(MloLink.isValidState(MloLink.MLO_LINK_STATE_IDLE));
906         assertFalse(MloLink.isValidState(MloLink.MLO_LINK_STATE_INVALID - 1));
907     }
908 }
909