1 /*
2  * Copyright (C) 2019 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;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.net.MacAddress;
24 import android.os.Build;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import androidx.annotation.RequiresApi;
29 
30 import com.android.internal.util.Preconditions;
31 import com.android.modules.utils.build.SdkLevel;
32 import com.android.wifi.flags.Flags;
33 
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.List;
37 import java.util.Objects;
38 
39 /**
40  * A class representing information about a specific SoftAP instance. A SoftAP instance may be a
41  * single band AP or a bridged AP (across multiple bands). To get the state of the AP interface
42  * itself, use {@link android.net.wifi.WifiManager.SoftApCallback#onStateChanged(SoftApState)}.
43  * {@see WifiManager}
44  *
45  * @hide
46  */
47 @SystemApi
48 public final class SoftApInfo implements Parcelable {
49 
50     /**
51      * AP Channel bandwidth is automatically selected by the chip.
52      *
53      * @see #getBandwidth()
54      */
55     public static final int CHANNEL_WIDTH_AUTO = -1;
56 
57    /**
58      * AP Channel bandwidth is invalid.
59      *
60      * @see #getBandwidth()
61      */
62     public static final int CHANNEL_WIDTH_INVALID = 0;
63 
64     /**
65      * AP Channel bandwidth is 20 MHZ but no HT.
66      *
67      * @see #getBandwidth()
68      */
69     public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1;
70 
71     /**
72      * AP Channel bandwidth is 20 MHZ.
73      *
74      * @see #getBandwidth()
75      */
76     public static final int CHANNEL_WIDTH_20MHZ = 2;
77 
78     /**
79      * AP Channel bandwidth is 40 MHZ.
80      *
81      * @see #getBandwidth()
82      */
83     public static final int CHANNEL_WIDTH_40MHZ = 3;
84 
85     /**
86      * AP Channel bandwidth is 80 MHZ.
87      *
88      * @see #getBandwidth()
89      */
90     public static final int CHANNEL_WIDTH_80MHZ = 4;
91 
92     /**
93      * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ.
94      *
95      * @see #getBandwidth()
96      */
97     public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5;
98 
99     /**
100      * AP Channel bandwidth is 160 MHZ.
101      *
102      * @see #getBandwidth()
103      */
104     public static final int CHANNEL_WIDTH_160MHZ = 6;
105 
106     /**
107      * AP Channel bandwidth is 2160 MHZ.
108      *
109      * @see #getBandwidth()
110      */
111     public static final int CHANNEL_WIDTH_2160MHZ = 7;
112 
113     /**
114      * AP Channel bandwidth is 4320 MHZ.
115      *
116      * @see #getBandwidth()
117      */
118     public static final int CHANNEL_WIDTH_4320MHZ = 8;
119 
120     /**
121      * AP Channel bandwidth is 6480 MHZ.
122      *
123      * @see #getBandwidth()
124      */
125     public static final int CHANNEL_WIDTH_6480MHZ = 9;
126 
127     /**
128      * AP Channel bandwidth is 8640 MHZ.
129      *
130      * @see #getBandwidth()
131      */
132     public static final int CHANNEL_WIDTH_8640MHZ = 10;
133 
134     /**
135      * AP Channel bandwidth is 320 MHZ.
136      *
137      * @see #getBandwidth()
138      */
139     public static final int CHANNEL_WIDTH_320MHZ = 11;
140 
141 
142     /** The frequency which AP resides on.  */
143     private int mFrequency = 0;
144 
145     @WifiAnnotations.Bandwidth
146     private int mBandwidth = CHANNEL_WIDTH_INVALID;
147 
148     /** The MAC Address which AP resides on. */
149     @Nullable
150     private MacAddress mBssid;
151 
152     /** The identifier of the AP instance which AP resides on with current info. */
153     @Nullable
154     private String mApInstanceIdentifier;
155 
156     /**
157      * The operational mode of the AP.
158      */
159     private @WifiAnnotations.WifiStandard int mWifiStandard = ScanResult.WIFI_STANDARD_UNKNOWN;
160 
161     /**
162      * The current shutdown timeout millis which applied on Soft AP.
163      */
164     private long mIdleShutdownTimeoutMillis;
165 
166     /** List of {@link OuiKeyedData} containing vendor-specific configuration data. */
167     private List<OuiKeyedData> mVendorData = Collections.emptyList();
168 
169     /**
170      * Get the frequency which AP resides on.
171      */
getFrequency()172     public int getFrequency() {
173         return mFrequency;
174     }
175 
176     /**
177      * Set the frequency which AP resides on.
178      * @hide
179      */
setFrequency(int freq)180     public void setFrequency(int freq) {
181         mFrequency = freq;
182     }
183 
184     /**
185      * Get AP Channel bandwidth.
186      *
187      * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
188      * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ},
189      * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, {@link #CHANNEL_WIDTH_320MHZ},
190      * {@link #CHANNEL_WIDTH_2160MHZ}, {@link #CHANNEL_WIDTH_4320MHZ},
191      * {@link #CHANNEL_WIDTH_6480MHZ}, {@link #CHANNEL_WIDTH_8640MHZ},
192      * {@link #CHANNEL_WIDTH_AUTO} ,or {@link #CHANNEL_WIDTH_INVALID}.
193      */
194     @WifiAnnotations.Bandwidth
getBandwidth()195     public int getBandwidth() {
196         return mBandwidth;
197     }
198 
199     /**
200      * Set AP Channel bandwidth.
201      * @hide
202      */
setBandwidth(@ifiAnnotations.Bandwidth int bandwidth)203     public void setBandwidth(@WifiAnnotations.Bandwidth int bandwidth) {
204         mBandwidth = bandwidth;
205     }
206 
207     /**
208      * Get the MAC address (BSSID) of the AP. Null when AP disabled.
209      */
210     @RequiresApi(Build.VERSION_CODES.S)
211     @Nullable
getBssid()212     public MacAddress getBssid() {
213         if (!SdkLevel.isAtLeastS()) {
214             throw new UnsupportedOperationException();
215         }
216         return getBssidInternal();
217     }
218 
219     /**
220      * @hide
221      */
222     @Nullable
getBssidInternal()223     public MacAddress getBssidInternal() {
224         return mBssid;
225     }
226 
227     /**
228       * Set the MAC address which AP resides on.
229       * <p>
230       * <li>If not set, defaults to null.</li>
231       * @param bssid BSSID, The caller is responsible for avoiding collisions.
232       * @throws IllegalArgumentException when the given BSSID is the all-zero or broadcast MAC
233       *                                  address.
234       *
235       * @hide
236       */
setBssid(@ullable MacAddress bssid)237     public void setBssid(@Nullable MacAddress bssid) {
238         if (bssid != null) {
239             Preconditions.checkArgument(!bssid.equals(WifiManager.ALL_ZEROS_MAC_ADDRESS));
240             Preconditions.checkArgument(!bssid.equals(MacAddress.BROADCAST_ADDRESS));
241         }
242         mBssid = bssid;
243     }
244 
245     /**
246      * Set the operational mode of the AP.
247      *
248      * @param wifiStandard values from {@link ScanResult}'s {@code WIFI_STANDARD_}
249      * @hide
250      */
setWifiStandard(@ifiAnnotations.WifiStandard int wifiStandard)251     public void setWifiStandard(@WifiAnnotations.WifiStandard int wifiStandard) {
252         mWifiStandard = wifiStandard;
253     }
254 
255     /**
256      * Get the operational mode of the AP.
257      * @return valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
258      */
259     @RequiresApi(Build.VERSION_CODES.S)
getWifiStandard()260     public @WifiAnnotations.WifiStandard int getWifiStandard() {
261         if (!SdkLevel.isAtLeastS()) {
262             throw new UnsupportedOperationException();
263         }
264         return getWifiStandardInternal();
265     }
266 
267     /**
268      * @hide
269      */
getWifiStandardInternal()270     public @WifiAnnotations.WifiStandard int getWifiStandardInternal() {
271         return mWifiStandard;
272     }
273 
274     /**
275      * Set the AP instance identifier.
276      * @hide
277      */
setApInstanceIdentifier(@onNull String apInstanceIdentifier)278     public void setApInstanceIdentifier(@NonNull String apInstanceIdentifier) {
279         mApInstanceIdentifier = apInstanceIdentifier;
280     }
281 
282     /**
283      * Get the AP instance identifier.
284      *
285      * The AP instance identifier is a unique identity which can be used to
286      * associate the {@link SoftApInfo} to a specific {@link WifiClient}
287      * - see {@link WifiClient#getApInstanceIdentifier()}
288      *
289      * @hide
290      */
291     @Nullable
getApInstanceIdentifier()292     public String getApInstanceIdentifier() {
293         return mApInstanceIdentifier;
294     }
295 
296 
297     /**
298      * Set current shutdown timeout millis which applied on Soft AP.
299      * @hide
300      */
setAutoShutdownTimeoutMillis(long idleShutdownTimeoutMillis)301     public void setAutoShutdownTimeoutMillis(long idleShutdownTimeoutMillis) {
302         mIdleShutdownTimeoutMillis = idleShutdownTimeoutMillis;
303     }
304 
305     /**
306      * Get auto shutdown timeout in millis.
307      *
308      * The shutdown timeout value is configured by
309      * {@link SoftApConfiguration.Builder#setAutoShutdownEnabled(int)} or
310      * the default timeout setting defined in device overlays.
311      *
312      * A value of 0 means that auto shutdown is disabled.
313      * {@see SoftApConfiguration#isAutoShutdownEnabled()}
314      */
getAutoShutdownTimeoutMillis()315     public long getAutoShutdownTimeoutMillis() {
316         return mIdleShutdownTimeoutMillis;
317     }
318 
319     /**
320      * Set additional vendor-provided configuration data.
321      *
322      * @param vendorData List of {@link android.net.wifi.OuiKeyedData} containing the
323      *                   vendor-provided configuration data. Note that multiple elements with
324      *                   the same OUI are allowed.
325      * @hide
326      */
327     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
328     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
329     @SystemApi
setVendorData(@onNull List<OuiKeyedData> vendorData)330     public void setVendorData(@NonNull List<OuiKeyedData> vendorData) {
331         if (!SdkLevel.isAtLeastV()) {
332             throw new UnsupportedOperationException();
333         }
334         if (vendorData == null) {
335             throw new IllegalArgumentException("setVendorData received a null value");
336         }
337         mVendorData = new ArrayList<>(vendorData);
338     }
339 
340     /**
341      * Get the vendor-provided configuration data, if it exists.
342      *
343      * @return Vendor configuration data, or empty list if it does not exist.
344      * @hide
345      */
346     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
347     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
348     @SystemApi
349     @NonNull
getVendorData()350     public List<OuiKeyedData> getVendorData() {
351         if (!SdkLevel.isAtLeastV()) {
352             throw new UnsupportedOperationException();
353         }
354         return mVendorData;
355     }
356 
357     /**
358      * @hide
359      */
SoftApInfo(@ullable SoftApInfo source)360     public SoftApInfo(@Nullable SoftApInfo source) {
361         if (source != null) {
362             mFrequency = source.mFrequency;
363             mBandwidth = source.mBandwidth;
364             mBssid = source.mBssid;
365             mWifiStandard = source.mWifiStandard;
366             mApInstanceIdentifier = source.mApInstanceIdentifier;
367             mIdleShutdownTimeoutMillis = source.mIdleShutdownTimeoutMillis;
368             mVendorData = new ArrayList<>(source.mVendorData);
369         }
370     }
371 
372     /**
373      * @hide
374      */
SoftApInfo()375     public SoftApInfo() {
376     }
377 
378     @Override
379     /** Implement the Parcelable interface. */
describeContents()380     public int describeContents() {
381         return 0;
382     }
383 
384     @Override
385     /** Implement the Parcelable interface */
writeToParcel(@onNull Parcel dest, int flags)386     public void writeToParcel(@NonNull Parcel dest, int flags) {
387         dest.writeInt(mFrequency);
388         dest.writeInt(mBandwidth);
389         dest.writeParcelable(mBssid, flags);
390         dest.writeInt(mWifiStandard);
391         dest.writeString(mApInstanceIdentifier);
392         dest.writeLong(mIdleShutdownTimeoutMillis);
393         dest.writeList(mVendorData);
394     }
395 
396     @NonNull
397     /** Implement the Parcelable interface */
398     public static final Creator<SoftApInfo> CREATOR = new Creator<SoftApInfo>() {
399         public SoftApInfo createFromParcel(Parcel in) {
400             SoftApInfo info = new SoftApInfo();
401             info.mFrequency = in.readInt();
402             info.mBandwidth = in.readInt();
403             info.mBssid = in.readParcelable(MacAddress.class.getClassLoader());
404             info.mWifiStandard = in.readInt();
405             info.mApInstanceIdentifier = in.readString();
406             info.mIdleShutdownTimeoutMillis = in.readLong();
407             info.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
408             return info;
409         }
410 
411         public SoftApInfo[] newArray(int size) {
412             return new SoftApInfo[size];
413         }
414     };
415 
416     @NonNull
417     @Override
toString()418     public String toString() {
419         StringBuilder sbuf = new StringBuilder();
420         sbuf.append("SoftApInfo{");
421         sbuf.append("bandwidth= ").append(mBandwidth);
422         sbuf.append(", frequency= ").append(mFrequency);
423         if (mBssid != null) sbuf.append(",bssid=").append(mBssid.toString());
424         sbuf.append(", wifiStandard= ").append(mWifiStandard);
425         sbuf.append(", mApInstanceIdentifier= ").append(mApInstanceIdentifier);
426         sbuf.append(", mIdleShutdownTimeoutMillis= ").append(mIdleShutdownTimeoutMillis);
427         sbuf.append(", mVendorData= ").append(mVendorData);
428         sbuf.append("}");
429         return sbuf.toString();
430     }
431 
432     @Override
equals(@ullable Object o)433     public boolean equals(@Nullable Object o) {
434         if (this == o) return true;
435         if (!(o instanceof SoftApInfo)) return false;
436         SoftApInfo softApInfo = (SoftApInfo) o;
437         return mFrequency == softApInfo.mFrequency
438                 && mBandwidth == softApInfo.mBandwidth
439                 && Objects.equals(mBssid, softApInfo.mBssid)
440                 && mWifiStandard == softApInfo.mWifiStandard
441                 && Objects.equals(mApInstanceIdentifier, softApInfo.mApInstanceIdentifier)
442                 && mIdleShutdownTimeoutMillis == softApInfo.mIdleShutdownTimeoutMillis
443                 && Objects.equals(mVendorData, softApInfo.mVendorData);
444     }
445 
446     @Override
hashCode()447     public int hashCode() {
448         return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard, mApInstanceIdentifier,
449                 mIdleShutdownTimeoutMillis, mVendorData);
450     }
451 }
452