(links);
mapAffiliatedMloLinks();
}
/**
* Update the MLO link STA MAC Address
*
* @param linkId for the link to be updated.
* @param macAddress value to be set in the link.
*
* @return true on success, false on failure
*
* @hide
*/
public boolean updateMloLinkStaAddress(int linkId, MacAddress macAddress) {
for (MloLink link : mAffiliatedMloLinks) {
if (link.getLinkId() == linkId) {
link.setStaMacAddress(macAddress);
return true;
}
}
return false;
}
/**
* Update the MLO link State
*
* @param linkId for the link to be updated.
* @param state value to be set in the link as one of {@link MloLink.MloLinkState}
*
* @return true on success, false on failure
*
* @hide
*/
public boolean updateMloLinkState(int linkId, @MloLink.MloLinkState int state) {
if (!MloLink.isValidState(state)) {
return false;
}
for (MloLink link : mAffiliatedMloLinks) {
if (link.getLinkId() == linkId) {
link.setState(state);
return true;
}
}
return false;
}
/**
* Return the basic service set identifier (BSSID) of the current access point. In case of
* Multi Link Operation (MLO), the BSSID corresponds to the BSSID of the link used for
* association.
*
* 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;
}
/**
* Return the Multi-Link Device (MLD) MAC Address for the connected access point.
*
* The returned MLD MAC Address will be {@code null} in the following cases:
* There is no network currently connected
* The connected access point is not an MLD access point,
* i.e. {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE}.
* The caller has insufficient permissions to access the access point MLD MAC Address.
*
*
* @return the MLD Mac address
*/
@Nullable
public MacAddress getApMldMacAddress() {
return mApMldMacAddress;
}
/**
* Return the access point Multi-Link Operation (MLO) link-id for Wi-Fi 7 access points.
* i.e. {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE},
* otherwise return {@link MloLink#INVALID_MLO_LINK_ID}.
*
* Valid values are 0-15 as described in IEEE 802.11be Specification, section 9.4.2.295b.2.
*
* @return {@link MloLink#INVALID_MLO_LINK_ID} or a valid value (0-15).
*/
@IntRange(from = MloLink.INVALID_MLO_LINK_ID, to = MloLink.MAX_MLO_LINK_ID)
public int getApMloLinkId() {
return mApMloLinkId;
}
/**
* Return the Multi-Link Operation (MLO) affiliated Links for Wi-Fi 7 access points.
* i.e. when {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE}.
*
* Affiliated links are the links supported by the Access Point Multi Link Device (AP MLD). The
* Station Multi Link Device (STA MLD) gathers affiliated link information from scan results.
* Depending on Station's capability, it associates to all or a subset of affiliated links.
* Note:{@link #getAssociatedMloLinks()} returns associated links.
*
* @return List of affiliated MLO links, or an empty list if access point is not Wi-Fi 7
*/
@NonNull
public List getAffiliatedMloLinks() {
return new ArrayList(mAffiliatedMloLinks);
}
/** @hide */
public MloLink getAffiliatedMloLink(int linkId) {
return mAffiliatedMloLinksMap.get(linkId);
}
/**
* Return the associated Multi-Link Operation (MLO) Links for Wi-Fi 7 access points.
* i.e. when {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE}.
*
* Affiliated links are the links supported by the Access Point Multi Link Device (AP MLD). The
* Station Multi Link Device (STA MLD) gathers affiliated link information from scan results.
* Depending on Station's capability, it associates to all or a subset of affiliated links.
* Note:{@link #getAffiliatedMloLinks()} returns affiliated links.
*
* @return List of associated MLO links, or an empty list if access point is not a multi-link
* device.
*/
@NonNull
public List getAssociatedMloLinks() {
ArrayList associatedMloLinks = new ArrayList();
for (MloLink link : getAffiliatedMloLinks()) {
if (link.getState() == MloLink.MLO_LINK_STATE_IDLE
|| link.getState() == MloLink.MLO_LINK_STATE_ACTIVE) {
associatedMloLinks.add(link);
}
}
return associatedMloLinks;
}
/**
* Returns the received signal strength indicator of the current 802.11 network, in dBm. In
* case of Multi Link Operation (MLO), returned RSSI is the highest of all associated links.
*
* 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;
mLastRssiUpdateMillis = SystemClock.elapsedRealtime();
}
/**
* @hide
*/
public long getLastRssiUpdateMillis() {
return mLastRssiUpdateMillis;
}
/**
* 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}. In case of Multi Link Operation
* (MLO), returned value is the current link speed of the associated link with the highest RSSI.
*
* @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. In case of Multi Link Operation (MLO),
* returned value is the current transmit link speed of the associated link with the highest
* RSSI.
*
* @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. In case of Multi Link Operation (MLO),
* returned value is the receive link speed of the associated link with the highest RSSI.
*
* @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}. In case of Multi Link Operation
* (MLO), returned value is the frequency of the associated link with the highest RSSI.
*
* @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. In case of Multi Link Operation (MLO),
* returned value is the Station MLD MAC address.
*
* @return MAC address of the connection or {@code "02:00:00:00:00:00"} if the caller has
* insufficient permission.
*
* Requires {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} and
* {@link android.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 setRestricted(boolean restricted) {
mRestricted = restricted;
}
/**
* Returns true if the current Wifi network is a restricted network, false otherwise.
* A restricted network has its {@link NetworkCapabilities#NET_CAPABILITY_NOT_RESTRICTED}
* capability removed.
* @see WifiNetworkSuggestion.Builder#setRestricted(boolean).
*/
public boolean isRestricted() {
return mRestricted;
}
/** @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() {
return mIsHiddenSsid;
}
/**
* Sets whether or not this network is using a hidden SSID. This value should be set from the
* corresponding {@link WifiConfiguration} of the network.
* @hide
*/
public void setHiddenSSID(boolean isHiddenSsid) {
mIsHiddenSsid = isHiddenSsid;
}
/**
* 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(", IP: ").append(mIpAddress)
.append(", Security type: ").append(mSecurityType)
.append(", Supplicant state: ")
.append(mSupplicantState == null ? none : mSupplicantState)
.append(", Wi-Fi standard: ").append(ScanResult.wifiStandardToString(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(", isUsable: ").append(mIsUsable)
.append(", CarrierMerged: ").append(mCarrierMerged)
.append(", SubscriptionId: ").append(mSubscriptionId)
.append(", IsPrimary: ").append(mIsPrimary)
.append(", Trusted: ").append(mTrusted)
.append(", Restricted: ").append(mRestricted)
.append(", Ephemeral: ").append(mEphemeral)
.append(", OEM paid: ").append(mOemPaid)
.append(", OEM private: ").append(mOemPrivate)
.append(", OSU AP: ").append(mOsuAp)
.append(", FQDN: ").append(mFqdn == null ? none : mFqdn)
.append(", Provider friendly name: ")
.append(mProviderFriendlyName == null ? none : mProviderFriendlyName)
.append(", Requesting package name: ")
.append(mRequestingPackageName == null ? none : mRequestingPackageName)
.append(mNetworkKey == null ? none : mNetworkKey)
.append("MLO Information: ")
.append(", Is TID-To-Link negotiation supported by the AP: ")
.append(mApTidToLinkMappingNegotiationSupported)
.append(", AP MLD Address: ").append(
mApMldMacAddress == null ? none : mApMldMacAddress.toString())
.append(", AP MLO Link Id: ").append(
mApMldMacAddress == null ? none : mApMloLinkId)
.append(", AP MLO Affiliated links: ").append(
mApMldMacAddress == null ? none : mAffiliatedMloLinks)
.append(", Vendor Data: ").append(
mVendorData == null || mVendorData.isEmpty() ? none : mVendorData);
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.writeBoolean(mIsUsable);
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);
dest.writeInt(mRestricted ? 1 : 0);
dest.writeString(mNetworkKey);
dest.writeParcelable(mApMldMacAddress, flags);
dest.writeInt(mApMloLinkId);
dest.writeTypedList(mAffiliatedMloLinks);
dest.writeBoolean(mApTidToLinkMappingNegotiationSupported);
dest.writeList(mVendorData);
}
/** 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.mIsUsable = in.readBoolean();
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();
info.mRestricted = in.readInt() != 0;
info.mNetworkKey = in.readString();
info.mApMldMacAddress = in.readParcelable(MacAddress.class.getClassLoader());
info.mApMloLinkId = in.readInt();
info.mAffiliatedMloLinks = in.createTypedArrayList(MloLink.CREATOR);
info.mApTidToLinkMappingNegotiationSupported = in.readBoolean();
info.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
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, or null if this connection is not Passpoint.
*/
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
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;
}
private List getSortedMloLinkList(List list) {
List newList = new ArrayList(list);
Collections.sort(newList, new Comparator() {
@Override
public int compare(MloLink lhs, MloLink rhs) {
return lhs.getLinkId() - rhs.getLinkId();
}
});
return newList;
}
@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;
// compare the MLO affiliated links irrespective of the order
if (!Objects.equals(getSortedMloLinkList(mAffiliatedMloLinks),
getSortedMloLinkList(thatWifiInfo.mAffiliatedMloLinks))) {
return false;
}
return Objects.equals(mWifiSsid, thatWifiInfo.mWifiSsid)
&& Objects.equals(mBSSID, thatWifiInfo.mBSSID)
&& Objects.equals(mApMldMacAddress, thatWifiInfo.mApMldMacAddress)
&& mApMloLinkId == thatWifiInfo.mApMloLinkId
&& 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(mIsUsable, thatWifiInfo.mIsUsable)
&& 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)
&& mIsPrimary == thatWifiInfo.mIsPrimary
&& mSecurityType == thatWifiInfo.mSecurityType
&& mRestricted == thatWifiInfo.mRestricted
&& Objects.equals(mNetworkKey, thatWifiInfo.mNetworkKey)
&& mApTidToLinkMappingNegotiationSupported
== thatWifiInfo.mApTidToLinkMappingNegotiationSupported
&& Objects.equals(mVendorData, thatWifiInfo.mVendorData);
}
@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,
mApMldMacAddress,
mApMloLinkId,
mAffiliatedMloLinks,
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,
mIsUsable,
mWifiStandard,
mMaxSupportedTxLinkSpeed,
mMaxSupportedRxLinkSpeed,
mPasspointUniqueId,
mInformationElements,
mIsPrimary,
mSecurityType,
mRestricted,
mNetworkKey,
mApTidToLinkMappingNegotiationSupported,
mVendorData);
}
/**
* 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 = convertWifiConfigurationSecurityType(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 @WifiAnnotations.SecurityType int getCurrentSecurityType() {
return mSecurityType;
}
/**
* Converts the WifiConfiguration.SecurityType to a WifiInfo.SecurityType
* @param wifiConfigSecurity WifiConfiguration.SecurityType to convert
* @return security type as a WifiInfo.SecurityType
* @hide
*/
public static @WifiAnnotations.SecurityType int convertWifiConfigurationSecurityType(
@WifiConfiguration.SecurityType int wifiConfigSecurity) {
switch (wifiConfigSecurity) {
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;
case WifiConfiguration.SECURITY_TYPE_DPP:
return SECURITY_TYPE_DPP;
default:
return SECURITY_TYPE_UNKNOWN;
}
}
/**
* Utility method to convert WifiInfo.SecurityType to DevicePolicyManager.WifiSecurity
* @param securityType WifiInfo.SecurityType to convert
* @return DevicePolicyManager.WifiSecurity security level, or
* {@link #DPM_SECURITY_TYPE_UNKNOWN} for unknown security types
* @hide
*/
public static int convertSecurityTypeToDpmWifiSecurity(
@WifiAnnotations.SecurityType int securityType) {
switch (securityType) {
case SECURITY_TYPE_OPEN:
case SECURITY_TYPE_OWE:
return DevicePolicyManager.WIFI_SECURITY_OPEN;
case SECURITY_TYPE_WEP:
case SECURITY_TYPE_PSK:
case SECURITY_TYPE_SAE:
case SECURITY_TYPE_WAPI_PSK:
return DevicePolicyManager.WIFI_SECURITY_PERSONAL;
case SECURITY_TYPE_EAP:
case SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
case SECURITY_TYPE_PASSPOINT_R1_R2:
case SECURITY_TYPE_PASSPOINT_R3:
case SECURITY_TYPE_WAPI_CERT:
return DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP;
case SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
return DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_192;
default:
return DPM_SECURITY_TYPE_UNKNOWN;
}
}
/**
* Set the network key for the current Wi-Fi network.
*
* Now we are using this identity to be a key when storing Wi-Fi data usage data.
* See: {@link WifiConfiguration#getNetworkKeyFromSecurityType(int)}.
*
* @param currentNetworkKey the network key of the current Wi-Fi network.
* @hide
*/
public void setNetworkKey(@NonNull String currentNetworkKey) {
mNetworkKey = currentNetworkKey;
}
/**
* Returns the network key of the current Wi-Fi network.
*
* The network key may be {@code null}, if there is no network currently connected
* or if the caller has insufficient permissions to access the network key.
*
* @hide
*/
@SystemApi
@Nullable
public String getNetworkKey() {
return mNetworkKey;
}
/**
* TID-to-Link mapping negotiation is an optional feature. This API returns whether the feature
* is supported by the AP.
*
* @return Return true if TID-to-Link mapping negotiation is supported by the AP, otherwise
* false.
*
* @hide
*/
@SystemApi
public boolean isApTidToLinkMappingNegotiationSupported() {
return mApTidToLinkMappingNegotiationSupported;
}
/** @hide */
public void enableApTidToLinkMappingNegotiationSupport(boolean enable) {
mApTidToLinkMappingNegotiationSupported = enable;
}
/**
* Return the vendor-provided configuration data, if it exists. See also {@link
* #setVendorData(List)}
*
* @return Vendor configuration data, or empty list if it does not exist.
* @hide
*/
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
@NonNull
@SystemApi
public List getVendorData() {
if (!SdkLevel.isAtLeastV()) {
throw new UnsupportedOperationException();
}
return mVendorData;
}
/**
* Set additional vendor-provided configuration data.
*
* @param vendorData List of {@link OuiKeyedData} containing the vendor-provided
* configuration data. Note that multiple elements with the same OUI are allowed.
* @hide
*/
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
@SystemApi
public void setVendorData(@NonNull List vendorData) {
if (!SdkLevel.isAtLeastV()) {
throw new UnsupportedOperationException();
}
if (vendorData == null) {
throw new IllegalArgumentException("setVendorData received a null value");
}
mVendorData = new ArrayList<>(vendorData);
}
}