summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorNate Jiang <qiangjiang@google.com>2019-12-10 02:34:07 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-12-10 02:34:07 +0000
commit47fc6c5f3eb6ba273c3f04890971a63c31324996 (patch)
tree57c9b66c1cf0f55d71e1145f3fe276dc7516f583 /service
parentf05e2f3f34b31061c22e5ceaed861a4e9f97a69d (diff)
parent3fe95912af8f17c5964a607aa9133c3f87bbe920 (diff)
Merge changes Ic33d2d48,Ic40a0e39,I96ef09f5,I996dd19a
* changes: [passpoint] match the best scanDetail to the provider allows multiple passpoint candidates rename evaluator to nominator [Evaluator] evaluator will only nominate candidates
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/CarrierNetworkNominator.java (renamed from service/java/com/android/server/wifi/CarrierNetworkEvaluator.java)33
-rw-r--r--service/java/com/android/server/wifi/CompatibilityScorer.java2
-rw-r--r--service/java/com/android/server/wifi/NetworkSuggestionNominator.java (renamed from service/java/com/android/server/wifi/NetworkSuggestionEvaluator.java)61
-rw-r--r--service/java/com/android/server/wifi/SavedNetworkEvaluator.java297
-rw-r--r--service/java/com/android/server/wifi/SavedNetworkNominator.java147
-rw-r--r--service/java/com/android/server/wifi/ScoreCardBasedScorer.java2
-rw-r--r--service/java/com/android/server/wifi/ScoredNetworkNominator.java (renamed from service/java/com/android/server/wifi/ScoredNetworkEvaluator.java)30
-rw-r--r--service/java/com/android/server/wifi/ThroughputScorer.java2
-rw-r--r--service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java2
-rw-r--r--service/java/com/android/server/wifi/WifiCandidates.java25
-rw-r--r--service/java/com/android/server/wifi/WifiConfigManager.java5
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java42
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java16
-rw-r--r--service/java/com/android/server/wifi/WifiNetworkSelector.java166
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointManager.java66
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java241
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominator.java259
17 files changed, 605 insertions, 791 deletions
diff --git a/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java b/service/java/com/android/server/wifi/CarrierNetworkNominator.java
index c9f567e89..c1a3e02a3 100644
--- a/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/CarrierNetworkNominator.java
@@ -23,7 +23,7 @@ import android.os.Process;
import android.telephony.TelephonyManager;
import android.util.LocalLog;
-import com.android.server.wifi.WifiNetworkSelector.NetworkEvaluator;
+import com.android.server.wifi.WifiNetworkSelector.NetworkNominator;
import com.android.server.wifi.util.ScanResultUtil;
import com.android.server.wifi.util.TelephonyUtil;
@@ -32,21 +32,18 @@ import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
/**
- * Evaluator to select a Carrier Wi-Fi network which can be connected to. The evaluator performs
+ * Nominator to select a Carrier Wi-Fi network which can be connected to. The Nominator performs
* two functions:
*
* 1. Filtering: figure out which of the networks is a Carrier Wi-Fi network (using the
* {@link CarrierNetworkConfig} APIs).
- * 2. Evaluation: current evaluator API has 2 outputs (effectively):
- * - Connectable networks: all networks which match #1 will be fed to this API
- * - Selected network: a single network 'selected' by the evaluator. A simple max(RSSI) will be
- * used to pick one network from among the connectable networks.
+ * 2. Nominating: Connectable networks: all networks which match #1 will be fed to this API
*
* Note: This class is not thread safe and meant to be used only from {@link WifiNetworkSelector}.
*/
@NotThreadSafe
-public class CarrierNetworkEvaluator implements NetworkEvaluator {
- private static final String TAG = "CarrierNetworkEvaluator";
+public class CarrierNetworkNominator implements NetworkNominator {
+ private static final String TAG = "CarrierNetworkNominator";
private final WifiConfigManager mWifiConfigManager;
private final CarrierNetworkConfig mCarrierNetworkConfig;
@@ -54,7 +51,7 @@ public class CarrierNetworkEvaluator implements NetworkEvaluator {
private final WifiInjector mWifiInjector;
private TelephonyManager mTelephonyManager;
- public CarrierNetworkEvaluator(WifiConfigManager wifiConfigManager,
+ public CarrierNetworkNominator(WifiConfigManager wifiConfigManager,
CarrierNetworkConfig carrierNetworkConfig, LocalLog localLog,
WifiInjector wifiInjector) {
mWifiConfigManager = wifiConfigManager;
@@ -71,8 +68,8 @@ public class CarrierNetworkEvaluator implements NetworkEvaluator {
}
@Override
- public @EvaluatorId int getId() {
- return EVALUATOR_ID_CARRIER;
+ public @NominatorId int getId() {
+ return NOMINATOR_ID_CARRIER;
}
@Override
@@ -86,15 +83,13 @@ public class CarrierNetworkEvaluator implements NetworkEvaluator {
}
@Override
- public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
+ public void nominateNetworks(List<ScanDetail> scanDetails,
WifiConfiguration currentNetwork, String currentBssid, boolean connected,
boolean untrustedNetworkAllowed, OnConnectableListener onConnectableListener) {
if (!mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()) {
- return null;
+ return;
}
- int currentMaxRssi = Integer.MIN_VALUE;
- WifiConfiguration configWithMaxRssi = null;
for (ScanDetail scanDetail : scanDetails) {
ScanResult scanResult = scanDetail.getScanResult();
@@ -168,13 +163,7 @@ public class CarrierNetworkEvaluator implements NetworkEvaluator {
mWifiConfigManager.updateScanDetailForNetwork(result.getNetworkId(), scanDetail);
}
- onConnectableListener.onConnectable(scanDetail, config, 0);
- if (scanResult.level > currentMaxRssi) {
- configWithMaxRssi = config;
- currentMaxRssi = scanResult.level;
- }
+ onConnectableListener.onConnectable(scanDetail, config);
}
-
- return configWithMaxRssi;
}
}
diff --git a/service/java/com/android/server/wifi/CompatibilityScorer.java b/service/java/com/android/server/wifi/CompatibilityScorer.java
index e354b70a8..f2ec5b9df 100644
--- a/service/java/com/android/server/wifi/CompatibilityScorer.java
+++ b/service/java/com/android/server/wifi/CompatibilityScorer.java
@@ -98,7 +98,7 @@ final class CompatibilityScorer implements WifiCandidates.CandidateScorer {
// To simulate the old strict priority rule, subtract a penalty based on
// which evaluator added the candidate.
- score -= 1000 * candidate.getEvaluatorId();
+ score -= 1000 * candidate.getNominatorId();
// The old method breaks ties on the basis of RSSI, which we can
// emulate easily since our score does not need to be an integer.
diff --git a/service/java/com/android/server/wifi/NetworkSuggestionEvaluator.java b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
index c8f370bcc..08bfb65a4 100644
--- a/service/java/com/android/server/wifi/NetworkSuggestionEvaluator.java
+++ b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
@@ -28,7 +28,6 @@ import com.android.server.wifi.util.ScanResultUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -39,30 +38,21 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
/**
- * Evaluator to pick the best network to connect to from the list of active network suggestions
- * provided by apps.
+ * Nominator nominate the highest available suggestion candidates.
* Note:
* <li> This class is not thread safe and meant to be used only from {@link WifiNetworkSelector}.
* </li>
*
- * This is a non-optimal implementation which picks any network suggestion which matches
- * the scan result with the highest RSSI.
- * TODO: More advanced implementation will follow!
- * Params to consider for evaluating network suggestions:
- * - Regular network evaluator params like security, band, RSSI, etc.
- * - Priority of suggestions provided by a single app.
- * - Whether the network suggestions requires user/app interaction or if it is metered.
- * - Historical quality of suggestions provided by the corresponding app.
*/
@NotThreadSafe
-public class NetworkSuggestionEvaluator implements WifiNetworkSelector.NetworkEvaluator {
- private static final String TAG = "NetworkSuggestionEvaluator";
+public class NetworkSuggestionNominator implements WifiNetworkSelector.NetworkNominator {
+ private static final String TAG = "NetworkSuggestionNominator";
private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
private final WifiConfigManager mWifiConfigManager;
private final LocalLog mLocalLog;
- NetworkSuggestionEvaluator(WifiNetworkSuggestionsManager networkSuggestionsManager,
+ NetworkSuggestionNominator(WifiNetworkSuggestionsManager networkSuggestionsManager,
WifiConfigManager wifiConfigManager, LocalLog localLog) {
mWifiNetworkSuggestionsManager = networkSuggestionsManager;
mWifiConfigManager = wifiConfigManager;
@@ -75,7 +65,7 @@ public class NetworkSuggestionEvaluator implements WifiNetworkSelector.NetworkEv
}
@Override
- public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
+ public void nominateNetworks(List<ScanDetail> scanDetails,
WifiConfiguration currentNetwork, String currentBssid, boolean connected,
boolean untrustedNetworkAllowed,
@NonNull OnConnectableListener onConnectableListener) {
@@ -133,17 +123,9 @@ public class NetworkSuggestionEvaluator implements WifiNetworkSelector.NetworkEv
// Return early on no match.
if (matchMetaInfo.isEmpty()) {
mLocalLog.log("did not see any matching network suggestions.");
- return null;
- }
- // Note: These matched sets should be very small & hence these additional manipulations that
- // follow should not be very expensive.
- PerNetworkSuggestionMatchMetaInfo candidate =
- matchMetaInfo.findConnectableNetworksAndPickBest(onConnectableListener);
- if (candidate == null) { // should never happen.
- Log.wtf(TAG, "Unexepectedly got null");
- return null;
+ return;
}
- return candidate.wCmConfiguredNetwork;
+ matchMetaInfo.findConnectableNetworksAndHighestPriority(onConnectableListener);
}
// Add and enable this network to the central database (i.e WifiConfigManager).
@@ -170,8 +152,8 @@ public class NetworkSuggestionEvaluator implements WifiNetworkSelector.NetworkEv
}
@Override
- public @EvaluatorId int getId() {
- return EVALUATOR_ID_SUGGESTION;
+ public @NominatorId int getId() {
+ return NOMINATOR_ID_SUGGESTION;
}
@Override
@@ -263,16 +245,11 @@ public class NetworkSuggestionEvaluator implements WifiNetworkSelector.NetworkEv
}
/**
- * Find all the connectable networks and pick the best network among the current match info
- * candidates.
- *
- * Among the highest priority suggestions from different packages, choose the suggestion
- * with the highest RSSI.
- * Note: This should need to be replaced by a more sophisticated algorithm.
+ * Run through all connectable suggestions and nominate highest priority networks from each
+ * app as candidates to {@link WifiNetworkSelector}.
*/
- public PerNetworkSuggestionMatchMetaInfo findConnectableNetworksAndPickBest(
+ public void findConnectableNetworksAndHighestPriority(
@NonNull OnConnectableListener onConnectableListener) {
- List<PerNetworkSuggestionMatchMetaInfo> allMatchedNetworkInfos = new ArrayList<>();
for (PerAppMatchMetaInfo appInfo : mAppInfos.values()) {
List<PerNetworkSuggestionMatchMetaInfo> matchedNetworkInfos =
appInfo.getHighestPriorityNetworks();
@@ -292,23 +269,11 @@ public class NetworkSuggestionEvaluator implements WifiNetworkSelector.NetworkEv
WifiNetworkSelector.toNetworkString(
matchedNetworkInfo.wCmConfiguredNetwork)));
}
- allMatchedNetworkInfos.add(matchedNetworkInfo);
- // Invoke onConnectable for the best networks from each app.
onConnectableListener.onConnectable(
matchedNetworkInfo.matchingScanDetail,
- matchedNetworkInfo.wCmConfiguredNetwork,
- 0);
+ matchedNetworkInfo.wCmConfiguredNetwork);
}
}
- PerNetworkSuggestionMatchMetaInfo networkInfo = allMatchedNetworkInfos
- .stream()
- .max(Comparator.comparing(e -> e.matchingScanDetail.getScanResult().level))
- .orElse(null);
- if (networkInfo == null) { // should never happen.
- Log.wtf(TAG, "Unexepectedly got null");
- return null;
- }
- return networkInfo;
}
}
diff --git a/service/java/com/android/server/wifi/SavedNetworkEvaluator.java b/service/java/com/android/server/wifi/SavedNetworkEvaluator.java
deleted file mode 100644
index d3254790b..000000000
--- a/service/java/com/android/server/wifi/SavedNetworkEvaluator.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wifi;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.util.LocalLog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.wifi.util.TelephonyUtil;
-import com.android.wifi.resources.R;
-
-import java.util.List;
-
-/**
- * This class is the WifiNetworkSelector.NetworkEvaluator implementation for
- * saved networks.
- */
-public class SavedNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator {
- private static final String NAME = "SavedNetworkEvaluator";
- private final WifiConfigManager mWifiConfigManager;
- private final Context mContext;
- private final Clock mClock;
- private final LocalLog mLocalLog;
- private final WifiConnectivityHelper mConnectivityHelper;
- private final TelephonyUtil mTelephonyUtil;
- private final ScoringParams mScoringParams;
-
- /**
- * Time it takes for the lastSelectionAward to decay by one point, in milliseconds
- */
- @VisibleForTesting
- public static final int LAST_SELECTION_AWARD_DECAY_MSEC = 60 * 1000;
-
-
- SavedNetworkEvaluator(final Context context, ScoringParams scoringParams,
- WifiConfigManager configManager, Clock clock,
- LocalLog localLog, WifiConnectivityHelper connectivityHelper,
- TelephonyUtil telephonyUtil) {
- mContext = context;
- mScoringParams = scoringParams;
- mWifiConfigManager = configManager;
- mClock = clock;
- mLocalLog = localLog;
- mConnectivityHelper = connectivityHelper;
- mTelephonyUtil = telephonyUtil;
-
- }
-
- private void localLog(String log) {
- mLocalLog.log(log);
- }
-
- /**
- * Get the evaluator type.
- */
- @Override
- public @EvaluatorId int getId() {
- return EVALUATOR_ID_SAVED;
- }
-
- /**
- * Get the evaluator name.
- */
- @Override
- public String getName() {
- return NAME;
- }
-
- /**
- * Update the evaluator.
- */
- @Override
- public void update(List<ScanDetail> scanDetails) { }
-
- private int calculateBssidScore(ScanResult scanResult, WifiConfiguration network,
- WifiConfiguration currentNetwork, String currentBssid,
- StringBuffer sbuf) {
- int score = 0;
- boolean is5GHz = scanResult.is5GHz();
- boolean is6GHz = scanResult.is6GHz();
-
- final int rssiScoreSlope = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_RSSI_SCORE_SLOPE);
- final int rssiScoreOffset = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_RSSI_SCORE_OFFSET);
- final int sameBssidAward = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_SAME_BSSID_AWARD);
- final int sameNetworkAward = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_current_network_boost);
- final int lastSelectionAward = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_LAST_SELECTION_AWARD);
- final int securityAward = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_SECURITY_AWARD);
- final int band5GHzAward = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_5GHz_preference_boost_factor);
- final int band6GHzAward = mContext.getResources().getInteger(
- R.integer.config_wifiFramework6ghzPreferenceBoostFactor);
-
- sbuf.append("[ ").append(scanResult.SSID).append(" ").append(scanResult.BSSID)
- .append(" RSSI:").append(scanResult.level).append(" ] ");
- // Calculate the RSSI score.
- int rssiSaturationThreshold = mScoringParams.getGoodRssi(scanResult.frequency);
- int rssi = Math.min(scanResult.level, rssiSaturationThreshold);
- score += (rssi + rssiScoreOffset) * rssiScoreSlope;
- sbuf.append(" RSSI score: ").append(score).append(",");
-
- // 5GHz band bonus.
- if (is5GHz) {
- score += band5GHzAward;
- sbuf.append(" 5GHz bonus: ").append(band5GHzAward).append(",");
- } else if (is6GHz) {
- score += band6GHzAward;
- sbuf.append(" 6GHz bonus: ").append(band6GHzAward).append(",");
- }
-
- // Last user selection award.
- int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork();
- if (lastUserSelectedNetworkId != WifiConfiguration.INVALID_NETWORK_ID
- && lastUserSelectedNetworkId == network.networkId) {
- long timeDifference = mClock.getElapsedSinceBootMillis()
- - mWifiConfigManager.getLastSelectedTimeStamp();
- if (timeDifference > 0) {
- int decay = (int) (timeDifference / LAST_SELECTION_AWARD_DECAY_MSEC);
- int bonus = Math.max(lastSelectionAward - decay, 0);
- score += bonus;
- sbuf.append(" User selection ").append(timeDifference)
- .append(" ms ago, bonus: ").append(bonus).append(",");
- }
- }
-
- // Same network award.
- if (currentNetwork != null && network.networkId == currentNetwork.networkId) {
- score += sameNetworkAward;
- sbuf.append(" Same network bonus: ").append(sameNetworkAward).append(",");
-
- // When firmware roaming is supported, equivalent BSSIDs (the ones under the
- // same network as the currently connected one) get the same BSSID award.
- if (mConnectivityHelper.isFirmwareRoamingSupported()
- && currentBssid != null && !currentBssid.equals(scanResult.BSSID)) {
- score += sameBssidAward;
- sbuf.append(" Equivalent BSSID bonus: ").append(sameBssidAward).append(",");
- }
- }
-
- // Same BSSID award.
- if (currentBssid != null && currentBssid.equals(scanResult.BSSID)) {
- score += sameBssidAward;
- sbuf.append(" Same BSSID bonus: ").append(sameBssidAward).append(",");
- }
-
- // Security award.
- if (!WifiConfigurationUtil.isConfigForOpenNetwork(network)) {
- score += securityAward;
- sbuf.append(" Secure network bonus: ").append(securityAward).append(",");
- }
-
- sbuf.append(" ## Total score: ").append(score).append("\n");
-
- return score;
- }
-
- /**
- * Evaluate all the networks from the scan results and return
- * the WifiConfiguration of the network chosen for connection.
- *
- * @return configuration of the chosen network;
- * null if no network in this category is available.
- */
- @Override
- public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
- WifiConfiguration currentNetwork, String currentBssid, boolean connected,
- boolean untrustedNetworkAllowed,
- @NonNull OnConnectableListener onConnectableListener) {
- int highestScore = Integer.MIN_VALUE;
- ScanResult scanResultCandidate = null;
- WifiConfiguration candidate = null;
- StringBuffer scoreHistory = new StringBuffer();
-
- for (ScanDetail scanDetail : scanDetails) {
- ScanResult scanResult = scanDetail.getScanResult();
-
- // One ScanResult can be associated with more than one network, hence we calculate all
- // the scores and use the highest one as the ScanResult's score.
- // TODO(b/112196799): this has side effects, rather not do that in an evaluator
- WifiConfiguration network =
- mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail);
-
- if (network == null) {
- continue;
- }
-
- // Ignore networks that the user has disallowed auto-join for.
- if (!network.allowAutojoin) {
- continue;
- }
-
- /**
- * Ignore Passpoint and Ephemeral networks. They are configured networks,
- * but without being persisted to the storage. They are evaluated by
- * {@link PasspointNetworkEvaluator} and {@link ScoredNetworkEvaluator}
- * respectively.
- */
- if (network.isPasspoint() || network.isEphemeral()) {
- continue;
- }
-
- WifiConfiguration.NetworkSelectionStatus status =
- network.getNetworkSelectionStatus();
- // TODO (b/112196799): another side effect
- status.setSeenInLastQualifiedNetworkSelection(true);
-
- if (!status.isNetworkEnabled()) {
- continue;
- } else if (network.BSSID != null && !network.BSSID.equals("any")
- && !network.BSSID.equals(scanResult.BSSID)) {
- // App has specified the only BSSID to connect for this
- // configuration. So only the matching ScanResult can be a candidate.
- localLog("Network " + WifiNetworkSelector.toNetworkString(network)
- + " has specified BSSID " + network.BSSID + ". Skip "
- + scanResult.BSSID);
- continue;
- } else if (network.enterpriseConfig != null
- && network.enterpriseConfig.requireSimCredential()) {
- int subId = mTelephonyUtil.getBestMatchSubscriptionId(network);
- if (!mTelephonyUtil.isSimPresent(subId)) {
- // Don't select if security type is EAP SIM/AKA/AKA' when SIM is not present.
- localLog("No SIM card is good for Network "
- + WifiNetworkSelector.toNetworkString(network));
- continue;
- }
- }
-
- int score = calculateBssidScore(scanResult, network, currentNetwork, currentBssid,
- scoreHistory);
-
- // Set candidate ScanResult for all saved networks to ensure that users can
- // override network selection. See WifiNetworkSelector#setUserConnectChoice.
- if (score > status.getCandidateScore()
- || (score == status.getCandidateScore()
- && status.getCandidate() != null
- && scanResult.level > status.getCandidate().level)) {
- mWifiConfigManager.setNetworkCandidateScanResult(
- network.networkId, scanResult, score);
- }
-
- // If the network is marked to use external scores, or is an open network with
- // curate saved open networks enabled, do not consider it for network selection.
- if (network.useExternalScores) {
- localLog("Network " + WifiNetworkSelector.toNetworkString(network)
- + " has external score.");
- continue;
- }
-
- onConnectableListener.onConnectable(scanDetail,
- mWifiConfigManager.getConfiguredNetwork(network.networkId), score);
-
- // TODO(b/112196799) - pull into common code
- if (score > highestScore
- || (score == highestScore
- && scanResultCandidate != null
- && scanResult.level > scanResultCandidate.level)) {
- highestScore = score;
- scanResultCandidate = scanResult;
- mWifiConfigManager.setNetworkCandidateScanResult(
- network.networkId, scanResultCandidate, highestScore);
- // Reload the network config with the updated info.
- candidate = mWifiConfigManager.getConfiguredNetwork(network.networkId);
- }
- }
-
- if (scoreHistory.length() > 0) {
- localLog("\n" + scoreHistory.toString());
- }
-
- if (scanResultCandidate == null) {
- localLog("did not see any good candidates.");
- }
- return candidate;
- }
-}
diff --git a/service/java/com/android/server/wifi/SavedNetworkNominator.java b/service/java/com/android/server/wifi/SavedNetworkNominator.java
new file mode 100644
index 000000000..7c00ce7e1
--- /dev/null
+++ b/service/java/com/android/server/wifi/SavedNetworkNominator.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import android.annotation.NonNull;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.util.LocalLog;
+
+import com.android.server.wifi.util.TelephonyUtil;
+
+import java.util.List;
+
+/**
+ * This class is the WifiNetworkSelector.NetworkNominator implementation for
+ * saved networks.
+ */
+public class SavedNetworkNominator implements WifiNetworkSelector.NetworkNominator {
+ private static final String NAME = "SavedNetworkNominator";
+ private final WifiConfigManager mWifiConfigManager;
+ private final LocalLog mLocalLog;
+ private final TelephonyUtil mTelephonyUtil;
+
+ SavedNetworkNominator(WifiConfigManager configManager, LocalLog localLog,
+ TelephonyUtil telephonyUtil) {
+ mWifiConfigManager = configManager;
+ mLocalLog = localLog;
+ mTelephonyUtil = telephonyUtil;
+ }
+
+ private void localLog(String log) {
+ mLocalLog.log(log);
+ }
+
+ /**
+ * Get the Nominator type.
+ */
+ @Override
+ public @NominatorId int getId() {
+ return NOMINATOR_ID_SAVED;
+ }
+
+ /**
+ * Get the Nominator name.
+ */
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ /**
+ * Update the Nominator.
+ */
+ @Override
+ public void update(List<ScanDetail> scanDetails) { }
+
+ /**
+ * Run through all scanDetails and nominate all connectable network as candidates.
+ *
+ */
+ @Override
+ public void nominateNetworks(List<ScanDetail> scanDetails,
+ WifiConfiguration currentNetwork, String currentBssid, boolean connected,
+ boolean untrustedNetworkAllowed,
+ @NonNull OnConnectableListener onConnectableListener) {
+
+ for (ScanDetail scanDetail : scanDetails) {
+ ScanResult scanResult = scanDetail.getScanResult();
+
+ // One ScanResult can be associated with more than one network, hence we calculate all
+ // the scores and use the highest one as the ScanResult's score.
+ // TODO(b/112196799): this has side effects, rather not do that in a nominator
+ WifiConfiguration network =
+ mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail);
+
+ if (network == null) {
+ continue;
+ }
+
+ // Ignore networks that the user has disallowed auto-join for.
+ if (!network.allowAutojoin) {
+ continue;
+ }
+
+ /**
+ * Ignore Passpoint and Ephemeral networks. They are configured networks,
+ * but without being persisted to the storage. They are nominated by
+ * {@link PasspointNetworkNominator} and {@link ScoredNetworkNominator}
+ * respectively.
+ */
+ if (network.isPasspoint() || network.isEphemeral()) {
+ continue;
+ }
+
+ WifiConfiguration.NetworkSelectionStatus status =
+ network.getNetworkSelectionStatus();
+ // TODO (b/112196799): another side effect
+ status.setSeenInLastQualifiedNetworkSelection(true);
+
+ if (!status.isNetworkEnabled()) {
+ continue;
+ } else if (network.BSSID != null && !network.BSSID.equals("any")
+ && !network.BSSID.equals(scanResult.BSSID)) {
+ // App has specified the only BSSID to connect for this
+ // configuration. So only the matching ScanResult can be a candidate.
+ localLog("Network " + WifiNetworkSelector.toNetworkString(network)
+ + " has specified BSSID " + network.BSSID + ". Skip "
+ + scanResult.BSSID);
+ continue;
+ } else if (network.enterpriseConfig != null
+ && network.enterpriseConfig.requireSimCredential()) {
+ int subId = mTelephonyUtil.getBestMatchSubscriptionId(network);
+ if (!mTelephonyUtil.isSimPresent(subId)) {
+ // Don't select if security type is EAP SIM/AKA/AKA' when SIM is not present.
+ localLog("No SIM card is good for Network "
+ + WifiNetworkSelector.toNetworkString(network));
+ continue;
+ }
+ }
+
+ // If the network is marked to use external scores, or is an open network with
+ // curate saved open networks enabled, do not consider it for network selection.
+ if (network.useExternalScores) {
+ localLog("Network " + WifiNetworkSelector.toNetworkString(network)
+ + " has external score.");
+ continue;
+ }
+
+ onConnectableListener.onConnectable(scanDetail,
+ mWifiConfigManager.getConfiguredNetwork(network.networkId));
+ }
+ }
+}
diff --git a/service/java/com/android/server/wifi/ScoreCardBasedScorer.java b/service/java/com/android/server/wifi/ScoreCardBasedScorer.java
index 8e0c3e778..e8617e11b 100644
--- a/service/java/com/android/server/wifi/ScoreCardBasedScorer.java
+++ b/service/java/com/android/server/wifi/ScoreCardBasedScorer.java
@@ -106,7 +106,7 @@ final class ScoreCardBasedScorer implements WifiCandidates.CandidateScorer {
// To simulate the old strict priority rule, subtract a penalty based on
// which evaluator added the candidate.
- score -= 1000 * candidate.getEvaluatorId();
+ score -= 1000 * candidate.getNominatorId();
return new ScoredCandidate(score, 10,
USE_USER_CONNECT_CHOICE, candidate);
diff --git a/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java b/service/java/com/android/server/wifi/ScoredNetworkNominator.java
index 000d1f69e..64df5ced7 100644
--- a/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/ScoredNetworkNominator.java
@@ -39,11 +39,11 @@ import java.util.ArrayList;
import java.util.List;
/**
- * {@link WifiNetworkSelector.NetworkEvaluator} implementation that uses scores obtained by
+ * {@link WifiNetworkSelector.NetworkNominator} implementation that uses scores obtained by
* {@link NetworkScoreManager#requestScores(NetworkKey[])} to make network connection decisions.
*/
-public class ScoredNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator {
- private static final String TAG = "ScoredNetworkEvaluator";
+public class ScoredNetworkNominator implements WifiNetworkSelector.NetworkNominator {
+ private static final String TAG = "ScoredNetworkNominator";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final NetworkScoreManager mNetworkScoreManager;
@@ -55,7 +55,7 @@ public class ScoredNetworkEvaluator implements WifiNetworkSelector.NetworkEvalua
private boolean mNetworkRecommendationsEnabled;
private WifiNetworkScoreCache mScoreCache;
- ScoredNetworkEvaluator(final Context context, Handler handler,
+ ScoredNetworkNominator(final Context context, Handler handler,
final FrameworkFacade frameworkFacade, NetworkScoreManager networkScoreManager,
PackageManager packageManager,
WifiConfigManager wifiConfigManager, LocalLog localLog,
@@ -78,7 +78,7 @@ public class ScoredNetworkEvaluator implements WifiNetworkSelector.NetworkEvalua
Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED),
false /* notifyForDescendents */, mContentObserver);
mContentObserver.onChange(false /* unused */);
- mLocalLog.log("ScoredNetworkEvaluator constructed. mNetworkRecommendationsEnabled: "
+ mLocalLog.log("ScoredNetworkNominator constructed. mNetworkRecommendationsEnabled: "
+ mNetworkRecommendationsEnabled);
}
@@ -131,13 +131,13 @@ public class ScoredNetworkEvaluator implements WifiNetworkSelector.NetworkEvalua
}
@Override
- public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
+ public void nominateNetworks(List<ScanDetail> scanDetails,
WifiConfiguration currentNetwork, String currentBssid, boolean connected,
boolean untrustedNetworkAllowed,
@NonNull OnConnectableListener onConnectableListener) {
if (!mNetworkRecommendationsEnabled) {
- mLocalLog.log("Skipping evaluateNetworks; Network recommendations disabled.");
- return null;
+ mLocalLog.log("Skipping nominateNetworks; Network recommendations disabled.");
+ return;
}
final ScoreTracker scoreTracker = new ScoreTracker();
@@ -188,11 +188,9 @@ public class ScoredNetworkEvaluator implements WifiNetworkSelector.NetworkEvalua
scoreTracker.trackExternallyScoredCandidate(
scanResult, configuredNetwork, isCurrentNetwork);
}
- onConnectableListener.onConnectable(scanDetail, configuredNetwork, 0);
+ onConnectableListener.onConnectable(scanDetail, configuredNetwork);
}
-
-
- return scoreTracker.getCandidateConfiguration(onConnectableListener);
+ scoreTracker.getCandidateConfiguration(onConnectableListener);
}
/** Used to track the network with the highest score. */
@@ -340,14 +338,14 @@ public class ScoredNetworkEvaluator implements WifiNetworkSelector.NetworkEvalua
break;
case ScoreTracker.EXTERNAL_SCORED_NONE:
default:
- mLocalLog.log("ScoredNetworkEvaluator did not see any good candidates.");
+ mLocalLog.log("ScoredNetworkNominator did not see any good candidates.");
break;
}
WifiConfiguration ans = mWifiConfigManager.getConfiguredNetwork(
candidateNetworkId);
if (ans != null && mScanDetailCandidate != null) {
// This is a newly created config, so we need to call onConnectable.
- onConnectableListener.onConnectable(mScanDetailCandidate, ans, 0);
+ onConnectableListener.onConnectable(mScanDetailCandidate, ans);
}
return ans;
}
@@ -360,8 +358,8 @@ public class ScoredNetworkEvaluator implements WifiNetworkSelector.NetworkEvalua
}
@Override
- public @EvaluatorId int getId() {
- return EVALUATOR_ID_SCORED;
+ public @NominatorId int getId() {
+ return NOMINATOR_ID_SCORED;
}
@Override
diff --git a/service/java/com/android/server/wifi/ThroughputScorer.java b/service/java/com/android/server/wifi/ThroughputScorer.java
index 1e42657c6..8177462de 100644
--- a/service/java/com/android/server/wifi/ThroughputScorer.java
+++ b/service/java/com/android/server/wifi/ThroughputScorer.java
@@ -97,7 +97,7 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer {
// To simulate the old strict priority rule, subtract a penalty based on
// which evaluator added the candidate.
- int evaluatorGroupScore = -1000 * candidate.getEvaluatorId();
+ int evaluatorGroupScore = -1000 * candidate.getNominatorId();
int score = rssiBaseScore + throughputBonusScore + lastSelectionBonusScore
+ currentNetworkBoost + securityAward + evaluatorGroupScore;
diff --git a/service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java b/service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java
index 7eae75827..f3dd6000c 100644
--- a/service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/UntrustedWifiNetworkFactory.java
@@ -27,7 +27,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
- * Network factory to handle untrusted (used for {@link ScoredNetworkEvaluator}) wifi network
+ * Network factory to handle untrusted (used for {@link ScoredNetworkNominator}) wifi network
* requests.
*/
public class UntrustedWifiNetworkFactory extends NetworkFactory {
diff --git a/service/java/com/android/server/wifi/WifiCandidates.java b/service/java/com/android/server/wifi/WifiCandidates.java
index d0f354232..1f6ed8dee 100644
--- a/service/java/com/android/server/wifi/WifiCandidates.java
+++ b/service/java/com/android/server/wifi/WifiCandidates.java
@@ -84,14 +84,15 @@ public class WifiCandidates {
/**
* Returns the ID of the evaluator that provided the candidate.
*/
- @WifiNetworkSelector.NetworkEvaluator.EvaluatorId int getEvaluatorId();
+ @WifiNetworkSelector.NetworkNominator.NominatorId
+ int getNominatorId();
/**
* Gets the score that was provided by the evaluator.
*
* Not all evaluators provide a useful score. Scores from different evaluators
* are not directly comparable.
*/
- int getEvaluatorScore();
+ int getNominatorScore();
/**
* Returns true if the candidate is in the same network as the
* current connection.
@@ -134,7 +135,7 @@ public class WifiCandidates {
public final ScanDetail scanDetail;
public final WifiConfiguration config;
// First evaluator to nominate this config
- public final @WifiNetworkSelector.NetworkEvaluator.EvaluatorId int evaluatorId;
+ public final @WifiNetworkSelector.NetworkNominator.NominatorId int evaluatorId;
public final int evaluatorScore; // Score provided by first nominating evaluator
public final double lastSelectionWeight; // Value between 0 and 1
@@ -147,7 +148,7 @@ public class WifiCandidates {
CandidateImpl(Key key,
ScanDetail scanDetail,
WifiConfiguration config,
- @WifiNetworkSelector.NetworkEvaluator.EvaluatorId int evaluatorId,
+ @WifiNetworkSelector.NetworkNominator.NominatorId int evaluatorId,
int evaluatorScore,
WifiScoreCard.PerBssid perBssid,
double lastSelectionWeight,
@@ -210,12 +211,12 @@ public class WifiCandidates {
}
@Override
- public @WifiNetworkSelector.NetworkEvaluator.EvaluatorId int getEvaluatorId() {
+ public @WifiNetworkSelector.NetworkNominator.NominatorId int getNominatorId() {
return evaluatorId;
}
@Override
- public int getEvaluatorScore() {
+ public int getNominatorScore() {
return evaluatorScore;
}
@@ -368,7 +369,7 @@ public class WifiCandidates {
*/
public boolean add(ScanDetail scanDetail,
WifiConfiguration config,
- @WifiNetworkSelector.NetworkEvaluator.EvaluatorId int evaluatorId,
+ @WifiNetworkSelector.NetworkNominator.NominatorId int evaluatorId,
int evaluatorScore,
double lastSelectionWeightBetweenZeroAndOne,
boolean isMetered,
@@ -383,9 +384,13 @@ public class WifiCandidates {
} catch (RuntimeException e) {
return failWithException(e);
}
- ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(config);
- ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanResult);
- if (!key1.equals(key2)) return failure(key1, key2);
+ ScanResultMatchInfo key1 = ScanResultMatchInfo.fromScanResult(scanResult);
+ if (!config.isPasspoint()) {
+ ScanResultMatchInfo key2 = ScanResultMatchInfo.fromWifiConfiguration(config);
+ if (!key1.equals(key2)) {
+ return failure(key1, key2);
+ }
+ }
Key key = new Key(key1, bssid, config.networkId);
CandidateImpl old = mCandidates.get(key);
if (old != null) {
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 44711096d..c00c33019 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -53,6 +53,7 @@ import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.hotspot2.PasspointManager;
+import com.android.server.wifi.hotspot2.PasspointNetworkNominator;
import com.android.server.wifi.util.TelephonyUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -939,7 +940,7 @@ public class WifiConfigManager {
}
// Passpoint configurations are generated and managed by PasspointManager. They can be
- // added by either PasspointNetworkEvaluator (for auto connection) or Settings app
+ // added by either PasspointNetworkNominator (for auto connection) or Settings app
// (for manual connection), and need to be removed once the connection is completed.
// Since it is "owned" by us, so always allow us to modify them.
if (config.isPasspoint() && uid == Process.WIFI_UID) {
@@ -2461,7 +2462,7 @@ public class WifiConfigManager {
/**
* Save the ScanDetail to the ScanDetailCache of the given network. This is used
- * by {@link com.android.server.wifi.hotspot2.PasspointNetworkEvaluator} for caching
+ * by {@link PasspointNetworkNominator} for caching
* ScanDetail for newly created {@link WifiConfiguration} for Passpoint network.
*
* @param networkId The ID of the network to save ScanDetail to
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 9e2fa6e2d..214e4a223 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -49,7 +49,7 @@ import android.util.Log;
import com.android.server.wifi.aware.WifiAwareMetrics;
import com.android.server.wifi.hotspot2.PasspointManager;
-import com.android.server.wifi.hotspot2.PasspointNetworkEvaluator;
+import com.android.server.wifi.hotspot2.PasspointNetworkNominator;
import com.android.server.wifi.hotspot2.PasspointObjectFactory;
import com.android.server.wifi.p2p.SupplicantP2pIfaceHal;
import com.android.server.wifi.p2p.WifiP2pMetrics;
@@ -124,11 +124,11 @@ public class WifiInjector {
private final WifiConnectivityHelper mWifiConnectivityHelper;
private final LocalLog mConnectivityLocalLog;
private final WifiNetworkSelector mWifiNetworkSelector;
- private final SavedNetworkEvaluator mSavedNetworkEvaluator;
- private final NetworkSuggestionEvaluator mNetworkSuggestionEvaluator;
- private final PasspointNetworkEvaluator mPasspointNetworkEvaluator;
- private final ScoredNetworkEvaluator mScoredNetworkEvaluator;
- private final CarrierNetworkEvaluator mCarrierNetworkEvaluator;
+ private final SavedNetworkNominator mSavedNetworkNominator;
+ private final NetworkSuggestionNominator mNetworkSuggestionNominator;
+ private final PasspointNetworkNominator mPasspointNetworkNominator;
+ private final ScoredNetworkNominator mScoredNetworkNominator;
+ private final CarrierNetworkNominator mCarrierNetworkNominator;
private final WifiNetworkScoreCache mWifiNetworkScoreCache;
private final NetworkScoreManager mNetworkScoreManager;
private WifiScanner mWifiScanner;
@@ -292,25 +292,23 @@ public class WifiInjector {
ThroughputScorer throughputScorer = new ThroughputScorer(mScoringParams);
mWifiNetworkSelector.registerCandidateScorer(throughputScorer);
mWifiMetrics.setWifiNetworkSelector(mWifiNetworkSelector);
- mSavedNetworkEvaluator = new SavedNetworkEvaluator(mContext, mScoringParams,
- mWifiConfigManager, mClock, mConnectivityLocalLog, mWifiConnectivityHelper,
- mTelephonyUtil);
+ mSavedNetworkNominator = new SavedNetworkNominator(
+ mWifiConfigManager, mConnectivityLocalLog, mTelephonyUtil);
mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, wifiHandler,
this, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore, mWifiMetrics,
mTelephonyUtil);
- mNetworkSuggestionEvaluator = new NetworkSuggestionEvaluator(mWifiNetworkSuggestionsManager,
+ mNetworkSuggestionNominator = new NetworkSuggestionNominator(mWifiNetworkSuggestionsManager,
mWifiConfigManager, mConnectivityLocalLog);
- mScoredNetworkEvaluator = new ScoredNetworkEvaluator(mContext, wifiHandler,
+ mScoredNetworkNominator = new ScoredNetworkNominator(mContext, wifiHandler,
mFrameworkFacade, mNetworkScoreManager, mContext.getPackageManager(),
mWifiConfigManager, mConnectivityLocalLog,
mWifiNetworkScoreCache, mWifiPermissionsUtil);
- mCarrierNetworkEvaluator = new CarrierNetworkEvaluator(mWifiConfigManager,
+ mCarrierNetworkNominator = new CarrierNetworkNominator(mWifiConfigManager,
mCarrierNetworkConfig, mConnectivityLocalLog, this);
mPasspointManager = new PasspointManager(mContext, this,
- wifiHandler, mWifiNative, mWifiKeyStore, mClock,
- new PasspointObjectFactory(), mWifiConfigManager, mWifiConfigStore,
- mWifiMetrics, mTelephonyUtil);
- mPasspointNetworkEvaluator = new PasspointNetworkEvaluator(
+ wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(),
+ mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mTelephonyUtil);
+ mPasspointNetworkNominator = new PasspointNetworkNominator(
mPasspointManager, mWifiConfigManager, mConnectivityLocalLog,
this, subscriptionManager);
mWifiMetrics.setPasspointManager(mPasspointManager);
@@ -358,12 +356,12 @@ public class WifiInjector {
mDppManager = new DppManager(wifiHandler, mWifiNative,
mWifiConfigManager, mContext, mDppMetrics);
- // Register the various network evaluators with the network selector.
- mWifiNetworkSelector.registerNetworkEvaluator(mSavedNetworkEvaluator);
- mWifiNetworkSelector.registerNetworkEvaluator(mNetworkSuggestionEvaluator);
- mWifiNetworkSelector.registerNetworkEvaluator(mPasspointNetworkEvaluator);
- mWifiNetworkSelector.registerNetworkEvaluator(mCarrierNetworkEvaluator);
- mWifiNetworkSelector.registerNetworkEvaluator(mScoredNetworkEvaluator);
+ // Register the various network Nominators with the network selector.
+ mWifiNetworkSelector.registerNetworkNominator(mSavedNetworkNominator);
+ mWifiNetworkSelector.registerNetworkNominator(mNetworkSuggestionNominator);
+ mWifiNetworkSelector.registerNetworkNominator(mPasspointNetworkNominator);
+ mWifiNetworkSelector.registerNetworkNominator(mCarrierNetworkNominator);
+ mWifiNetworkSelector.registerNetworkNominator(mScoredNetworkNominator);
mClientModeImpl.start();
}
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index a94521aea..e8d62a56d 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -2139,13 +2139,9 @@ public class WifiMetrics {
}
ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(scanResult);
- Pair<PasspointProvider, PasspointMatch> providerMatch = null;
- PasspointProvider passpointProvider = null;
+ List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = null;
if (networkDetail.isInterworking()) {
- providerMatch =
- mPasspointManager.matchProvider(scanResult);
- passpointProvider = providerMatch != null ? providerMatch.first : null;
-
+ matchedProviders = mPasspointManager.matchProvider(scanResult);
if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
passpointR1Aps++;
} else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
@@ -2190,7 +2186,6 @@ public class WifiMetrics {
mWifiConfigManager.getConfiguredNetworkForScanDetail(scanDetail);
boolean isSaved = (config != null) && !config.isEphemeral()
&& !config.isPasspoint();
- boolean isSavedPasspoint = passpointProvider != null;
if (isOpen) {
openSsids.add(matchInfo);
openBssids++;
@@ -2203,8 +2198,11 @@ public class WifiMetrics {
openOrSavedBssids++;
// Calculate openOrSavedSsids union later
}
- if (isSavedPasspoint) {
- savedPasspointProviderProfiles.add(passpointProvider);
+ if (matchedProviders != null && !matchedProviders.isEmpty()) {
+ for (Pair<PasspointProvider, PasspointMatch> passpointProvider :
+ matchedProviders) {
+ savedPasspointProviderProfiles.add(passpointProvider.first);
+ }
savedPasspointProviderBssids++;
}
}
diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java
index 433fd0b01..e794ef7bc 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java
@@ -29,7 +29,6 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
import android.util.Pair;
@@ -125,51 +124,49 @@ public class WifiNetworkSelector {
/**
* WiFi Network Selector supports various categories of networks. Each category
- * has an evaluator to choose the best WiFi network to connect to. Evaluators
- * should be registered in order, by decreasing importance.
+ * has an nominator to choose the best WiFi network to connect to.
* Wifi Network Selector iterates through the registered scorers in registration order
* before making a final selection from among the candidates.
*/
/**
- * Interface for WiFi Network Evaluator
+ * Interface for WiFi Network Nominator
*
- * A network evaluator examines the scan results and recommends the
- * best network in its category to connect to; it also reports the
+ * A network nominator examines the scan results reports the
* connectable candidates in its category for further consideration.
*/
- public interface NetworkEvaluator {
- /** Type of evaluators */
- int EVALUATOR_ID_SAVED = 0;
- int EVALUATOR_ID_SUGGESTION = 1;
- int EVALUATOR_ID_PASSPOINT = 2;
- int EVALUATOR_ID_CARRIER = 3;
- int EVALUATOR_ID_SCORED = 4;
-
- @IntDef(prefix = { "EVALUATOR_ID_" }, value = {
- EVALUATOR_ID_SAVED,
- EVALUATOR_ID_SUGGESTION,
- EVALUATOR_ID_PASSPOINT,
- EVALUATOR_ID_CARRIER,
- EVALUATOR_ID_SCORED})
+ public interface NetworkNominator {
+ /** Type of nominators */
+ int NOMINATOR_ID_SAVED = 0;
+ int NOMINATOR_ID_SUGGESTION = 1;
+ int NOMINATOR_ID_PASSPOINT = 2;
+ int NOMINATOR_ID_CARRIER = 3;
+ int NOMINATOR_ID_SCORED = 4;
+
+ @IntDef(prefix = { "NOMINATOR_ID_" }, value = {
+ NOMINATOR_ID_SAVED,
+ NOMINATOR_ID_SUGGESTION,
+ NOMINATOR_ID_PASSPOINT,
+ NOMINATOR_ID_CARRIER,
+ NOMINATOR_ID_SCORED})
@Retention(RetentionPolicy.SOURCE)
- public @interface EvaluatorId {}
+ public @interface NominatorId {}
/**
- * Get the evaluator type.
+ * Get the nominator type.
*/
- @EvaluatorId int getId();
+ @NominatorId int getId();
/**
- * Get the evaluator name.
+ * Get the nominator name.
*/
String getName();
/**
- * Update the evaluator.
+ * Update the nominator.
*
- * Certain evaluators have to be updated with the new scan results. For example
- * the ScoredNetworkEvaluator needs to refresh its Score Cache.
+ * Certain nominators have to be updated with the new scan results. For example
+ * the ScoredNetworkNominator needs to refresh its Score Cache.
*
* @param scanDetails a list of scan details constructed from the scan results
*/
@@ -189,14 +186,11 @@ public class WifiNetworkSelector {
* ephemeral networks are allowed
* @param onConnectableListener callback to record all of the connectable networks
*
- * @return configuration of the chosen network;
- * null if no network in this category is available.
*/
- @Nullable
- WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
- WifiConfiguration currentNetwork, String currentBssid,
- boolean connected, boolean untrustedNetworkAllowed,
- OnConnectableListener onConnectableListener);
+ void nominateNetworks(List<ScanDetail> scanDetails,
+ WifiConfiguration currentNetwork, String currentBssid,
+ boolean connected, boolean untrustedNetworkAllowed,
+ OnConnectableListener onConnectableListener);
/**
* Callback for recording connectable candidates
@@ -207,13 +201,12 @@ public class WifiNetworkSelector {
*
* @param scanDetail describes the specific access point
* @param config is the WifiConfiguration for the network
- * @param score is the score assigned by the evaluator
*/
- void onConnectable(ScanDetail scanDetail, WifiConfiguration config, int score);
+ void onConnectable(ScanDetail scanDetail, WifiConfiguration config);
}
}
- private final List<NetworkEvaluator> mEvaluators = new ArrayList<>(3);
+ private final List<NetworkNominator> mNominators = new ArrayList<>(3);
// A helper to log debugging information in the local log buffer, which can
// be retrieved in bugreport.
@@ -380,8 +373,8 @@ public class WifiNetworkSelector {
private List<ScanDetail> filterScanResults(List<ScanDetail> scanDetails,
Set<String> bssidBlacklist, boolean isConnected, String currentBssid) {
- ArrayList<NetworkKey> unscoredNetworks = new ArrayList<NetworkKey>();
- List<ScanDetail> validScanDetails = new ArrayList<ScanDetail>();
+ ArrayList<NetworkKey> unscoredNetworks = new ArrayList<>();
+ List<ScanDetail> validScanDetails = new ArrayList<>();
StringBuffer noValidSsid = new StringBuffer();
StringBuffer blacklistedBssid = new StringBuffer();
StringBuffer lowRssi = new StringBuffer();
@@ -640,7 +633,7 @@ public class WifiNetworkSelector {
}
/**
- * Overrides the {@code candidate} chosen by the {@link #mEvaluators} with the user chosen
+ * Overrides the {@code candidate} chosen by the {@link #mNominators} with the user chosen
* {@link WifiConfiguration} if one exists.
*
* @return the user chosen {@link WifiConfiguration} if one exists, {@code candidate} otherwise
@@ -715,9 +708,9 @@ public class WifiNetworkSelector {
// Update all configured networks before initiating network selection.
updateConfiguredNetworks();
- // Update the registered network evaluators.
- for (NetworkEvaluator registeredEvaluator : mEvaluators) {
- registeredEvaluator.update(scanDetails);
+ // Update the registered network nominators.
+ for (NetworkNominator registeredNominator : mNominators) {
+ registeredNominator.update(scanDetails);
}
// Filter out unwanted networks.
@@ -730,43 +723,30 @@ public class WifiNetworkSelector {
// Determine the weight for the last user selection
final int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork();
final double lastSelectionWeight = calculateLastSelectionWeight();
- final ArraySet<Integer> mNetworkIds = new ArraySet<>();
- // Go through the registered network evaluators in order
- WifiConfiguration selectedNetwork = null;
WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard);
if (currentNetwork != null) {
wifiCandidates.setCurrent(currentNetwork.networkId, currentBssid);
}
- for (NetworkEvaluator registeredEvaluator : mEvaluators) {
- localLog("About to run " + registeredEvaluator.getName() + " :");
- WifiConfiguration choice = registeredEvaluator.evaluateNetworks(
+ for (NetworkNominator registeredNominator : mNominators) {
+ localLog("About to run " + registeredNominator.getName() + " :");
+ registeredNominator.nominateNetworks(
new ArrayList<>(mFilteredNetworks), currentNetwork, currentBssid, connected,
untrustedNetworkAllowed,
- (scanDetail, config, score) -> {
+ (scanDetail, config) -> {
if (config != null) {
mConnectableNetworks.add(Pair.create(scanDetail, config));
- mNetworkIds.add(config.networkId);
wifiCandidates.add(scanDetail, config,
- registeredEvaluator.getId(),
- score,
+ registeredNominator.getId(),
+ 0,
(config.networkId == lastUserSelectedNetworkId)
? lastSelectionWeight : 0.0,
WifiConfiguration.isMetered(config, wifiInfo),
predictThroughput(scanDetail));
mWifiMetrics.setNominatorForNetwork(config.networkId,
- evaluatorIdToNominatorId(registeredEvaluator.getId()));
+ toProtoNominatorId(registeredNominator.getId()));
}
});
- if (choice != null && !mNetworkIds.contains(choice.networkId)) {
- Log.wtf(TAG, registeredEvaluator.getName()
- + " failed to report choice with noConnectibleListener");
- }
- if (selectedNetwork == null && choice != null) {
- selectedNetwork = choice; // First one wins
- localLog(registeredEvaluator.getName() + " selects "
- + WifiNetworkSelector.toNetworkString(selectedNetwork));
- }
}
if (mConnectableNetworks.size() != wifiCandidates.size()) {
@@ -782,12 +762,12 @@ public class WifiNetworkSelector {
WifiCandidates.Candidate best = null;
for (WifiCandidates.Candidate candidate: group) {
// Of all the candidates with the same networkId, choose the
- // one with the smallest evaluatorId, and break ties by
+ // one with the smallest nominatorId, and break ties by
// picking the one with the highest score.
if (best == null
- || candidate.getEvaluatorId() < best.getEvaluatorId()
- || (candidate.getEvaluatorId() == best.getEvaluatorId()
- && candidate.getEvaluatorScore() > best.getEvaluatorScore())) {
+ || candidate.getNominatorId() < best.getNominatorId()
+ || (candidate.getNominatorId() == best.getNominatorId()
+ && candidate.getNominatorScore() > best.getNominatorScore())) {
best = candidate;
}
}
@@ -795,18 +775,14 @@ public class WifiNetworkSelector {
ScanDetail scanDetail = best.getScanDetail();
if (scanDetail != null) {
mWifiConfigManager.setNetworkCandidateScanResult(best.getNetworkConfigId(),
- scanDetail.getScanResult(), best.getEvaluatorScore());
+ scanDetail.getScanResult(), best.getNominatorScore());
}
}
}
ArrayMap<Integer, Integer> experimentNetworkSelections = new ArrayMap<>(); // for metrics
- final int legacySelectedNetworkId = selectedNetwork == null
- ? WifiConfiguration.INVALID_NETWORK_ID
- : selectedNetwork.networkId;
-
- int selectedNetworkId = legacySelectedNetworkId;
+ int selectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
// Run all the CandidateScorers
boolean legacyOverrideWanted = true;
@@ -827,6 +803,7 @@ public class WifiNetworkSelector {
chooses = " chooses ";
legacyOverrideWanted = choice.userConnectChoiceOverride;
selectedNetworkId = networkId;
+ updateChosenPasspointNetwork(choice);
}
String id = candidateScorer.getIdentifier();
int expid = experimentIdFromIdentifier(id);
@@ -837,9 +814,7 @@ public class WifiNetworkSelector {
}
// Update metrics about differences in the selections made by various methods
- final int activeExperimentId = activeScorer == null ? LEGACY_CANDIDATE_SCORER_EXP_ID
- : experimentIdFromIdentifier(activeScorer.getIdentifier());
- experimentNetworkSelections.put(LEGACY_CANDIDATE_SCORER_EXP_ID, legacySelectedNetworkId);
+ final int activeExperimentId = experimentIdFromIdentifier(activeScorer.getIdentifier());
for (Map.Entry<Integer, Integer> entry :
experimentNetworkSelections.entrySet()) {
int experimentId = entry.getKey();
@@ -851,7 +826,8 @@ public class WifiNetworkSelector {
}
// Get a fresh copy of WifiConfiguration reflecting any scan result updates
- selectedNetwork = mWifiConfigManager.getConfiguredNetwork(selectedNetworkId);
+ WifiConfiguration selectedNetwork =
+ mWifiConfigManager.getConfiguredNetwork(selectedNetworkId);
if (selectedNetwork != null && legacyOverrideWanted) {
selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork);
mLastNetworkSelectionTimeStamp = mClock.getElapsedSinceBootMillis();
@@ -859,20 +835,32 @@ public class WifiNetworkSelector {
return selectedNetwork;
}
- private static int evaluatorIdToNominatorId(@NetworkEvaluator.EvaluatorId int evaluatorId) {
- switch (evaluatorId) {
- case NetworkEvaluator.EVALUATOR_ID_SAVED:
+ private void updateChosenPasspointNetwork(WifiCandidates.ScoredCandidate choice) {
+ if (choice.candidateKey == null) {
+ return;
+ }
+ WifiConfiguration config =
+ mWifiConfigManager.getConfiguredNetwork(choice.candidateKey.networkId);
+ if (config.isPasspoint()) {
+ config.SSID = choice.candidateKey.matchInfo.networkSsid;
+ mWifiConfigManager.addOrUpdateNetwork(config, config.creatorUid, config.creatorName);
+ }
+ }
+
+ private static int toProtoNominatorId(@NetworkNominator.NominatorId int nominatorId) {
+ switch (nominatorId) {
+ case NetworkNominator.NOMINATOR_ID_SAVED:
return WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED;
- case NetworkEvaluator.EVALUATOR_ID_SUGGESTION:
+ case NetworkNominator.NOMINATOR_ID_SUGGESTION:
return WifiMetricsProto.ConnectionEvent.NOMINATOR_SUGGESTION;
- case NetworkEvaluator.EVALUATOR_ID_PASSPOINT:
+ case NetworkNominator.NOMINATOR_ID_PASSPOINT:
return WifiMetricsProto.ConnectionEvent.NOMINATOR_PASSPOINT;
- case NetworkEvaluator.EVALUATOR_ID_CARRIER:
+ case NetworkNominator.NOMINATOR_ID_CARRIER:
return WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER;
- case NetworkEvaluator.EVALUATOR_ID_SCORED:
+ case NetworkNominator.NOMINATOR_ID_SCORED:
return WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED;
default:
- Log.e(TAG, "UnrecognizedEvaluatorId" + evaluatorId);
+ Log.e(TAG, "UnrecognizedNominatorId" + nominatorId);
return WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN;
}
}
@@ -932,13 +920,13 @@ public class WifiNetworkSelector {
}
/**
- * Register a network evaluator
+ * Register a network nominator
*
- * @param evaluator the network evaluator to be registered
+ * @param nominator the network nominator to be registered
*
*/
- public void registerNetworkEvaluator(@NonNull NetworkEvaluator evaluator) {
- mEvaluators.add(Preconditions.checkNotNull(evaluator));
+ public void registerNetworkNominator(@NonNull NetworkNominator nominator) {
+ mNominators.add(Preconditions.checkNotNull(nominator));
}
/**
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index 42fac2912..26edf2e56 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -509,47 +509,52 @@ public class PasspointManager {
}
/**
- * Find the best provider that can provide service through the given AP, which means the
- * provider contained credential to authenticate with the given AP.
+ * Find all providers that can provide service through the given AP, which means the
+ * providers 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
+ * If there is any home provider available, will return a list of matched home providers.
+ * Otherwise will return a list of matched roaming providers.
*
- * A {code null} will be returned if no matching is found.
+ * A empty list will be returned if no matching is found.
*
* @param scanResult The scan result associated with the AP
- * @return A pair of {@link PasspointProvider} and match status.
+ * @return a list of pairs of {@link PasspointProvider} and match status.
*/
- public Pair<PasspointProvider, PasspointMatch> matchProvider(ScanResult scanResult) {
+ public @NonNull List<Pair<PasspointProvider, PasspointMatch>> matchProvider(
+ ScanResult scanResult) {
List<Pair<PasspointProvider, PasspointMatch>> allMatches = getAllMatchedProviders(
scanResult);
- if (allMatches == null) {
- return null;
+ if (allMatches.isEmpty()) {
+ return allMatches;
}
- Pair<PasspointProvider, PasspointMatch> bestMatch = null;
+ List<Pair<PasspointProvider, PasspointMatch>> homeProviders = new ArrayList<>();
+ List<Pair<PasspointProvider, PasspointMatch>> roamingProviders = new ArrayList<>();
for (Pair<PasspointProvider, PasspointMatch> match : allMatches) {
- if (!isExpired(match.first.getConfig())) {
- if (match.second == PasspointMatch.HomeProvider) {
- bestMatch = match;
- break;
- }
- if (match.second == PasspointMatch.RoamingProvider && bestMatch == null) {
- bestMatch = match;
- }
+ if (isExpired(match.first.getConfig())) {
+ continue;
}
- }
- if (bestMatch != null) {
- Log.d(TAG, String.format("Matched %s to %s as %s", scanResult.SSID,
- bestMatch.first.getConfig().getHomeSp().getFqdn(),
- bestMatch.second == PasspointMatch.HomeProvider ? "Home Provider"
- : "Roaming Provider"));
- } else {
- if (mVerboseLoggingEnabled) {
- Log.d(TAG, "No service provider found for " + scanResult.SSID);
+ if (match.second == PasspointMatch.HomeProvider) {
+ homeProviders.add(match);
+ } else {
+ roamingProviders.add(match);
}
}
- return bestMatch;
+
+ if (!homeProviders.isEmpty()) {
+ Log.d(TAG, String.format("Matched %s to %s providers as %s", scanResult.SSID,
+ homeProviders.size(), "Home Provider"));
+ return homeProviders;
+ }
+ if (!roamingProviders.isEmpty()) {
+ Log.d(TAG, String.format("Matched %s to %s providers as %s", scanResult.SSID,
+ allMatches.size(), "Roaming Provider"));
+ return roamingProviders;
+ }
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "No service provider found for " + scanResult.SSID);
+ }
+ return new ArrayList<>();
}
/**
@@ -558,7 +563,7 @@ public class PasspointManager {
* @param scanResult The scan result associated with the AP
* @return a list of pairs of {@link PasspointProvider} and match status.
*/
- public List<Pair<PasspointProvider, PasspointMatch>> getAllMatchedProviders(
+ public @NonNull List<Pair<PasspointProvider, PasspointMatch>> getAllMatchedProviders(
ScanResult scanResult) {
List<Pair<PasspointProvider, PasspointMatch>> allMatches = new ArrayList<>();
@@ -1001,7 +1006,6 @@ public class PasspointManager {
return true;
}
}
-
return false;
}
}
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
deleted file mode 100644
index 6396f2c7c..000000000
--- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wifi.hotspot2;
-
-import android.annotation.NonNull;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.os.Process;
-import android.telephony.SubscriptionManager;
-import android.text.TextUtils;
-import android.util.LocalLog;
-import android.util.Pair;
-
-import com.android.server.wifi.NetworkUpdateResult;
-import com.android.server.wifi.ScanDetail;
-import com.android.server.wifi.WifiConfigManager;
-import com.android.server.wifi.WifiInjector;
-import com.android.server.wifi.WifiNetworkSelector;
-import com.android.server.wifi.util.ScanResultUtil;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * This class is the WifiNetworkSelector.NetworkEvaluator implementation for
- * Passpoint networks.
- */
-public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator {
- private static final String NAME = "PasspointNetworkEvaluator";
-
- private final PasspointManager mPasspointManager;
- private final WifiConfigManager mWifiConfigManager;
- private final LocalLog mLocalLog;
- private final WifiInjector mWifiInjector;
- private SubscriptionManager mSubscriptionManager;
- /**
- * Contained information for a Passpoint network candidate.
- */
- private class PasspointNetworkCandidate {
- PasspointNetworkCandidate(PasspointProvider provider, PasspointMatch matchStatus,
- ScanDetail scanDetail) {
- mProvider = provider;
- mMatchStatus = matchStatus;
- mScanDetail = scanDetail;
- }
- PasspointProvider mProvider;
- PasspointMatch mMatchStatus;
- ScanDetail mScanDetail;
- }
-
- public PasspointNetworkEvaluator(PasspointManager passpointManager,
- WifiConfigManager wifiConfigManager, LocalLog localLog,
- WifiInjector wifiInjector,
- SubscriptionManager subscriptionManager) {
- mPasspointManager = passpointManager;
- mWifiConfigManager = wifiConfigManager;
- mLocalLog = localLog;
- mWifiInjector = wifiInjector;
- mSubscriptionManager = subscriptionManager;
- }
-
- @Override
- public @EvaluatorId int getId() {
- return EVALUATOR_ID_PASSPOINT;
- }
-
- @Override
- public String getName() {
- return NAME;
- }
-
- @Override
- public void update(List<ScanDetail> scanDetails) {}
-
- @Override
- public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
- WifiConfiguration currentNetwork, String currentBssid,
- boolean connected, boolean untrustedNetworkAllowed,
- @NonNull OnConnectableListener onConnectableListener) {
- // Sweep the ANQP cache to remove any expired ANQP entries.
- mPasspointManager.sweepCache();
- List<ScanDetail> filteredScanDetails = scanDetails.stream()
- .filter(s -> s.getNetworkDetail().isInterworking())
- .filter(s -> {
- if (!mWifiConfigManager.wasEphemeralNetworkDeleted(
- ScanResultUtil.createQuotedSSID(s.getScanResult().SSID))) {
- return true;
- } else {
- // If the user previously disconnects this network, don't select it.
- mLocalLog.log("Ignoring disabled the SSID of Passpoint AP: "
- + WifiNetworkSelector.toScanId(s.getScanResult()));
- return false;
- }
- }).collect(Collectors.toList());
-
- // Go through each ScanDetail and find the best provider for each ScanDetail.
- List<PasspointNetworkCandidate> candidateList = new ArrayList<>();
- for (ScanDetail scanDetail : filteredScanDetails) {
- ScanResult scanResult = scanDetail.getScanResult();
-
- // Find the best provider for this ScanDetail.
- Pair<PasspointProvider, PasspointMatch> bestProvider =
- mPasspointManager.matchProvider(scanResult);
- if (bestProvider != null) {
- candidateList.add(new PasspointNetworkCandidate(
- bestProvider.first, bestProvider.second, scanDetail));
- }
- }
-
- // Done if no candidate is found.
- if (candidateList.isEmpty()) {
- localLog("No suitable Passpoint network found");
- return null;
- }
-
- // Find the best Passpoint network among all candidates.
- PasspointNetworkCandidate bestNetwork =
- findBestNetwork(candidateList, currentNetwork == null ? null : currentNetwork.SSID);
-
- // Return the configuration for the current connected network if it is the best network.
- if (currentNetwork != null && TextUtils.equals(currentNetwork.SSID,
- ScanResultUtil.createQuotedSSID(bestNetwork.mScanDetail.getSSID()))) {
- localLog("Staying with current Passpoint network " + currentNetwork.SSID);
-
- // Update current network with the latest scan info. TODO - pull into common code
- mWifiConfigManager.setNetworkCandidateScanResult(currentNetwork.networkId,
- bestNetwork.mScanDetail.getScanResult(), 0);
- mWifiConfigManager.updateScanDetailForNetwork(currentNetwork.networkId,
- bestNetwork.mScanDetail);
- onConnectableListener.onConnectable(bestNetwork.mScanDetail, currentNetwork, 0);
- return currentNetwork;
- }
-
- WifiConfiguration config = createWifiConfigForProvider(bestNetwork);
- if (config != null) {
- onConnectableListener.onConnectable(bestNetwork.mScanDetail, config, 0);
- localLog("Passpoint network to connect to: " + config.SSID);
- }
- return config;
- }
-
- /**
- * Create and return a WifiConfiguration for the given ScanDetail and PasspointProvider.
- * The newly created WifiConfiguration will also be added to WifiConfigManager.
- *
- * @param networkInfo Contained information for the Passpoint network to connect to
- * @return {@link WifiConfiguration}
- */
- private WifiConfiguration createWifiConfigForProvider(PasspointNetworkCandidate networkInfo) {
- WifiConfiguration config = networkInfo.mProvider.getWifiConfig();
- config.SSID = ScanResultUtil.createQuotedSSID(networkInfo.mScanDetail.getSSID());
- if (networkInfo.mMatchStatus == PasspointMatch.HomeProvider) {
- config.isHomeProviderNetwork = true;
- }
-
- WifiConfiguration existingNetwork = mWifiConfigManager.getConfiguredNetwork(
- config.getKey());
- if (existingNetwork != null) {
- WifiConfiguration.NetworkSelectionStatus status =
- existingNetwork.getNetworkSelectionStatus();
- if (!(status.isNetworkEnabled()
- || mWifiConfigManager.tryEnableNetwork(existingNetwork.networkId))) {
- localLog("Current configuration for the Passpoint AP " + config.SSID
- + " is disabled, skip this candidate");
- return null;
- }
- }
-
- // Add or update with the newly created WifiConfiguration to WifiConfigManager.
- NetworkUpdateResult result;
- if (config.fromWifiNetworkSuggestion) {
- result = mWifiConfigManager.addOrUpdateNetwork(
- config, config.creatorUid, config.creatorName);
- } else {
- result = mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);
- }
- if (!result.isSuccess()) {
- localLog("Failed to add passpoint network");
- return existingNetwork;
- }
-
- mWifiConfigManager.enableNetwork(result.getNetworkId(), false, Process.WIFI_UID, null);
- mWifiConfigManager.setNetworkCandidateScanResult(result.getNetworkId(),
- networkInfo.mScanDetail.getScanResult(), 0);
- mWifiConfigManager.updateScanDetailForNetwork(
- result.getNetworkId(), networkInfo.mScanDetail);
- return mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
- }
-
- /**
- * 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}.
- *
- * @param networkList List of Passpoint networks
- * @param currentNetworkSsid The SSID of the currently connected network, null if not connected
- * @return {@link PasspointNetworkCandidate}
- */
- private PasspointNetworkCandidate findBestNetwork(
- List<PasspointNetworkCandidate> networkList, String currentNetworkSsid) {
- PasspointNetworkCandidate bestCandidate = null;
- int bestScore = Integer.MIN_VALUE;
- for (PasspointNetworkCandidate candidate : networkList) {
- ScanDetail scanDetail = candidate.mScanDetail;
- PasspointMatch match = candidate.mMatchStatus;
-
- boolean isActiveNetwork = TextUtils.equals(currentNetworkSsid,
- ScanResultUtil.createQuotedSSID(scanDetail.getSSID()));
- int score = PasspointNetworkScore.calculateScore(match == PasspointMatch.HomeProvider,
- scanDetail, mPasspointManager.getANQPElements(scanDetail.getScanResult()),
- isActiveNetwork);
-
- if (score > bestScore) {
- bestCandidate = candidate;
- bestScore = score;
- }
- }
- localLog("Best Passpoint network " + bestCandidate.mScanDetail.getSSID() + " provided by "
- + bestCandidate.mProvider.getConfig().getHomeSp().getFqdn());
- return bestCandidate;
- }
-
- private void localLog(String log) {
- mLocalLog.log(log);
- }
-}
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominator.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominator.java
new file mode 100644
index 000000000..7dbce2290
--- /dev/null
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominator.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.hotspot2;
+
+import android.annotation.NonNull;
+import android.net.wifi.WifiConfiguration;
+import android.os.Process;
+import android.telephony.SubscriptionManager;
+import android.util.LocalLog;
+import android.util.Pair;
+
+import com.android.server.wifi.NetworkUpdateResult;
+import com.android.server.wifi.ScanDetail;
+import com.android.server.wifi.WifiConfigManager;
+import com.android.server.wifi.WifiInjector;
+import com.android.server.wifi.WifiNetworkSelector;
+import com.android.server.wifi.hotspot2.anqp.ANQPElement;
+import com.android.server.wifi.hotspot2.anqp.Constants;
+import com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement;
+import com.android.server.wifi.util.ScanResultUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * This class is the WifiNetworkSelector.NetworkNominator implementation for
+ * Passpoint networks.
+ */
+public class PasspointNetworkNominator implements WifiNetworkSelector.NetworkNominator {
+ private static final String NAME = "PasspointNetworkNominator";
+
+ private final PasspointManager mPasspointManager;
+ private final WifiConfigManager mWifiConfigManager;
+ private final LocalLog mLocalLog;
+ private final WifiInjector mWifiInjector;
+ private SubscriptionManager mSubscriptionManager;
+ /**
+ * Contained information for a Passpoint network candidate.
+ */
+ private class PasspointNetworkCandidate {
+ PasspointNetworkCandidate(PasspointProvider provider, PasspointMatch matchStatus,
+ ScanDetail scanDetail) {
+ mProvider = provider;
+ mMatchStatus = matchStatus;
+ mScanDetail = scanDetail;
+ }
+ PasspointProvider mProvider;
+ PasspointMatch mMatchStatus;
+ ScanDetail mScanDetail;
+ }
+
+ public PasspointNetworkNominator(PasspointManager passpointManager,
+ WifiConfigManager wifiConfigManager, LocalLog localLog,
+ WifiInjector wifiInjector,
+ SubscriptionManager subscriptionManager) {
+ mPasspointManager = passpointManager;
+ mWifiConfigManager = wifiConfigManager;
+ mLocalLog = localLog;
+ mWifiInjector = wifiInjector;
+ mSubscriptionManager = subscriptionManager;
+ }
+
+ @Override
+ public @NominatorId int getId() {
+ return NOMINATOR_ID_PASSPOINT;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public void update(List<ScanDetail> scanDetails) {}
+
+ @Override
+ public void nominateNetworks(List<ScanDetail> scanDetails,
+ WifiConfiguration currentNetwork, String currentBssid,
+ boolean connected, boolean untrustedNetworkAllowed,
+ @NonNull OnConnectableListener onConnectableListener) {
+ // Sweep the ANQP cache to remove any expired ANQP entries.
+ mPasspointManager.sweepCache();
+ List<ScanDetail> filteredScanDetails = new ArrayList<>();
+ // Filter out all invalid scanDetail
+ for (ScanDetail scanDetail : scanDetails) {
+ if (scanDetail.getNetworkDetail() == null
+ || !scanDetail.getNetworkDetail().isInterworking()) {
+ // If scanDetail is not passpoint network, ignore.
+ continue;
+ }
+
+ if (!scanDetail.getNetworkDetail().isInternet()
+ || isApWanLinkStatusDown(scanDetail)) {
+ // If scanDetail has no internet connection, ignore.
+ mLocalLog.log("Ignoring no internet connection Passpoint AP: "
+ + WifiNetworkSelector.toScanId(scanDetail.getScanResult()));
+ continue;
+ }
+
+ if (mWifiConfigManager.wasEphemeralNetworkDeleted(
+ ScanResultUtil.createQuotedSSID(scanDetail.getScanResult().SSID))) {
+ // If the user previously disconnects this network, don't select it.
+ mLocalLog.log("Ignoring disabled the SSID of Passpoint AP: "
+ + WifiNetworkSelector.toScanId(scanDetail.getScanResult()));
+ continue;
+ }
+ filteredScanDetails.add(scanDetail);
+ }
+
+ List<Pair<ScanDetail, WifiConfiguration>> matchedCandidates =
+ findBestMatchScanDetailForProviders(filteredScanDetails);
+ for (Pair<ScanDetail, WifiConfiguration> candidate : matchedCandidates) {
+ onConnectableListener.onConnectable(candidate.first, candidate.second);
+ }
+ }
+
+ /**
+ * Check if ANQP element inside that scanDetail indicate AP WAN port link status is down.
+ *
+ * @param scanDetail contains ANQP element to check.
+ * @return return true is link status is down, otherwise return false.
+ */
+ private boolean isApWanLinkStatusDown(ScanDetail scanDetail) {
+ Map<Constants.ANQPElementType, ANQPElement> anqpElements =
+ mPasspointManager.getANQPElements(scanDetail.getScanResult());
+ if (anqpElements == null) {
+ return false;
+ }
+ HSWanMetricsElement wm = (HSWanMetricsElement) anqpElements.get(
+ Constants.ANQPElementType.HSWANMetrics);
+ if (wm == null) {
+ return false;
+ }
+ return wm.getStatus() != HSWanMetricsElement.LINK_STATUS_UP || wm.isCapped();
+ }
+
+ /**
+ * Match available providers for each scan detail. Then for each available provider, find the
+ * best scan detail for it.
+ * @param scanDetails all details for this scan.
+ * @return List of pair of WifiConfig from available provider and matched scanDetail.
+ */
+ private @NonNull List<Pair<ScanDetail, WifiConfiguration>> findBestMatchScanDetailForProviders(
+ List<ScanDetail> scanDetails) {
+ List<Pair<ScanDetail, WifiConfiguration>> results = new ArrayList<>();
+ Map<PasspointProvider, List<PasspointNetworkCandidate>> candidatesPerProvider =
+ new HashMap<>();
+ // Match each scanDetail with best provider (home > roaming), and grouped by FQDN.
+ for (ScanDetail scanDetail : scanDetails) {
+ List<Pair<PasspointProvider, PasspointMatch>> matchedProviders =
+ mPasspointManager.matchProvider(scanDetail.getScanResult());
+ if (matchedProviders == null) {
+ continue;
+ }
+ for (Pair<PasspointProvider, PasspointMatch> matchedProvider : matchedProviders) {
+ List<PasspointNetworkCandidate> candidates = candidatesPerProvider
+ .computeIfAbsent(matchedProvider.first, k -> new ArrayList<>());
+ candidates.add(new PasspointNetworkCandidate(matchedProvider.first,
+ matchedProvider.second, scanDetail));
+ }
+ }
+ // For each provider find the best scanDetail for it and create selection candidate pair.
+ for (List<PasspointNetworkCandidate> candidates : candidatesPerProvider.values()) {
+ List<PasspointNetworkCandidate> bestCandidates = findHomeNetworksIfPossible(candidates);
+ for (PasspointNetworkCandidate candidate : bestCandidates) {
+ WifiConfiguration config = createWifiConfigForProvider(candidate);
+ if (config == null) {
+ continue;
+ }
+ results.add(Pair.create(candidate.mScanDetail, config));
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Create and return a WifiConfiguration for the given ScanDetail and PasspointProvider.
+ * The newly created WifiConfiguration will also be added to WifiConfigManager.
+ *
+ * @return {@link WifiConfiguration}
+ */
+ private WifiConfiguration createWifiConfigForProvider(
+ PasspointNetworkCandidate candidate) {
+ WifiConfiguration config = candidate.mProvider.getWifiConfig();
+ config.SSID = ScanResultUtil.createQuotedSSID(candidate.mScanDetail.getSSID());
+ if (candidate.mMatchStatus == PasspointMatch.HomeProvider) {
+ config.isHomeProviderNetwork = true;
+ }
+
+ WifiConfiguration existingNetwork = mWifiConfigManager.getConfiguredNetwork(
+ config.getKey());
+ if (existingNetwork != null) {
+ WifiConfiguration.NetworkSelectionStatus status =
+ existingNetwork.getNetworkSelectionStatus();
+ if (!(status.isNetworkEnabled()
+ || mWifiConfigManager.tryEnableNetwork(existingNetwork.networkId))) {
+ mLocalLog.log("Current configuration for the Passpoint AP " + config.SSID
+ + " is disabled, skip this candidate");
+ return null;
+ }
+ }
+
+ // Add or update with the newly created WifiConfiguration to WifiConfigManager.
+ NetworkUpdateResult result;
+ if (config.fromWifiNetworkSuggestion) {
+ result = mWifiConfigManager.addOrUpdateNetwork(
+ config, config.creatorUid, config.creatorName);
+ } else {
+ result = mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);
+ }
+ if (!result.isSuccess()) {
+ mLocalLog.log("Failed to add passpoint network");
+ return existingNetwork;
+ }
+
+ mWifiConfigManager.enableNetwork(result.getNetworkId(), false, Process.WIFI_UID, null);
+ mWifiConfigManager.setNetworkCandidateScanResult(result.getNetworkId(),
+ candidate.mScanDetail.getScanResult(), 0);
+ mWifiConfigManager.updateScanDetailForNetwork(
+ result.getNetworkId(), candidate.mScanDetail);
+ return mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
+ }
+
+ /**
+ * Given a list of Passpoint networks (with both provider and scan info), return all
+ * homeProvider matching networks if there is any, otherwise return all roamingProvider matching
+ * networks.
+ *
+ * @param networkList List of Passpoint networks
+ * @return List of {@link PasspointNetworkCandidate}
+ */
+ private @NonNull List<PasspointNetworkCandidate> findHomeNetworksIfPossible(
+ @NonNull List<PasspointNetworkCandidate> networkList) {
+ List<PasspointNetworkCandidate> homeProviderCandidates = networkList.stream()
+ .filter(candidate -> candidate.mMatchStatus == PasspointMatch.HomeProvider)
+ .collect(Collectors.toList());
+ if (homeProviderCandidates.isEmpty()) {
+ return networkList;
+ }
+ return homeProviderCandidates;
+ }
+}