1 /*
2  * Copyright (C) 2008 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.IntRange;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.compat.annotation.UnsupportedAppUsage;
24 import android.net.NetworkInfo.DetailedState;
25 import android.os.Build;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 import android.text.TextUtils;
29 
30 import com.android.net.module.util.Inet4AddressUtils;
31 
32 import java.net.Inet4Address;
33 import java.net.InetAddress;
34 import java.net.UnknownHostException;
35 import java.util.EnumMap;
36 import java.util.Locale;
37 
38 /**
39  * Describes the state of any Wi-Fi connection that is active or
40  * is in the process of being set up.
41  */
42 public class WifiInfo implements Parcelable {
43     private static final String TAG = "WifiInfo";
44     /**
45      * This is the map described in the Javadoc comment above. The positions
46      * of the elements of the array must correspond to the ordinal values
47      * of <code>DetailedState</code>.
48      */
49     private static final EnumMap<SupplicantState, DetailedState> stateMap =
50             new EnumMap<SupplicantState, DetailedState>(SupplicantState.class);
51 
52     /**
53      * Default MAC address reported to a client that does not have the
54      * android.permission.LOCAL_MAC_ADDRESS permission.
55      *
56      * @hide
57      */
58     @SystemApi
59     public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
60 
61     static {
stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED)62         stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED)63         stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE)64         stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING)65         stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING)66         stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING)67         stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING)68         stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING)69         stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING)70         stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR)71         stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR);
stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED)72         stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE)73         stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE);
stateMap.put(SupplicantState.INVALID, DetailedState.FAILED)74         stateMap.put(SupplicantState.INVALID, DetailedState.FAILED);
75     }
76 
77     private SupplicantState mSupplicantState;
78     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
79     private String mBSSID;
80     @UnsupportedAppUsage
81     private WifiSsid mWifiSsid;
82     private int mNetworkId;
83 
84     /**
85      * Used to indicate that the RSSI is invalid, for example if no RSSI measurements are available
86      * yet.
87      * @hide
88      */
89     @SystemApi
90     public static final int INVALID_RSSI = -127;
91 
92     /** @hide **/
93     public static final int MIN_RSSI = -126;
94 
95     /** @hide **/
96     public static final int MAX_RSSI = 200;
97 
98 
99     /**
100      * Received Signal Strength Indicator
101      */
102     private int mRssi;
103 
104     /**
105      * Wi-Fi standard for the connection
106      */
107     private @WifiAnnotations.WifiStandard int mWifiStandard;
108 
109     /**
110      * The unit in which links speeds are expressed.
111      */
112     public static final String LINK_SPEED_UNITS = "Mbps";
113     private int mLinkSpeed;
114 
115     /**
116      * Constant for unknown link speed.
117      */
118     public static final int LINK_SPEED_UNKNOWN = -1;
119 
120     /**
121      * Tx(transmit) Link speed in Mbps
122      */
123     private int mTxLinkSpeed;
124 
125     /**
126      * Max supported Tx(transmit) link speed in Mbps
127      */
128     private int mMaxSupportedTxLinkSpeed;
129 
130     /**
131      * Rx(receive) Link speed in Mbps
132      */
133     private int mRxLinkSpeed;
134 
135     /**
136      * Max supported Rx(receive) link speed in Mbps
137      */
138     private int mMaxSupportedRxLinkSpeed;
139 
140     /**
141      * Frequency in MHz
142      */
143     public static final String FREQUENCY_UNITS = "MHz";
144     private int mFrequency;
145 
146     @UnsupportedAppUsage
147     private InetAddress mIpAddress;
148     @UnsupportedAppUsage
149     private String mMacAddress = DEFAULT_MAC_ADDRESS;
150 
151     /**
152      * Whether the network is ephemeral or not.
153      */
154     private boolean mEphemeral;
155 
156     /**
157      * Whether the network is trusted or not.
158      */
159     private boolean mTrusted;
160 
161     /**
162      * OSU (Online Sign Up) AP for Passpoint R2.
163      */
164     private boolean mOsuAp;
165 
166     /**
167      * Fully qualified domain name of a Passpoint configuration
168      */
169     private String mFqdn;
170 
171     /**
172      * Name of Passpoint credential provider
173      */
174     private String mProviderFriendlyName;
175 
176     /**
177      * If connected to a network suggestion or specifier, store the package name of the app,
178      * else null.
179      */
180     private String mRequestingPackageName;
181 
182     /**
183      * Running total count of lost (not ACKed) transmitted unicast data packets.
184      * @hide
185      */
186     public long txBad;
187     /**
188      * Running total count of transmitted unicast data retry packets.
189      * @hide
190      */
191     public long txRetries;
192     /**
193      * Running total count of successfully transmitted (ACKed) unicast data packets.
194      * @hide
195      */
196     public long txSuccess;
197     /**
198      * Running total count of received unicast data packets.
199      * @hide
200      */
201     public long rxSuccess;
202 
203     private double mLostTxPacketsPerSecond;
204 
205     /**
206      * Average rate of lost transmitted packets, in units of packets per second.
207      * @hide
208      */
209     @SystemApi
getLostTxPacketsPerSecond()210     public double getLostTxPacketsPerSecond() {
211         return mLostTxPacketsPerSecond;
212     }
213 
214     /** @hide */
setLostTxPacketsPerSecond(double lostTxPacketsPerSecond)215     public void setLostTxPacketsPerSecond(double lostTxPacketsPerSecond) {
216         mLostTxPacketsPerSecond = lostTxPacketsPerSecond;
217     }
218 
219     private double mTxRetriedTxPacketsPerSecond;
220 
221     /**
222      * Average rate of transmitted retry packets, in units of packets per second.
223      * @hide
224      */
225     @SystemApi
getRetriedTxPacketsPerSecond()226     public double getRetriedTxPacketsPerSecond() {
227         return mTxRetriedTxPacketsPerSecond;
228     }
229 
230     /** @hide */
setRetriedTxPacketsRate(double txRetriedTxPacketsPerSecond)231     public void setRetriedTxPacketsRate(double txRetriedTxPacketsPerSecond) {
232         mTxRetriedTxPacketsPerSecond = txRetriedTxPacketsPerSecond;
233     }
234 
235     private double mSuccessfulTxPacketsPerSecond;
236 
237     /**
238      * Average rate of successfully transmitted unicast packets, in units of packets per second.
239      * @hide
240      */
241     @SystemApi
getSuccessfulTxPacketsPerSecond()242     public double getSuccessfulTxPacketsPerSecond() {
243         return mSuccessfulTxPacketsPerSecond;
244     }
245 
246     /** @hide */
setSuccessfulTxPacketsPerSecond(double successfulTxPacketsPerSecond)247     public void setSuccessfulTxPacketsPerSecond(double successfulTxPacketsPerSecond) {
248         mSuccessfulTxPacketsPerSecond = successfulTxPacketsPerSecond;
249     }
250 
251     private double mSuccessfulRxPacketsPerSecond;
252 
253     /**
254      * Average rate of received unicast data packets, in units of packets per second.
255      * @hide
256      */
257     @SystemApi
getSuccessfulRxPacketsPerSecond()258     public double getSuccessfulRxPacketsPerSecond() {
259         return mSuccessfulRxPacketsPerSecond;
260     }
261 
262     /** @hide */
setSuccessfulRxPacketsPerSecond(double successfulRxPacketsPerSecond)263     public void setSuccessfulRxPacketsPerSecond(double successfulRxPacketsPerSecond) {
264         mSuccessfulRxPacketsPerSecond = successfulRxPacketsPerSecond;
265     }
266 
267     /** @hide */
268     @UnsupportedAppUsage
269     public int score;
270 
271     /**
272      * The current Wifi score.
273      * NOTE: this value should only be used for debugging purposes. Do not rely on this value for
274      * any computations. The meaning of this value can and will change at any time without warning.
275      * @hide
276      */
277     @SystemApi
getScore()278     public int getScore() {
279         return score;
280     }
281 
282     /** @hide */
setScore(int score)283     public void setScore(int score) {
284         this.score = score;
285     }
286 
287     /**
288      * Flag indicating that AP has hinted that upstream connection is metered,
289      * and sensitive to heavy data transfers.
290      */
291     private boolean mMeteredHint;
292 
293     /**
294      * Passpoint unique key
295      */
296     private String mPasspointUniqueId;
297 
298     /** @hide */
299     @UnsupportedAppUsage
WifiInfo()300     public WifiInfo() {
301         mWifiSsid = null;
302         mBSSID = null;
303         mNetworkId = -1;
304         mSupplicantState = SupplicantState.UNINITIALIZED;
305         mRssi = INVALID_RSSI;
306         mLinkSpeed = LINK_SPEED_UNKNOWN;
307         mFrequency = -1;
308     }
309 
310     /** @hide */
reset()311     public void reset() {
312         setInetAddress(null);
313         setBSSID(null);
314         setSSID(null);
315         setNetworkId(-1);
316         setRssi(INVALID_RSSI);
317         setLinkSpeed(LINK_SPEED_UNKNOWN);
318         setTxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
319         setRxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
320         setMaxSupportedTxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
321         setMaxSupportedRxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
322         setFrequency(-1);
323         setMeteredHint(false);
324         setEphemeral(false);
325         setOsuAp(false);
326         setRequestingPackageName(null);
327         setFQDN(null);
328         setProviderFriendlyName(null);
329         setPasspointUniqueId(null);
330         txBad = 0;
331         txSuccess = 0;
332         rxSuccess = 0;
333         txRetries = 0;
334         mLostTxPacketsPerSecond = 0;
335         mSuccessfulTxPacketsPerSecond = 0;
336         mSuccessfulRxPacketsPerSecond = 0;
337         mTxRetriedTxPacketsPerSecond = 0;
338         score = 0;
339     }
340 
341     /**
342      * Copy constructor
343      * @hide
344      */
WifiInfo(WifiInfo source)345     public WifiInfo(WifiInfo source) {
346         if (source != null) {
347             mSupplicantState = source.mSupplicantState;
348             mBSSID = source.mBSSID;
349             mWifiSsid = source.mWifiSsid;
350             mNetworkId = source.mNetworkId;
351             mRssi = source.mRssi;
352             mLinkSpeed = source.mLinkSpeed;
353             mTxLinkSpeed = source.mTxLinkSpeed;
354             mRxLinkSpeed = source.mRxLinkSpeed;
355             mFrequency = source.mFrequency;
356             mIpAddress = source.mIpAddress;
357             mMacAddress = source.mMacAddress;
358             mMeteredHint = source.mMeteredHint;
359             mEphemeral = source.mEphemeral;
360             mTrusted = source.mTrusted;
361             mRequestingPackageName =
362                     source.mRequestingPackageName;
363             mOsuAp = source.mOsuAp;
364             mFqdn = source.mFqdn;
365             mProviderFriendlyName = source.mProviderFriendlyName;
366             txBad = source.txBad;
367             txRetries = source.txRetries;
368             txSuccess = source.txSuccess;
369             rxSuccess = source.rxSuccess;
370             mLostTxPacketsPerSecond = source.mLostTxPacketsPerSecond;
371             mTxRetriedTxPacketsPerSecond = source.mTxRetriedTxPacketsPerSecond;
372             mSuccessfulTxPacketsPerSecond = source.mSuccessfulTxPacketsPerSecond;
373             mSuccessfulRxPacketsPerSecond = source.mSuccessfulRxPacketsPerSecond;
374             score = source.score;
375             mWifiStandard = source.mWifiStandard;
376             mMaxSupportedTxLinkSpeed = source.mMaxSupportedTxLinkSpeed;
377             mMaxSupportedRxLinkSpeed = source.mMaxSupportedRxLinkSpeed;
378             mPasspointUniqueId = source.mPasspointUniqueId;
379         }
380     }
381 
382     /** Builder for WifiInfo */
383     public static final class Builder {
384         private final WifiInfo mWifiInfo = new WifiInfo();
385 
386         /**
387          * Set the SSID, in the form of a raw byte array.
388          * @see WifiInfo#getSSID()
389          */
390         @NonNull
setSsid(@onNull byte[] ssid)391         public Builder setSsid(@NonNull byte[] ssid) {
392             mWifiInfo.setSSID(WifiSsid.createFromByteArray(ssid));
393             return this;
394         }
395 
396         /**
397          * Set the BSSID.
398          * @see WifiInfo#getBSSID()
399          */
400         @NonNull
setBssid(@onNull String bssid)401         public Builder setBssid(@NonNull String bssid) {
402             mWifiInfo.setBSSID(bssid);
403             return this;
404         }
405 
406         /**
407          * Set the RSSI, in dBm.
408          * @see WifiInfo#getRssi()
409          */
410         @NonNull
setRssi(int rssi)411         public Builder setRssi(int rssi) {
412             mWifiInfo.setRssi(rssi);
413             return this;
414         }
415 
416         /**
417          * Set the network ID.
418          * @see WifiInfo#getNetworkId()
419          */
420         @NonNull
setNetworkId(int networkId)421         public Builder setNetworkId(int networkId) {
422             mWifiInfo.setNetworkId(networkId);
423             return this;
424         }
425 
426         /**
427          * Build a WifiInfo object.
428          */
429         @NonNull
build()430         public WifiInfo build() {
431             return new WifiInfo(mWifiInfo);
432         }
433     }
434 
435     /** @hide */
setSSID(WifiSsid wifiSsid)436     public void setSSID(WifiSsid wifiSsid) {
437         mWifiSsid = wifiSsid;
438     }
439 
440     /**
441      * Returns the service set identifier (SSID) of the current 802.11 network.
442      * <p>
443      * If the SSID can be decoded as UTF-8, it will be returned surrounded by double
444      * quotation marks. Otherwise, it is returned as a string of hex digits.
445      * The SSID may be {@link WifiManager#UNKNOWN_SSID}, if there is no network currently connected
446      * or if the caller has insufficient permissions to access the SSID.
447      * </p>
448      * <p>
449      * Prior to {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method
450      * always returned the SSID with no quotes around it.
451      * </p>
452      *
453      * @return the SSID.
454      */
getSSID()455     public String getSSID() {
456         if (mWifiSsid != null) {
457             String unicode = mWifiSsid.toString();
458             if (!TextUtils.isEmpty(unicode)) {
459                 return "\"" + unicode + "\"";
460             } else {
461                 String hex = mWifiSsid.getHexString();
462                 return (hex != null) ? hex : WifiManager.UNKNOWN_SSID;
463             }
464         }
465         return WifiManager.UNKNOWN_SSID;
466     }
467 
468     /** @hide */
469     @UnsupportedAppUsage
getWifiSsid()470     public WifiSsid getWifiSsid() {
471         return mWifiSsid;
472     }
473 
474     /** @hide */
475     @UnsupportedAppUsage
setBSSID(String BSSID)476     public void setBSSID(String BSSID) {
477         mBSSID = BSSID;
478     }
479 
480     /**
481      * Return the basic service set identifier (BSSID) of the current access point.
482      * <p>
483      * The BSSID may be
484      * <lt>{@code null}, if there is no network currently connected.</lt>
485      * <lt>{@code "02:00:00:00:00:00"}, if the caller has insufficient permissions to access the
486      * BSSID.<lt>
487      * </p>
488      *
489      * @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}
490      */
getBSSID()491     public String getBSSID() {
492         return mBSSID;
493     }
494 
495     /**
496      * Returns the received signal strength indicator of the current 802.11
497      * network, in dBm.
498      *
499      * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
500      * an absolute signal level which can be displayed to a user.
501      *
502      * @return the RSSI.
503      */
getRssi()504     public int getRssi() {
505         return mRssi;
506     }
507 
508     /** @hide */
509     @UnsupportedAppUsage
setRssi(int rssi)510     public void setRssi(int rssi) {
511         if (rssi < INVALID_RSSI)
512             rssi = INVALID_RSSI;
513         if (rssi > MAX_RSSI)
514             rssi = MAX_RSSI;
515         mRssi = rssi;
516     }
517 
518     /**
519      * Sets the Wi-Fi standard
520      * @hide
521      */
setWifiStandard(@ifiAnnotations.WifiStandard int wifiStandard)522     public void setWifiStandard(@WifiAnnotations.WifiStandard int wifiStandard) {
523         mWifiStandard = wifiStandard;
524     }
525 
526     /**
527      * Get connection Wi-Fi standard
528      * @return the connection Wi-Fi standard
529      */
getWifiStandard()530     public @WifiAnnotations.WifiStandard int getWifiStandard() {
531         return mWifiStandard;
532     }
533 
534     /**
535      * Returns the current link speed in {@link #LINK_SPEED_UNITS}.
536      * @return the link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
537      * @see #LINK_SPEED_UNITS
538      * @see #LINK_SPEED_UNKNOWN
539      */
getLinkSpeed()540     public int getLinkSpeed() {
541         return mLinkSpeed;
542     }
543 
544     /** @hide */
545     @UnsupportedAppUsage
setLinkSpeed(int linkSpeed)546     public void setLinkSpeed(int linkSpeed) {
547         mLinkSpeed = linkSpeed;
548     }
549 
550     /**
551      * Returns the current transmit link speed in Mbps.
552      * @return the Tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
553      * @see #LINK_SPEED_UNKNOWN
554      */
555     @IntRange(from = -1)
getTxLinkSpeedMbps()556     public int getTxLinkSpeedMbps() {
557         return mTxLinkSpeed;
558     }
559 
560     /**
561      * Returns the maximum supported transmit link speed in Mbps
562      * @return the max supported tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is
563      * unknown. @see #LINK_SPEED_UNKNOWN
564      */
getMaxSupportedTxLinkSpeedMbps()565     public int getMaxSupportedTxLinkSpeedMbps() {
566         return mMaxSupportedTxLinkSpeed;
567     }
568 
569     /**
570      * Update the last transmitted packet bit rate in Mbps.
571      * @hide
572      */
setTxLinkSpeedMbps(int txLinkSpeed)573     public void setTxLinkSpeedMbps(int txLinkSpeed) {
574         mTxLinkSpeed = txLinkSpeed;
575     }
576 
577     /**
578      * Set the maximum supported transmit link speed in Mbps
579      * @hide
580      */
setMaxSupportedTxLinkSpeedMbps(int maxSupportedTxLinkSpeed)581     public void setMaxSupportedTxLinkSpeedMbps(int maxSupportedTxLinkSpeed) {
582         mMaxSupportedTxLinkSpeed = maxSupportedTxLinkSpeed;
583     }
584 
585     /**
586      * Returns the current receive link speed in Mbps.
587      * @return the Rx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
588      * @see #LINK_SPEED_UNKNOWN
589      */
590     @IntRange(from = -1)
getRxLinkSpeedMbps()591     public int getRxLinkSpeedMbps() {
592         return mRxLinkSpeed;
593     }
594 
595     /**
596      * Returns the maximum supported receive link speed in Mbps
597      * @return the max supported Rx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is
598      * unknown. @see #LINK_SPEED_UNKNOWN
599      */
getMaxSupportedRxLinkSpeedMbps()600     public int getMaxSupportedRxLinkSpeedMbps() {
601         return mMaxSupportedRxLinkSpeed;
602     }
603 
604     /**
605      * Update the last received packet bit rate in Mbps.
606      * @hide
607      */
setRxLinkSpeedMbps(int rxLinkSpeed)608     public void setRxLinkSpeedMbps(int rxLinkSpeed) {
609         mRxLinkSpeed = rxLinkSpeed;
610     }
611 
612     /**
613      * Set the maximum supported receive link speed in Mbps
614      * @hide
615      */
setMaxSupportedRxLinkSpeedMbps(int maxSupportedRxLinkSpeed)616     public void setMaxSupportedRxLinkSpeedMbps(int maxSupportedRxLinkSpeed) {
617         mMaxSupportedRxLinkSpeed = maxSupportedRxLinkSpeed;
618     }
619 
620     /**
621      * Returns the current frequency in {@link #FREQUENCY_UNITS}.
622      * @return the frequency.
623      * @see #FREQUENCY_UNITS
624      */
getFrequency()625     public int getFrequency() {
626         return mFrequency;
627     }
628 
629     /** @hide */
setFrequency(int frequency)630     public void setFrequency(int frequency) {
631         this.mFrequency = frequency;
632     }
633 
634     /**
635      * @hide
636      */
is24GHz()637     public boolean is24GHz() {
638         return ScanResult.is24GHz(mFrequency);
639     }
640 
641     /**
642      * @hide
643      */
644     @UnsupportedAppUsage
is5GHz()645     public boolean is5GHz() {
646         return ScanResult.is5GHz(mFrequency);
647     }
648 
649     /**
650      * @hide
651      */
is6GHz()652     public boolean is6GHz() {
653         return ScanResult.is6GHz(mFrequency);
654     }
655 
656     /**
657      * Record the MAC address of the WLAN interface
658      * @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
659      * @hide
660      */
661     @UnsupportedAppUsage
setMacAddress(String macAddress)662     public void setMacAddress(String macAddress) {
663         this.mMacAddress = macAddress;
664     }
665 
getMacAddress()666     public String getMacAddress() {
667         return mMacAddress;
668     }
669 
670     /**
671      * @return true if {@link #getMacAddress()} has a real MAC address.
672      *
673      * @hide
674      */
hasRealMacAddress()675     public boolean hasRealMacAddress() {
676         return mMacAddress != null && !DEFAULT_MAC_ADDRESS.equals(mMacAddress);
677     }
678 
679     /**
680      * Indicates if we've dynamically detected this active network connection as
681      * being metered.
682      *
683      * @see WifiConfiguration#isMetered(WifiConfiguration, WifiInfo)
684      * @hide
685      */
setMeteredHint(boolean meteredHint)686     public void setMeteredHint(boolean meteredHint) {
687         mMeteredHint = meteredHint;
688     }
689 
690     /** {@hide} */
691     @UnsupportedAppUsage
getMeteredHint()692     public boolean getMeteredHint() {
693         return mMeteredHint;
694     }
695 
696     /** {@hide} */
setEphemeral(boolean ephemeral)697     public void setEphemeral(boolean ephemeral) {
698         mEphemeral = ephemeral;
699     }
700 
701     /**
702      * Returns true if the current Wifi network is ephemeral, false otherwise.
703      * An ephemeral network is a network that is temporary and not persisted in the system.
704      * Ephemeral networks cannot be forgotten, only disabled with
705      * {@link WifiManager#disableEphemeralNetwork(String)}.
706      *
707      * @hide
708      */
709     @SystemApi
isEphemeral()710     public boolean isEphemeral() {
711         return mEphemeral;
712     }
713 
714     /** {@hide} */
setTrusted(boolean trusted)715     public void setTrusted(boolean trusted) {
716         mTrusted = trusted;
717     }
718 
719     /** {@hide} */
isTrusted()720     public boolean isTrusted() {
721         return mTrusted;
722     }
723 
724     /** {@hide} */
setOsuAp(boolean osuAp)725     public void setOsuAp(boolean osuAp) {
726         mOsuAp = osuAp;
727     }
728 
729     /** {@hide} */
730     @SystemApi
isOsuAp()731     public boolean isOsuAp() {
732         return mOsuAp;
733     }
734 
735     /** {@hide} */
736     @SystemApi
isPasspointAp()737     public boolean isPasspointAp() {
738         return mFqdn != null && mProviderFriendlyName != null;
739     }
740 
741     /** {@hide} */
setFQDN(@ullable String fqdn)742     public void setFQDN(@Nullable String fqdn) {
743         mFqdn = fqdn;
744     }
745 
746     /**
747      * Returns the Fully Qualified Domain Name of the network if it is a Passpoint network.
748      * <p>
749      * The FQDN may be
750      * <lt>{@code null} if no network currently connected, currently connected network is not
751      * passpoint network or the caller has insufficient permissions to access the FQDN.</lt>
752      * </p>
753      */
getPasspointFqdn()754     public @Nullable String getPasspointFqdn() {
755         return mFqdn;
756     }
757 
758     /** {@hide} */
setProviderFriendlyName(@ullable String providerFriendlyName)759     public void setProviderFriendlyName(@Nullable String providerFriendlyName) {
760         mProviderFriendlyName = providerFriendlyName;
761     }
762 
763     /**
764      * Returns the Provider Friendly Name of the network if it is a Passpoint network.
765      * <p>
766      * The Provider Friendly Name may be
767      * <lt>{@code null} if no network currently connected, currently connected network is not
768      * passpoint network or the caller has insufficient permissions to access the Provider Friendly
769      * Name. </lt>
770      * </p>
771      */
getPasspointProviderFriendlyName()772     public @Nullable String getPasspointProviderFriendlyName() {
773         return mProviderFriendlyName;
774     }
775 
776     /** {@hide} */
setRequestingPackageName(@ullable String packageName)777     public void setRequestingPackageName(@Nullable String packageName) {
778         mRequestingPackageName = packageName;
779     }
780 
781     /**
782      * If this network was created in response to an app request (e.g. through Network Suggestion
783      * or Network Specifier), return the package name of the app that made the request.
784      * Null otherwise.
785      * @hide
786      */
787     @SystemApi
getRequestingPackageName()788     public @Nullable String getRequestingPackageName() {
789         return mRequestingPackageName;
790     }
791 
792 
793     /** @hide */
794     @UnsupportedAppUsage
setNetworkId(int id)795     public void setNetworkId(int id) {
796         mNetworkId = id;
797     }
798 
799     /**
800      * Each configured network has a unique small integer ID, used to identify
801      * the network. This method returns the ID for the currently connected network.
802      * <p>
803      * The networkId may be {@code -1} if there is no currently connected network or if the caller
804      * has insufficient permissions to access the network ID.
805      * </p>
806      *
807      * @return the network ID.
808      */
getNetworkId()809     public int getNetworkId() {
810         return mNetworkId;
811     }
812 
813     /**
814      * Return the detailed state of the supplicant's negotiation with an
815      * access point, in the form of a {@link SupplicantState SupplicantState} object.
816      * @return the current {@link SupplicantState SupplicantState}
817      */
getSupplicantState()818     public SupplicantState getSupplicantState() {
819         return mSupplicantState;
820     }
821 
822     /** @hide */
823     @UnsupportedAppUsage
setSupplicantState(SupplicantState state)824     public void setSupplicantState(SupplicantState state) {
825         mSupplicantState = state;
826     }
827 
828     /** @hide */
setInetAddress(InetAddress address)829     public void setInetAddress(InetAddress address) {
830         mIpAddress = address;
831     }
832 
getIpAddress()833     public int getIpAddress() {
834         int result = 0;
835         if (mIpAddress instanceof Inet4Address) {
836             result = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) mIpAddress);
837         }
838         return result;
839     }
840 
841     /**
842      * @return {@code true} if this network does not broadcast its SSID, so an
843      * SSID-specific probe request must be used for scans.
844      */
getHiddenSSID()845     public boolean getHiddenSSID() {
846         if (mWifiSsid == null) return false;
847         return mWifiSsid.isHidden();
848     }
849 
850     /**
851      * Map a supplicant state into a fine-grained network connectivity state.
852      * @param suppState the supplicant state
853      * @return the corresponding {@link DetailedState}
854      */
getDetailedStateOf(SupplicantState suppState)855     public static DetailedState getDetailedStateOf(SupplicantState suppState) {
856         return stateMap.get(suppState);
857     }
858 
859     /**
860      * Set the <code>SupplicantState</code> from the string name
861      * of the state.
862      * @param stateName the name of the state, as a <code>String</code> returned
863      * in an event sent by {@code wpa_supplicant}.
864      */
865     @UnsupportedAppUsage
setSupplicantState(String stateName)866     void setSupplicantState(String stateName) {
867         mSupplicantState = valueOf(stateName);
868     }
869 
valueOf(String stateName)870     static SupplicantState valueOf(String stateName) {
871         if ("4WAY_HANDSHAKE".equalsIgnoreCase(stateName))
872             return SupplicantState.FOUR_WAY_HANDSHAKE;
873         else {
874             try {
875                 return SupplicantState.valueOf(stateName.toUpperCase(Locale.ROOT));
876             } catch (IllegalArgumentException e) {
877                 return SupplicantState.INVALID;
878             }
879         }
880     }
881 
882     /**
883      * Remove double quotes (") surrounding a SSID string, if present. Otherwise, return the
884      * string unmodified. Return null if the input string was null.
885      * @hide
886      */
887     @Nullable
888     @SystemApi
sanitizeSsid(@ullable String string)889     public static String sanitizeSsid(@Nullable String string) {
890         return removeDoubleQuotes(string);
891     }
892 
893     /** @hide */
894     @UnsupportedAppUsage
895     @Nullable
removeDoubleQuotes(@ullable String string)896     public static String removeDoubleQuotes(@Nullable String string) {
897         if (string == null) return null;
898         final int length = string.length();
899         if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
900             return string.substring(1, length - 1);
901         }
902         return string;
903     }
904 
905     @Override
toString()906     public String toString() {
907         StringBuffer sb = new StringBuffer();
908         String none = "<none>";
909 
910         sb.append("SSID: ").append(mWifiSsid == null ? WifiManager.UNKNOWN_SSID : mWifiSsid)
911                 .append(", BSSID: ").append(mBSSID == null ? none : mBSSID)
912                 .append(", MAC: ").append(mMacAddress == null ? none : mMacAddress)
913                 .append(", Supplicant state: ")
914                 .append(mSupplicantState == null ? none : mSupplicantState)
915                 .append(", Wi-Fi standard: ").append(mWifiStandard)
916                 .append(", RSSI: ").append(mRssi)
917                 .append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS)
918                 .append(", Tx Link speed: ").append(mTxLinkSpeed).append(LINK_SPEED_UNITS)
919                 .append(", Max Supported Tx Link speed: ")
920                 .append(mMaxSupportedTxLinkSpeed).append(LINK_SPEED_UNITS)
921                 .append(", Rx Link speed: ").append(mRxLinkSpeed).append(LINK_SPEED_UNITS)
922                 .append(", Max Supported Rx Link speed: ")
923                 .append(mMaxSupportedRxLinkSpeed).append(LINK_SPEED_UNITS)
924                 .append(", Frequency: ").append(mFrequency).append(FREQUENCY_UNITS)
925                 .append(", Net ID: ").append(mNetworkId)
926                 .append(", Metered hint: ").append(mMeteredHint)
927                 .append(", score: ").append(Integer.toString(score));
928         return sb.toString();
929     }
930 
931     /** Implement the Parcelable interface {@hide} */
describeContents()932     public int describeContents() {
933         return 0;
934     }
935 
936     /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)937     public void writeToParcel(Parcel dest, int flags) {
938         dest.writeInt(mNetworkId);
939         dest.writeInt(mRssi);
940         dest.writeInt(mLinkSpeed);
941         dest.writeInt(mTxLinkSpeed);
942         dest.writeInt(mRxLinkSpeed);
943         dest.writeInt(mFrequency);
944         if (mIpAddress != null) {
945             dest.writeByte((byte)1);
946             dest.writeByteArray(mIpAddress.getAddress());
947         } else {
948             dest.writeByte((byte)0);
949         }
950         if (mWifiSsid != null) {
951             dest.writeInt(1);
952             mWifiSsid.writeToParcel(dest, flags);
953         } else {
954             dest.writeInt(0);
955         }
956         dest.writeString(mBSSID);
957         dest.writeString(mMacAddress);
958         dest.writeInt(mMeteredHint ? 1 : 0);
959         dest.writeInt(mEphemeral ? 1 : 0);
960         dest.writeInt(mTrusted ? 1 : 0);
961         dest.writeInt(score);
962         dest.writeLong(txSuccess);
963         dest.writeDouble(mSuccessfulTxPacketsPerSecond);
964         dest.writeLong(txRetries);
965         dest.writeDouble(mTxRetriedTxPacketsPerSecond);
966         dest.writeLong(txBad);
967         dest.writeDouble(mLostTxPacketsPerSecond);
968         dest.writeLong(rxSuccess);
969         dest.writeDouble(mSuccessfulRxPacketsPerSecond);
970         mSupplicantState.writeToParcel(dest, flags);
971         dest.writeInt(mOsuAp ? 1 : 0);
972         dest.writeString(mRequestingPackageName);
973         dest.writeString(mFqdn);
974         dest.writeString(mProviderFriendlyName);
975         dest.writeInt(mWifiStandard);
976         dest.writeInt(mMaxSupportedTxLinkSpeed);
977         dest.writeInt(mMaxSupportedRxLinkSpeed);
978         dest.writeString(mPasspointUniqueId);
979     }
980 
981     /** Implement the Parcelable interface {@hide} */
982     @UnsupportedAppUsage
983     public static final @android.annotation.NonNull Creator<WifiInfo> CREATOR =
984         new Creator<WifiInfo>() {
985             public WifiInfo createFromParcel(Parcel in) {
986                 WifiInfo info = new WifiInfo();
987                 info.setNetworkId(in.readInt());
988                 info.setRssi(in.readInt());
989                 info.setLinkSpeed(in.readInt());
990                 info.setTxLinkSpeedMbps(in.readInt());
991                 info.setRxLinkSpeedMbps(in.readInt());
992                 info.setFrequency(in.readInt());
993                 if (in.readByte() == 1) {
994                     try {
995                         info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
996                     } catch (UnknownHostException e) {}
997                 }
998                 if (in.readInt() == 1) {
999                     info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in);
1000                 }
1001                 info.mBSSID = in.readString();
1002                 info.mMacAddress = in.readString();
1003                 info.mMeteredHint = in.readInt() != 0;
1004                 info.mEphemeral = in.readInt() != 0;
1005                 info.mTrusted = in.readInt() != 0;
1006                 info.score = in.readInt();
1007                 info.txSuccess = in.readLong();
1008                 info.mSuccessfulTxPacketsPerSecond = in.readDouble();
1009                 info.txRetries = in.readLong();
1010                 info.mTxRetriedTxPacketsPerSecond = in.readDouble();
1011                 info.txBad = in.readLong();
1012                 info.mLostTxPacketsPerSecond = in.readDouble();
1013                 info.rxSuccess = in.readLong();
1014                 info.mSuccessfulRxPacketsPerSecond = in.readDouble();
1015                 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
1016                 info.mOsuAp = in.readInt() != 0;
1017                 info.mRequestingPackageName = in.readString();
1018                 info.mFqdn = in.readString();
1019                 info.mProviderFriendlyName = in.readString();
1020                 info.mWifiStandard = in.readInt();
1021                 info.mMaxSupportedTxLinkSpeed = in.readInt();
1022                 info.mMaxSupportedRxLinkSpeed = in.readInt();
1023                 info.mPasspointUniqueId = in.readString();
1024                 return info;
1025             }
1026 
1027             public WifiInfo[] newArray(int size) {
1028                 return new WifiInfo[size];
1029             }
1030         };
1031 
1032     /**
1033      * Set the Passpoint unique identifier for the current connection
1034      *
1035      * @param passpointUniqueId Unique identifier
1036      * @hide
1037      */
setPasspointUniqueId(@ullable String passpointUniqueId)1038     public void setPasspointUniqueId(@Nullable String passpointUniqueId) {
1039         mPasspointUniqueId = passpointUniqueId;
1040     }
1041 
1042     /**
1043      * Get the Passpoint unique identifier for the current connection
1044      *
1045      * @return Passpoint unique identifier
1046      * @hide
1047      */
getPasspointUniqueId()1048     public @Nullable String getPasspointUniqueId() {
1049         return mPasspointUniqueId;
1050     }
1051 }
1052