KnownBandsChannelHelper.java revision 39175cc807488dd849e2c530f8be30dd674fbd9f
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;
20import android.util.ArraySet;
21
22import com.android.server.wifi.WifiNative;
23
24import 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 */
30public class KnownBandsChannelHelper extends ChannelHelper {
31
32    private static final WifiScanner.ChannelSpec[] NO_CHANNELS = new WifiScanner.ChannelSpec[0];
33
34    private WifiScanner.ChannelSpec[][] mBandsToChannels;
35
36    public KnownBandsChannelHelper(int[] channels2G, int[] channels5G, int[] channelsDfs) {
37        mBandsToChannels = new WifiScanner.ChannelSpec[8][];
38
39        mBandsToChannels[0] = NO_CHANNELS;
40
41        mBandsToChannels[1] = new WifiScanner.ChannelSpec[channels2G.length];
42        copyChannels(mBandsToChannels[1], 0, channels2G);
43
44        mBandsToChannels[2] = new WifiScanner.ChannelSpec[channels5G.length];
45        copyChannels(mBandsToChannels[2], 0, channels5G);
46
47        mBandsToChannels[3] = new WifiScanner.ChannelSpec[channels2G.length + channels5G.length];
48        copyChannels(mBandsToChannels[3], 0, channels2G);
49        copyChannels(mBandsToChannels[3], channels2G.length, channels5G);
50
51        mBandsToChannels[4] = new WifiScanner.ChannelSpec[channelsDfs.length];
52        copyChannels(mBandsToChannels[4], 0, channelsDfs);
53
54        mBandsToChannels[5] = new WifiScanner.ChannelSpec[channels2G.length + channelsDfs.length];
55        copyChannels(mBandsToChannels[5], 0, channels2G);
56        copyChannels(mBandsToChannels[5], channels2G.length, channelsDfs);
57
58        mBandsToChannels[6] = new WifiScanner.ChannelSpec[channels5G.length + channelsDfs.length];
59        copyChannels(mBandsToChannels[6], 0, channels5G);
60        copyChannels(mBandsToChannels[6], channels5G.length, channelsDfs);
61
62        mBandsToChannels[7] = new WifiScanner.ChannelSpec[
63                channels2G.length + channels5G.length + channelsDfs.length];
64        copyChannels(mBandsToChannels[7], 0, channels2G);
65        copyChannels(mBandsToChannels[7], channels2G.length, channels5G);
66        copyChannels(mBandsToChannels[7], channels2G.length + channels5G.length, channelsDfs);
67    }
68
69    private static void copyChannels(
70            WifiScanner.ChannelSpec[] channelSpec, int offset, int[] channels) {
71        for (int i = 0; i < channels.length; i++) {
72            channelSpec[offset + i] = new WifiScanner.ChannelSpec(channels[i]);
73        }
74    }
75
76    private WifiScanner.ChannelSpec[] getChannelsForBand(int band) {
77        if (band < WifiScanner.WIFI_BAND_24_GHZ || band > WifiScanner.WIFI_BAND_BOTH_WITH_DFS) {
78            // invalid value for band
79            return NO_CHANNELS;
80        } else {
81            return mBandsToChannels[band];
82        }
83    }
84
85    private boolean isDfsChannel(int frequency) {
86        for (WifiScanner.ChannelSpec dfsChannel :
87                mBandsToChannels[WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY]) {
88            if (frequency == dfsChannel.frequency) {
89                return true;
90            }
91        }
92        return false;
93    }
94
95    // TODO this should be rewritten to be based on the input data instead of hardcoded ranges
96    private int getBandFromChannel(int frequency) {
97        if (2400 <= frequency && frequency < 2500) {
98            return WifiScanner.WIFI_BAND_24_GHZ;
99        } else if (isDfsChannel(frequency)) {
100            return WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY;
101        } else if (5100 <= frequency && frequency < 6000) {
102            return WifiScanner.WIFI_BAND_5_GHZ;
103        } else {
104            return WifiScanner.WIFI_BAND_UNSPECIFIED;
105        }
106    }
107
108    @Override
109    public boolean settingsContainChannel(WifiScanner.ScanSettings settings, int channel) {
110        WifiScanner.ChannelSpec[] settingsChannels;
111        if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
112            settingsChannels = settings.channels;
113        } else {
114            settingsChannels = getChannelsForBand(settings.band);
115        }
116        for (int i = 0; i < settingsChannels.length; ++i) {
117            if (settingsChannels[i].frequency == channel) {
118                return true;
119            }
120        }
121        return false;
122    }
123
124    /**
125     * ChannelCollection that merges channels so that the optimal schedule will be generated.
126     * When the max channels value is satisfied this implementation will always create a channel
127     * list that includes no more than the added channels.
128     */
129    public class KnownBandsChannelCollection extends ChannelCollection {
130        /**
131         * Stores all channels, including those that belong to added bands.
132         */
133        private final ArraySet<Integer> mChannels = new ArraySet<Integer>();
134        /**
135         * Contains only the bands that were explicitly added as bands.
136         */
137        private int mExactBands = 0;
138        /**
139         * Contains all bands, including those that were added because an added channel was in that
140         * band.
141         */
142        private int mAllBands = 0;
143
144        @Override
145        public void addChannel(int frequency) {
146            mChannels.add(frequency);
147            mAllBands |= getBandFromChannel(frequency);
148        }
149
150        @Override
151        public void addBand(int band) {
152            mExactBands |= band;
153            mAllBands |= band;
154            WifiScanner.ChannelSpec[] bandChannels = getChannelsForBand(band);
155            for (int i = 0; i < bandChannels.length; ++i) {
156                mChannels.add(bandChannels[i].frequency);
157            }
158        }
159
160        @Override
161        public boolean containsChannel(int channel) {
162            return mChannels.contains(channel);
163        }
164
165        @Override
166        public boolean isEmpty() {
167            return mChannels.isEmpty();
168        }
169
170        @Override
171        public void clear() {
172            mAllBands = 0;
173            mExactBands = 0;
174            mChannels.clear();
175        }
176
177        @Override
178        public void fillBucketSettings(WifiNative.BucketSettings bucketSettings, int maxChannels) {
179            if ((mChannels.size() > maxChannels || mAllBands == mExactBands)
180                    && mAllBands != 0) {
181                bucketSettings.band = mAllBands;
182                bucketSettings.num_channels = 0;
183                bucketSettings.channels = null;
184            } else {
185                bucketSettings.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
186                bucketSettings.num_channels = mChannels.size();
187                bucketSettings.channels = new WifiNative.ChannelSettings[mChannels.size()];
188                for (int i = 0; i < mChannels.size(); ++i) {
189                    WifiNative.ChannelSettings channelSettings = new WifiNative.ChannelSettings();
190                    channelSettings.frequency = mChannels.valueAt(i);
191                    bucketSettings.channels[i] = channelSettings;
192                }
193            }
194        }
195
196        @Override
197        public Set<Integer> getSupplicantScanFreqs() {
198            if (mAllBands == mExactBands && mExactBands == WifiScanner.WIFI_BAND_BOTH_WITH_DFS) {
199                return null;
200            } else {
201                return new ArraySet<Integer>(mChannels);
202            }
203        }
204    }
205
206    @Override
207    public ChannelCollection createChannelCollection() {
208        return new KnownBandsChannelCollection();
209    }
210}
211