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 that offers channel manipulation utilities when the channels in a band are known.
     28  * This allows more fine operations on channels than if band channels are not known.
     29  */
     30 public class KnownBandsChannelHelper extends ChannelHelper {
     31 
     32     private WifiScanner.ChannelSpec[][] mBandsToChannels;
     33 
     34     protected void setBandChannels(int[] channels2G, int[] channels5G, int[] channelsDfs) {
     35         mBandsToChannels = new WifiScanner.ChannelSpec[8][];
     36 
     37         mBandsToChannels[0] = NO_CHANNELS;
     38 
     39         mBandsToChannels[1] = new WifiScanner.ChannelSpec[channels2G.length];
     40         copyChannels(mBandsToChannels[1], 0, channels2G);
     41 
     42         mBandsToChannels[2] = new WifiScanner.ChannelSpec[channels5G.length];
     43         copyChannels(mBandsToChannels[2], 0, channels5G);
     44 
     45         mBandsToChannels[3] = new WifiScanner.ChannelSpec[channels2G.length + channels5G.length];
     46         copyChannels(mBandsToChannels[3], 0, channels2G);
     47         copyChannels(mBandsToChannels[3], channels2G.length, channels5G);
     48 
     49         mBandsToChannels[4] = new WifiScanner.ChannelSpec[channelsDfs.length];
     50         copyChannels(mBandsToChannels[4], 0, channelsDfs);
     51 
     52         mBandsToChannels[5] = new WifiScanner.ChannelSpec[channels2G.length + channelsDfs.length];
     53         copyChannels(mBandsToChannels[5], 0, channels2G);
     54         copyChannels(mBandsToChannels[5], channels2G.length, channelsDfs);
     55 
     56         mBandsToChannels[6] = new WifiScanner.ChannelSpec[channels5G.length + channelsDfs.length];
     57         copyChannels(mBandsToChannels[6], 0, channels5G);
     58         copyChannels(mBandsToChannels[6], channels5G.length, channelsDfs);
     59 
     60         mBandsToChannels[7] = new WifiScanner.ChannelSpec[
     61                 channels2G.length + channels5G.length + channelsDfs.length];
     62         copyChannels(mBandsToChannels[7], 0, channels2G);
     63         copyChannels(mBandsToChannels[7], channels2G.length, channels5G);
     64         copyChannels(mBandsToChannels[7], channels2G.length + channels5G.length, channelsDfs);
     65     }
     66 
     67     private static void copyChannels(
     68             WifiScanner.ChannelSpec[] channelSpec, int offset, int[] channels) {
     69         for (int i = 0; i < channels.length; i++) {
     70             channelSpec[offset + i] = new WifiScanner.ChannelSpec(channels[i]);
     71         }
     72     }
     73 
     74     @Override
     75     public WifiScanner.ChannelSpec[] getAvailableScanChannels(int band) {
     76         if (band < WifiScanner.WIFI_BAND_24_GHZ || band > WifiScanner.WIFI_BAND_BOTH_WITH_DFS) {
     77             // invalid value for band
     78             return NO_CHANNELS;
     79         } else {
     80             return mBandsToChannels[band];
     81         }
     82     }
     83 
     84     @Override
     85     public int estimateScanDuration(WifiScanner.ScanSettings settings) {
     86         if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
     87             return settings.channels.length * SCAN_PERIOD_PER_CHANNEL_MS;
     88         } else {
     89             return getAvailableScanChannels(settings.band).length * SCAN_PERIOD_PER_CHANNEL_MS;
     90         }
     91     }
     92 
     93     private boolean isDfsChannel(int frequency) {
     94         for (WifiScanner.ChannelSpec dfsChannel :
     95                 mBandsToChannels[WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY]) {
     96             if (frequency == dfsChannel.frequency) {
     97                 return true;
     98             }
     99         }
    100         return false;
    101     }
    102 
    103     // TODO this should be rewritten to be based on the input data instead of hardcoded ranges
    104     private int getBandFromChannel(int frequency) {
    105         if (2400 <= frequency && frequency < 2500) {
    106             return WifiScanner.WIFI_BAND_24_GHZ;
    107         } else if (isDfsChannel(frequency)) {
    108             return WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY;
    109         } else if (5100 <= frequency && frequency < 6000) {
    110             return WifiScanner.WIFI_BAND_5_GHZ;
    111         } else {
    112             return WifiScanner.WIFI_BAND_UNSPECIFIED;
    113         }
    114     }
    115 
    116     @Override
    117     public boolean settingsContainChannel(WifiScanner.ScanSettings settings, int channel) {
    118         WifiScanner.ChannelSpec[] settingsChannels;
    119         if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
    120             settingsChannels = settings.channels;
    121         } else {
    122             settingsChannels = getAvailableScanChannels(settings.band);
    123         }
    124         for (int i = 0; i < settingsChannels.length; ++i) {
    125             if (settingsChannels[i].frequency == channel) {
    126                 return true;
    127             }
    128         }
    129         return false;
    130     }
    131 
    132     /**
    133      * ChannelCollection that merges channels so that the optimal schedule will be generated.
    134      * When the max channels value is satisfied this implementation will always create a channel
    135      * list that includes no more than the added channels.
    136      */
    137     public class KnownBandsChannelCollection extends ChannelCollection {
    138         /**
    139          * Stores all channels, including those that belong to added bands.
    140          */
    141         private final ArraySet<Integer> mChannels = new ArraySet<Integer>();
    142         /**
    143          * Contains only the bands that were explicitly added as bands.
    144          */
    145         private int mExactBands = 0;
    146         /**
    147          * Contains all bands, including those that were added because an added channel was in that
    148          * band.
    149          */
    150         private int mAllBands = 0;
    151 
    152         @Override
    153         public void addChannel(int frequency) {
    154             mChannels.add(frequency);
    155             mAllBands |= getBandFromChannel(frequency);
    156         }
    157 
    158         @Override
    159         public void addBand(int band) {
    160             mExactBands |= band;
    161             mAllBands |= band;
    162             WifiScanner.ChannelSpec[] bandChannels = getAvailableScanChannels(band);
    163             for (int i = 0; i < bandChannels.length; ++i) {
    164                 mChannels.add(bandChannels[i].frequency);
    165             }
    166         }
    167 
    168         @Override
    169         public boolean containsChannel(int channel) {
    170             return mChannels.contains(channel);
    171         }
    172 
    173         @Override
    174         public boolean containsBand(int band) {
    175             WifiScanner.ChannelSpec[] bandChannels = getAvailableScanChannels(band);
    176             for (int i = 0; i < bandChannels.length; ++i) {
    177                 if (!mChannels.contains(bandChannels[i].frequency)) {
    178                     return false;
    179                 }
    180             }
    181             return true;
    182         }
    183 
    184         @Override
    185         public boolean partiallyContainsBand(int band) {
    186             WifiScanner.ChannelSpec[] bandChannels = getAvailableScanChannels(band);
    187             for (int i = 0; i < bandChannels.length; ++i) {
    188                 if (mChannels.contains(bandChannels[i].frequency)) {
    189                     return true;
    190                 }
    191             }
    192             return false;
    193         }
    194 
    195         @Override
    196         public boolean isEmpty() {
    197             return mChannels.isEmpty();
    198         }
    199 
    200         @Override
    201         public boolean isAllChannels() {
    202             return getAvailableScanChannels(WifiScanner.WIFI_BAND_BOTH_WITH_DFS).length ==
    203                     mChannels.size();
    204         }
    205 
    206         @Override
    207         public void clear() {
    208             mAllBands = 0;
    209             mExactBands = 0;
    210             mChannels.clear();
    211         }
    212 
    213         @Override
    214         public Set<Integer> getMissingChannelsFromBand(int band) {
    215             ArraySet<Integer> missingChannels = new ArraySet<>();
    216             WifiScanner.ChannelSpec[] bandChannels = getAvailableScanChannels(band);
    217             for (int i = 0; i < bandChannels.length; ++i) {
    218                 if (!mChannels.contains(bandChannels[i].frequency)) {
    219                     missingChannels.add(bandChannels[i].frequency);
    220                 }
    221             }
    222             return missingChannels;
    223         }
    224 
    225         @Override
    226         public Set<Integer> getContainingChannelsFromBand(int band) {
    227             ArraySet<Integer> containingChannels = new ArraySet<>();
    228             WifiScanner.ChannelSpec[] bandChannels = getAvailableScanChannels(band);
    229             for (int i = 0; i < bandChannels.length; ++i) {
    230                 if (mChannels.contains(bandChannels[i].frequency)) {
    231                     containingChannels.add(bandChannels[i].frequency);
    232                 }
    233             }
    234             return containingChannels;
    235         }
    236 
    237         @Override
    238         public Set<Integer> getChannelSet() {
    239             if (!isEmpty() && mAllBands != mExactBands) {
    240                 return mChannels;
    241             } else {
    242                 return new ArraySet<>();
    243             }
    244         }
    245 
    246         @Override
    247         public void fillBucketSettings(WifiNative.BucketSettings bucketSettings, int maxChannels) {
    248             if ((mChannels.size() > maxChannels || mAllBands == mExactBands)
    249                     && mAllBands != 0) {
    250                 bucketSettings.band = mAllBands;
    251                 bucketSettings.num_channels = 0;
    252                 bucketSettings.channels = null;
    253             } else {
    254                 bucketSettings.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
    255                 bucketSettings.num_channels = mChannels.size();
    256                 bucketSettings.channels = new WifiNative.ChannelSettings[mChannels.size()];
    257                 for (int i = 0; i < mChannels.size(); ++i) {
    258                     WifiNative.ChannelSettings channelSettings = new WifiNative.ChannelSettings();
    259                     channelSettings.frequency = mChannels.valueAt(i);
    260                     bucketSettings.channels[i] = channelSettings;
    261                 }
    262             }
    263         }
    264 
    265         @Override
    266         public Set<Integer> getScanFreqs() {
    267             if (mExactBands == WifiScanner.WIFI_BAND_BOTH_WITH_DFS) {
    268                 return null;
    269             } else {
    270                 return new ArraySet<Integer>(mChannels);
    271             }
    272         }
    273 
    274         public Set<Integer> getAllChannels() {
    275             return new ArraySet<Integer>(mChannels);
    276         }
    277     }
    278 
    279     @Override
    280 
    281     public KnownBandsChannelCollection createChannelCollection() {
    282         return new KnownBandsChannelCollection();
    283     }
    284 }
    285