mInformationElements;
/**
* @see #isPrimary()
* The field is stored as an int since is a tristate internally - true, false, no permission.
*/
private @IsPrimaryValues int mIsPrimary;
/** @hide */
@UnsupportedAppUsage
public WifiInfo() {
mWifiSsid = null;
mBSSID = null;
mNetworkId = -1;
mSupplicantState = SupplicantState.UNINITIALIZED;
mRssi = INVALID_RSSI;
mLinkSpeed = LINK_SPEED_UNKNOWN;
mFrequency = -1;
mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
mSecurityType = -1;
mIsPrimary = IS_PRIMARY_FALSE;
}
/** @hide */
public void reset() {
setInetAddress(null);
setBSSID(null);
setSSID(null);
setNetworkId(-1);
setRssi(INVALID_RSSI);
setLinkSpeed(LINK_SPEED_UNKNOWN);
setTxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
setRxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
setMaxSupportedTxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
setMaxSupportedRxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
setFrequency(-1);
setMeteredHint(false);
setEphemeral(false);
setTrusted(false);
setOemPaid(false);
setOemPrivate(false);
setCarrierMerged(false);
setOsuAp(false);
setRequestingPackageName(null);
setFQDN(null);
setProviderFriendlyName(null);
setPasspointUniqueId(null);
setSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
setInformationElements(null);
setIsPrimary(false);
txBad = 0;
txSuccess = 0;
rxSuccess = 0;
txRetries = 0;
mLostTxPacketsPerSecond = 0;
mSuccessfulTxPacketsPerSecond = 0;
mSuccessfulRxPacketsPerSecond = 0;
mTxRetriedTxPacketsPerSecond = 0;
score = 0;
mSecurityType = -1;
}
/**
* Copy constructor
* @hide
*/
public WifiInfo(WifiInfo source) {
this(source, NetworkCapabilities.REDACT_NONE);
}
/**
* Copy constructor
* @hide
*/
private WifiInfo(WifiInfo source, long redactions) {
if (source != null) {
mSupplicantState = source.mSupplicantState;
mBSSID = shouldRedactLocationSensitiveFields(redactions)
? DEFAULT_MAC_ADDRESS : source.mBSSID;
mWifiSsid = shouldRedactLocationSensitiveFields(redactions)
? WifiSsid.createFromHex(null) : source.mWifiSsid;
mNetworkId = shouldRedactLocationSensitiveFields(redactions)
? INVALID_NETWORK_ID : source.mNetworkId;
mRssi = source.mRssi;
mLinkSpeed = source.mLinkSpeed;
mTxLinkSpeed = source.mTxLinkSpeed;
mRxLinkSpeed = source.mRxLinkSpeed;
mFrequency = source.mFrequency;
mIpAddress = source.mIpAddress;
mMacAddress = (shouldRedactLocalMacAddressFields(redactions)
|| shouldRedactLocationSensitiveFields(redactions))
? DEFAULT_MAC_ADDRESS : source.mMacAddress;
mMeteredHint = source.mMeteredHint;
mEphemeral = source.mEphemeral;
mTrusted = source.mTrusted;
mOemPaid = source.mOemPaid;
mOemPrivate = source.mOemPrivate;
mCarrierMerged = source.mCarrierMerged;
mRequestingPackageName =
source.mRequestingPackageName;
mOsuAp = source.mOsuAp;
mFqdn = shouldRedactLocationSensitiveFields(redactions)
? null : source.mFqdn;
mProviderFriendlyName = shouldRedactLocationSensitiveFields(redactions)
? null : source.mProviderFriendlyName;
mSubscriptionId = source.mSubscriptionId;
txBad = source.txBad;
txRetries = source.txRetries;
txSuccess = source.txSuccess;
rxSuccess = source.rxSuccess;
mLostTxPacketsPerSecond = source.mLostTxPacketsPerSecond;
mTxRetriedTxPacketsPerSecond = source.mTxRetriedTxPacketsPerSecond;
mSuccessfulTxPacketsPerSecond = source.mSuccessfulTxPacketsPerSecond;
mSuccessfulRxPacketsPerSecond = source.mSuccessfulRxPacketsPerSecond;
score = source.score;
mWifiStandard = source.mWifiStandard;
mMaxSupportedTxLinkSpeed = source.mMaxSupportedTxLinkSpeed;
mMaxSupportedRxLinkSpeed = source.mMaxSupportedRxLinkSpeed;
mPasspointUniqueId = shouldRedactLocationSensitiveFields(redactions)
? null : source.mPasspointUniqueId;
if (source.mInformationElements != null
&& !shouldRedactLocationSensitiveFields(redactions)) {
mInformationElements = new ArrayList<>(source.mInformationElements);
}
mIsPrimary = shouldRedactNetworkSettingsFields(redactions)
? IS_PRIMARY_NO_PERMISSION : source.mIsPrimary;
mSecurityType = source.mSecurityType;
}
}
/** Builder for WifiInfo */
public static final class Builder {
private final WifiInfo mWifiInfo = new WifiInfo();
/**
* Set the SSID, in the form of a raw byte array.
* @see WifiInfo#getSSID()
*/
@NonNull
public Builder setSsid(@NonNull byte[] ssid) {
mWifiInfo.setSSID(WifiSsid.createFromByteArray(ssid));
return this;
}
/**
* Set the BSSID.
* @see WifiInfo#getBSSID()
*/
@NonNull
public Builder setBssid(@NonNull String bssid) {
mWifiInfo.setBSSID(bssid);
return this;
}
/**
* Set the RSSI, in dBm.
* @see WifiInfo#getRssi()
*/
@NonNull
public Builder setRssi(int rssi) {
mWifiInfo.setRssi(rssi);
return this;
}
/**
* Set the network ID.
* @see WifiInfo#getNetworkId()
*/
@NonNull
public Builder setNetworkId(int networkId) {
mWifiInfo.setNetworkId(networkId);
return this;
}
/**
* Set the current security type
* @see WifiInfo#getCurrentSecurityType()
*/
@NonNull
public Builder setCurrentSecurityType(@WifiConfiguration.SecurityType int securityType) {
mWifiInfo.setCurrentSecurityType(securityType);
return this;
}
/**
* Build a WifiInfo object.
*/
@NonNull
public WifiInfo build() {
return new WifiInfo(mWifiInfo);
}
}
/** @hide */
public void setSSID(WifiSsid wifiSsid) {
mWifiSsid = wifiSsid;
}
/**
* Returns the service set identifier (SSID) of the current 802.11 network.
*
* If the SSID can be decoded as UTF-8, it will be returned surrounded by double
* quotation marks. Otherwise, it is returned as a string of hex digits.
* The SSID may be {@link WifiManager#UNKNOWN_SSID}, if there is no network currently connected
* or if the caller has insufficient permissions to access the SSID.
*
*
* Prior to {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method
* always returned the SSID with no quotes around it.
*
*
* @return the SSID.
*/
public String getSSID() {
if (mWifiSsid != null) {
String unicode = mWifiSsid.toString();
if (!TextUtils.isEmpty(unicode)) {
return "\"" + unicode + "\"";
} else {
String hex = mWifiSsid.getHexString();
return (hex != null) ? hex : WifiManager.UNKNOWN_SSID;
}
}
return WifiManager.UNKNOWN_SSID;
}
/** @hide */
@UnsupportedAppUsage
public WifiSsid getWifiSsid() {
return mWifiSsid;
}
/** @hide */
@UnsupportedAppUsage
public void setBSSID(String BSSID) {
mBSSID = BSSID;
}
/**
* Return the basic service set identifier (BSSID) of the current access point.
*
* The BSSID may be
* {@code null}, if there is no network currently connected.
* {@code "02:00:00:00:00:00"}, if the caller has insufficient permissions to access the
* BSSID.
*
*
* @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}
*/
public String getBSSID() {
return mBSSID;
}
/**
* Returns the received signal strength indicator of the current 802.11
* network, in dBm.
*
* Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
* an absolute signal level which can be displayed to a user.
*
* @return the RSSI.
*/
public int getRssi() {
return mRssi;
}
/** @hide */
@UnsupportedAppUsage
public void setRssi(int rssi) {
if (rssi < INVALID_RSSI)
rssi = INVALID_RSSI;
if (rssi > MAX_RSSI)
rssi = MAX_RSSI;
mRssi = rssi;
}
/**
* Sets the Wi-Fi standard
* @hide
*/
public void setWifiStandard(@WifiAnnotations.WifiStandard int wifiStandard) {
mWifiStandard = wifiStandard;
}
/**
* Get connection Wi-Fi standard
* @return the connection Wi-Fi standard
*/
public @WifiAnnotations.WifiStandard int getWifiStandard() {
return mWifiStandard;
}
/**
* Returns the current link speed in {@link #LINK_SPEED_UNITS}.
* @return the link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
* @see #LINK_SPEED_UNITS
* @see #LINK_SPEED_UNKNOWN
*/
public int getLinkSpeed() {
return mLinkSpeed;
}
/** @hide */
@UnsupportedAppUsage
public void setLinkSpeed(int linkSpeed) {
mLinkSpeed = linkSpeed;
}
/**
* Returns the current transmit link speed in Mbps.
* @return the Tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
* @see #LINK_SPEED_UNKNOWN
*/
@IntRange(from = -1)
public int getTxLinkSpeedMbps() {
return mTxLinkSpeed;
}
/**
* Returns the maximum supported transmit link speed in Mbps
* @return the max supported tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is
* unknown. @see #LINK_SPEED_UNKNOWN
*/
public int getMaxSupportedTxLinkSpeedMbps() {
return mMaxSupportedTxLinkSpeed;
}
/**
* Update the last transmitted packet bit rate in Mbps.
* @hide
*/
public void setTxLinkSpeedMbps(int txLinkSpeed) {
mTxLinkSpeed = txLinkSpeed;
}
/**
* Set the maximum supported transmit link speed in Mbps
* @hide
*/
public void setMaxSupportedTxLinkSpeedMbps(int maxSupportedTxLinkSpeed) {
mMaxSupportedTxLinkSpeed = maxSupportedTxLinkSpeed;
}
/**
* Returns the current receive link speed in Mbps.
* @return the Rx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
* @see #LINK_SPEED_UNKNOWN
*/
@IntRange(from = -1)
public int getRxLinkSpeedMbps() {
return mRxLinkSpeed;
}
/**
* Returns the maximum supported receive link speed in Mbps
* @return the max supported Rx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is
* unknown. @see #LINK_SPEED_UNKNOWN
*/
public int getMaxSupportedRxLinkSpeedMbps() {
return mMaxSupportedRxLinkSpeed;
}
/**
* Update the last received packet bit rate in Mbps.
* @hide
*/
public void setRxLinkSpeedMbps(int rxLinkSpeed) {
mRxLinkSpeed = rxLinkSpeed;
}
/**
* Set the maximum supported receive link speed in Mbps
* @hide
*/
public void setMaxSupportedRxLinkSpeedMbps(int maxSupportedRxLinkSpeed) {
mMaxSupportedRxLinkSpeed = maxSupportedRxLinkSpeed;
}
/**
* Returns the current frequency in {@link #FREQUENCY_UNITS}.
* @return the frequency.
* @see #FREQUENCY_UNITS
*/
public int getFrequency() {
return mFrequency;
}
/** @hide */
public void setFrequency(int frequency) {
this.mFrequency = frequency;
}
/**
* @hide
*/
public boolean is24GHz() {
return ScanResult.is24GHz(mFrequency);
}
/**
* @hide
*/
@UnsupportedAppUsage
public boolean is5GHz() {
return ScanResult.is5GHz(mFrequency);
}
/**
* @hide
*/
public boolean is6GHz() {
return ScanResult.is6GHz(mFrequency);
}
/**
* Record the MAC address of the WLAN interface
* @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
* @hide
*/
@UnsupportedAppUsage
public void setMacAddress(String macAddress) {
this.mMacAddress = macAddress;
}
/**
* Returns the MAC address used for this connection.
* @return MAC address of the connection or {@code "02:00:00:00:00:00"} if the caller has
* insufficient permission.
*/
@RequiresPermission(allOf = {
Manifest.permission.LOCAL_MAC_ADDRESS,
Manifest.permission.ACCESS_FINE_LOCATION
})
public String getMacAddress() {
return mMacAddress;
}
/**
* @return true if {@link #getMacAddress()} has a real MAC address.
*
* @hide
*/
public boolean hasRealMacAddress() {
return mMacAddress != null && !DEFAULT_MAC_ADDRESS.equals(mMacAddress);
}
/**
* Indicates if we've dynamically detected this active network connection as
* being metered.
*
* @see WifiConfiguration#isMetered(WifiConfiguration, WifiInfo)
* @hide
*/
public void setMeteredHint(boolean meteredHint) {
mMeteredHint = meteredHint;
}
/** {@hide} */
@UnsupportedAppUsage
public boolean getMeteredHint() {
return mMeteredHint;
}
/** {@hide} */
public void setEphemeral(boolean ephemeral) {
mEphemeral = ephemeral;
}
/**
* Returns true if the current Wifi network is ephemeral, false otherwise.
* An ephemeral network is a network that is temporary and not persisted in the system.
* Ephemeral networks cannot be forgotten, only disabled with
* {@link WifiManager#disableEphemeralNetwork(String)}.
*
* @hide
*/
@SystemApi
public boolean isEphemeral() {
return mEphemeral;
}
/** {@hide} */
public void setTrusted(boolean trusted) {
mTrusted = trusted;
}
/**
* Returns true if the current Wifi network is a trusted network, false otherwise.
* @see WifiNetworkSuggestion.Builder#setUntrusted(boolean).
* {@hide}
*/
@SystemApi
public boolean isTrusted() {
return mTrusted;
}
/** {@hide} */
public void setOemPaid(boolean oemPaid) {
mOemPaid = oemPaid;
}
/**
* Returns true if the current Wifi network is an oem paid network, false otherwise.
* @see WifiNetworkSuggestion.Builder#setOemPaid(boolean).
* {@hide}
*/
@RequiresApi(Build.VERSION_CODES.S)
@SystemApi
public boolean isOemPaid() {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
return mOemPaid;
}
/** {@hide} */
public void setOemPrivate(boolean oemPrivate) {
mOemPrivate = oemPrivate;
}
/**
* Returns true if the current Wifi network is an oem private network, false otherwise.
* @see WifiNetworkSuggestion.Builder#setOemPrivate(boolean).
* {@hide}
*/
@RequiresApi(Build.VERSION_CODES.S)
@SystemApi
public boolean isOemPrivate() {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
return mOemPrivate;
}
/**
* {@hide}
*/
public void setCarrierMerged(boolean carrierMerged) {
mCarrierMerged = carrierMerged;
}
/**
* Returns true if the current Wifi network is a carrier merged network, false otherwise.
* @see WifiNetworkSuggestion.Builder#setCarrierMerged(boolean).
* {@hide}
*/
@SystemApi
@RequiresApi(Build.VERSION_CODES.S)
public boolean isCarrierMerged() {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
return mCarrierMerged;
}
/** {@hide} */
public void setOsuAp(boolean osuAp) {
mOsuAp = osuAp;
}
/** {@hide} */
@SystemApi
public boolean isOsuAp() {
return mOsuAp;
}
/** {@hide} */
@SystemApi
public boolean isPasspointAp() {
return mFqdn != null && mProviderFriendlyName != null;
}
/** {@hide} */
public void setFQDN(@Nullable String fqdn) {
mFqdn = fqdn;
}
/**
* Returns the Fully Qualified Domain Name of the network if it is a Passpoint network.
*
* The FQDN may be
* {@code null} if no network currently connected, currently connected network is not
* passpoint network or the caller has insufficient permissions to access the FQDN.
*
*/
public @Nullable String getPasspointFqdn() {
return mFqdn;
}
/** {@hide} */
public void setProviderFriendlyName(@Nullable String providerFriendlyName) {
mProviderFriendlyName = providerFriendlyName;
}
/**
* Returns the Provider Friendly Name of the network if it is a Passpoint network.
*
* The Provider Friendly Name may be
* {@code null} if no network currently connected, currently connected network is not
* passpoint network or the caller has insufficient permissions to access the Provider Friendly
* Name.
*
*/
public @Nullable String getPasspointProviderFriendlyName() {
return mProviderFriendlyName;
}
/** {@hide} */
public void setRequestingPackageName(@Nullable String packageName) {
mRequestingPackageName = packageName;
}
/**
* If this network was created in response to an app request (e.g. through Network Suggestion
* or Network Specifier), return the package name of the app that made the request.
* Null otherwise.
* @hide
*/
@SystemApi
public @Nullable String getRequestingPackageName() {
return mRequestingPackageName;
}
/** {@hide} */
public void setSubscriptionId(int subId) {
mSubscriptionId = subId;
}
/**
* If this network is provisioned by a carrier, returns subscription Id corresponding to the
* associated SIM on the device. If this network is not provisioned by a carrier, returns
* {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID}
*
* @see WifiNetworkSuggestion.Builder#setSubscriptionId(int)
* @see android.telephony.SubscriptionInfo#getSubscriptionId()
*/
@RequiresApi(Build.VERSION_CODES.S)
public int getSubscriptionId() {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
return mSubscriptionId;
}
/** @hide */
@UnsupportedAppUsage
public void setNetworkId(int id) {
mNetworkId = id;
}
/**
* Each configured network has a unique small integer ID, used to identify
* the network. This method returns the ID for the currently connected network.
*
* The networkId may be {@code -1} if there is no currently connected network or if the caller
* has insufficient permissions to access the network ID.
*
*
* @return the network ID.
*/
public int getNetworkId() {
return mNetworkId;
}
/**
* Return the detailed state of the supplicant's negotiation with an
* access point, in the form of a {@link SupplicantState SupplicantState} object.
* @return the current {@link SupplicantState SupplicantState}
*/
public SupplicantState getSupplicantState() {
return mSupplicantState;
}
/** @hide */
@UnsupportedAppUsage
public void setSupplicantState(SupplicantState state) {
mSupplicantState = state;
}
/** @hide */
public void setInetAddress(InetAddress address) {
mIpAddress = address;
}
/**
* @deprecated Use the methods on {@link android.net.LinkProperties} which can be obtained
* either via {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)} or
* {@link ConnectivityManager#getLinkProperties(Network)}.
*/
@Deprecated
public int getIpAddress() {
int result = 0;
if (mIpAddress instanceof Inet4Address) {
result = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) mIpAddress);
}
return result;
}
/**
* @return {@code true} if this network does not broadcast its SSID, so an
* SSID-specific probe request must be used for scans.
*/
public boolean getHiddenSSID() {
if (mWifiSsid == null) return false;
return mWifiSsid.isHidden();
}
/**
* Map a supplicant state into a fine-grained network connectivity state.
* @param suppState the supplicant state
* @return the corresponding {@link DetailedState}
*/
public static DetailedState getDetailedStateOf(SupplicantState suppState) {
return stateMap.get(suppState);
}
/**
* Set the SupplicantState
from the string name
* of the state.
* @param stateName the name of the state, as a String
returned
* in an event sent by {@code wpa_supplicant}.
*/
@UnsupportedAppUsage
void setSupplicantState(String stateName) {
mSupplicantState = valueOf(stateName);
}
static SupplicantState valueOf(String stateName) {
if ("4WAY_HANDSHAKE".equalsIgnoreCase(stateName))
return SupplicantState.FOUR_WAY_HANDSHAKE;
else {
try {
return SupplicantState.valueOf(stateName.toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
return SupplicantState.INVALID;
}
}
}
/**
* Remove double quotes (") surrounding a SSID string, if present. Otherwise, return the
* string unmodified. Return null if the input string was null.
* @hide
*/
@Nullable
@SystemApi
public static String sanitizeSsid(@Nullable String string) {
return removeDoubleQuotes(string);
}
/** @hide */
@UnsupportedAppUsage
@Nullable
public static String removeDoubleQuotes(@Nullable String string) {
if (string == null) return null;
final int length = string.length();
if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
return string.substring(1, length - 1);
}
return string;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
String none = "";
sb.append("SSID: ").append(getSSID())
.append(", BSSID: ").append(mBSSID == null ? none : mBSSID)
.append(", MAC: ").append(mMacAddress == null ? none : mMacAddress)
.append(", Security type: ").append(mSecurityType)
.append(", Supplicant state: ")
.append(mSupplicantState == null ? none : mSupplicantState)
.append(", Wi-Fi standard: ").append(mWifiStandard)
.append(", RSSI: ").append(mRssi)
.append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS)
.append(", Tx Link speed: ").append(mTxLinkSpeed).append(LINK_SPEED_UNITS)
.append(", Max Supported Tx Link speed: ")
.append(mMaxSupportedTxLinkSpeed).append(LINK_SPEED_UNITS)
.append(", Rx Link speed: ").append(mRxLinkSpeed).append(LINK_SPEED_UNITS)
.append(", Max Supported Rx Link speed: ")
.append(mMaxSupportedRxLinkSpeed).append(LINK_SPEED_UNITS)
.append(", Frequency: ").append(mFrequency).append(FREQUENCY_UNITS)
.append(", Net ID: ").append(mNetworkId)
.append(", Metered hint: ").append(mMeteredHint)
.append(", score: ").append(Integer.toString(score))
.append(", CarrierMerged: ").append(mCarrierMerged)
.append(", SubscriptionId: ").append(mSubscriptionId)
.append(", IsPrimary: ").append(mIsPrimary);
return sb.toString();
}
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
return 0;
}
private boolean shouldRedactLocationSensitiveFields(long redactions) {
return (redactions & NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION) != 0;
}
private boolean shouldRedactLocalMacAddressFields(long redactions) {
return (redactions & NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS) != 0;
}
private boolean shouldRedactNetworkSettingsFields(long redactions) {
return (redactions & NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS) != 0;
}
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mNetworkId);
dest.writeInt(mRssi);
dest.writeInt(mLinkSpeed);
dest.writeInt(mTxLinkSpeed);
dest.writeInt(mRxLinkSpeed);
dest.writeInt(mFrequency);
if (mIpAddress != null) {
dest.writeByte((byte)1);
dest.writeByteArray(mIpAddress.getAddress());
} else {
dest.writeByte((byte)0);
}
if (mWifiSsid != null) {
dest.writeInt(1);
mWifiSsid.writeToParcel(dest, flags);
} else {
dest.writeInt(0);
}
dest.writeString(mBSSID);
dest.writeString(mMacAddress);
dest.writeInt(mMeteredHint ? 1 : 0);
dest.writeInt(mEphemeral ? 1 : 0);
dest.writeInt(mTrusted ? 1 : 0);
dest.writeInt(mOemPaid ? 1 : 0);
dest.writeInt(mOemPrivate ? 1 : 0);
dest.writeInt(mCarrierMerged ? 1 : 0);
dest.writeInt(score);
dest.writeLong(txSuccess);
dest.writeDouble(mSuccessfulTxPacketsPerSecond);
dest.writeLong(txRetries);
dest.writeDouble(mTxRetriedTxPacketsPerSecond);
dest.writeLong(txBad);
dest.writeDouble(mLostTxPacketsPerSecond);
dest.writeLong(rxSuccess);
dest.writeDouble(mSuccessfulRxPacketsPerSecond);
mSupplicantState.writeToParcel(dest, flags);
dest.writeInt(mOsuAp ? 1 : 0);
dest.writeString(mRequestingPackageName);
dest.writeString(mFqdn);
dest.writeString(mProviderFriendlyName);
dest.writeInt(mWifiStandard);
dest.writeInt(mMaxSupportedTxLinkSpeed);
dest.writeInt(mMaxSupportedRxLinkSpeed);
dest.writeString(mPasspointUniqueId);
dest.writeInt(mSubscriptionId);
dest.writeTypedList(mInformationElements);
if (SdkLevel.isAtLeastS()) {
dest.writeInt(mIsPrimary);
}
dest.writeInt(mSecurityType);
}
/** Implement the Parcelable interface {@hide} */
@UnsupportedAppUsage
public static final @android.annotation.NonNull Creator CREATOR =
new Creator() {
public WifiInfo createFromParcel(Parcel in) {
WifiInfo info = new WifiInfo();
info.setNetworkId(in.readInt());
info.setRssi(in.readInt());
info.setLinkSpeed(in.readInt());
info.setTxLinkSpeedMbps(in.readInt());
info.setRxLinkSpeedMbps(in.readInt());
info.setFrequency(in.readInt());
if (in.readByte() == 1) {
try {
info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
} catch (UnknownHostException e) {}
}
if (in.readInt() == 1) {
info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in);
}
info.mBSSID = in.readString();
info.mMacAddress = in.readString();
info.mMeteredHint = in.readInt() != 0;
info.mEphemeral = in.readInt() != 0;
info.mTrusted = in.readInt() != 0;
info.mOemPaid = in.readInt() != 0;
info.mOemPrivate = in.readInt() != 0;
info.mCarrierMerged = in.readInt() != 0;
info.score = in.readInt();
info.txSuccess = in.readLong();
info.mSuccessfulTxPacketsPerSecond = in.readDouble();
info.txRetries = in.readLong();
info.mTxRetriedTxPacketsPerSecond = in.readDouble();
info.txBad = in.readLong();
info.mLostTxPacketsPerSecond = in.readDouble();
info.rxSuccess = in.readLong();
info.mSuccessfulRxPacketsPerSecond = in.readDouble();
info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
info.mOsuAp = in.readInt() != 0;
info.mRequestingPackageName = in.readString();
info.mFqdn = in.readString();
info.mProviderFriendlyName = in.readString();
info.mWifiStandard = in.readInt();
info.mMaxSupportedTxLinkSpeed = in.readInt();
info.mMaxSupportedRxLinkSpeed = in.readInt();
info.mPasspointUniqueId = in.readString();
info.mSubscriptionId = in.readInt();
info.mInformationElements = in.createTypedArrayList(
ScanResult.InformationElement.CREATOR);
if (SdkLevel.isAtLeastS()) {
info.mIsPrimary = in.readInt();
}
info.mSecurityType = in.readInt();
return info;
}
public WifiInfo[] newArray(int size) {
return new WifiInfo[size];
}
};
/**
* Set the Passpoint unique identifier for the current connection
*
* @param passpointUniqueId Unique identifier
* @hide
*/
public void setPasspointUniqueId(@Nullable String passpointUniqueId) {
mPasspointUniqueId = passpointUniqueId;
}
/**
* Get the Passpoint unique identifier for the current connection
*
* @return Passpoint unique identifier
* @hide
*/
public @Nullable String getPasspointUniqueId() {
return mPasspointUniqueId;
}
/**
* Set the information elements found in the becaon of the connected bssid.
* @hide
*/
public void setInformationElements(@Nullable List infoElements) {
if (infoElements == null) {
mInformationElements = null;
return;
}
mInformationElements = new ArrayList<>(infoElements);
}
/**
* Get all information elements found in the beacon of the connected bssid.
*
* The information elements will be {@code null} if there is no network currently connected or
* if the caller has insufficient permissions to access the info elements.
*
*
* @return List of information elements {@link ScanResult.InformationElement} or null.
*/
@Nullable
@SuppressWarnings("NullableCollection")
public List getInformationElements() {
if (mInformationElements == null) return null;
return new ArrayList<>(mInformationElements);
}
/**
* @see #isPrimary()
* @hide
*/
public void setIsPrimary(boolean isPrimary) {
mIsPrimary = isPrimary ? IS_PRIMARY_TRUE : IS_PRIMARY_FALSE;
}
/**
* Returns whether this is the primary wifi connection or not.
*
* Wifi service considers this connection to be the best among all Wifi connections, and this
* connection should be the one surfaced to the user if only one can be displayed.
*
* Note that the default route (chosen by Connectivity Service) may not correspond to the
* primary Wifi connection e.g. when there exists a better cellular network, or if the
* primary Wifi connection doesn't have internet access.
*
* @return whether this is the primary connection or not.
*
* @hide
*/
@RequiresApi(Build.VERSION_CODES.S)
@RequiresPermission(Manifest.permission.NETWORK_SETTINGS)
@SystemApi
public boolean isPrimary() {
if (!SdkLevel.isAtLeastS()) {
// Intentional - since we don't support STA + STA on older devices, this field
// is redundant. Don't allow anyone to use this.
throw new UnsupportedOperationException();
}
if (mIsPrimary == IS_PRIMARY_NO_PERMISSION) {
throw new SecurityException("Not allowed to access this field");
}
return mIsPrimary == IS_PRIMARY_TRUE;
}
@Override
public boolean equals(Object that) {
if (this == that) return true;
// Potential API behavior change, so don't change behavior on older devices.
if (!SdkLevel.isAtLeastS()) return false;
if (!(that instanceof WifiInfo)) return false;
WifiInfo thatWifiInfo = (WifiInfo) that;
return Objects.equals(mWifiSsid, thatWifiInfo.mWifiSsid)
&& Objects.equals(mBSSID, thatWifiInfo.mBSSID)
&& Objects.equals(mNetworkId, thatWifiInfo.mNetworkId)
&& Objects.equals(mRssi, thatWifiInfo.mRssi)
&& Objects.equals(mSupplicantState, thatWifiInfo.mSupplicantState)
&& Objects.equals(mLinkSpeed, thatWifiInfo.mLinkSpeed)
&& Objects.equals(mTxLinkSpeed, thatWifiInfo.mTxLinkSpeed)
&& Objects.equals(mRxLinkSpeed, thatWifiInfo.mRxLinkSpeed)
&& Objects.equals(mFrequency, thatWifiInfo.mFrequency)
&& Objects.equals(mIpAddress, thatWifiInfo.mIpAddress)
&& Objects.equals(mMacAddress, thatWifiInfo.mMacAddress)
&& Objects.equals(mMeteredHint, thatWifiInfo.mMeteredHint)
&& Objects.equals(mEphemeral, thatWifiInfo.mEphemeral)
&& Objects.equals(mTrusted, thatWifiInfo.mTrusted)
&& Objects.equals(mOemPaid, thatWifiInfo.mOemPaid)
&& Objects.equals(mOemPrivate, thatWifiInfo.mOemPrivate)
&& Objects.equals(mCarrierMerged, thatWifiInfo.mCarrierMerged)
&& Objects.equals(mRequestingPackageName, thatWifiInfo.mRequestingPackageName)
&& Objects.equals(mOsuAp, thatWifiInfo.mOsuAp)
&& Objects.equals(mFqdn, thatWifiInfo.mFqdn)
&& Objects.equals(mProviderFriendlyName, thatWifiInfo.mProviderFriendlyName)
&& Objects.equals(mSubscriptionId, thatWifiInfo.mSubscriptionId)
&& Objects.equals(txBad, thatWifiInfo.txBad)
&& Objects.equals(txRetries, thatWifiInfo.txRetries)
&& Objects.equals(txSuccess, thatWifiInfo.txSuccess)
&& Objects.equals(rxSuccess, thatWifiInfo.rxSuccess)
&& Objects.equals(mLostTxPacketsPerSecond, thatWifiInfo.mLostTxPacketsPerSecond)
&& Objects.equals(mTxRetriedTxPacketsPerSecond,
thatWifiInfo.mTxRetriedTxPacketsPerSecond)
&& Objects.equals(mSuccessfulTxPacketsPerSecond,
thatWifiInfo.mSuccessfulTxPacketsPerSecond)
&& Objects.equals(mSuccessfulRxPacketsPerSecond,
thatWifiInfo.mSuccessfulRxPacketsPerSecond)
&& Objects.equals(score, thatWifiInfo.score)
&& Objects.equals(mWifiStandard, thatWifiInfo.mWifiStandard)
&& Objects.equals(mMaxSupportedTxLinkSpeed, thatWifiInfo.mMaxSupportedTxLinkSpeed)
&& Objects.equals(mMaxSupportedRxLinkSpeed, thatWifiInfo.mMaxSupportedRxLinkSpeed)
&& Objects.equals(mPasspointUniqueId, thatWifiInfo.mPasspointUniqueId)
&& Objects.equals(mInformationElements, thatWifiInfo.mInformationElements)
&& Objects.equals(mIsPrimary, thatWifiInfo.mIsPrimary)
&& Objects.equals(mSecurityType, thatWifiInfo.mSecurityType);
}
@Override
public int hashCode() {
// Potential API behavior change, so don't change behavior on older devices.
if (!SdkLevel.isAtLeastS()) return System.identityHashCode(this);
return Objects.hash(mWifiSsid,
mBSSID,
mNetworkId,
mRssi,
mSupplicantState,
mLinkSpeed,
mTxLinkSpeed,
mRxLinkSpeed,
mFrequency,
mIpAddress,
mMacAddress,
mMeteredHint,
mEphemeral,
mTrusted,
mOemPaid,
mOemPrivate,
mCarrierMerged,
mRequestingPackageName,
mOsuAp,
mFqdn,
mProviderFriendlyName,
mSubscriptionId,
txBad,
txRetries,
txSuccess,
rxSuccess,
mLostTxPacketsPerSecond,
mTxRetriedTxPacketsPerSecond,
mSuccessfulTxPacketsPerSecond,
mSuccessfulRxPacketsPerSecond,
score,
mWifiStandard,
mMaxSupportedTxLinkSpeed,
mMaxSupportedRxLinkSpeed,
mPasspointUniqueId,
mInformationElements,
mIsPrimary,
mSecurityType);
}
/**
* Create a copy of a {@link WifiInfo} with some fields redacted based on the permissions
* held by the receiving app.
*
* @param redactions bitmask of redactions that needs to be performed on this instance.
* @return Copy of this instance with the necessary redactions.
*/
@Override
@NonNull
public WifiInfo makeCopy(long redactions) {
return new WifiInfo(this, redactions);
}
/**
* Returns a bitmask of all the applicable redactions (based on the permissions held by the
* receiving app) to be performed on this TransportInfo.
*
* @return bitmask of redactions applicable on this instance.
*/
@Override
public long getApplicableRedactions() {
return NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION
| NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS
| NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
}
/**
* Set the security type of the current connection
* @hide
*/
public void setCurrentSecurityType(@WifiConfiguration.SecurityType int securityType) {
mSecurityType = convertSecurityTypeToWifiInfo(securityType);
}
/**
* Clear the last set security type
* @hide
*/
public void clearCurrentSecurityType() {
mSecurityType = SECURITY_TYPE_UNKNOWN;
}
/**
* Returns the security type of the current 802.11 network connection.
*
* @return the security type, or {@link #SECURITY_TYPE_UNKNOWN} if not currently connected.
*/
public @SecurityType int getCurrentSecurityType() {
return mSecurityType;
}
private @SecurityType int convertSecurityTypeToWifiInfo(
@WifiConfiguration.SecurityType int securityType) {
switch (securityType) {
case WifiConfiguration.SECURITY_TYPE_OPEN:
return SECURITY_TYPE_OPEN;
case WifiConfiguration.SECURITY_TYPE_WEP:
return SECURITY_TYPE_WEP;
case WifiConfiguration.SECURITY_TYPE_PSK:
return SECURITY_TYPE_PSK;
case WifiConfiguration.SECURITY_TYPE_EAP:
return SECURITY_TYPE_EAP;
case WifiConfiguration.SECURITY_TYPE_SAE:
return SECURITY_TYPE_SAE;
case WifiConfiguration.SECURITY_TYPE_OWE:
return SECURITY_TYPE_OWE;
case WifiConfiguration.SECURITY_TYPE_WAPI_PSK:
return SECURITY_TYPE_WAPI_PSK;
case WifiConfiguration.SECURITY_TYPE_WAPI_CERT:
return SECURITY_TYPE_WAPI_CERT;
case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
return SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
return SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2:
return SECURITY_TYPE_PASSPOINT_R1_R2;
case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3:
return SECURITY_TYPE_PASSPOINT_R3;
default:
return SECURITY_TYPE_UNKNOWN;
}
}
}