From 6c5626edfc621e190408101e95c225549afa9943 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 14 Aug 2020 07:17:59 -0700 Subject: Convert WifiInfo to TransportInfo Also, deprecate WifiManager.getConnectionInfo() and add a note to help apps to migrate. The deprecation is purely cosmetic, no plans to remove any existing functionality from the WifiManager API. Bug: 162602799 Test: Compiles Change-Id: I12c473185dc5518f5684e83c2f49e07271738cb5 Merged-In: I12c473185dc5518f5684e83c2f49e07271738cb5 --- wifi/api/current.txt | 4 +-- wifi/api/system-current.txt | 2 +- wifi/java/android/net/wifi/WifiInfo.java | 12 ++++++- wifi/java/android/net/wifi/WifiManager.java | 52 +++++++++++++++++++++++++---- 4 files changed, 60 insertions(+), 10 deletions(-) (limited to 'wifi') diff --git a/wifi/api/current.txt b/wifi/api/current.txt index 53c3b33d9845..28224cf4ef2d 100644 --- a/wifi/api/current.txt +++ b/wifi/api/current.txt @@ -264,7 +264,7 @@ package android.net.wifi { field public static final int SIM = 5; // 0x5 } - public class WifiInfo implements android.os.Parcelable { + public class WifiInfo implements android.os.Parcelable android.net.TransportInfo { method public int describeContents(); method public String getBSSID(); method public static android.net.NetworkInfo.DetailedState getDetailedStateOf(android.net.wifi.SupplicantState); @@ -315,7 +315,7 @@ package android.net.wifi { method @Deprecated public boolean disconnect(); method @Deprecated public boolean enableNetwork(int, boolean); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public java.util.List getConfiguredNetworks(); - method public android.net.wifi.WifiInfo getConnectionInfo(); + method @Deprecated public android.net.wifi.WifiInfo getConnectionInfo(); method public android.net.DhcpInfo getDhcpInfo(); method public int getMaxNumberOfNetworkSuggestionsPerApp(); method @IntRange(from=0) public int getMaxSignalLevel(); diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt index 07793c1eb02a..afc39b97501f 100644 --- a/wifi/api/system-current.txt +++ b/wifi/api/system-current.txt @@ -401,7 +401,7 @@ package android.net.wifi { method public static void registerServiceWrappers(); } - public class WifiInfo implements android.os.Parcelable { + public class WifiInfo implements android.os.Parcelable android.net.TransportInfo { method public double getLostTxPacketsPerSecond(); method @Nullable public String getRequestingPackageName(); method public double getRetriedTxPacketsPerSecond(); diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index 53883674e058..cc437a8e552a 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkInfo.DetailedState; +import android.net.TransportInfo; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -38,8 +39,17 @@ import java.util.Locale; /** * Describes the state of any Wi-Fi connection that is active or * is in the process of being set up. + * + * In the connected state, access to location sensitive fields requires + * the same permissions as {@link WifiManager#getScanResults}. If such access is not allowed, + * {@link #getSSID} will return {@link WifiManager#UNKNOWN_SSID} and + * {@link #getBSSID} will return {@code "02:00:00:00:00:00"}. + * {@link #getNetworkId()} will return {@code -1}. + * {@link #getPasspointFqdn()} will return null. + * {@link #getPasspointProviderFriendlyName()} will return null. */ -public class WifiInfo implements Parcelable { +public class WifiInfo implements TransportInfo, Parcelable { + // TODO(b/162602799): Implement equals/hahscode methods. private static final String TAG = "WifiInfo"; /** * This is the map described in the Javadoc comment above. The positions diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index ccf8a80665aa..9844e4b3ec7f 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -36,9 +36,11 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.ParceledListSlice; import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; import android.net.DhcpInfo; import android.net.MacAddress; import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkStack; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; @@ -2744,15 +2746,53 @@ public class WifiManager { /** * Return dynamic information about the current Wi-Fi connection, if any is active. *

- * In the connected state, access to the SSID and BSSID requires - * the same permissions as {@link #getScanResults}. If such access is not allowed, - * {@link WifiInfo#getSSID} will return {@link #UNKNOWN_SSID} and - * {@link WifiInfo#getBSSID} will return {@code "02:00:00:00:00:00"}. - * {@link WifiInfo#getPasspointFqdn()} will return null. - * {@link WifiInfo#getPasspointProviderFriendlyName()} will return null. * * @return the Wi-Fi information, contained in {@link WifiInfo}. + * + * @deprecated Starting with {@link Build.VERSION_CODES#S}, WifiInfo retrieval is moved to + * {@link ConnectivityManager} API surface. WifiInfo is attached in + * {@link NetworkCapabilities#getTransportInfo()} which is available via callback in + * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} or on-demand from + * {@link ConnectivityManager#getNetworkCapabilities(Network)}. + * + *

+ * Usage example: + *
{@code
+     * final NetworkRequest request =
+     *      new NetworkRequest.Builder()
+     *      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+     *      .build();
+     * final ConnectivityManager connectivityManager =
+     *      context.getSystemService(ConnectivityManager.class);
+     * final NetworkCallback networkCallback = new NetworkCallback() {
+     *      ...
+     *      {@literal @}Override
+     *      void onAvailable(Network network) {}
+     *
+     *      {@literal @}Override
+     *      void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
+     *          WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
+     *      }
+     *      // etc.
+     * };
+     * connectivityManager.requestNetwork(request, networkCallback); // For request
+     * connectivityManager.registerNetworkCallback(request, networkCallback); // For listen
+     * }
+ *

+ * Compatibility Note: + *

  • Apps can continue using this API, however newer features + * such as ability to mask out location sensitive data in WifiInfo will not be supported + * via this API.
  • + *
  • On devices supporting concurrent connections (indicated via + * {@link #isMultiStaConcurrencySupported()}), this API will return the details + * of the internet providing connection (if any) to all apps, except for the apps that triggered + * the creation of the concurrent connection. For such apps, this API will return the details of + * the connection they created. For ex: apps using {@link WifiNetworkSpecifier} will + * will trigger a concurrent connection on supported devices and hence this API will provide + * details of their peer to peer connection (not the internet providing connection).
  • + *

    */ + @Deprecated public WifiInfo getConnectionInfo() { try { return mService.getConnectionInfo(mContext.getOpPackageName(), -- cgit v1.2.3 From 3653444d0256c9c5fc560bb269f302281a32d749 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 23 Nov 2020 08:11:08 -0800 Subject: WifiInfo: Add equals implementation This is needed for connectivity to compare TransportInfo instances. Bug: 162602799 Test: atest android.net.wifi Change-Id: I215b769339f68b76a1b2fa15f66c4527d184b696 Merged-In: I215b769339f68b76a1b2fa15f66c4527d184b696 --- wifi/java/android/net/wifi/WifiInfo.java | 87 ++++++++++++++++++++++- wifi/tests/src/android/net/wifi/WifiInfoTest.java | 81 +++++++++++++++++++++ 2 files changed, 167 insertions(+), 1 deletion(-) (limited to 'wifi') diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index cc437a8e552a..74370827f9e9 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -28,6 +28,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.Inet4AddressUtils; import java.net.Inet4Address; @@ -35,6 +36,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.EnumMap; import java.util.Locale; +import java.util.Objects; /** * Describes the state of any Wi-Fi connection that is active or @@ -49,7 +51,6 @@ import java.util.Locale; * {@link #getPasspointProviderFriendlyName()} will return null. */ public class WifiInfo implements TransportInfo, Parcelable { - // TODO(b/162602799): Implement equals/hahscode methods. private static final String TAG = "WifiInfo"; /** * This is the map described in the Javadoc comment above. The positions @@ -1058,4 +1059,88 @@ public class WifiInfo implements TransportInfo, Parcelable { public @Nullable String getPasspointUniqueId() { return mPasspointUniqueId; } + + @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(mRequestingPackageName, thatWifiInfo.mRequestingPackageName) + && Objects.equals(mOsuAp, thatWifiInfo.mOsuAp) + && Objects.equals(mFqdn, thatWifiInfo.mFqdn) + && Objects.equals(mProviderFriendlyName, thatWifiInfo.mProviderFriendlyName) + && 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); + } + + @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, + mRequestingPackageName, + mOsuAp, + mFqdn, + mProviderFriendlyName, + txBad, + txRetries, + txSuccess, + rxSuccess, + mLostTxPacketsPerSecond, + mTxRetriedTxPacketsPerSecond, + mSuccessfulTxPacketsPerSecond, + mSuccessfulRxPacketsPerSecond, + score, + mWifiStandard, + mMaxSupportedTxLinkSpeed, + mMaxSupportedRxLinkSpeed, + mPasspointUniqueId); + } } diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java index 311bbc41b8fe..9787cc05ea24 100644 --- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java +++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java @@ -17,6 +17,7 @@ package android.net.wifi; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; @@ -25,6 +26,8 @@ import android.os.Parcel; import androidx.test.filters.SmallTest; +import com.android.modules.utils.build.SdkLevel; + import org.junit.Test; import java.nio.charset.StandardCharsets; @@ -148,4 +151,82 @@ public class WifiInfoTest { assertEquals(TEST_RSSI, info2.getRssi()); assertEquals(TEST_NETWORK_ID2, info2.getNetworkId()); } + + @Test + public void testWifiInfoEquals() throws Exception { + WifiInfo.Builder builder = new WifiInfo.Builder() + .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8)) + .setBssid(TEST_BSSID) + .setRssi(TEST_RSSI) + .setNetworkId(TEST_NETWORK_ID); + + WifiInfo info1 = builder.build(); + WifiInfo info2 = builder.build(); + if (SdkLevel.isAtLeastS()) { + assertEquals(info1, info2); + } else { + assertNotEquals(info1, info2); + } + + info1.setTrusted(false); + // Same behavior pre-S & post-S. + assertNotEquals(info1, info2); + + info2.setTrusted(false); + if (SdkLevel.isAtLeastS()) { + assertEquals(info1, info2); + } else { + assertNotEquals(info1, info2); + } + + info1.setSSID(WifiSsid.createFromHex(null)); + // Same behavior pre-S & post-S. + assertNotEquals(info1, info2); + + info2.setSSID(WifiSsid.createFromHex(null)); + if (SdkLevel.isAtLeastS()) { + assertEquals(info1, info2); + } else { + assertNotEquals(info1, info2); + } + } + + @Test + public void testWifiInfoHashcode() throws Exception { + WifiInfo.Builder builder = new WifiInfo.Builder() + .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8)) + .setBssid(TEST_BSSID) + .setRssi(TEST_RSSI) + .setNetworkId(TEST_NETWORK_ID); + + WifiInfo info1 = builder.build(); + WifiInfo info2 = builder.build(); + if (SdkLevel.isAtLeastS()) { + assertEquals(info1.hashCode(), info2.hashCode()); + } else { + assertNotEquals(info1.hashCode(), info2.hashCode()); + } + + info1.setTrusted(false); + // Same behavior pre-S & post-S. + assertNotEquals(info1.hashCode(), info2.hashCode()); + + info2.setTrusted(false); + if (SdkLevel.isAtLeastS()) { + assertEquals(info1.hashCode(), info2.hashCode()); + } else { + assertNotEquals(info1.hashCode(), info2.hashCode()); + } + + info1.setSSID(WifiSsid.createFromHex(null)); + // Same behavior pre-S & post-S. + assertNotEquals(info1.hashCode(), info2.hashCode()); + + info2.setSSID(WifiSsid.createFromHex(null)); + if (SdkLevel.isAtLeastS()) { + assertEquals(info1.hashCode(), info2.hashCode()); + } else { + assertNotEquals(info1.hashCode(), info2.hashCode()); + } + } } -- cgit v1.2.3