1 /*
2  * Copyright (C) 2021 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 package android.net.wifi;
17 
18 import android.annotation.FlaggedApi;
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import com.android.wifi.flags.Flags;
26 
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.util.Objects;
30 
31 /**
32  * Contains information about a Wifi channel and bitmask of Wifi operational modes allowed on that
33  * channel. Use {@link WifiManager#getAllowedChannels(int, int)} to retrieve the list of channels
34  * filtered by regulatory constraints. Use {@link WifiManager#getUsableChannels(int, int)} to
35  * retrieve the list of channels filtered by regulatory and dynamic constraints like concurrency and
36  * interference due to other radios.
37  */
38 public final class WifiAvailableChannel implements Parcelable {
39 
40     /**
41      * Wifi Infrastructure client (STA) operational mode.
42      */
43     public static final int OP_MODE_STA = 1 << 0;
44 
45     /**
46      * Wifi SoftAp (Mobile Hotspot) operational mode.
47      */
48     public static final int OP_MODE_SAP = 1 << 1;
49 
50     /**
51      * Wifi Direct client (CLI) operational mode.
52      */
53     public static final int OP_MODE_WIFI_DIRECT_CLI = 1 << 2;
54 
55     /**
56      * Wifi Direct Group Owner (GO) operational mode.
57      */
58     public static final int OP_MODE_WIFI_DIRECT_GO = 1 << 3;
59 
60     /**
61      * Wifi Aware (NAN) operational mode.
62      */
63     public static final int OP_MODE_WIFI_AWARE = 1 << 4;
64 
65     /**
66      * Wifi Tunneled Direct Link Setup (TDLS) operational mode.
67      */
68     public static final int OP_MODE_TDLS = 1 << 5;
69 
70     /**
71      * @hide
72      */
73     @Retention(RetentionPolicy.SOURCE)
74     @IntDef(flag = true, prefix = {"OP_MODE_"}, value = {
75             OP_MODE_STA,
76             OP_MODE_SAP,
77             OP_MODE_WIFI_DIRECT_CLI,
78             OP_MODE_WIFI_DIRECT_GO,
79             OP_MODE_WIFI_AWARE,
80             OP_MODE_TDLS,
81     })
82     public @interface OpMode {}
83 
84     /**
85      * Filter channel based on regulatory constraints.
86      * @hide
87      */
88     public static final int FILTER_REGULATORY = 0;
89 
90     /**
91      * Filter channel based on interference from cellular radio.
92      * @hide
93      */
94     public static final int FILTER_CELLULAR_COEXISTENCE = 1 << 0;
95 
96     /**
97      * Filter channel based on current concurrency state.
98      * @hide
99      */
100     public static final int FILTER_CONCURRENCY = 1 << 1;
101 
102     /**
103      * Filter channel for the Wi-Fi Aware instant communication mode.
104      * @hide
105      */
106     public static final int FILTER_NAN_INSTANT_MODE = 1 << 2;
107 
108     /**
109      * @hide
110      */
111     @Retention(RetentionPolicy.SOURCE)
112     @IntDef(flag = true, prefix = {"FILTER_"}, value = {
113             FILTER_REGULATORY,
114             FILTER_CELLULAR_COEXISTENCE,
115             FILTER_CONCURRENCY,
116             FILTER_NAN_INSTANT_MODE,
117     })
118     public @interface Filter {}
119 
120     /**
121      * Wifi channel frequency in MHz.
122      */
123     private int mFrequency;
124 
125     /**
126      * Bitwise OR of modes (OP_MODE_*) allowed on this channel.
127      */
128     private @OpMode int mOpModes;
129 
130     /**
131      * Wifi channel bandwidth.
132      */
133     private @WifiAnnotations.ChannelWidth int mChannelWidth;
134 
WifiAvailableChannel(int freq, @OpMode int opModes)135     public WifiAvailableChannel(int freq, @OpMode int opModes) {
136         this(freq, opModes, ScanResult.CHANNEL_WIDTH_20MHZ);
137     }
138 
139     /**
140      * @hide
141      */
WifiAvailableChannel(int freq, @OpMode int opModes, @WifiAnnotations.ChannelWidth int channelWidth)142     public WifiAvailableChannel(int freq, @OpMode int opModes,
143             @WifiAnnotations.ChannelWidth int channelWidth) {
144         mFrequency = freq;
145         mOpModes = opModes;
146         mChannelWidth = channelWidth;
147     }
148 
WifiAvailableChannel(@onNull Parcel in)149     private WifiAvailableChannel(@NonNull Parcel in) {
150         readFromParcel(in);
151     }
152 
readFromParcel(@onNull Parcel in)153     private void readFromParcel(@NonNull Parcel in) {
154         mFrequency = in.readInt();
155         mOpModes = in.readInt();
156         mChannelWidth = in.readInt();
157     }
158 
159     /**
160      * Get the channel frequency in MHz.
161      */
getFrequencyMhz()162     public int getFrequencyMhz() {
163         return mFrequency;
164     }
165 
166     /**
167      * Get the operational modes allowed on a channel.
168      */
getOperationalModes()169     public @OpMode int getOperationalModes() {
170         return mOpModes;
171     }
172 
173     /**
174      * Usable filter implies filter channels by regulatory constraints and
175      * other dynamic constraints like concurrency state and interference due
176      * to other radios like cellular.
177      * @hide
178      */
getUsableFilter()179     public static @Filter int getUsableFilter() {
180         return FILTER_REGULATORY
181                 | FILTER_CONCURRENCY
182                 | FILTER_CELLULAR_COEXISTENCE;
183     }
184 
185     /**
186      * Get the channel bandwidth, which indicates the amount of frequency spectrum allocated for
187      * data transmission within a channel.
188      *
189      * @return the bandwidth representation of the Wi-Fi channel from
190      * {@link ScanResult#CHANNEL_WIDTH_20MHZ}, {@link ScanResult#CHANNEL_WIDTH_40MHZ},
191      * {@link ScanResult#CHANNEL_WIDTH_80MHZ}, {@link ScanResult#CHANNEL_WIDTH_160MHZ},
192      * {@link ScanResult#CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link ScanResult#CHANNEL_WIDTH_320MHZ}.
193      */
194     @FlaggedApi(Flags.FLAG_GET_CHANNEL_WIDTH_API)
getChannelWidth()195     public @WifiAnnotations.ChannelWidth int getChannelWidth() {
196         return mChannelWidth;
197     }
198 
199     @Override
describeContents()200     public int describeContents() {
201         return 0;
202     }
203 
204     @Override
equals(@ullable Object o)205     public boolean equals(@Nullable Object o) {
206         if (this == o) return true;
207         if (o == null || getClass() != o.getClass()) return false;
208         WifiAvailableChannel that = (WifiAvailableChannel) o;
209         return mFrequency == that.mFrequency
210                 && mOpModes == that.mOpModes
211                 && mChannelWidth == that.mChannelWidth;
212     }
213 
214     @Override
hashCode()215     public int hashCode() {
216         return Objects.hash(mFrequency, mOpModes, mChannelWidth);
217     }
218 
219     @Override
toString()220     public String toString() {
221         StringBuilder sbuf = new StringBuilder();
222         sbuf.append("mFrequency = ")
223             .append(mFrequency)
224             .append(", mChannelWidth = ")
225             .append(mChannelWidth)
226             .append(", mOpModes = ")
227             .append(String.format("%x", mOpModes));
228         return sbuf.toString();
229     }
230 
231     @Override
writeToParcel(@onNull Parcel dest, int flags)232     public void writeToParcel(@NonNull Parcel dest, int flags) {
233         dest.writeInt(mFrequency);
234         dest.writeInt(mOpModes);
235         dest.writeInt(mChannelWidth);
236     }
237 
238     public static final @android.annotation.NonNull Creator<WifiAvailableChannel> CREATOR =
239             new Creator<WifiAvailableChannel>() {
240                 @Override
241                 public WifiAvailableChannel createFromParcel(@NonNull Parcel in) {
242                     return new WifiAvailableChannel(in);
243                 }
244 
245                 @Override
246                 public WifiAvailableChannel[] newArray(int size) {
247                     return new WifiAvailableChannel[size];
248                 }
249             };
250 }
251