diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-03-16 23:20:44 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-03-16 23:20:45 +0000 |
commit | 44104c69e83ee6ee07f0449cbf720dad53c0cdfb (patch) | |
tree | a28cfe6df9818e81352c8dbf91166a7e6e6f074a /service | |
parent | 9b7ac0c52f2a5d6a4e409e902692c437698c52b6 (diff) | |
parent | 9ef555a48ac600c8766f703fa60db15b69e20301 (diff) |
Merge changes from topic 'legacy passpoint indicator'
* changes:
WifiConfigurationXmlUtil: persist additional fields for legacy Passpoint configuration
WifiConfigMangaer: use updated legacy Passpoint config indicator
hotspot2: add support for WifiStateMachine#syncGetMatchingWifiConfig
hotspot2: update semantics for PasspointManager#matchProvider
hotspot2: use ScanResult to match Passpoint providers
Diffstat (limited to 'service')
8 files changed, 133 insertions, 85 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 7c8cddae8..48dfc2fd1 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -34,7 +34,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; -import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -2666,17 +2665,14 @@ public class WifiConfigManager { // List of network IDs for legacy Passpoint configuration to be removed. List<Integer> legacyPasspointNetId = new ArrayList<>(); for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { - // Ignore ephemeral and temporary Passpoint networks. Temporary Passpoint networks - // are created by {@link PasspointNetworkEvaluator} using WIFI_UID. - if (config.ephemeral || (config.isPasspoint() - && config.creatorUid == Process.WIFI_UID)) { + // Ignore ephemeral networks and non-legacy Passpoint configurations. + if (config.ephemeral || (config.isPasspoint() && !config.isLegacyPasspointConfig)) { continue; } - // Legacy Passpoint configuration represented by WifiConfiguration is created by an - // actual user, so migrate the configurations owned by the current user to + // Migrate the legacy Passpoint configurations owned by the current user to // {@link PasspointManager}. - if (config.isPasspoint() && WifiConfigurationUtil.doesUidBelongToAnyProfile( + if (config.isLegacyPasspointConfig && WifiConfigurationUtil.doesUidBelongToAnyProfile( config.creatorUid, mUserManager.getProfiles(mCurrentUserId))) { legacyPasspointNetId.add(config.networkId); // Migrate the legacy Passpoint configuration and add it to PasspointManager. diff --git a/service/java/com/android/server/wifi/WifiConfigStoreLegacy.java b/service/java/com/android/server/wifi/WifiConfigStoreLegacy.java index e7a7335d7..42a91de67 100644 --- a/service/java/com/android/server/wifi/WifiConfigStoreLegacy.java +++ b/service/java/com/android/server/wifi/WifiConfigStoreLegacy.java @@ -226,6 +226,7 @@ public class WifiConfigStoreLegacy { // Update the missing Passpoint configuration fields to this WifiConfiguration. LegacyPasspointConfig passpointConfig = passpointConfigMap.get(fqdn); + wifiConfig.isLegacyPasspointConfig = true; wifiConfig.FQDN = fqdn; wifiConfig.providerFriendlyName = passpointConfig.mFriendlyName; if (passpointConfig.mRoamingConsortiumOis != null) { diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index a5dc9375f..2f86743f2 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -1836,7 +1836,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss public WifiConfiguration syncGetMatchingWifiConfig(ScanResult scanResult, AsyncChannel channel) { Message resultMsg = channel.sendMessageSynchronously(CMD_GET_MATCHING_CONFIG, scanResult); - return (WifiConfiguration) resultMsg.obj; + WifiConfiguration config = (WifiConfiguration) resultMsg.obj; + resultMsg.recycle(); + return config; } /** @@ -4952,8 +4954,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss } break; case CMD_GET_MATCHING_CONFIG: - // TODO(b/31065385) - replyToMessage(message, message.what, null); + replyToMessage(message, message.what, + mPasspointManager.getMatchingWifiConfig((ScanResult) message.obj)); break; case CMD_RECONNECT: mWifiConnectivityManager.forceConnectivityScan(); diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPRequestManager.java b/service/java/com/android/server/wifi/hotspot2/ANQPRequestManager.java index fd756c3a2..dfdf4ad16 100644 --- a/service/java/com/android/server/wifi/hotspot2/ANQPRequestManager.java +++ b/service/java/com/android/server/wifi/hotspot2/ANQPRequestManager.java @@ -20,7 +20,6 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wifi.Clock; -import com.android.server.wifi.ScanDetail; import com.android.server.wifi.hotspot2.anqp.Constants; import java.util.ArrayList; @@ -43,7 +42,7 @@ public class ANQPRequestManager { /** * List of pending ANQP request associated with an AP (BSSID). */ - private final Map<Long, ScanDetail> mPendingQueries; + private final Map<Long, ANQPNetworkKey> mPendingQueries; /** * List of hold off time information associated with APs specified by their BSSID. @@ -109,14 +108,14 @@ public class ANQPRequestManager { * supported Hotspot 2.0 release version). * * @param bssid The BSSID of the AP - * @param scanDetail The ScanDetail associated with this request + * @param anqpNetworkKey The unique network key associated with this request * @param rcOIs Flag indicating the inclusion of roaming consortium OIs. When set to true, * Roaming Consortium ANQP element will be requested * @param hsReleaseR2 Flag indicating the support of Hotspot 2.0 Release 2. When set to true, * the Release 2 ANQP elements {@link #R2_ANQP_BASE_SET} will be requested * @return true if a request was sent successfully */ - public boolean requestANQPElements(long bssid, ScanDetail scanDetail, boolean rcOIs, + public boolean requestANQPElements(long bssid, ANQPNetworkKey anqpNetworkKey, boolean rcOIs, boolean hsReleaseR2) { // Check if we are allow to send the request now. if (!canSendRequestNow(bssid)) { @@ -132,7 +131,7 @@ public class ANQPRequestManager { // the given AP. updateHoldOffInfo(bssid); - mPendingQueries.put(bssid, scanDetail); + mPendingQueries.put(bssid, anqpNetworkKey); return true; } @@ -141,9 +140,9 @@ public class ANQPRequestManager { * * @param bssid The BSSID of the AP * @param success Flag indicating the result of the query - * @return {@link ScanDetail} associated with the completed request + * @return {@link ANQPNetworkKey} associated with the completed request */ - public ScanDetail onRequestCompleted(long bssid, boolean success) { + public ANQPNetworkKey onRequestCompleted(long bssid, boolean success) { if (success) { // Query succeeded. No need to hold off request to the given AP. mHoldOffInfo.remove(bssid); diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java index ff8b50f77..c3acd39c3 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java @@ -29,6 +29,7 @@ import static android.net.wifi.WifiManager.EXTRA_URL; import android.content.Context; import android.content.Intent; import android.net.wifi.IconInfo; +import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.hotspot2.PasspointConfiguration; @@ -39,13 +40,14 @@ import android.util.Pair; import com.android.server.wifi.Clock; import com.android.server.wifi.SIMAccessor; -import com.android.server.wifi.ScanDetail; import com.android.server.wifi.WifiConfigManager; import com.android.server.wifi.WifiConfigStore; import com.android.server.wifi.WifiKeyStore; import com.android.server.wifi.WifiNative; import com.android.server.wifi.hotspot2.anqp.ANQPElement; import com.android.server.wifi.hotspot2.anqp.Constants; +import com.android.server.wifi.util.InformationElementUtil; +import com.android.server.wifi.util.ScanResultUtil; import java.util.ArrayList; import java.util.HashMap; @@ -103,23 +105,16 @@ public class PasspointManager { public void onANQPResponse(long bssid, Map<Constants.ANQPElementType, ANQPElement> anqpElements) { // Notify request manager for the completion of a request. - ScanDetail scanDetail = + ANQPNetworkKey anqpKey = mAnqpRequestManager.onRequestCompleted(bssid, anqpElements != null); - if (anqpElements == null || scanDetail == null) { + if (anqpElements == null || anqpKey == null) { // Query failed or the request wasn't originated from us (not tracked by the // request manager). Nothing to be done. return; } // Add new entry to the cache. - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - ANQPNetworkKey anqpKey = ANQPNetworkKey.buildKey(networkDetail.getSSID(), - networkDetail.getBSSID(), networkDetail.getHESSID(), - networkDetail.getAnqpDomainID()); mAnqpCache.addEntry(anqpKey, anqpElements); - - // Update ANQP elements in the ScanDetail. - scanDetail.propagateANQPInfo(anqpElements); } @Override @@ -281,44 +276,57 @@ public class PasspointManager { } /** - * Find the providers that can provide service through the given AP, which means the - * providers contained credential to authenticate with the given AP. + * Find the best provider that can provide service through the given AP, which means the + * provider contained credential to authenticate with the given AP. + * + * Here is the current precedence of the matching rule in descending order: + * 1. Home Provider + * 2. Roaming Provider * - * An empty list will returned in the case when no match is found. + * A {code null} will be returned if no matching is found. * - * @param scanDetail The detail information of the AP - * @return List of {@link PasspointProvider} + * @param scanResult The scan result associated with the AP + * @return A pair of {@link PasspointProvider} and match status. */ - public List<Pair<PasspointProvider, PasspointMatch>> matchProvider(ScanDetail scanDetail) { + public Pair<PasspointProvider, PasspointMatch> matchProvider(ScanResult scanResult) { // Nothing to be done if no Passpoint provider is installed. if (mProviders.isEmpty()) { - return new ArrayList<Pair<PasspointProvider, PasspointMatch>>(); + return null; } + // Retrieve the relevant information elements, mainly Roaming Consortium IE and Hotspot 2.0 + // Vendor Specific IE. + InformationElementUtil.RoamingConsortium roamingConsortium = + InformationElementUtil.getRoamingConsortiumIE(scanResult.informationElements); + InformationElementUtil.Vsa vsa = InformationElementUtil.getHS2VendorSpecificIE( + scanResult.informationElements); + // Lookup ANQP data in the cache. - NetworkDetail networkDetail = scanDetail.getNetworkDetail(); - ANQPNetworkKey anqpKey = ANQPNetworkKey.buildKey(networkDetail.getSSID(), - networkDetail.getBSSID(), networkDetail.getHESSID(), - networkDetail.getAnqpDomainID()); + long bssid = Utils.parseMac(scanResult.BSSID); + ANQPNetworkKey anqpKey = ANQPNetworkKey.buildKey(scanResult.SSID, bssid, scanResult.hessid, + vsa.anqpDomainID); ANQPData anqpEntry = mAnqpCache.getEntry(anqpKey); if (anqpEntry == null) { - mAnqpRequestManager.requestANQPElements(networkDetail.getBSSID(), scanDetail, - networkDetail.getAnqpOICount() > 0, - networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2); - return new ArrayList<Pair<PasspointProvider, PasspointMatch>>(); + mAnqpRequestManager.requestANQPElements(bssid, anqpKey, + roamingConsortium.anqpOICount > 0, + vsa.hsRelease == NetworkDetail.HSRelease.R2); + return null; } - List<Pair<PasspointProvider, PasspointMatch>> results = new ArrayList<>(); + Pair<PasspointProvider, PasspointMatch> bestMatch = null; for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { PasspointProvider provider = entry.getValue(); PasspointMatch matchStatus = provider.match(anqpEntry.getElements()); - if (matchStatus == PasspointMatch.HomeProvider - || matchStatus == PasspointMatch.RoamingProvider) { - results.add(new Pair<PasspointProvider, PasspointMatch>(provider, matchStatus)); + if (matchStatus == PasspointMatch.HomeProvider) { + bestMatch = Pair.create(provider, matchStatus); + break; + } + if (matchStatus == PasspointMatch.RoamingProvider && bestMatch == null) { + bestMatch = Pair.create(provider, matchStatus); } } - return results; + return bestMatch; } /** @@ -383,6 +391,51 @@ public class PasspointManager { } /** + * Lookup the ANQP elements associated with the given AP from the cache. An empty map + * will be returned if no match found in the cache. + * + * @param scanResult The scan result associated with the AP + * @return Map of ANQP elements + */ + public Map<Constants.ANQPElementType, ANQPElement> getANQPElements(ScanResult scanResult) { + // Retrieve the Hotspot 2.0 Vendor Specific IE. + InformationElementUtil.Vsa vsa = + InformationElementUtil.getHS2VendorSpecificIE(scanResult.informationElements); + + // Lookup ANQP data in the cache. + long bssid = Utils.parseMac(scanResult.BSSID); + ANQPData anqpEntry = mAnqpCache.getEntry(ANQPNetworkKey.buildKey( + scanResult.SSID, bssid, scanResult.hessid, vsa.anqpDomainID)); + if (anqpEntry != null) { + return anqpEntry.getElements(); + } + return new HashMap<Constants.ANQPElementType, ANQPElement>(); + } + + /** + * Match the given WiFi AP to an installed Passpoint provider. A {@link WifiConfiguration} + * will be generated and returned if a match is found. The returned {@link WifiConfiguration} + * will contained all the necessary credentials for connecting to the given WiFi AP. + * + * A {code null} will be returned if no matching provider is found. + * + * @param scanResult The scan result of the given AP + * @return {@link WifiConfiguration} + */ + public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { + if (scanResult == null) { + return null; + } + Pair<PasspointProvider, PasspointMatch> matchedProvider = matchProvider(scanResult); + if (matchedProvider == null) { + return null; + } + WifiConfiguration config = matchedProvider.first.getWifiConfig(); + config.SSID = ScanResultUtil.createQuotedSSID(scanResult.SSID); + return config; + } + + /** * Add a legacy Passpoint configuration represented by a {@link WifiConfiguration}. * * @param wifiConfig {@link WifiConfiguration} representation of the Passpoint configuration diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java index f08b5de32..740a302cc 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java @@ -62,6 +62,9 @@ public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEva WifiConfiguration currentNetwork, String currentBssid, boolean connected, boolean untrustedNetworkAllowed, List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) { + // Sweep the ANQP cache to remove any expired ANQP entries. + mPasspointManager.sweepCache(); + // Go through each ScanDetail and find the best provider for each ScanDetail. List<Pair<ScanDetail, Pair<PasspointProvider, PasspointMatch>>> providerList = new ArrayList<>(); @@ -71,12 +74,9 @@ public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEva continue; } - List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = - mPasspointManager.matchProvider(scanDetail); - // Find the best provider for this ScanDetail. Pair<PasspointProvider, PasspointMatch> bestProvider = - findBestProvider(matchedProviders); + mPasspointManager.matchProvider(scanDetail.getScanResult()); if (bestProvider != null) { providerList.add(Pair.create(scanDetail, bestProvider)); } @@ -132,33 +132,6 @@ public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEva } /** - * Given a list of provider associated with a ScanDetail, determine and return the best - * provider from the list. - * - * Currently the only criteria is to prefer home provider over roaming provider. Additional - * criteria will be added when Hotspot 2.0 Release 2 support is added. - * - * A null will be returned if no match is found (providerList is empty). - * - * @param providerList The list of matched providers - * @return Pair of {@link PasspointProvider} with its matching status - */ - private Pair<PasspointProvider, PasspointMatch> findBestProvider( - List<Pair<PasspointProvider, PasspointMatch>> providerList) { - Pair<PasspointProvider, PasspointMatch> bestMatch = null; - for (Pair<PasspointProvider, PasspointMatch> providerMatch : providerList) { - if (providerMatch.second == PasspointMatch.HomeProvider) { - // Home provider found, done. - bestMatch = providerMatch; - break; - } else if (bestMatch == null) { - bestMatch = providerMatch; - } - } - return bestMatch; - } - - /** * Given a list of Passpoint networks (with both provider and scan info), find and return * the one with highest score. The score is calculated using * {@link PasspointNetworkScore#calculateScore}. @@ -181,7 +154,8 @@ public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEva boolean isActiveNetwork = TextUtils.equals(currentNetworkSsid, ScanResultUtil.createQuotedSSID(scanDetail.getSSID())); int score = PasspointNetworkScore.calculateScore(match == PasspointMatch.HomeProvider, - scanDetail, isActiveNetwork); + scanDetail, mPasspointManager.getANQPElements(scanDetail.getScanResult()), + isActiveNetwork); if (score > bestScore) { bestScanDetail = scanDetail; diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkScore.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkScore.java index 2dc3789f5..03f2e4c2d 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkScore.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkScore.java @@ -145,7 +145,7 @@ public class PasspointNetworkScore { * @return integer score */ public static int calculateScore(boolean isHomeProvider, ScanDetail scanDetail, - boolean isActiveNetwork) { + Map<ANQPElementType, ANQPElement> anqpElements, boolean isActiveNetwork) { NetworkDetail networkDetail = scanDetail.getNetworkDetail(); int score = 0; if (isHomeProvider) { @@ -158,9 +158,9 @@ public class PasspointNetworkScore { // Adjust score based on the network type. score += NETWORK_TYPE_SCORES.get(networkDetail.getAnt()); - Map<ANQPElementType, ANQPElement> anqp = networkDetail.getANQPElements(); - if (anqp != null) { - HSWanMetricsElement wm = (HSWanMetricsElement) anqp.get(ANQPElementType.HSWANMetrics); + if (anqpElements != null) { + HSWanMetricsElement wm = + (HSWanMetricsElement) anqpElements.get(ANQPElementType.HSWANMetrics); if (wm != null) { if (wm.getStatus() != HSWanMetricsElement.LINK_STATUS_UP || wm.isCapped()) { score -= WAN_PORT_DOWN_OR_CAPPED_PENALTY; @@ -168,7 +168,7 @@ public class PasspointNetworkScore { } IPAddressTypeAvailabilityElement ipa = (IPAddressTypeAvailabilityElement) - anqp.get(ANQPElementType.ANQPIPAddrAvailability); + anqpElements.get(ANQPElementType.ANQPIPAddrAvailability); if (ipa != null) { Integer v4Score = IPV4_SCORES.get(ipa.getV4Availability()); diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java index 76b8a3292..42303b009 100644 --- a/service/java/com/android/server/wifi/util/XmlUtil.java +++ b/service/java/com/android/server/wifi/util/XmlUtil.java @@ -336,6 +336,8 @@ public class XmlUtil { public static final String XML_TAG_LAST_UPDATE_UID = "LastUpdateUid"; public static final String XML_TAG_LAST_UPDATE_NAME = "LastUpdateName"; public static final String XML_TAG_LAST_CONNECT_UID = "LastConnectUid"; + public static final String XML_TAG_IS_LEGACY_PASSPOINT_CONFIG = "IsLegacyPasspointConfig"; + public static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs"; /** * Write WepKeys to the XML stream. @@ -448,6 +450,11 @@ public class XmlUtil { XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_UID, configuration.lastUpdateUid); XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_NAME, configuration.lastUpdateName); XmlUtil.writeNextValue(out, XML_TAG_LAST_CONNECT_UID, configuration.lastConnectUid); + XmlUtil.writeNextValue( + out, XML_TAG_IS_LEGACY_PASSPOINT_CONFIG, + configuration.isLegacyPasspointConfig); + XmlUtil.writeNextValue( + out, XML_TAG_ROAMING_CONSORTIUM_OIS, configuration.roamingConsortiumIds); } /** @@ -598,6 +605,12 @@ public class XmlUtil { case XML_TAG_LAST_CONNECT_UID: configuration.lastConnectUid = (int) value; break; + case XML_TAG_IS_LEGACY_PASSPOINT_CONFIG: + configuration.isLegacyPasspointConfig = (boolean) value; + break; + case XML_TAG_ROAMING_CONSORTIUM_OIS: + configuration.roamingConsortiumIds = (long[]) value; + break; default: throw new XmlPullParserException( "Unknown value name found: " + valueName[0]); @@ -949,6 +962,8 @@ public class XmlUtil { public static final String XML_TAG_CA_PATH = "CaPath"; public static final String XML_TAG_EAP_METHOD = "EapMethod"; public static final String XML_TAG_PHASE2_METHOD = "Phase2Method"; + public static final String XML_TAG_PLMN = "PLMN"; + public static final String XML_TAG_REALM = "Realm"; /** * Write the WifiEnterpriseConfig data elements from the provided config to the XML @@ -985,6 +1000,8 @@ public class XmlUtil { enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY)); XmlUtil.writeNextValue(out, XML_TAG_EAP_METHOD, enterpriseConfig.getEapMethod()); XmlUtil.writeNextValue(out, XML_TAG_PHASE2_METHOD, enterpriseConfig.getPhase2Method()); + XmlUtil.writeNextValue(out, XML_TAG_PLMN, enterpriseConfig.getPlmn()); + XmlUtil.writeNextValue(out, XML_TAG_REALM, enterpriseConfig.getRealm()); } /** @@ -1060,6 +1077,12 @@ public class XmlUtil { case XML_TAG_PHASE2_METHOD: enterpriseConfig.setPhase2Method((int) value); break; + case XML_TAG_PLMN: + enterpriseConfig.setPlmn((String) value); + break; + case XML_TAG_REALM: + enterpriseConfig.setRealm((String) value); + break; default: throw new XmlPullParserException( "Unknown value name found: " + valueName[0]); |