diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 221f644409692..d4e024dbe0c7d 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -270,4 +270,6 @@ interface IWifiManager void setScanThrottleEnabled(boolean enable); boolean isScanThrottleEnabled(); + + Map getAllMatchingPasspointProfilesForScanResults(in List scanResult); } diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 7c3d0b92dd0ae..a720236689d37 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -2112,7 +2112,8 @@ public class WifiConfiguration implements Parcelable { return !TextUtils.isEmpty(FQDN) && !TextUtils.isEmpty(providerFriendlyName) && enterpriseConfig != null - && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; + && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE + && !TextUtils.isEmpty(mPasspointUniqueId); } /** @@ -2494,12 +2495,17 @@ public class WifiConfiguration implements Parcelable { */ @NonNull public String getKey() { - String key = providerFriendlyName == null - ? getSsidAndSecurityTypeString() - : FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP]; + // Passpoint ephemeral networks have their unique identifier set. Return it as is to be + // able to match internally. + if (mPasspointUniqueId != null) { + return mPasspointUniqueId; + } + + String key = getSsidAndSecurityTypeString(); if (!shared) { key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier(); } + return key; } @@ -2754,6 +2760,7 @@ public class WifiConfiguration implements Parcelable { requirePMF = source.requirePMF; updateIdentifier = source.updateIdentifier; carrierId = source.carrierId; + mPasspointUniqueId = source.mPasspointUniqueId; } } @@ -2826,6 +2833,7 @@ public class WifiConfiguration implements Parcelable { dest.writeInt(osu ? 1 : 0); dest.writeLong(randomizedMacExpirationTimeMs); dest.writeInt(carrierId); + dest.writeString(mPasspointUniqueId); } /** Implement the Parcelable interface {@hide} */ @@ -2900,6 +2908,7 @@ public class WifiConfiguration implements Parcelable { config.osu = in.readInt() != 0; config.randomizedMacExpirationTimeMs = in.readLong(); config.carrierId = in.readInt(); + config.mPasspointUniqueId = in.readString(); return config; } @@ -2907,4 +2916,28 @@ public class WifiConfiguration implements Parcelable { return new WifiConfiguration[size]; } }; + + /** + * Passpoint Unique identifier + * @hide + */ + private String mPasspointUniqueId = null; + + /** + * Set the Passpoint unique identifier + * @param uniqueId Passpoint unique identifier to be set + * @hide + */ + public void setPasspointUniqueId(String uniqueId) { + mPasspointUniqueId = uniqueId; + } + + /** + * Set the Passpoint unique identifier + * @hide + */ + public String getPasspointUniqueId() { + return mPasspointUniqueId; + } + } diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index 24b2a8e8994fd..0c306b4fb8cc0 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -291,6 +291,11 @@ public class WifiInfo implements Parcelable { */ private boolean mMeteredHint; + /** + * Passpoint unique key + */ + private String mPasspointUniqueId; + /** @hide */ @UnsupportedAppUsage public WifiInfo() { @@ -322,6 +327,7 @@ public class WifiInfo implements Parcelable { setRequestingPackageName(null); setFQDN(null); setProviderFriendlyName(null); + setPasspointUniqueId(null); txBad = 0; txSuccess = 0; rxSuccess = 0; @@ -370,6 +376,7 @@ public class WifiInfo implements Parcelable { mWifiStandard = source.mWifiStandard; mMaxSupportedTxLinkSpeed = source.mMaxSupportedTxLinkSpeed; mMaxSupportedRxLinkSpeed = source.mMaxSupportedRxLinkSpeed; + mPasspointUniqueId = source.mPasspointUniqueId; } } @@ -977,6 +984,7 @@ public class WifiInfo implements Parcelable { dest.writeInt(mWifiStandard); dest.writeInt(mMaxSupportedTxLinkSpeed); dest.writeInt(mMaxSupportedRxLinkSpeed); + dest.writeString(mPasspointUniqueId); } /** Implement the Parcelable interface {@hide} */ @@ -1021,6 +1029,7 @@ public class WifiInfo implements Parcelable { info.mWifiStandard = in.readInt(); info.mMaxSupportedTxLinkSpeed = in.readInt(); info.mMaxSupportedRxLinkSpeed = in.readInt(); + info.mPasspointUniqueId = in.readString(); return info; } @@ -1028,4 +1037,24 @@ public class WifiInfo implements Parcelable { 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; + } } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 1682023c33122..0b30f0946bf38 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1400,8 +1400,7 @@ public class WifiManager { List>>> configs = new ArrayList<>(); try { Map>> results = - mService.getAllMatchingFqdnsForScanResults( - scanResults); + mService.getAllMatchingPasspointProfilesForScanResults(scanResults); if (results.isEmpty()) { return configs; } @@ -1409,8 +1408,8 @@ public class WifiManager { mService.getWifiConfigsForPasspointProfiles( new ArrayList<>(results.keySet())); for (WifiConfiguration configuration : wifiConfigurations) { - Map> scanResultsPerNetworkType = results.get( - configuration.FQDN); + Map> scanResultsPerNetworkType = + results.get(configuration.getKey()); if (scanResultsPerNetworkType != null) { configs.add(Pair.create(configuration, scanResultsPerNetworkType)); } @@ -1962,9 +1961,11 @@ public class WifiManager { * for connecting to Passpoint networks that are operated by the Passpoint * service provider specified in the configuration. * - * Each configuration is uniquely identified by its FQDN (Fully Qualified Domain - * Name). In the case when there is an existing configuration with the same - * FQDN, the new configuration will replace the existing configuration. + * Each configuration is uniquely identified by a unique key which depends on the contents of + * the configuration. This allows the caller to install multiple profiles with the same FQDN + * (Fully qualified domain name). Therefore, in order to update an existing profile, it is + * first required to remove it using {@link WifiManager#removePasspointConfiguration(String)}. + * Otherwise, a new profile will be added with both configuration. * * @param config The Passpoint configuration to be added * @throws IllegalArgumentException if configuration is invalid or Passpoint is not enabled on diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index 720149695abc0..a854a4ba3ae59 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -569,6 +569,7 @@ public final class WifiNetworkSuggestion implements Parcelable { private WifiConfiguration buildWifiConfigurationForPasspoint() { WifiConfiguration wifiConfiguration = new WifiConfiguration(); wifiConfiguration.FQDN = mPasspointConfiguration.getHomeSp().getFqdn(); + wifiConfiguration.setPasspointUniqueId(mPasspointConfiguration.getUniqueId()); wifiConfiguration.priority = mPriority; wifiConfiguration.meteredOverride = mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED @@ -804,7 +805,7 @@ public final class WifiNetworkSuggestion implements Parcelable { @Override public int hashCode() { return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID, - wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN); + wifiConfiguration.allowedKeyManagement, wifiConfiguration.getKey()); } /** @@ -827,7 +828,8 @@ public final class WifiNetworkSuggestion implements Parcelable { && TextUtils.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID) && Objects.equals(this.wifiConfiguration.allowedKeyManagement, lhs.wifiConfiguration.allowedKeyManagement) - && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN); + && TextUtils.equals(this.wifiConfiguration.getKey(), + lhs.wifiConfiguration.getKey()); } @Override diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java index 615331f652583..9f581849efca5 100644 --- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java @@ -908,6 +908,9 @@ public final class PasspointConfiguration implements Parcelable { throw new IllegalStateException("Credential or HomeSP are not initialized"); } - return mHomeSp.getFqdn(); + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%s_%x%x", mHomeSp.getFqdn(), mHomeSp.hashCode(), + mCredential.hashCode())); + return sb.toString(); } } diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java index 49a76c33d2093..a5de3318f4545 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java +++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java @@ -16,8 +16,8 @@ package android.net.wifi.hotspot2.pps; -import android.os.Parcelable; import android.os.Parcel; +import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; @@ -299,8 +299,10 @@ public final class HomeSp implements Parcelable { @Override public int hashCode() { - return Objects.hash(mFqdn, mFriendlyName, mIconUrl, mHomeNetworkIds, mMatchAllOis, - mMatchAnyOis, mOtherHomePartners, mRoamingConsortiumOis); + return Objects.hash(mFqdn, mFriendlyName, mIconUrl, + mHomeNetworkIds, Arrays.hashCode(mMatchAllOis), + Arrays.hashCode(mMatchAnyOis), Arrays.hashCode(mOtherHomePartners), + Arrays.hashCode(mRoamingConsortiumOis)); } @Override diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index 53e9755eaf528..847040ca914ae 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -1551,14 +1551,15 @@ public class WifiManagerTest { */ @Test public void testGetAllMatchingWifiConfigs() throws Exception { - Map> fqdns = new HashMap<>(); - fqdns.put("www.test.com", new ArrayList<>()); - when(mWifiService.getAllMatchingFqdnsForScanResults(any(List.class))).thenReturn(fqdns); + Map> passpointProfiles = new HashMap<>(); + passpointProfiles.put("www.test.com_987a69bca26", new ArrayList<>()); + when(mWifiService.getAllMatchingPasspointProfilesForScanResults( + any(List.class))).thenReturn(passpointProfiles); InOrder inOrder = inOrder(mWifiService); mWifiManager.getAllMatchingWifiConfigs(new ArrayList<>()); - inOrder.verify(mWifiService).getAllMatchingFqdnsForScanResults(any(List.class)); + inOrder.verify(mWifiService).getAllMatchingPasspointProfilesForScanResults(any(List.class)); inOrder.verify(mWifiService).getWifiConfigsForPasspointProfiles(any(List.class)); } diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java index ce542c2bc4e98..8f6beb19091b4 100644 --- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java @@ -20,8 +20,11 @@ import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; +import android.net.wifi.hotspot2.pps.Credential; +import android.net.wifi.hotspot2.pps.HomeSp; import android.os.Parcel; import androidx.test.filters.SmallTest; @@ -367,16 +370,55 @@ public class PasspointConfigurationTest { } /** - * Verify that the unique identifier generated is correct. + * Verify that the unique identifier generated is identical for two instances * * @throws Exception */ @Test public void validateUniqueId() throws Exception { - PasspointConfiguration config = PasspointTestUtils.createConfig(); - String uniqueId; - uniqueId = config.getUniqueId(); - assertEquals(uniqueId, config.getHomeSp().getFqdn()); + PasspointConfiguration config1 = PasspointTestUtils.createConfig(); + PasspointConfiguration config2 = PasspointTestUtils.createConfig(); + + assertEquals(config1.getUniqueId(), config2.getUniqueId()); + } + + /** + * Verify that the unique identifier generated is different for two instances with different + * HomeSp node + * + * @throws Exception + */ + @Test + public void validateUniqueIdDifferentHomeSp() throws Exception { + PasspointConfiguration config1 = PasspointTestUtils.createConfig(); + + // Modify config2's RCOIs to a different set of values + PasspointConfiguration config2 = PasspointTestUtils.createConfig(); + HomeSp homeSp = config2.getHomeSp(); + homeSp.setRoamingConsortiumOis(new long[] {0xaa, 0xbb}); + config2.setHomeSp(homeSp); + + assertNotEquals(config1.getUniqueId(), config2.getUniqueId()); + } + + /** + * Verify that the unique identifier generated is different for two instances with different + * Credential node + * + * @throws Exception + */ + @Test + public void validateUniqueIdDifferentCredential() throws Exception { + PasspointConfiguration config1 = PasspointTestUtils.createConfig(); + + // Modify config2's RCOIs to a different set of values + PasspointConfiguration config2 = PasspointTestUtils.createConfig(); + Credential credential = config2.getCredential(); + credential.setRealm("realm2.example.com"); + credential.getSimCredential().setImsi("350460*"); + config2.setCredential(credential); + + assertNotEquals(config1.getUniqueId(), config2.getUniqueId()); } /**