• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
createChannelCollection()45     public abstract ChannelCollection createChannelCollection();
46 
47     /**
48      * Return true if the specified channel is expected for a scan with the given settings
49      */
settingsContainChannel(WifiScanner.ScanSettings settings, int channel)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      */
getAvailableScanChannels(int band)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      */
estimateScanDuration(WifiScanner.ScanSettings settings)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      */
updateChannels()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          */
addChannel(int channel)81         public abstract void addChannel(int channel);
82         /**
83          * Add all channels in the band to the collection
84          */
addBand(int band)85         public abstract void addBand(int band);
86         /**
87          * @return true if the collection contains the supplied channel
88          */
containsChannel(int channel)89         public abstract boolean containsChannel(int channel);
90         /**
91          * @return true if the collection contains all the channels of the supplied band
92          */
containsBand(int band)93         public abstract boolean containsBand(int band);
94         /**
95          * @return true if the collection contains some of the channels of the supplied band
96          */
partiallyContainsBand(int band)97         public abstract boolean partiallyContainsBand(int band);
98         /**
99          * @return true if the collection contains no channels
100          */
isEmpty()101         public abstract boolean isEmpty();
102         /**
103          * Remove all channels from the collection
104          */
clear()105         public abstract void clear();
106         /**
107          * Retrieves a list of channels from the band which are missing in the channel collection.
108          */
getMissingChannelsFromBand(int band)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          */
getContainingChannelsFromBand(int band)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          */
getChannelSet()118         public abstract Set<Integer> getChannelSet();
119 
120         /**
121          * Add all channels in the ScanSetting to the collection
122          */
addChannels(WifiScanner.ScanSettings scanSettings)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          */
addChannels(WifiNative.BucketSettings bucketSettings)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          */
containsSettings(WifiScanner.ScanSettings scanSettings)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          */
partiallyContainsSettings(WifiScanner.ScanSettings scanSettings)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          */
getMissingChannelsFromSettings(WifiScanner.ScanSettings scanSettings)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          */
getContainingChannelsFromSettings( WifiScanner.ScanSettings scanSettings)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          */
fillBucketSettings(WifiNative.BucketSettings bucket, int maxChannels)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          */
getSupplicantScanFreqs()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      */
toString(WifiScanner.ScanSettings scanSettings)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      */
toString(WifiNative.BucketSettings bucketSettings)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 
toString(WifiScanner.ChannelSpec[] channels)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 
toString(WifiNative.ChannelSettings[] channels, int numChannels)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 
toString(int band)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