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 setBandChannels(int[] channels2G, int[] channels5G, int[] channelsDfs)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 copyChannels( WifiScanner.ChannelSpec[] channelSpec, int offset, int[] channels)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 getAvailableScanChannels(int band)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 estimateScanDuration(WifiScanner.ScanSettings settings)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 isDfsChannel(int frequency)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 getBandFromChannel(int frequency)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 settingsContainChannel(WifiScanner.ScanSettings settings, int channel)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 addChannel(int frequency)153 public void addChannel(int frequency) { 154 mChannels.add(frequency); 155 mAllBands |= getBandFromChannel(frequency); 156 } 157 158 @Override addBand(int band)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 containsChannel(int channel)169 public boolean containsChannel(int channel) { 170 return mChannels.contains(channel); 171 } 172 173 @Override containsBand(int band)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 partiallyContainsBand(int band)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 isEmpty()196 public boolean isEmpty() { 197 return mChannels.isEmpty(); 198 } 199 200 @Override isAllChannels()201 public boolean isAllChannels() { 202 return getAvailableScanChannels(WifiScanner.WIFI_BAND_BOTH_WITH_DFS).length == 203 mChannels.size(); 204 } 205 206 @Override clear()207 public void clear() { 208 mAllBands = 0; 209 mExactBands = 0; 210 mChannels.clear(); 211 } 212 213 @Override getMissingChannelsFromBand(int band)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 getContainingChannelsFromBand(int band)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 getChannelSet()238 public Set<Integer> getChannelSet() { 239 if (!isEmpty() && mAllBands != mExactBands) { 240 return mChannels; 241 } else { 242 return new ArraySet<>(); 243 } 244 } 245 246 @Override fillBucketSettings(WifiNative.BucketSettings bucketSettings, int maxChannels)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 getScanFreqs()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 getAllChannels()274 public Set<Integer> getAllChannels() { 275 return new ArraySet<Integer>(mChannels); 276 } 277 } 278 279 @Override 280 createChannelCollection()281 public KnownBandsChannelCollection createChannelCollection() { 282 return new KnownBandsChannelCollection(); 283 } 284 } 285