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          * Remove all channels from the collection
    104          */
    105         public abstract void clear();
    106         /**
    107          * Retrieves a list of channels from the band which are missing in the channel collection.
    108          */
    109         public abstract Set<Integer> getMissingChannelsFromBand(int band);
    110         /**
    111          * Retrieves a list of channels from the band which are contained in the channel collection.
    112          */
    113         public abstract Set<Integer> getContainingChannelsFromBand(int band);
    114         /**
    115          * Gets a list of channels specified in the current channel collection. This will return
    116          * an empty set if an entire Band if specified or if the list is empty.
    117          */
    118         public abstract Set<Integer> getChannelSet();
    119 
    120         /**
    121          * Add all channels in the ScanSetting to the collection
    122          */
    123         public void addChannels(WifiScanner.ScanSettings scanSettings) {
    124             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    125                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    126                     addChannel(scanSettings.channels[j].frequency);
    127                 }
    128             } else {
    129                 addBand(scanSettings.band);
    130             }
    131         }
    132 
    133         /**
    134          * Add all channels in the BucketSettings to the collection
    135          */
    136         public void addChannels(WifiNative.BucketSettings bucketSettings) {
    137             if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    138                 for (int j = 0; j < bucketSettings.channels.length; ++j) {
    139                     addChannel(bucketSettings.channels[j].frequency);
    140                 }
    141             } else {
    142                 addBand(bucketSettings.band);
    143             }
    144         }
    145 
    146         /**
    147          * Checks if all channels in ScanSetting is in the collection
    148          */
    149         public boolean containsSettings(WifiScanner.ScanSettings scanSettings) {
    150             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    151                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    152                     if (!containsChannel(scanSettings.channels[j].frequency)) {
    153                         return false;
    154                     }
    155                 }
    156                 return true;
    157             } else {
    158                 return containsBand(scanSettings.band);
    159             }
    160         }
    161 
    162         /**
    163          * Checks if at least some of the channels in ScanSetting is in the collection
    164          */
    165         public boolean partiallyContainsSettings(WifiScanner.ScanSettings scanSettings) {
    166             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    167                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    168                     if (containsChannel(scanSettings.channels[j].frequency)) {
    169                         return true;
    170                     }
    171                 }
    172                 return false;
    173             } else {
    174                 return partiallyContainsBand(scanSettings.band);
    175             }
    176         }
    177 
    178         /**
    179          * Retrieves a list of missing channels in the collection from the provided settings.
    180          */
    181         public Set<Integer> getMissingChannelsFromSettings(WifiScanner.ScanSettings scanSettings) {
    182             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    183                 ArraySet<Integer> missingChannels = new ArraySet<>();
    184                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    185                     if (!containsChannel(scanSettings.channels[j].frequency)) {
    186                         missingChannels.add(scanSettings.channels[j].frequency);
    187                     }
    188                 }
    189                 return missingChannels;
    190             } else {
    191                 return getMissingChannelsFromBand(scanSettings.band);
    192             }
    193         }
    194 
    195         /**
    196          * Retrieves a list of containing channels in the collection from the provided settings.
    197          */
    198         public Set<Integer> getContainingChannelsFromSettings(
    199                 WifiScanner.ScanSettings scanSettings) {
    200             if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    201                 ArraySet<Integer> containingChannels = new ArraySet<>();
    202                 for (int j = 0; j < scanSettings.channels.length; ++j) {
    203                     if (containsChannel(scanSettings.channels[j].frequency)) {
    204                         containingChannels.add(scanSettings.channels[j].frequency);
    205                     }
    206                 }
    207                 return containingChannels;
    208             } else {
    209                 return getContainingChannelsFromBand(scanSettings.band);
    210             }
    211         }
    212 
    213         /**
    214          * Store the channels in this collection in the supplied BucketSettings. If maxChannels is
    215          * exceeded or a band better describes the channels then a band is specified instead of a
    216          * channel list.
    217          */
    218         public abstract void fillBucketSettings(WifiNative.BucketSettings bucket, int maxChannels);
    219 
    220         /**
    221          * Gets the list of channels that should be supplied to supplicant for a scan. Will either
    222          * be a collection of all channels or null if all channels should be scanned.
    223          */
    224         public abstract Set<Integer> getSupplicantScanFreqs();
    225     }
    226 
    227 
    228     /*
    229      * Utility methods for converting band/channels to strings
    230      */
    231 
    232     /**
    233      * Create a string representation of the channels in the ScanSettings.
    234      * If it contains a list of channels then the channels are returned, otherwise a string name of
    235      * the band is returned.
    236      */
    237     public static String toString(WifiScanner.ScanSettings scanSettings) {
    238         if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    239             return toString(scanSettings.channels);
    240         } else {
    241             return toString(scanSettings.band);
    242         }
    243     }
    244 
    245     /**
    246      * Create a string representation of the channels in the BucketSettings.
    247      * If it contains a list of channels then the channels are returned, otherwise a string name of
    248      * the band is returned.
    249      */
    250     public static String toString(WifiNative.BucketSettings bucketSettings) {
    251         if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    252             return toString(bucketSettings.channels, bucketSettings.num_channels);
    253         } else {
    254             return toString(bucketSettings.band);
    255         }
    256     }
    257 
    258     private static String toString(WifiScanner.ChannelSpec[] channels) {
    259         if (channels == null) {
    260             return "null";
    261         }
    262 
    263         StringBuilder sb = new StringBuilder();
    264         sb.append("[");
    265         for (int c = 0; c < channels.length; c++) {
    266             sb.append(channels[c].frequency);
    267             if (c != channels.length - 1) {
    268                 sb.append(",");
    269             }
    270         }
    271         sb.append("]");
    272         return sb.toString();
    273     }
    274 
    275     private static String toString(WifiNative.ChannelSettings[] channels, int numChannels) {
    276         if (channels == null) {
    277             return "null";
    278         }
    279 
    280         StringBuilder sb = new StringBuilder();
    281         sb.append("[");
    282         for (int c = 0; c < numChannels; c++) {
    283             sb.append(channels[c].frequency);
    284             if (c != numChannels - 1) {
    285                 sb.append(",");
    286             }
    287         }
    288         sb.append("]");
    289         return sb.toString();
    290     }
    291 
    292     private static String toString(int band) {
    293         switch (band) {
    294             case WifiScanner.WIFI_BAND_UNSPECIFIED:
    295                 return "unspecified";
    296             case WifiScanner.WIFI_BAND_24_GHZ:
    297                 return "24Ghz";
    298             case WifiScanner.WIFI_BAND_5_GHZ:
    299                 return "5Ghz (no DFS)";
    300             case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
    301                 return "5Ghz (DFS only)";
    302             case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS:
    303                 return "5Ghz (DFS incl)";
    304             case WifiScanner.WIFI_BAND_BOTH:
    305                 return "24Ghz & 5Ghz (no DFS)";
    306             case WifiScanner.WIFI_BAND_BOTH_WITH_DFS:
    307                 return "24Ghz & 5Ghz (DFS incl)";
    308         }
    309 
    310         return "invalid band";
    311     }
    312 }
    313