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 not
28 * known. Operations performed may simplify any band to include all channels.
29 */
30public class NoBandChannelHelper extends ChannelHelper {
31
32    /**
33     * These parameters are used to estimate the scan duration.
34     * This is a guess at the number of channels the device supports for use when a ScanSettings
35     * specifies a band instead of a list of channels.
36     */
37    private static final int ALL_BAND_CHANNEL_COUNT_ESTIMATE = 36;
38
39    @Override
40    public boolean settingsContainChannel(WifiScanner.ScanSettings settings, int channel) {
41        if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
42            for (int i = 0; i < settings.channels.length; ++i) {
43                if (settings.channels[i].frequency == channel) {
44                    return true;
45                }
46            }
47            return false;
48        } else {
49            return true;
50        }
51    }
52
53    @Override
54    public WifiScanner.ChannelSpec[] getAvailableScanChannels(int band) {
55        return NO_CHANNELS; // not supported
56    }
57
58    @Override
59    public int estimateScanDuration(WifiScanner.ScanSettings settings) {
60        if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
61            return settings.channels.length * SCAN_PERIOD_PER_CHANNEL_MS;
62        } else {
63            return ALL_BAND_CHANNEL_COUNT_ESTIMATE * SCAN_PERIOD_PER_CHANNEL_MS;
64        }
65    }
66
67    /**
68     * ChannelCollection that merges channels without knowing which channels are in each band. In
69     * order to do this if any band is added or the maxChannels is exceeded then all channels will
70     * be included.
71     */
72    public class NoBandChannelCollection extends ChannelCollection {
73        private final ArraySet<Integer> mChannels = new ArraySet<Integer>();
74        private boolean mAllChannels = false;
75
76        @Override
77        public void addChannel(int frequency) {
78            mChannels.add(frequency);
79        }
80
81        @Override
82        public void addBand(int band) {
83            if (band != WifiScanner.WIFI_BAND_UNSPECIFIED) {
84                mAllChannels = true;
85            }
86        }
87
88        @Override
89        public boolean containsChannel(int channel) {
90            return mAllChannels || mChannels.contains(channel);
91        }
92
93        @Override
94        public boolean containsBand(int band) {
95            if (band != WifiScanner.WIFI_BAND_UNSPECIFIED) {
96                return mAllChannels;
97            }
98            return false;
99        }
100
101        @Override
102        public boolean partiallyContainsBand(int band) {
103            // We don't need to partially collapse settings in wificond scanner because we
104            // don't have any limitation on the number of channels that can be scanned. We also
105            // don't currently keep track of bands very well in NoBandChannelHelper.
106            return false;
107        }
108
109        @Override
110        public boolean isEmpty() {
111            return !mAllChannels && mChannels.isEmpty();
112        }
113
114        @Override
115        public boolean isAllChannels() {
116            return mAllChannels;
117        }
118
119        @Override
120        public void clear() {
121            mAllChannels = false;
122            mChannels.clear();
123        }
124
125        @Override
126        public Set<Integer> getMissingChannelsFromBand(int band) {
127            // We don't need to partially collapse settings in wificond scanner because we
128            // don't have any limitation on the number of channels that can be scanned. We also
129            // don't currently keep track of bands very well in NoBandChannelHelper.
130            return new ArraySet<Integer>();
131        }
132
133        @Override
134        public Set<Integer> getContainingChannelsFromBand(int band) {
135            // We don't need to partially collapse settings in wificond scanner because we
136            // don't have any limitation on the number of channels that can be scanned. We also
137            // don't currently keep track of bands very well in NoBandChannelHelper.
138            return new ArraySet<Integer>();
139        }
140
141        @Override
142        public Set<Integer> getChannelSet() {
143            if (!isEmpty() && !mAllChannels) {
144                return mChannels;
145            } else {
146                return new ArraySet<>();
147            }
148        }
149
150        @Override
151        public void fillBucketSettings(WifiNative.BucketSettings bucketSettings, int maxChannels) {
152            if (mAllChannels || mChannels.size() > maxChannels) {
153                bucketSettings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
154                bucketSettings.num_channels = 0;
155                bucketSettings.channels = null;
156            } else {
157                bucketSettings.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
158                bucketSettings.num_channels = mChannels.size();
159                bucketSettings.channels = new WifiNative.ChannelSettings[mChannels.size()];
160                for (int i = 0; i < mChannels.size(); ++i) {
161                    WifiNative.ChannelSettings channelSettings = new WifiNative.ChannelSettings();
162                    channelSettings.frequency = mChannels.valueAt(i);
163                    bucketSettings.channels[i] = channelSettings;
164                }
165            }
166        }
167
168        @Override
169        public Set<Integer> getScanFreqs() {
170            if (mAllChannels) {
171                return null;
172            } else {
173                return new ArraySet<Integer>(mChannels);
174            }
175        }
176    }
177
178    @Override
179    public ChannelCollection createChannelCollection() {
180        return new NoBandChannelCollection();
181    }
182}
183