• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.wifi;
18 
19 import static org.junit.Assert.*;
20 import static org.junit.Assume.*;
21 import static org.mockito.Mockito.*;
22 
23 import android.net.wifi.ScanResult;
24 import android.net.wifi.WifiScanner;
25 import android.net.wifi.WifiScanner.ScanData;
26 import android.net.wifi.WifiSsid;
27 
28 import com.android.modules.utils.build.SdkLevel;
29 import com.android.net.module.util.MacAddressUtils;
30 import com.android.server.wifi.scanner.ChannelHelper;
31 import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection;
32 
33 import org.hamcrest.Description;
34 import org.hamcrest.Matcher;
35 import org.hamcrest.TypeSafeDiagnosingMatcher;
36 
37 import java.util.Arrays;
38 import java.util.Comparator;
39 import java.util.HashSet;
40 import java.util.Set;
41 
42 /**
43  * Utilities for testing Wifi Scanning
44  */
45 public class ScanTestUtil {
46 
setupMockChannels(WifiNative wifiNative, int[] channels24, int[] channels5, int[] channelsDfs, int[] channels6, int[] channels60)47     public static void setupMockChannels(WifiNative wifiNative, int[] channels24, int[] channels5,
48             int[] channelsDfs, int[] channels6, int[] channels60) throws Exception {
49         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ))
50                 .thenReturn(channels24);
51         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ))
52                 .thenReturn(channels5);
53         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY))
54                 .thenReturn(channelsDfs);
55         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ))
56                 .thenReturn(channels6);
57         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ))
58                 .thenReturn(channels60);
59     }
60 
createRequest(WifiScanner.ChannelSpec[] channels, int period, int batch, int bssidsPerScan, int reportEvents)61     public static WifiScanner.ScanSettings createRequest(WifiScanner.ChannelSpec[] channels,
62             int period, int batch, int bssidsPerScan, int reportEvents) {
63         WifiScanner.ScanSettings request = new WifiScanner.ScanSettings();
64         request.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
65         request.channels = channels;
66         request.periodInMs = period;
67         request.numBssidsPerScan = bssidsPerScan;
68         request.maxScansToCache = batch;
69         request.reportEvents = reportEvents;
70         return request;
71     }
72 
createRequest(int type, int band, int period, int batch, int bssidsPerScan, int reportEvents)73     public static WifiScanner.ScanSettings createRequest(int type, int band, int period, int batch,
74             int bssidsPerScan, int reportEvents) {
75         return createRequest(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, band, period, 0, 0,
76                 batch, bssidsPerScan, reportEvents);
77     }
78 
createRequest(int band, int period, int batch, int bssidsPerScan, int reportEvents)79     public static WifiScanner.ScanSettings createRequest(int band, int period, int batch,
80             int bssidsPerScan, int reportEvents) {
81         return createRequest(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, band, period, 0, 0, batch,
82                 bssidsPerScan, reportEvents);
83     }
84 
85     /**
86      * Create an exponential back off scan request if maxPeriod != period && maxPeriod != 0.
87      */
createRequest(int type, int band, int period, int maxPeriod, int stepCount, int batch, int bssidsPerScan, int reportEvents)88     public static WifiScanner.ScanSettings createRequest(int type, int band, int period,
89             int maxPeriod, int stepCount, int batch, int bssidsPerScan, int reportEvents) {
90         WifiScanner.ScanSettings request = new WifiScanner.ScanSettings();
91         request.type = type;
92         request.band = band;
93         request.channels = null;
94         request.periodInMs = period;
95         request.maxPeriodInMs = maxPeriod;
96         request.stepCount = stepCount;
97         request.numBssidsPerScan = bssidsPerScan;
98         request.maxScansToCache = batch;
99         request.reportEvents = reportEvents;
100         return request;
101     }
102 
103     /**
104      * Builder to create WifiNative.ScanSettings objects for testing
105      */
106     public static class NativeScanSettingsBuilder {
107         private final WifiNative.ScanSettings mSettings = new WifiNative.ScanSettings();
NativeScanSettingsBuilder()108         public NativeScanSettingsBuilder() {
109             mSettings.scanType = WifiScanner.SCAN_TYPE_LOW_LATENCY;
110             mSettings.buckets = new WifiNative.BucketSettings[0];
111             mSettings.num_buckets = 0;
112             mSettings.report_threshold_percent = 100;
113         }
114 
withType(int type)115         public NativeScanSettingsBuilder withType(int type) {
116             mSettings.scanType = type;
117             return this;
118         }
withBasePeriod(int basePeriod)119         public NativeScanSettingsBuilder withBasePeriod(int basePeriod) {
120             mSettings.base_period_ms = basePeriod;
121             return this;
122         }
withMaxApPerScan(int maxAp)123         public NativeScanSettingsBuilder withMaxApPerScan(int maxAp) {
124             mSettings.max_ap_per_scan = maxAp;
125             return this;
126         }
withMaxScansToCache(int maxScans)127         public NativeScanSettingsBuilder withMaxScansToCache(int maxScans) {
128             mSettings.report_threshold_num_scans = maxScans;
129             return this;
130         }
withMaxPercentToCache(int percent)131         public NativeScanSettingsBuilder withMaxPercentToCache(int percent) {
132             mSettings.report_threshold_percent = percent;
133             return this;
134         }
withEnable6GhzRnr(boolean enable)135         public NativeScanSettingsBuilder withEnable6GhzRnr(boolean enable) {
136             mSettings.enable6GhzRnr = enable;
137             return this;
138         }
139 
140         /**
141          * Add the provided hidden network SSIDs to scan request.
142          * @param networkSSIDs List of hidden network SSIDs
143          * @return builder object
144          */
withHiddenNetworkSSIDs(String[] networkSSIDs)145         public NativeScanSettingsBuilder withHiddenNetworkSSIDs(String[] networkSSIDs) {
146             mSettings.hiddenNetworks = new WifiNative.HiddenNetwork[networkSSIDs.length];
147             for (int i = 0; i < networkSSIDs.length; i++) {
148                 mSettings.hiddenNetworks[i] = new WifiNative.HiddenNetwork();
149                 mSettings.hiddenNetworks[i].ssid = networkSSIDs[i];
150             }
151             return this;
152         }
153 
addBucketWithChannelCollection( int period, int reportEvents, ChannelCollection channelCollection)154         public NativeScanSettingsBuilder addBucketWithChannelCollection(
155                 int period, int reportEvents, ChannelCollection channelCollection) {
156             WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
157             bucket.bucket = mSettings.num_buckets;
158             bucket.period_ms = period;
159             bucket.report_events = reportEvents;
160             channelCollection.fillBucketSettings(bucket, Integer.MAX_VALUE);
161             return addBucket(bucket);
162         }
163 
addBucketWithBand( int period, int reportEvents, int band)164         public NativeScanSettingsBuilder addBucketWithBand(
165                 int period, int reportEvents, int band) {
166             WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
167             bucket.bucket = mSettings.num_buckets;
168             bucket.band = band;
169             bucket.period_ms = period;
170             bucket.report_events = reportEvents;
171             return addBucket(bucket);
172         }
173 
addBucketWithChannels( int period, int reportEvents, WifiScanner.ChannelSpec... channels)174         public NativeScanSettingsBuilder addBucketWithChannels(
175                 int period, int reportEvents, WifiScanner.ChannelSpec... channels) {
176             int[] channelFreqs = new int[channels.length];
177             for (int i = 0; i < channels.length; ++i) {
178                 channelFreqs[i] = channels[i].frequency;
179             }
180             return addBucketWithChannels(period, reportEvents, channelFreqs);
181         }
182 
addBucketWithChannels( int period, int reportEvents, int... channels)183         public NativeScanSettingsBuilder addBucketWithChannels(
184                 int period, int reportEvents, int... channels) {
185             WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
186             bucket.bucket = mSettings.num_buckets;
187             bucket.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
188             bucket.num_channels = channels.length;
189             bucket.channels = channelsToNativeSettings(channels);
190             bucket.period_ms = period;
191             bucket.report_events = reportEvents;
192             return addBucket(bucket);
193         }
194 
addBucket(WifiNative.BucketSettings bucket)195         public NativeScanSettingsBuilder addBucket(WifiNative.BucketSettings bucket) {
196             mSettings.buckets = Arrays.copyOf(mSettings.buckets, mSettings.num_buckets + 1);
197             mSettings.buckets[mSettings.num_buckets] = bucket;
198             mSettings.num_buckets = mSettings.num_buckets + 1;
199             return this;
200         }
201 
build()202         public WifiNative.ScanSettings build() {
203             return mSettings;
204         }
205 
206     }
207 
208     /**
209      * Compute the expected native scan settings that are expected for the given
210      * WifiScanner.ScanSettings using the given ChannelHelper.
211      * This method is created to test 6Ghz PSC scanning.
212      */
computeSingleScanNativeSettingsWithChannelHelper( WifiScanner.ScanSettings requestSettings, ChannelHelper channelHelper)213     public static WifiNative.ScanSettings computeSingleScanNativeSettingsWithChannelHelper(
214             WifiScanner.ScanSettings requestSettings, ChannelHelper channelHelper) {
215         int reportEvents = requestSettings.reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
216         NativeScanSettingsBuilder builder = new NativeScanSettingsBuilder()
217                 .withBasePeriod(0)
218                 .withMaxApPerScan(0)
219                 .withMaxPercentToCache(0)
220                 .withMaxScansToCache(0)
221                 .withType(requestSettings.type);
222         if (SdkLevel.isAtLeastS()) {
223             builder.withEnable6GhzRnr(requestSettings.getRnrSetting()
224                     == WifiScanner.WIFI_RNR_ENABLED
225                     || (requestSettings.getRnrSetting()
226                     == WifiScanner.WIFI_RNR_ENABLED_IF_WIFI_BAND_6_GHZ_SCANNED
227                     && ChannelHelper.is6GhzBandIncluded(requestSettings.band)));
228         }
229         ChannelCollection channelCollection = channelHelper.createChannelCollection();
230         channelCollection.addChannels(requestSettings);
231         builder.addBucketWithChannelCollection(0, reportEvents, channelCollection);
232         return builder.build();
233     }
234 
235     /**
236      * Compute the expected native scan settings that are expected for the given
237      * WifiScanner.ScanSettings.
238      */
computeSingleScanNativeSettings( WifiScanner.ScanSettings requestSettings)239     public static WifiNative.ScanSettings computeSingleScanNativeSettings(
240             WifiScanner.ScanSettings requestSettings) {
241         int reportEvents = requestSettings.reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
242         NativeScanSettingsBuilder builder = new NativeScanSettingsBuilder()
243                 .withBasePeriod(0)
244                 .withMaxApPerScan(0)
245                 .withMaxPercentToCache(0)
246                 .withMaxScansToCache(0)
247                 .withType(requestSettings.type);
248         if (SdkLevel.isAtLeastS()) {
249             builder.withEnable6GhzRnr(requestSettings.getRnrSetting()
250                     == WifiScanner.WIFI_RNR_ENABLED
251                     || (requestSettings.getRnrSetting()
252                     == WifiScanner.WIFI_RNR_ENABLED_IF_WIFI_BAND_6_GHZ_SCANNED
253                     && ChannelHelper.is6GhzBandIncluded(requestSettings.band)));
254         }
255         if (requestSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
256             builder.addBucketWithChannels(0, reportEvents, requestSettings.channels);
257         } else {
258             builder.addBucketWithBand(0, reportEvents, requestSettings.band);
259         }
260 
261         return builder.build();
262     }
263 
264     /**
265      * Compute the expected native scan settings that are expected for the given channels.
266      */
createSingleScanNativeSettingsForChannels( int reportEvents, WifiScanner.ChannelSpec... channels)267     public static WifiNative.ScanSettings createSingleScanNativeSettingsForChannels(
268             int reportEvents, WifiScanner.ChannelSpec... channels) {
269         return createSingleScanNativeSettingsForChannels(
270             WifiScanner.SCAN_TYPE_LOW_LATENCY, reportEvents, channels);
271     }
272 
273     /**
274      * Compute the expected native scan settings that are expected for the given channels & type.
275      */
createSingleScanNativeSettingsForChannels( int nativeScanType, int reportEvents, WifiScanner.ChannelSpec... channels)276     public static WifiNative.ScanSettings createSingleScanNativeSettingsForChannels(
277             int nativeScanType, int reportEvents, WifiScanner.ChannelSpec... channels) {
278         int actualReportEvents = reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
279         return new NativeScanSettingsBuilder()
280                 .withBasePeriod(0)
281                 .withMaxApPerScan(0)
282                 .withMaxPercentToCache(0)
283                 .withMaxScansToCache(0)
284                 .addBucketWithChannels(0, actualReportEvents, channels)
285                 .withType(nativeScanType)
286                 .build();
287     }
288 
createFreqSet(int... elements)289     public static Set<Integer> createFreqSet(int... elements) {
290         Set<Integer> set = new HashSet<>();
291         for (int e : elements) {
292             set.add(e);
293         }
294         return set;
295     }
296 
createScanResult(int freq)297     public static ScanResult createScanResult(int freq) {
298         return new ScanResult(WifiSsid.createFromAsciiEncoded("AN SSID"),
299                 MacAddressUtils.createRandomUnicastAddress().toString(), 0L,
300                 -1, null, "", 0, freq, 0);
301     }
302 
createScanData(int[] freqs, int bucketsScanned, int bandScanned)303     private static ScanData createScanData(int[] freqs, int bucketsScanned, int bandScanned) {
304         ScanResult[] results = new ScanResult[freqs.length];
305         for (int i = 0; i < freqs.length; ++i) {
306             results[i] = createScanResult(freqs[i]);
307         }
308         return new ScanData(0, 0, bucketsScanned, bandScanned, results);
309     }
310 
createScanData(int[] freqs, int bucketsScanned)311     private static ScanData createScanData(int[] freqs, int bucketsScanned) {
312         return createScanData(freqs, bucketsScanned, WifiScanner.WIFI_BAND_UNSPECIFIED);
313     }
314 
createScanDatas( int[][] freqs, int[] bucketsScanned, int[] bandsScanned)315     public static ScanData[] createScanDatas(
316             int[][] freqs, int[] bucketsScanned, int[] bandsScanned) {
317         assumeTrue(freqs.length == bucketsScanned.length);
318         assumeTrue(freqs.length == bandsScanned.length);
319         ScanData[] data = new ScanData[freqs.length];
320         for (int i = 0; i < freqs.length; ++i) {
321             data[i] = createScanData(freqs[i], bucketsScanned[i], bandsScanned[i]);
322         }
323         return data;
324     }
325 
createScanDatas(int[][] freqs, int[] bucketsScanned)326     public static ScanData[] createScanDatas(int[][] freqs, int[] bucketsScanned) {
327         assumeTrue(freqs.length == bucketsScanned.length);
328         ScanData[] data = new ScanData[freqs.length];
329         for (int i = 0; i < freqs.length; ++i) {
330             data[i] = createScanData(freqs[i], bucketsScanned[i]);
331         }
332         return data;
333     }
334 
createScanDatas(int[][] freqs)335     public static ScanData[] createScanDatas(int[][] freqs) {
336         return createScanDatas(freqs, new int[freqs.length] /* defaults all 0 */);
337     }
338 
assertScanResultEquals( String prefix, ScanResult expected, ScanResult actual)339     private static void assertScanResultEquals(
340             String prefix, ScanResult expected, ScanResult actual) {
341         assertEquals(prefix + "SSID", expected.SSID, actual.SSID);
342         assertEquals(prefix + "wifiSsid", expected.wifiSsid.toString(), actual.wifiSsid.toString());
343         assertEquals(prefix + "BSSID", expected.BSSID, actual.BSSID);
344         assertEquals(prefix + "capabilities", expected.capabilities, actual.capabilities);
345         assertEquals(prefix + "level", expected.level, actual.level);
346         assertEquals(prefix + "frequency", expected.frequency, actual.frequency);
347         assertEquals(prefix + "timestamp", expected.timestamp, actual.timestamp);
348         assertEquals(prefix + "seen", expected.seen, actual.seen);
349     }
350 
assertScanResultsEquals(String prefix, ScanResult[] expected, ScanResult[] actual)351     private static void assertScanResultsEquals(String prefix, ScanResult[] expected,
352             ScanResult[] actual) {
353         assertNotNull(prefix + "expected ScanResults was null", expected);
354         assertNotNull(prefix + "actual ScanResults was null", actual);
355         assertEquals(prefix + "results.length", expected.length, actual.length);
356         for (int j = 0; j < expected.length; ++j) {
357             ScanResult expectedResult = expected[j];
358             ScanResult actualResult = actual[j];
359             assertScanResultEquals(prefix + "results[" + j + "]", actualResult, expectedResult);
360         }
361     }
362 
assertScanResultsEqualsAnyOrder(String prefix, ScanResult[] expected, ScanResult[] actual)363     private static void assertScanResultsEqualsAnyOrder(String prefix, ScanResult[] expected,
364             ScanResult[] actual) {
365         assertNotNull(prefix + "expected ScanResults was null", expected);
366         assertNotNull(prefix + "actual ScanResults was null", actual);
367         assertEquals(prefix + "results.length", expected.length, actual.length);
368 
369         // Sort using the bssids.
370         ScanResult[] sortedExpected = Arrays
371                 .stream(expected)
372                 .sorted(Comparator.comparing(s -> s.BSSID))
373                 .toArray(ScanResult[]::new);
374         ScanResult[] sortedActual = Arrays
375                 .stream(actual)
376                 .sorted(Comparator.comparing(s -> s.BSSID))
377                 .toArray(ScanResult[]::new);
378         assertScanResultsEquals(prefix, sortedExpected, sortedActual);
379     }
380 
381     /**
382      * Asserts if the provided scan results are the same.
383      */
assertScanResultEquals(ScanResult expected, ScanResult actual)384     public static void assertScanResultEquals(ScanResult expected, ScanResult actual) {
385         assertScanResultEquals("", expected, actual);
386     }
387 
388     /**
389      * Asserts if the provided scan result arrays are the same.
390      */
assertScanResultsEquals(ScanResult[] expected, ScanResult[] actual)391     public static void assertScanResultsEquals(ScanResult[] expected, ScanResult[] actual) {
392         assertScanResultsEquals("", expected, actual);
393     }
394 
395     /**
396      * Asserts if the provided scan result arrays are the same.
397      */
assertScanResultsEqualsAnyOrder(ScanResult[] expected, ScanResult[] actual)398     public static void assertScanResultsEqualsAnyOrder(ScanResult[] expected, ScanResult[] actual) {
399         assertScanResultsEqualsAnyOrder("", expected, actual);
400     }
401 
assertScanDataEquals(String prefix, ScanData expected, ScanData actual)402     private static void assertScanDataEquals(String prefix, ScanData expected, ScanData actual) {
403         assertNotNull(prefix + "expected ScanData was null", expected);
404         assertNotNull(prefix + "actual ScanData was null", actual);
405         assertEquals(prefix + "id", expected.getId(), actual.getId());
406         assertEquals(prefix + "flags", expected.getFlags(), actual.getFlags());
407         assertEquals(prefix + "band", expected.getScannedBandsInternal(),
408                 actual.getScannedBandsInternal());
409         assertScanResultsEquals(prefix, expected.getResults(), actual.getResults());
410     }
411 
assertScanDataEquals(ScanData expected, ScanData actual)412     public static void assertScanDataEquals(ScanData expected, ScanData actual) {
413         assertScanDataEquals("", expected, actual);
414     }
415 
assertScanDatasEquals(String prefix, ScanData[] expected, ScanData[] actual)416     public static void assertScanDatasEquals(String prefix, ScanData[] expected, ScanData[] actual) {
417         assertNotNull("expected " + prefix + "ScanData[] was null", expected);
418         assertNotNull("actaul " + prefix + "ScanData[] was null", actual);
419         assertEquals(prefix + "ScanData.length", expected.length, actual.length);
420         for (int i = 0; i < expected.length; ++i) {
421             assertScanDataEquals(prefix + "ScanData[" + i + "].", expected[i], actual[i]);
422         }
423     }
424 
assertScanDatasEquals(ScanData[] expected, ScanData[] actual)425     public static void assertScanDatasEquals(ScanData[] expected, ScanData[] actual) {
426         assertScanDatasEquals("", expected, actual);
427     }
428 
channelsToSpec(int... channels)429     public static WifiScanner.ChannelSpec[] channelsToSpec(int... channels) {
430         WifiScanner.ChannelSpec[] channelSpecs = new WifiScanner.ChannelSpec[channels.length];
431         for (int i = 0; i < channels.length; ++i) {
432             channelSpecs[i] = new WifiScanner.ChannelSpec(channels[i]);
433         }
434         return channelSpecs;
435     }
436 
assertNativeScanSettingsEquals(WifiNative.ScanSettings expected, WifiNative.ScanSettings actual)437     public static void assertNativeScanSettingsEquals(WifiNative.ScanSettings expected,
438             WifiNative.ScanSettings actual) {
439         assertEquals("scan type", expected.scanType, actual.scanType);
440         assertEquals("bssids per scan", expected.max_ap_per_scan, actual.max_ap_per_scan);
441         assertEquals("scans to cache", expected.report_threshold_num_scans,
442                 actual.report_threshold_num_scans);
443         assertEquals("percent to cache", expected.report_threshold_percent,
444                 actual.report_threshold_percent);
445         assertEquals("base period", expected.base_period_ms, actual.base_period_ms);
446         assertEquals("enable 6Ghz RNR", expected.enable6GhzRnr, actual.enable6GhzRnr);
447 
448         assertEquals("number of buckets", expected.num_buckets, actual.num_buckets);
449         assertNotNull("buckets was null", actual.buckets);
450         for (int i = 0; i < expected.buckets.length; ++i) {
451             assertNotNull("buckets[" + i + "] was null", actual.buckets[i]);
452             assertEquals("buckets[" + i + "].period",
453                     expected.buckets[i].period_ms, actual.buckets[i].period_ms);
454             assertEquals("buckets[" + i + "].reportEvents",
455                     expected.buckets[i].report_events, actual.buckets[i].report_events);
456 
457             assertEquals("buckets[" + i + "].band",
458                     expected.buckets[i].band, actual.buckets[i].band);
459             if (expected.buckets[i].band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
460                 Set<Integer> expectedChannels = new HashSet<>();
461                 for (WifiNative.ChannelSettings channel : expected.buckets[i].channels) {
462                     expectedChannels.add(channel.frequency);
463                 }
464                 Set<Integer> actualChannels = new HashSet<>();
465                 for (WifiNative.ChannelSettings channel : actual.buckets[i].channels) {
466                     actualChannels.add(channel.frequency);
467                 }
468                 assertEquals("channels", expectedChannels, actualChannels);
469             } else {
470                 // since num_channels and channels are ignored when band is not
471                 // WifiScanner.WIFI_BAND_UNSPECIFIED just assert that there are no channels
472                 // the band equality was already checked above
473                 assertEquals("buckets[" + i + "].num_channels not 0", 0,
474                         actual.buckets[i].num_channels);
475                 assertTrue("buckets[" + i + "].channels not null or empty",
476                         actual.buckets[i].channels == null
477                         || actual.buckets[i].channels.length == 0);
478             }
479         }
480     }
481 
482     /**
483      * Asserts if the provided pno settings are the same.
484      */
assertNativePnoSettingsEquals(WifiNative.PnoSettings expected, WifiNative.PnoSettings actual)485     public static void assertNativePnoSettingsEquals(WifiNative.PnoSettings expected,
486             WifiNative.PnoSettings actual) {
487         assertNotNull("expected was null", expected);
488         assertNotNull("actaul was null", actual);
489         assertEquals("min5GHzRssi", expected.min5GHzRssi, actual.min5GHzRssi);
490         assertEquals("min24GHzRssi", expected.min24GHzRssi, actual.min24GHzRssi);
491         assertEquals("min6GHzRssi", expected.min6GHzRssi, actual.min6GHzRssi);
492         assertEquals("isConnected", expected.isConnected, actual.isConnected);
493         assertNotNull("expected networkList was null", expected.networkList);
494         assertNotNull("actual networkList was null", actual.networkList);
495         assertEquals("networkList.length", expected.networkList.length, actual.networkList.length);
496         for (int i = 0; i < expected.networkList.length; i++) {
497             assertEquals("networkList[" + i + "].ssid",
498                     expected.networkList[i].ssid, actual.networkList[i].ssid);
499             assertEquals("networkList[" + i + "].flags",
500                     expected.networkList[i].flags, actual.networkList[i].flags);
501             assertEquals("networkList[" + i + "].auth_bit_field",
502                     expected.networkList[i].auth_bit_field, actual.networkList[i].auth_bit_field);
503         }
504     }
505 
506     /**
507      * Convert a list of channel frequencies to an array of equivalent WifiNative.ChannelSettings
508      */
channelsToNativeSettings(int... channels)509     public static WifiNative.ChannelSettings[] channelsToNativeSettings(int... channels) {
510         WifiNative.ChannelSettings[] channelSpecs = new WifiNative.ChannelSettings[channels.length];
511         for (int i = 0; i < channels.length; ++i) {
512             channelSpecs[i] = new WifiNative.ChannelSettings();
513             channelSpecs[i].frequency = channels[i];
514         }
515         return channelSpecs;
516     }
517 
518     /**
519      * Matcher to check that a BucketSettings has the given band
520      */
bandIs(final int expectedBand)521     public static Matcher<WifiNative.BucketSettings> bandIs(final int expectedBand) {
522         return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() {
523             @Override
524             public boolean matchesSafely(WifiNative.BucketSettings bucketSettings,
525                     Description mismatchDescription) {
526                 if (bucketSettings.band != expectedBand) {
527                     mismatchDescription
528                             .appendText("did not have expected band ").appendValue(expectedBand)
529                             .appendText(", was ").appendValue(bucketSettings.band);
530                     return false;
531                 } else {
532                     return true;
533                 }
534             }
535 
536             @Override
537             public void describeTo(final Description description) {
538                 description.appendText("bucket band is ").appendValue(expectedBand);
539             }
540         };
541     }
542 
543     /**
544      * Matcher to check that a BucketSettings has exactly the given channels
545      */
546     public static Matcher<WifiNative.BucketSettings> channelsAre(final int... expectedChannels) {
547         return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() {
548             @Override
549             public boolean matchesSafely(WifiNative.BucketSettings bucketSettings,
550                     Description mismatchDescription) {
551                 if (bucketSettings.band != WifiScanner.WIFI_BAND_UNSPECIFIED) {
552                     mismatchDescription.appendText("did not have expected unspecified band, was ")
553                             .appendValue(bucketSettings.band);
554                     return false;
555                 } else if (bucketSettings.num_channels != expectedChannels.length) {
556                     mismatchDescription
557                             .appendText("did not have expected num_channels ")
558                             .appendValue(expectedChannels.length)
559                             .appendText(", was ").appendValue(bucketSettings.num_channels);
560                     return false;
561                 } else if (bucketSettings.channels == null) {
562                     mismatchDescription.appendText("had null channels array");
563                     return false;
564                 } else if (bucketSettings.channels.length != expectedChannels.length) {
565                     mismatchDescription
566                             .appendText("did not have channels array length matching excepted ")
567                             .appendValue(expectedChannels.length)
568                             .appendText(", was ").appendValue(bucketSettings.channels.length);
569                     return false;
570                 } else {
571                     Set<Integer> foundChannelsSet = new HashSet<>();
572                     for (int i = 0; i < bucketSettings.channels.length; ++i) {
573                         foundChannelsSet.add(bucketSettings.channels[i].frequency);
574                     }
575                     Set<Integer> expectedChannelsSet = new HashSet<>();
576                     for (int i = 0; i < expectedChannels.length; ++i) {
577                         expectedChannelsSet.add(expectedChannels[i]);
578                     }
579 
580                     if (!foundChannelsSet.containsAll(expectedChannelsSet)
581                             || foundChannelsSet.size() != expectedChannelsSet.size()) {
582                         Set<Integer> extraChannelsSet = new HashSet<>(foundChannelsSet);
583                         extraChannelsSet.removeAll(expectedChannelsSet);
584                         expectedChannelsSet.removeAll(foundChannelsSet);
585                         mismatchDescription
586                                 .appendText("does not contain expected channels ")
587                                 .appendValue(expectedChannelsSet);
588                         if (extraChannelsSet.size() > 0) {
589                             mismatchDescription
590                                     .appendText(", but contains extra channels ")
591                                     .appendValue(extraChannelsSet);
592                         }
593                         return false;
594                     } else {
595                         return true;
596                     }
597                 }
598             }
599 
600             @Override
601             public void describeTo(final Description description) {
602                 description.appendText("bucket channels are ").appendValue(expectedChannels);
603             }
604         };
605     }
606 }
607