1 /*
2  * Copyright (C) 2020 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 android.net.wifi.nl80211;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.net.wifi.ScanResult;
22 import android.net.wifi.WifiAnnotations.ChannelWidth;
23 import android.net.wifi.WifiAnnotations.WifiStandard;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.util.Log;
27 
28 import java.util.Objects;
29 
30 /**
31  * DeviceWiphyCapabilities for wificond
32  *
33  * Contains the WiFi physical layer attributes and capabilities of the device.
34  * It is used to collect these attributes from the device driver via wificond.
35  *
36  * @hide
37  */
38 @SystemApi
39 public final class DeviceWiphyCapabilities implements Parcelable {
40     private static final String TAG = "DeviceWiphyCapabilities";
41 
42     private boolean m80211nSupported;
43     private boolean m80211acSupported;
44     private boolean m80211axSupported;
45     private boolean m80211beSupported;
46     private boolean mChannelWidth160MhzSupported;
47     private boolean mChannelWidth80p80MhzSupported;
48     private boolean mChannelWidth320MhzSupported;
49     private int mMaxNumberTxSpatialStreams;
50     private int mMaxNumberRxSpatialStreams;
51 
52 
53     /** public constructor */
DeviceWiphyCapabilities()54     public DeviceWiphyCapabilities() {
55         m80211nSupported = false;
56         m80211acSupported = false;
57         m80211axSupported = false;
58         m80211beSupported = false;
59         mChannelWidth160MhzSupported = false;
60         mChannelWidth80p80MhzSupported = false;
61         mChannelWidth320MhzSupported = false;
62         mMaxNumberTxSpatialStreams = 1;
63         mMaxNumberRxSpatialStreams = 1;
64     }
65 
66     /**
67      * Get the IEEE 802.11 standard support
68      *
69      * @param standard the IEEE 802.11 standard to check on its support.
70      *        valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
71      * @return {@code true} if supported, {@code false} otherwise.
72      */
isWifiStandardSupported(@ifiStandard int standard)73     public boolean isWifiStandardSupported(@WifiStandard int standard) {
74         switch (standard) {
75             case ScanResult.WIFI_STANDARD_LEGACY:
76                 return true;
77             case ScanResult.WIFI_STANDARD_11N:
78                 return m80211nSupported;
79             case ScanResult.WIFI_STANDARD_11AC:
80                 return m80211acSupported;
81             case ScanResult.WIFI_STANDARD_11AX:
82                 return m80211axSupported;
83             case ScanResult.WIFI_STANDARD_11BE:
84                 return m80211beSupported;
85             default:
86                 Log.e(TAG, "isWifiStandardSupported called with invalid standard: " + standard);
87                 return false;
88         }
89     }
90 
91     /**
92      * Set the IEEE 802.11 standard support
93      *
94      * @param standard the IEEE 802.11 standard to set its support.
95      *        valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
96      * @param support {@code true} if supported, {@code false} otherwise.
97      */
setWifiStandardSupport(@ifiStandard int standard, boolean support)98     public void setWifiStandardSupport(@WifiStandard int standard, boolean support) {
99         switch (standard) {
100             case ScanResult.WIFI_STANDARD_11N:
101                 m80211nSupported = support;
102                 break;
103             case ScanResult.WIFI_STANDARD_11AC:
104                 m80211acSupported = support;
105                 break;
106             case ScanResult.WIFI_STANDARD_11AX:
107                 m80211axSupported = support;
108                 break;
109             case ScanResult.WIFI_STANDARD_11BE:
110                 m80211beSupported = support;
111                 break;
112             default:
113                 Log.e(TAG, "setWifiStandardSupport called with invalid standard: " + standard);
114         }
115     }
116 
117     /**
118      * Get the support for channel bandwidth
119      *
120      * @param chWidth valid values from {@link ScanResult}'s {@code CHANNEL_WIDTH_}
121      *
122      * @return {@code true} if supported, {@code false} otherwise.
123      */
isChannelWidthSupported(@hannelWidth int chWidth)124     public boolean isChannelWidthSupported(@ChannelWidth int chWidth) {
125         switch (chWidth) {
126             case ScanResult.CHANNEL_WIDTH_20MHZ:
127                 return true;
128             case ScanResult.CHANNEL_WIDTH_40MHZ:
129                 return (m80211nSupported || m80211acSupported || m80211axSupported
130                     || m80211beSupported);
131             case ScanResult.CHANNEL_WIDTH_80MHZ:
132                 return (m80211acSupported || m80211axSupported || m80211beSupported);
133             case ScanResult.CHANNEL_WIDTH_160MHZ:
134                 return mChannelWidth160MhzSupported;
135             case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
136                 return mChannelWidth80p80MhzSupported;
137             case ScanResult.CHANNEL_WIDTH_320MHZ:
138                 return mChannelWidth320MhzSupported;
139             default:
140                 Log.e(TAG, "isChannelWidthSupported called with invalid channel width: " + chWidth);
141         }
142         return false;
143     }
144 
145     /**
146      * Set support for channel bandwidth
147      *
148      * @param chWidth valid values are {@link ScanResult#CHANNEL_WIDTH_160MHZ},
149      *        {@link ScanResult#CHANNEL_WIDTH_80MHZ_PLUS_MHZ} and
150      *        {@link ScanResult#CHANNEL_WIDTH_320MHZ}
151      * @param support {@code true} if supported, {@code false} otherwise.
152      *
153      * @hide
154      */
setChannelWidthSupported(@hannelWidth int chWidth, boolean support)155     public void setChannelWidthSupported(@ChannelWidth int chWidth, boolean support) {
156         switch (chWidth) {
157             case ScanResult.CHANNEL_WIDTH_160MHZ:
158                 mChannelWidth160MhzSupported = support;
159                 break;
160             case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
161                 mChannelWidth80p80MhzSupported = support;
162                 break;
163             case ScanResult.CHANNEL_WIDTH_320MHZ:
164                 mChannelWidth320MhzSupported = support;
165                 break;
166             default:
167                 Log.e(TAG, "setChannelWidthSupported called with Invalid channel width: "
168                         + chWidth);
169         }
170     }
171 
172     /**
173      * Get maximum number of transmit spatial streams
174      *
175      * @return number of spatial streams
176      */
getMaxNumberTxSpatialStreams()177     public int getMaxNumberTxSpatialStreams() {
178         return mMaxNumberTxSpatialStreams;
179     }
180 
181     /**
182      * Set maximum number of transmit spatial streams
183      *
184      * @param streams number of spatial streams
185      *
186      * @hide
187      */
setMaxNumberTxSpatialStreams(int streams)188     public void setMaxNumberTxSpatialStreams(int streams) {
189         mMaxNumberTxSpatialStreams = streams;
190     }
191 
192     /**
193      * Get maximum number of receive spatial streams
194      *
195      * @return number of streams
196      */
getMaxNumberRxSpatialStreams()197     public int getMaxNumberRxSpatialStreams() {
198         return mMaxNumberRxSpatialStreams;
199     }
200 
201     /**
202      * Set maximum number of receive spatial streams
203      *
204      * @param streams number of streams
205      *
206      * @hide
207      */
setMaxNumberRxSpatialStreams(int streams)208     public void setMaxNumberRxSpatialStreams(int streams) {
209         mMaxNumberRxSpatialStreams = streams;
210     }
211 
212     /** override comparator */
213     @Override
equals(Object rhs)214     public boolean equals(Object rhs) {
215         if (this == rhs) return true;
216         if (!(rhs instanceof DeviceWiphyCapabilities)) {
217             return false;
218         }
219         DeviceWiphyCapabilities capa = (DeviceWiphyCapabilities) rhs;
220 
221         return m80211nSupported == capa.m80211nSupported
222                 && m80211acSupported == capa.m80211acSupported
223                 && m80211axSupported == capa.m80211axSupported
224                 && m80211beSupported == capa.m80211beSupported
225                 && mChannelWidth160MhzSupported == capa.mChannelWidth160MhzSupported
226                 && mChannelWidth80p80MhzSupported == capa.mChannelWidth80p80MhzSupported
227                 && mChannelWidth320MhzSupported == capa.mChannelWidth320MhzSupported
228                 && mMaxNumberTxSpatialStreams == capa.mMaxNumberTxSpatialStreams
229                 && mMaxNumberRxSpatialStreams == capa.mMaxNumberRxSpatialStreams;
230     }
231 
232     /** override hash code */
233     @Override
hashCode()234     public int hashCode() {
235         return Objects.hash(m80211nSupported, m80211acSupported, m80211axSupported,
236                 m80211beSupported, mChannelWidth160MhzSupported, mChannelWidth80p80MhzSupported,
237                 mChannelWidth320MhzSupported, mMaxNumberTxSpatialStreams,
238                 mMaxNumberRxSpatialStreams);
239     }
240 
241     /** implement Parcelable interface */
242     @Override
describeContents()243     public int describeContents() {
244         return 0;
245     }
246 
247     /**
248      * implement Parcelable interface
249      * |flags| is ignored.
250      */
251     @Override
writeToParcel(@onNull Parcel out, int flags)252     public void writeToParcel(@NonNull Parcel out, int flags) {
253         out.writeBoolean(m80211nSupported);
254         out.writeBoolean(m80211acSupported);
255         out.writeBoolean(m80211axSupported);
256         out.writeBoolean(m80211beSupported);
257         out.writeBoolean(mChannelWidth160MhzSupported);
258         out.writeBoolean(mChannelWidth80p80MhzSupported);
259         out.writeBoolean(mChannelWidth320MhzSupported);
260         out.writeInt(mMaxNumberTxSpatialStreams);
261         out.writeInt(mMaxNumberRxSpatialStreams);
262     }
263 
264     @Override
toString()265     public String toString() {
266         StringBuilder sb = new StringBuilder();
267         sb.append("m80211nSupported:").append(m80211nSupported ? "Yes" : "No");
268         sb.append("m80211acSupported:").append(m80211acSupported ? "Yes" : "No");
269         sb.append("m80211axSupported:").append(m80211axSupported ? "Yes" : "No");
270         sb.append("m80211beSupported:").append(m80211beSupported ? "Yes" : "No");
271         sb.append("mChannelWidth160MhzSupported: ")
272                 .append(mChannelWidth160MhzSupported ? "Yes" : "No");
273         sb.append("mChannelWidth80p80MhzSupported: ")
274                 .append(mChannelWidth80p80MhzSupported ? "Yes" : "No");
275         sb.append("mChannelWidth320MhzSupported: ")
276                 .append(mChannelWidth320MhzSupported ? "Yes" : "No");
277         sb.append("mMaxNumberTxSpatialStreams: ").append(mMaxNumberTxSpatialStreams);
278         sb.append("mMaxNumberRxSpatialStreams: ").append(mMaxNumberRxSpatialStreams);
279 
280         return sb.toString();
281     }
282 
283     /** implement Parcelable interface */
284     public static final @NonNull Parcelable.Creator<DeviceWiphyCapabilities> CREATOR =
285             new Parcelable.Creator<DeviceWiphyCapabilities>() {
286         /**
287          * Caller is responsible for providing a valid parcel.
288          */
289         @Override
290         public DeviceWiphyCapabilities createFromParcel(Parcel in) {
291             DeviceWiphyCapabilities capabilities = new DeviceWiphyCapabilities();
292             capabilities.m80211nSupported = in.readBoolean();
293             capabilities.m80211acSupported = in.readBoolean();
294             capabilities.m80211axSupported = in.readBoolean();
295             capabilities.m80211beSupported = in.readBoolean();
296             capabilities.mChannelWidth160MhzSupported = in.readBoolean();
297             capabilities.mChannelWidth80p80MhzSupported = in.readBoolean();
298             capabilities.mChannelWidth320MhzSupported = in.readBoolean();
299             capabilities.mMaxNumberTxSpatialStreams = in.readInt();
300             capabilities.mMaxNumberRxSpatialStreams = in.readInt();
301             return capabilities;
302         }
303 
304         @Override
305         public DeviceWiphyCapabilities[] newArray(int size) {
306             return new DeviceWiphyCapabilities[size];
307         }
308     };
309 }
310