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