Home | History | Annotate | Download | only in scanner
      1 /*
      2  * Copyright (C) 2016 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.scanner;
     18 
     19 import android.net.wifi.WifiScanner;
     20 import android.util.ArraySet;
     21 
     22 import com.android.server.wifi.WifiNative;
     23 
     24 import java.util.Set;
     25 
     26 /**
     27  * ChannelHelper offers an abstraction for channel manipulation utilities allowing operation to be
     28  * adjusted based on the amount of information known about the available channels.
     29  */
     30 public abstract class ChannelHelper {
     31 
     32     // TODO: Currently this is simply an estimate and is used for both active and passive channels
     33     //       scans. Eventually it should be split between passive and active and perhaps retrieved
     34     //       from the driver.
     35     /**
     36      * The estimated period spent scanning each channel. This is used for estimating scan duration.
     37      */
     38     public static final int SCAN_PERIOD_PER_CHANNEL_MS = 200;
     39 
     40     protected static final WifiScanner.ChannelSpec[] NO_CHANNELS = new WifiScanner.ChannelSpec[0];
     41 
     42     /**
     43      * Create a new collection that can be used to store channels
     44      */
     45     public abstract ChannelCollection createChannelCollection();
     46 
     47     /**
     48      * Return true if the specified channel is expected for a scan with the given settings
     49      */
     50     public abstract boolean settingsContainChannel(WifiScanner.ScanSettings settings, int channel);
     51 
     52     /**
     53      * Get the channels that are available for scanning on the supplied band.
     54      * This method may return empty if the information is not available.
     55      */
     56     public abstract WifiScanner.ChannelSpec[] getAvailableScanChannels(int band);
     57 
     58     /**
     59      * Estimates the duration that the chip will spend scanning with the given settings
     60      */
     61     public abstract int estimateScanDuration(WifiScanner.ScanSettings settings);
     62 
     63     /**
     64      * Update the channel information that this object has. The source of the update is
     65      * implementation dependent and may result in no change. Warning the behavior of a
     66      * ChannelCollection created using {@link #createChannelCollection createChannelCollection} is
     67      * undefined after calling this method until the {@link ChannelColleciton#clear() clear} method
     68      * is called on it.
     69      */
     70     public void updateChannels() {
     71         // default implementation does nothing
     72     }
     73 
     74     /**
     75      * Object that supports accumulation of channels and bands
     76      */
     77     public abstract class ChannelCollection {
     78         /**
     79          * Add a channel to the collection
     80          */
     81         public abstract void addChannel(int channel);
     82         /**
     83          * Add all channels in the band to the collection
     84          */
     85         public abstract void addBand(int band);
     86         /**
     87          * @return true if the collection contains the supplied channel
     88          */
     89         public abstract boolean containsChannel(int channel);
     90         /**
     91          * @return true if the collection contains all the channels of the supplied band
     92          */
     93         public abstract boolean containsBand(int band);
     94         /**
     95          * @return true if the collection contains some of the channels of the supplied band
     96          */
     97         public abstract boolean partiallyContainsBand(int band);
     98         /**
     99          * @return true if the collection contains no channels
    100          */
    101         public abstract boolean isEmpty();
    102         /**
    103          * @return true if the collection contains all available channels
    104          */
    105         public abstract boolean isAllChannels();
    106         /**
    107          * Remove all channels from the collection
    108          */
    109         public abstract void clear();
    110         /**
    111          * Retrieves a list of channels from the band which are missing in the channel collection.
    112          */
    113         public abstract Set<Integer> getMissingChannelsFromBand(int band);
    114         /**
    115          * Retrieves a list of channels from the band which are contained in the channel collection.
    116          */
    117         public abstract Set<Integer> getContainingChannelsFromBand(int band);
    118         /**
    119          * Gets a list of channels specified in the current channel collection. This will return
    120          * an empty set if an entire Band if specified or if the list is empty.
    121          */
    122         public abstract Set<Integer> getChannelSet();
    123 
    124         /**
    125          * Add all channels in the ScanSetting to the collection
    126          */
    127         public void addChannels(WifiScanner.ScanSettings scanSettings) {
    128             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    129                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    130                     addChannel(scanSettings.channels[j].frequency);
    131                 }
    132             } else {
    133                 addBand(scanSettings.band);
    134             }
    135         }
    136 
    137         /**
    138          * Add all channels in the BucketSettings to the collection
    139          */
    140         public void addChannels(WifiNative.BucketSettings bucketSettings) {
    141             if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    142                 for (int j = 0; j < bucketSettings.channels.length; ++j) {
    143                     addChannel(bucketSettings.channels[j].frequency);
    144                 }
    145             } else {
    146                 addBand(bucketSettings.band);
    147             }
    148         }
    149 
    150         /**
    151          * Checks if all channels in ScanSetting is in the collection
    152          */
    153         public boolean containsSettings(WifiScanner.ScanSettings scanSettings) {
    154             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    155                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    156                     if (!containsChannel(scanSettings.channels[j].frequency)) {
    157                         return false;
    158                     }
    159                 }
    160                 return true;
    161             } else {
    162                 return containsBand(scanSettings.band);
    163             }
    164         }
    165 
    166         /**
    167          * Checks if at least some of the channels in ScanSetting is in the collection
    168          */
    169         public boolean partiallyContainsSettings(WifiScanner.ScanSettings scanSettings) {
    170             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    171                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    172                     if (containsChannel(scanSettings.channels[j].frequency)) {
    173                         return true;
    174                     }
    175                 }
    176                 return false;
    177             } else {
    178                 return partiallyContainsBand(scanSettings.band);
    179             }
    180         }
    181 
    182         /**
    183          * Retrieves a list of missing channels in the collection from the provided settings.
    184          */
    185         public Set<Integer> getMissingChannelsFromSettings(WifiScanner.ScanSettings scanSettings) {
    186             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    187                 ArraySet<Integer> missingChannels = new ArraySet<>();
    188                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    189                     if (!containsChannel(scanSettings.channels[j].frequency)) {
    190                         missingChannels.add(scanSettings.channels[j].frequency);
    191                     }
    192                 }
    193                 return missingChannels;
    194             } else {
    195                 return getMissingChannelsFromBand(scanSettings.band);
    196             }
    197         }
    198 
    199         /**
    200          * Retrieves a list of containing channels in the collection from the provided settings.
    201          */
    202         public Set<Integer> getContainingChannelsFromSettings(
    203                 WifiScanner.ScanSettings scanSettings) {
    204             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    205                 ArraySet<Integer> containingChannels = new ArraySet<>();
    206                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    207                     if (containsChannel(scanSettings.channels[j].frequency)) {
    208                         containingChannels.add(scanSettings.channels[j].frequency);
    209                     }
    210                 }
    211                 return containingChannels;
    212             } else {
    213                 return getContainingChannelsFromBand(scanSettings.band);
    214             }
    215         }
    216 
    217         /**
    218          * Store the channels in this collection in the supplied BucketSettings. If maxChannels is
    219          * exceeded or a band better describes the channels then a band is specified instead of a
    220          * channel list.
    221          */
    222         public abstract void fillBucketSettings(WifiNative.BucketSettings bucket, int maxChannels);
    223 
    224         /**
    225          * Gets the list of channels that should be supplied to supplicant for a scan. Will either
    226          * be a collection of all channels or null if all channels should be scanned.
    227          */
    228         public abstract Set<Integer> getSupplicantScanFreqs();
    229     }
    230 
    231 
    232     /*
    233      * Utility methods for converting band/channels to strings
    234      */
    235 
    236     /**
    237      * Create a string representation of the channels in the ScanSettings.
    238      * If it contains a list of channels then the channels are returned, otherwise a string name of
    239      * the band is returned.
    240      */
    241     public static String toString(WifiScanner.ScanSettings scanSettings) {
    242         if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    243             return toString(scanSettings.channels);
    244         } else {
    245             return toString(scanSettings.band);
    246         }
    247     }
    248 
    249     /**
    250      * Create a string representation of the channels in the BucketSettings.
    251      * If it contains a list of channels then the channels are returned, otherwise a string name of
    252      * the band is returned.
    253      */
    254     public static String toString(WifiNative.BucketSettings bucketSettings) {
    255         if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    256             return toString(bucketSettings.channels, bucketSettings.num_channels);
    257         } else {
    258             return toString(bucketSettings.band);
    259         }
    260     }
    261 
    262     private static String toString(WifiScanner.ChannelSpec[] channels) {
    263         if (channels == null) {
    264             return "null";
    265         }
    266 
    267         StringBuilder sb = new StringBuilder();
    268         sb.append("[");
    269         for (int c = 0; c < channels.length; c++) {
    270             sb.append(channels[c].frequency);
    271             if (c != channels.length - 1) {
    272                 sb.append(",");
    273             }
    274         }
    275         sb.append("]");
    276         return sb.toString();
    277     }
    278 
    279     private static String toString(WifiNative.ChannelSettings[] channels, int numChannels) {
    280         if (channels == null) {
    281             return "null";
    282         }
    283 
    284         StringBuilder sb = new StringBuilder();
    285         sb.append("[");
    286         for (int c = 0; c < numChannels; c++) {
    287             sb.append(channels[c].frequency);
    288             if (c != numChannels - 1) {
    289                 sb.append(",");
    290             }
    291         }
    292         sb.append("]");
    293         return sb.toString();
    294     }
    295 
    296     private static String toString(int band) {
    297         switch (band) {
    298             case WifiScanner.WIFI_BAND_UNSPECIFIED:
    299                 return "unspecified";
    300             case WifiScanner.WIFI_BAND_24_GHZ:
    301                 return "24Ghz";
    302             case WifiScanner.WIFI_BAND_5_GHZ:
    303                 return "5Ghz (no DFS)";
    304             case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
    305                 return "5Ghz (DFS only)";
    306             case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS:
    307                 return "5Ghz (DFS incl)";
    308             case WifiScanner.WIFI_BAND_BOTH:
    309                 return "24Ghz & 5Ghz (no DFS)";
    310             case WifiScanner.WIFI_BAND_BOTH_WITH_DFS:
    311                 return "24Ghz & 5Ghz (DFS incl)";
    312         }
    313 
    314         return "invalid band";
    315     }
    316 }
    317