ChannelHelper.java revision e6d8fa5fb50afdfc04922f7f87c2cac08db5bbec
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
17package com.android.server.wifi.scanner;
18
19import android.net.wifi.WifiScanner;
20
21import com.android.server.wifi.WifiNative;
22
23import java.util.Set;
24
25/**
26 * ChannelHelper offers an abstraction for channel manipulation utilities allowing operation to be
27 * adjusted based on the amount of information known about the available channels.
28 */
29public abstract class ChannelHelper {
30
31    // TODO: Currently this is simply an estimate and is used for both active and passive channels
32    //       scans. Eventually it should be split between passive and active and perhaps retrieved
33    //       from the driver.
34    /**
35     * The estimated period spent scanning each channel. This is used for estimating scan duration.
36     */
37    public static final int SCAN_PERIOD_PER_CHANNEL_MS = 200;
38
39    protected static final WifiScanner.ChannelSpec[] NO_CHANNELS = new WifiScanner.ChannelSpec[0];
40
41    /**
42     * Create a new collection that can be used to store channels
43     */
44    public abstract ChannelCollection createChannelCollection();
45
46    /**
47     * Return true if the specified channel is expected for a scan with the given settings
48     */
49    public abstract boolean settingsContainChannel(WifiScanner.ScanSettings settings, int channel);
50
51    /**
52     * Get the channels that are available for scanning on the supplied band.
53     * This method may return empty if the information is not available.
54     */
55    public abstract WifiScanner.ChannelSpec[] getAvailableScanChannels(int band);
56
57    /**
58     * Estimates the duration that the chip will spend scanning with the given settings
59     */
60    public abstract int estimateScanDuration(WifiScanner.ScanSettings settings);
61
62    /**
63     * Update the channel information that this object has. The source of the update is
64     * implementation dependent and may result in no change. Warning the behavior of a
65     * ChannelCollection created using {@link #createChannelCollection createChannelCollection} is
66     * undefined after calling this method until the {@link ChannelColleciton#clear() clear} method
67     * is called on it.
68     */
69    public void updateChannels() {
70        // default implementation does nothing
71    }
72
73    /**
74     * Object that supports accumulation of channels and bands
75     */
76    public abstract class ChannelCollection {
77        /**
78         * Add a channel to the collection
79         */
80        public abstract void addChannel(int channel);
81        /**
82         * Add all channels in the band to the collection
83         */
84        public abstract void addBand(int band);
85        /**
86         * @return true if the collection contains the supplied channel
87         */
88        public abstract boolean containsChannel(int channel);
89        /**
90         * @return true if the collection contains no channels
91         */
92        public abstract boolean isEmpty();
93        /**
94         * Remove all channels from the collection
95         */
96        public abstract void clear();
97
98        /**
99         * Add all channels in the ScanSetting to the collection
100         */
101        public void addChannels(WifiScanner.ScanSettings scanSettings) {
102            if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
103                for (int j = 0; j < scanSettings.channels.length; ++j) {
104                    addChannel(scanSettings.channels[j].frequency);
105                }
106            } else {
107                addBand(scanSettings.band);
108            }
109        }
110
111        /**
112         * Add all channels in the BucketSettings to the collection
113         */
114        public void addChannels(WifiNative.BucketSettings bucketSettings) {
115            if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
116                for (int j = 0; j < bucketSettings.channels.length; ++j) {
117                    addChannel(bucketSettings.channels[j].frequency);
118                }
119            } else {
120                addBand(bucketSettings.band);
121            }
122        }
123
124        /**
125         * Store the channels in this collection in the supplied BucketSettings. If maxChannels is
126         * exceeded or a band better describes the channels then a band is specified instead of a
127         * channel list.
128         */
129        public abstract void fillBucketSettings(WifiNative.BucketSettings bucket, int maxChannels);
130
131        /**
132         * Gets the list of channels that should be supplied to supplicant for a scan. Will either
133         * be a collection of all channels or null if all channels should be scanned.
134         */
135        public abstract Set<Integer> getSupplicantScanFreqs();
136    }
137
138
139    /*
140     * Utility methods for converting band/channels to strings
141     */
142
143    /**
144     * Create a string representation of the channels in the ScanSettings.
145     * If it contains a list of channels then the channels are returned, otherwise a string name of
146     * the band is returned.
147     */
148    public static String toString(WifiScanner.ScanSettings scanSettings) {
149        if (scanSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
150            return toString(scanSettings.channels);
151        } else {
152            return toString(scanSettings.band);
153        }
154    }
155
156    /**
157     * Create a string representation of the channels in the BucketSettings.
158     * If it contains a list of channels then the channels are returned, otherwise a string name of
159     * the band is returned.
160     */
161    public static String toString(WifiNative.BucketSettings bucketSettings) {
162        if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
163            return toString(bucketSettings.channels, bucketSettings.num_channels);
164        } else {
165            return toString(bucketSettings.band);
166        }
167    }
168
169    private static String toString(WifiScanner.ChannelSpec[] channels) {
170        if (channels == null) {
171            return "null";
172        }
173
174        StringBuilder sb = new StringBuilder();
175        sb.append("[");
176        for (int c = 0; c < channels.length; c++) {
177            sb.append(channels[c].frequency);
178            if (c != channels.length - 1) {
179                sb.append(",");
180            }
181        }
182        sb.append("]");
183        return sb.toString();
184    }
185
186    private static String toString(WifiNative.ChannelSettings[] channels, int numChannels) {
187        if (channels == null) {
188            return "null";
189        }
190
191        StringBuilder sb = new StringBuilder();
192        sb.append("[");
193        for (int c = 0; c < numChannels; c++) {
194            sb.append(channels[c].frequency);
195            if (c != numChannels - 1) {
196                sb.append(",");
197            }
198        }
199        sb.append("]");
200        return sb.toString();
201    }
202
203    private static String toString(int band) {
204        switch (band) {
205            case WifiScanner.WIFI_BAND_UNSPECIFIED:
206                return "unspecified";
207            case WifiScanner.WIFI_BAND_24_GHZ:
208                return "24Ghz";
209            case WifiScanner.WIFI_BAND_5_GHZ:
210                return "5Ghz (no DFS)";
211            case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
212                return "5Ghz (DFS only)";
213            case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS:
214                return "5Ghz (DFS incl)";
215            case WifiScanner.WIFI_BAND_BOTH:
216                return "24Ghz & 5Ghz (no DFS)";
217            case WifiScanner.WIFI_BAND_BOTH_WITH_DFS:
218                return "24Ghz & 5Ghz (DFS incl)";
219        }
220
221        return "invalid band";
222    }
223}
224