• 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 org.hamcrest.Description;
29 import org.hamcrest.Matcher;
30 import org.hamcrest.TypeSafeDiagnosingMatcher;
31 
32 import java.util.Arrays;
33 import java.util.HashSet;
34 import java.util.Set;
35 
36 /**
37  * Utilities for testing Wifi Scanning
38  */
39 public class ScanTestUtil {
40 
setupMockChannels(WifiNative wifiNative, int[] channels24, int[] channels5, int[] channelsDfs)41     public static void setupMockChannels(WifiNative wifiNative, int[] channels24, int[] channels5,
42             int[] channelsDfs) throws Exception {
43         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ))
44                 .thenReturn(channels24);
45         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ))
46                 .thenReturn(channels5);
47         when(wifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY))
48                 .thenReturn(channelsDfs);
49     }
50 
createRequest(WifiScanner.ChannelSpec[] channels, int period, int batch, int bssidsPerScan, int reportEvents)51     public static WifiScanner.ScanSettings createRequest(WifiScanner.ChannelSpec[] channels,
52             int period, int batch, int bssidsPerScan, int reportEvents) {
53         WifiScanner.ScanSettings request = new WifiScanner.ScanSettings();
54         request.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
55         request.channels = channels;
56         request.periodInMs = period;
57         request.numBssidsPerScan = bssidsPerScan;
58         request.maxScansToCache = batch;
59         request.reportEvents = reportEvents;
60         return request;
61     }
62 
createRequest(int band, int period, int batch, int bssidsPerScan, int reportEvents)63     public static WifiScanner.ScanSettings createRequest(int band, int period, int batch,
64             int bssidsPerScan, int reportEvents) {
65         return createRequest(band, period, 0, 0, batch, bssidsPerScan, reportEvents);
66     }
67 
68     /**
69      * Create an exponential back off scan request if maxPeriod != period && maxPeriod != 0.
70      */
createRequest(int band, int period, int maxPeriod, int stepCount, int batch, int bssidsPerScan, int reportEvents)71     public static WifiScanner.ScanSettings createRequest(int band, int period, int maxPeriod,
72             int stepCount, int batch, int bssidsPerScan, int reportEvents) {
73         WifiScanner.ScanSettings request = new WifiScanner.ScanSettings();
74         request.band = band;
75         request.channels = null;
76         request.periodInMs = period;
77         request.maxPeriodInMs = maxPeriod;
78         request.stepCount = stepCount;
79         request.numBssidsPerScan = bssidsPerScan;
80         request.maxScansToCache = batch;
81         request.reportEvents = reportEvents;
82         return request;
83     }
84 
85     /**
86      * Builder to create WifiNative.ScanSettings objects for testing
87      */
88     public static class NativeScanSettingsBuilder {
89         private final WifiNative.ScanSettings mSettings = new WifiNative.ScanSettings();
NativeScanSettingsBuilder()90         public NativeScanSettingsBuilder() {
91             mSettings.buckets = new WifiNative.BucketSettings[0];
92             mSettings.num_buckets = 0;
93             mSettings.report_threshold_percent = 100;
94         }
95 
withBasePeriod(int basePeriod)96         public NativeScanSettingsBuilder withBasePeriod(int basePeriod) {
97             mSettings.base_period_ms = basePeriod;
98             return this;
99         }
withMaxApPerScan(int maxAp)100         public NativeScanSettingsBuilder withMaxApPerScan(int maxAp) {
101             mSettings.max_ap_per_scan = maxAp;
102             return this;
103         }
withMaxScansToCache(int maxScans)104         public NativeScanSettingsBuilder withMaxScansToCache(int maxScans) {
105             mSettings.report_threshold_num_scans = maxScans;
106             return this;
107         }
withMaxPercentToCache(int percent)108         public NativeScanSettingsBuilder withMaxPercentToCache(int percent) {
109             mSettings.report_threshold_percent = percent;
110             return this;
111         }
112 
113         /**
114          * Add the provided hidden network IDs to scan request.
115          * @param networkIds List of hidden network IDs
116          * @return builder object
117          */
withHiddenNetworkIds(int[] networkIds)118         public NativeScanSettingsBuilder withHiddenNetworkIds(int[] networkIds) {
119             mSettings.hiddenNetworkIds = networkIds;
120             return this;
121         }
122 
addBucketWithBand( int period, int reportEvents, int band)123         public NativeScanSettingsBuilder addBucketWithBand(
124                 int period, int reportEvents, int band) {
125             WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
126             bucket.bucket = mSettings.num_buckets;
127             bucket.band = band;
128             bucket.period_ms = period;
129             bucket.report_events = reportEvents;
130             return addBucket(bucket);
131         }
132 
addBucketWithChannels( int period, int reportEvents, WifiScanner.ChannelSpec... channels)133         public NativeScanSettingsBuilder addBucketWithChannels(
134                 int period, int reportEvents, WifiScanner.ChannelSpec... channels) {
135             int[] channelFreqs = new int[channels.length];
136             for (int i = 0; i < channels.length; ++i) {
137                 channelFreqs[i] = channels[i].frequency;
138             }
139             return addBucketWithChannels(period, reportEvents, channelFreqs);
140         }
141 
addBucketWithChannels( int period, int reportEvents, int... channels)142         public NativeScanSettingsBuilder addBucketWithChannels(
143                 int period, int reportEvents, int... channels) {
144             WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
145             bucket.bucket = mSettings.num_buckets;
146             bucket.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
147             bucket.num_channels = channels.length;
148             bucket.channels = channelsToNativeSettings(channels);
149             bucket.period_ms = period;
150             bucket.report_events = reportEvents;
151             return addBucket(bucket);
152         }
153 
addBucket(WifiNative.BucketSettings bucket)154         public NativeScanSettingsBuilder addBucket(WifiNative.BucketSettings bucket) {
155             mSettings.buckets = Arrays.copyOf(mSettings.buckets, mSettings.num_buckets + 1);
156             mSettings.buckets[mSettings.num_buckets] = bucket;
157             mSettings.num_buckets = mSettings.num_buckets + 1;
158             return this;
159         }
160 
build()161         public WifiNative.ScanSettings build() {
162             return mSettings;
163         }
164     }
165 
166     /**
167      * Compute the expected native scan settings that are expected for the given
168      * WifiScanner.ScanSettings.
169      */
computeSingleScanNativeSettings( WifiScanner.ScanSettings requestSettings)170     public static WifiNative.ScanSettings computeSingleScanNativeSettings(
171             WifiScanner.ScanSettings requestSettings) {
172         int reportEvents = requestSettings.reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
173         NativeScanSettingsBuilder builder = new NativeScanSettingsBuilder()
174                 .withBasePeriod(0)
175                 .withMaxApPerScan(0)
176                 .withMaxPercentToCache(0)
177                 .withMaxScansToCache(0);
178         if (requestSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
179             builder.addBucketWithChannels(0, reportEvents, requestSettings.channels);
180         } else {
181             builder.addBucketWithBand(0, reportEvents, requestSettings.band);
182         }
183 
184         return builder.build();
185     }
186 
187     /**
188      * Compute the expected native scan settings that are expected for the given channels.
189      */
createSingleScanNativeSettingsForChannels( int reportEvents, WifiScanner.ChannelSpec... channels)190     public static WifiNative.ScanSettings createSingleScanNativeSettingsForChannels(
191             int reportEvents, WifiScanner.ChannelSpec... channels) {
192         int actualReportEvents = reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
193         return new NativeScanSettingsBuilder()
194                 .withBasePeriod(0)
195                 .withMaxApPerScan(0)
196                 .withMaxPercentToCache(0)
197                 .withMaxScansToCache(0)
198                 .addBucketWithChannels(0, actualReportEvents, channels)
199                 .build();
200     }
201 
createFreqSet(int... elements)202     public static Set<Integer> createFreqSet(int... elements) {
203         Set<Integer> set = new HashSet<>();
204         for (int e : elements) {
205             set.add(e);
206         }
207         return set;
208     }
209 
createScanResult(int freq)210     public static ScanResult createScanResult(int freq) {
211         return new ScanResult(WifiSsid.createFromAsciiEncoded("AN SSID"), "00:00:00:00:00:00", 0L,
212                 -1, null, "", 0, freq, 0);
213     }
214 
createScanData(int[] freqs, int bucketsScanned)215     private static ScanData createScanData(int[] freqs, int bucketsScanned) {
216         ScanResult[] results = new ScanResult[freqs.length];
217         for (int i = 0; i < freqs.length; ++i) {
218             results[i] = createScanResult(freqs[i]);
219         }
220         return new ScanData(0, 0, bucketsScanned, results);
221     }
222 
createScanDatas(int[][] freqs, int[] bucketsScanned)223     public static ScanData[] createScanDatas(int[][] freqs, int[] bucketsScanned) {
224         assumeTrue(freqs.length == bucketsScanned.length);
225         ScanData[] data = new ScanData[freqs.length];
226         for (int i = 0; i < freqs.length; ++i) {
227             data[i] = createScanData(freqs[i], bucketsScanned[i]);
228         }
229         return data;
230     }
231 
createScanDatas(int[][] freqs)232     public static ScanData[] createScanDatas(int[][] freqs) {
233         return createScanDatas(freqs, new int[freqs.length] /* defaults all 0 */);
234     }
235 
assertScanResultsEquals(String prefix, ScanResult[] expected, ScanResult[] actual)236     private static void assertScanResultsEquals(String prefix, ScanResult[] expected,
237             ScanResult[] actual) {
238         assertNotNull(prefix + "expected ScanResults was null", expected);
239         assertNotNull(prefix + "actual ScanResults was null", actual);
240         assertEquals(prefix + "results.length", expected.length, actual.length);
241         for (int j = 0; j < expected.length; ++j) {
242             ScanResult expectedResult = expected[j];
243             ScanResult actualResult = actual[j];
244             assertEquals(prefix + "results[" + j + "].SSID",
245                     expectedResult.SSID, actualResult.SSID);
246             assertEquals(prefix + "results[" + j + "].wifiSsid",
247                     expectedResult.wifiSsid.toString(), actualResult.wifiSsid.toString());
248             assertEquals(prefix + "results[" + j + "].BSSID",
249                     expectedResult.BSSID, actualResult.BSSID);
250             assertEquals(prefix + "results[" + j + "].capabilities",
251                     expectedResult.capabilities, actualResult.capabilities);
252             assertEquals(prefix + "results[" + j + "].level",
253                     expectedResult.level, actualResult.level);
254             assertEquals(prefix + "results[" + j + "].frequency",
255                     expectedResult.frequency, actualResult.frequency);
256             assertEquals(prefix + "results[" + j + "].timestamp",
257                     expectedResult.timestamp, actualResult.timestamp);
258             assertEquals(prefix + "results[" + j + "].seen",
259                     expectedResult.seen, actualResult.seen);
260         }
261     }
262 
263     /**
264      * Asserts if the provided scan result arrays are the same.
265      */
assertScanResultsEquals(ScanResult[] expected, ScanResult[] actual)266     public static void assertScanResultsEquals(ScanResult[] expected, ScanResult[] actual) {
267         assertScanResultsEquals("", expected, actual);
268     }
269 
assertScanDataEquals(String prefix, ScanData expected, ScanData actual)270     private static void assertScanDataEquals(String prefix, ScanData expected, ScanData actual) {
271         assertNotNull(prefix + "expected ScanData was null", expected);
272         assertNotNull(prefix + "actual ScanData was null", actual);
273         assertEquals(prefix + "id", expected.getId(), actual.getId());
274         assertEquals(prefix + "flags", expected.getFlags(), actual.getFlags());
275         assertScanResultsEquals(prefix, expected.getResults(), actual.getResults());
276     }
277 
assertScanDataEquals(ScanData expected, ScanData actual)278     public static void assertScanDataEquals(ScanData expected, ScanData actual) {
279         assertScanDataEquals("", expected, actual);
280     }
281 
assertScanDatasEquals(String prefix, ScanData[] expected, ScanData[] actual)282     public static void assertScanDatasEquals(String prefix, ScanData[] expected, ScanData[] actual) {
283         assertNotNull("expected " + prefix + "ScanData[] was null", expected);
284         assertNotNull("actaul " + prefix + "ScanData[] was null", actual);
285         assertEquals(prefix + "ScanData.length", expected.length, actual.length);
286         for (int i = 0; i < expected.length; ++i) {
287             assertScanDataEquals(prefix + "ScanData[" + i + "].", expected[i], actual[i]);
288         }
289     }
290 
assertScanDatasEquals(ScanData[] expected, ScanData[] actual)291     public static void assertScanDatasEquals(ScanData[] expected, ScanData[] actual) {
292         assertScanDatasEquals("", expected, actual);
293     }
294 
channelsToSpec(int... channels)295     public static WifiScanner.ChannelSpec[] channelsToSpec(int... channels) {
296         WifiScanner.ChannelSpec[] channelSpecs = new WifiScanner.ChannelSpec[channels.length];
297         for (int i = 0; i < channels.length; ++i) {
298             channelSpecs[i] = new WifiScanner.ChannelSpec(channels[i]);
299         }
300         return channelSpecs;
301     }
302 
assertNativeScanSettingsEquals(WifiNative.ScanSettings expected, WifiNative.ScanSettings actual)303     public static void assertNativeScanSettingsEquals(WifiNative.ScanSettings expected,
304             WifiNative.ScanSettings actual) {
305         assertEquals("bssids per scan", expected.max_ap_per_scan, actual.max_ap_per_scan);
306         assertEquals("scans to cache", expected.report_threshold_num_scans,
307                 actual.report_threshold_num_scans);
308         assertEquals("percent to cache", expected.report_threshold_percent,
309                 actual.report_threshold_percent);
310         assertEquals("base period", expected.base_period_ms, actual.base_period_ms);
311 
312         assertEquals("number of buckets", expected.num_buckets, actual.num_buckets);
313         assertNotNull("buckets was null", actual.buckets);
314         for (int i = 0; i < expected.buckets.length; ++i) {
315             assertNotNull("buckets[" + i + "] was null", actual.buckets[i]);
316             assertEquals("buckets[" + i + "].period",
317                     expected.buckets[i].period_ms, actual.buckets[i].period_ms);
318             assertEquals("buckets[" + i + "].reportEvents",
319                     expected.buckets[i].report_events, actual.buckets[i].report_events);
320 
321             assertEquals("buckets[" + i + "].band",
322                     expected.buckets[i].band, actual.buckets[i].band);
323             if (expected.buckets[i].band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
324                 Set<Integer> expectedChannels = new HashSet<>();
325                 for (WifiNative.ChannelSettings channel : expected.buckets[i].channels) {
326                     expectedChannels.add(channel.frequency);
327                 }
328                 Set<Integer> actualChannels = new HashSet<>();
329                 for (WifiNative.ChannelSettings channel : actual.buckets[i].channels) {
330                     actualChannels.add(channel.frequency);
331                 }
332                 assertEquals("channels", expectedChannels, actualChannels);
333             } else {
334                 // since num_channels and channels are ignored when band is not
335                 // WifiScanner.WIFI_BAND_UNSPECIFIED just assert that there are no channels
336                 // the band equality was already checked above
337                 assertEquals("buckets[" + i + "].num_channels not 0", 0,
338                         actual.buckets[i].num_channels);
339                 assertTrue("buckets[" + i + "].channels not null or empty",
340                         actual.buckets[i].channels == null
341                         || actual.buckets[i].channels.length == 0);
342             }
343         }
344     }
345 
346     /**
347      * Asserts if the provided pno settings are the same.
348      */
assertNativePnoSettingsEquals(WifiNative.PnoSettings expected, WifiNative.PnoSettings actual)349     public static void assertNativePnoSettingsEquals(WifiNative.PnoSettings expected,
350             WifiNative.PnoSettings actual) {
351         assertNotNull("expected was null", expected);
352         assertNotNull("actaul was null", actual);
353         assertEquals("min5GHzRssi", expected.min5GHzRssi, actual.min5GHzRssi);
354         assertEquals("min24GHzRssi", expected.min24GHzRssi, actual.min24GHzRssi);
355         assertEquals("initialScoreMax", expected.initialScoreMax, actual.initialScoreMax);
356         assertEquals("currentConnectionBonus", expected.currentConnectionBonus,
357                 actual.currentConnectionBonus);
358         assertEquals("sameNetworkBonus", expected.sameNetworkBonus, actual.sameNetworkBonus);
359         assertEquals("secureBonus", expected.secureBonus, actual.secureBonus);
360         assertEquals("band5GHzBonus", expected.band5GHzBonus, actual.band5GHzBonus);
361         assertEquals("isConnected", expected.isConnected, actual.isConnected);
362         assertNotNull("expected networkList was null", expected.networkList);
363         assertNotNull("actual networkList was null", actual.networkList);
364         assertEquals("networkList.length", expected.networkList.length, actual.networkList.length);
365         for (int i = 0; i < expected.networkList.length; i++) {
366             assertEquals("networkList[" + i + "].ssid",
367                     expected.networkList[i].ssid, actual.networkList[i].ssid);
368             assertEquals("networkList[" + i + "].networkId",
369                     expected.networkList[i].networkId, actual.networkList[i].networkId);
370             assertEquals("networkList[" + i + "].priority",
371                     expected.networkList[i].priority, actual.networkList[i].priority);
372             assertEquals("networkList[" + i + "].flags",
373                     expected.networkList[i].flags, actual.networkList[i].flags);
374             assertEquals("networkList[" + i + "].auth_bit_field",
375                     expected.networkList[i].auth_bit_field, actual.networkList[i].auth_bit_field);
376         }
377     }
378 
379     /**
380      * Convert a list of channel frequencies to an array of equivalent WifiNative.ChannelSettings
381      */
channelsToNativeSettings(int... channels)382     public static WifiNative.ChannelSettings[] channelsToNativeSettings(int... channels) {
383         WifiNative.ChannelSettings[] channelSpecs = new WifiNative.ChannelSettings[channels.length];
384         for (int i = 0; i < channels.length; ++i) {
385             channelSpecs[i] = new WifiNative.ChannelSettings();
386             channelSpecs[i].frequency = channels[i];
387         }
388         return channelSpecs;
389     }
390 
391     /**
392      * Matcher to check that a BucketSettings has the given band
393      */
bandIs(final int expectedBand)394     public static Matcher<WifiNative.BucketSettings> bandIs(final int expectedBand) {
395         return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() {
396             @Override
397             public boolean matchesSafely(WifiNative.BucketSettings bucketSettings,
398                     Description mismatchDescription) {
399                 if (bucketSettings.band != expectedBand) {
400                     mismatchDescription
401                             .appendText("did not have expected band ").appendValue(expectedBand)
402                             .appendText(", was ").appendValue(bucketSettings.band);
403                     return false;
404                 } else {
405                     return true;
406                 }
407             }
408 
409             @Override
410             public void describeTo(final Description description) {
411                 description.appendText("bucket band is ").appendValue(expectedBand);
412             }
413         };
414     }
415 
416     /**
417      * Matcher to check that a BucketSettings has exactly the given channels
418      */
419     public static Matcher<WifiNative.BucketSettings> channelsAre(final int... expectedChannels) {
420         return new TypeSafeDiagnosingMatcher<WifiNative.BucketSettings>() {
421             @Override
422             public boolean matchesSafely(WifiNative.BucketSettings bucketSettings,
423                     Description mismatchDescription) {
424                 if (bucketSettings.band != WifiScanner.WIFI_BAND_UNSPECIFIED) {
425                     mismatchDescription.appendText("did not have expected unspecified band, was ")
426                             .appendValue(bucketSettings.band);
427                     return false;
428                 } else if (bucketSettings.num_channels != expectedChannels.length) {
429                     mismatchDescription
430                             .appendText("did not have expected num_channels ")
431                             .appendValue(expectedChannels.length)
432                             .appendText(", was ").appendValue(bucketSettings.num_channels);
433                     return false;
434                 } else if (bucketSettings.channels == null) {
435                     mismatchDescription.appendText("had null channels array");
436                     return false;
437                 } else if (bucketSettings.channels.length != expectedChannels.length) {
438                     mismatchDescription
439                             .appendText("did not have channels array length matching excepted ")
440                             .appendValue(expectedChannels.length)
441                             .appendText(", was ").appendValue(bucketSettings.channels.length);
442                     return false;
443                 } else {
444                     Set<Integer> foundChannelsSet = new HashSet<>();
445                     for (int i = 0; i < bucketSettings.channels.length; ++i) {
446                         foundChannelsSet.add(bucketSettings.channels[i].frequency);
447                     }
448                     Set<Integer> expectedChannelsSet = new HashSet<>();
449                     for (int i = 0; i < expectedChannels.length; ++i) {
450                         expectedChannelsSet.add(expectedChannels[i]);
451                     }
452 
453                     if (!foundChannelsSet.containsAll(expectedChannelsSet)
454                             || foundChannelsSet.size() != expectedChannelsSet.size()) {
455                         Set<Integer> extraChannelsSet = new HashSet<>(foundChannelsSet);
456                         extraChannelsSet.removeAll(expectedChannelsSet);
457                         expectedChannelsSet.removeAll(foundChannelsSet);
458                         mismatchDescription
459                                 .appendText("does not contain expected channels ")
460                                 .appendValue(expectedChannelsSet);
461                         if (extraChannelsSet.size() > 0) {
462                             mismatchDescription
463                                     .appendText(", but contains extra channels ")
464                                     .appendValue(extraChannelsSet);
465                         }
466                         return false;
467                     } else {
468                         return true;
469                     }
470                 }
471             }
472 
473             @Override
474             public void describeTo(final Description description) {
475                 description.appendText("bucket channels are ").appendValue(expectedChannels);
476             }
477         };
478     }
479 }
480