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