From f14e4b8fdd949b4ba0feb63dded4d9b233859300 Mon Sep 17 00:00:00 2001 From: Amin Shaikh Date: Fri, 14 Apr 2017 15:02:09 -0700 Subject: Create ScoredNetworkEvaluator. - Bring back WifiNetworkScoreCache into the wifi framework - Replace RecommendedNetworkEvaluator with ScoredNetworkEvalutor, which is the same as the previous ExternalScoreEvaluator (ag/1865733) with some changes: * Check whether a ScanResult matches the current network by comparing the matching WifiConfiguration instead of the current bssid * Only create untrusted WifiConfigurations for open networks * Set candidate ScanResults for all WifiConfigurations - not only the final chosen WifiConfiguration * Mark newly created ephemeral WifiConfiguration as enabled for network selection * Log a maximum of one LocalLog line per round of network selection Bug: 37357981 Test: ./test/wifitests/runtests.sh Change-Id: I99da4edb371928efb7ca7a9dcd28ddaca9209da8 --- .../server/wifi/RecommendedNetworkEvaluator.java | 328 --------------------- .../server/wifi/ScoredNetworkEvaluator.java | 322 ++++++++++++++++++++ .../server/wifi/WifiConnectivityManager.java | 8 +- .../java/com/android/server/wifi/WifiInjector.java | 20 +- 4 files changed, 339 insertions(+), 339 deletions(-) delete mode 100644 service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java create mode 100644 service/java/com/android/server/wifi/ScoredNetworkEvaluator.java (limited to 'service') diff --git a/service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java b/service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java deleted file mode 100644 index 80d1501a2..000000000 --- a/service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java +++ /dev/null @@ -1,328 +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.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.net.INetworkScoreCache; -import android.net.NetworkKey; -import android.net.NetworkScoreManager; -import android.net.RecommendationRequest; -import android.net.RecommendationResult; -import android.net.ScoredNetwork; -import android.net.WifiKey; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.os.Handler; -import android.os.Looper; -import android.os.Process; -import android.os.RemoteException; -import android.os.SystemClock; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.LocalLog; -import android.util.LruCache; -import android.util.Pair; -import android.util.Slog; - -import com.android.server.wifi.util.ScanResultUtil; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import javax.annotation.concurrent.GuardedBy; - -/** - * {@link WifiNetworkSelector.NetworkEvaluator} implementation that uses - * {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}. - */ -public class RecommendedNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator { - private static final String TAG = "RecNetEvaluator"; - private final NetworkScoreManager mNetworkScoreManager; - private final WifiConfigManager mWifiConfigManager; - private final LocalLog mLocalLog; - private final ContentObserver mContentObserver; - private final RequestedScoreCache mRequestedScoreCache; - private boolean mNetworkRecommendationsEnabled; - - RecommendedNetworkEvaluator(final Context context, ContentResolver contentResolver, - Looper looper, final FrameworkFacade frameworkFacade, - NetworkScoreManager networkScoreManager, WifiConfigManager wifiConfigManager, - LocalLog localLog) { - mRequestedScoreCache = new RequestedScoreCache(frameworkFacade.getLongSetting( - context, Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS, - TimeUnit.DAYS.toMillis(1))); - mNetworkScoreManager = networkScoreManager; - mWifiConfigManager = wifiConfigManager; - mLocalLog = localLog; - mContentObserver = new ContentObserver(new Handler(looper)) { - @Override - public void onChange(boolean selfChange) { - mNetworkRecommendationsEnabled = frameworkFacade.getIntegerSetting(context, - Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1; - } - }; - frameworkFacade.registerContentObserver(context, - Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), - false /* notifyForDescendents */, mContentObserver); - mContentObserver.onChange(false /* unused */); - mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mRequestedScoreCache, - NetworkScoreManager.CACHE_FILTER_NONE); - mLocalLog.log("RecommendedNetworkEvaluator constructed. mNetworkRecommendationsEnabled: " - + mNetworkRecommendationsEnabled); - } - - @Override - public void update(List scanDetails) { - if (mNetworkRecommendationsEnabled) { - updateNetworkScoreCache(scanDetails); - } - clearNotRecommendedFlag(); - } - - private void updateNetworkScoreCache(List scanDetails) { - ArrayList unscoredNetworks = new ArrayList(); - - for (int i = 0; i < scanDetails.size(); i++) { - ScanResult scanResult = scanDetails.get(i).getScanResult(); - try { - WifiKey wifiKey = new WifiKey( - ScanResultUtil.createQuotedSSID(scanResult.SSID), scanResult.BSSID); - // Have we requested a score for this network? If not, request a score. - if (mRequestedScoreCache.shouldRequestScore(wifiKey)) { - unscoredNetworks.add(new NetworkKey(wifiKey)); - } - } catch (IllegalArgumentException e) { - mLocalLog.log("Invalid SSID=" + scanResult.SSID + " BSSID=" + scanResult.BSSID - + " for network score. Skip."); - } - } - - // Kick the score manager if there are any unscored network. - if (!unscoredNetworks.isEmpty()) { - NetworkKey[] unscoredNetworkKeys = - unscoredNetworks.toArray(new NetworkKey[unscoredNetworks.size()]); - mNetworkScoreManager.requestScores(unscoredNetworkKeys); - } - } - - private void clearNotRecommendedFlag() { - List savedNetworks = mWifiConfigManager.getSavedNetworks(); - for (int i = 0; i < savedNetworks.size(); i++) { - mWifiConfigManager.updateNetworkNotRecommended( - savedNetworks.get(i).networkId, false /* notRecommended*/); - } - } - - @Override - public WifiConfiguration evaluateNetworks(List scanDetails, - WifiConfiguration currentNetwork, String currentBssid, boolean connected, - boolean untrustedNetworkAllowed, - List> connectableNetworks) { - if (!mNetworkRecommendationsEnabled) { - mLocalLog.log("Skipping evaluateNetworks; Network recommendations disabled."); - return null; - } - Set availableConfiguredNetworks = new ArraySet<>(); - List scanResults = new ArrayList<>(); - for (int i = 0; i < scanDetails.size(); i++) { - ScanDetail scanDetail = scanDetails.get(i); - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) continue; - if (mWifiConfigManager.wasEphemeralNetworkDeleted( - ScanResultUtil.createQuotedSSID(scanResult.SSID))) { - continue; - } - - final WifiConfiguration configuredNetwork = - mWifiConfigManager.getSavedNetworkForScanDetailAndCache(scanDetail); - - scanResult.untrusted = configuredNetwork == null || configuredNetwork.ephemeral; - - if (!untrustedNetworkAllowed && scanResult.untrusted) { - continue; - } - - if (configuredNetwork != null) { - if (!configuredNetwork.getNetworkSelectionStatus().isNetworkEnabled()) { - continue; - } - availableConfiguredNetworks.add(configuredNetwork); - } - scanResults.add(scanResult); - // Track potential connectable networks for the watchdog. - if (connectableNetworks != null) { - connectableNetworks.add(Pair.create(scanDetail, configuredNetwork)); - } - } - - if (scanResults.isEmpty()) { - return null; - } - - ScanResult[] scanResultArray = scanResults.toArray(new ScanResult[scanResults.size()]); - WifiConfiguration[] availableConfigsArray = availableConfiguredNetworks - .toArray(new WifiConfiguration[availableConfiguredNetworks.size()]); - int lastSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork(); - long lastSelectedNetworkTimestamp = mWifiConfigManager.getLastSelectedTimeStamp(); - RecommendationRequest request = new RecommendationRequest.Builder() - .setScanResults(scanResultArray) - .setConnectedWifiConfig(currentNetwork) - .setConnectableConfigs(availableConfigsArray) - .setLastSelectedNetwork(lastSelectedNetworkId, lastSelectedNetworkTimestamp) - // TODO: pass in currently recommended network - .build(); - RecommendationResult result = mNetworkScoreManager.requestRecommendation(request); - if (result == null) { - // Recommendation provider could not be reached. - return null; - } - - if (result.getWifiConfiguration() == null) { - // Recommendation provider recommended not connecting to any network. - for (int i = 0; i < availableConfigsArray.length; i++) { - if (availableConfigsArray[i].getNetworkSelectionStatus().isNetworkEnabled()) { - mWifiConfigManager.updateNetworkNotRecommended( - availableConfigsArray[i].networkId, true /* notRecommended*/); - } - } - return null; - } - - WifiConfiguration recommendedConfig = result.getWifiConfiguration(); - ScanDetail matchingScanDetail = findMatchingScanDetail(scanDetails, recommendedConfig); - if (matchingScanDetail == null) { - Slog.e(TAG, "Could not match WifiConfiguration to a ScanDetail."); - return null; - } - ScanResult matchingScanResult = matchingScanDetail.getScanResult(); - - // Look for a matching saved config. This can be null for ephemeral networks. - final WifiConfiguration existingConfig = - mWifiConfigManager.getSavedNetworkForScanDetailAndCache(matchingScanDetail); - - final int networkId; - if (existingConfig == null) { // attempt to add a new ephemeral network. - networkId = addEphemeralNetwork(recommendedConfig, matchingScanResult); - if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { - return null; - } - } else { // Use the existing config - networkId = existingConfig.networkId; - } - mWifiConfigManager.setNetworkCandidateScanResult(networkId, - matchingScanResult, 0 /* score */); - return mWifiConfigManager.getConfiguredNetwork(networkId); - } - - private static ScanDetail findMatchingScanDetail(List scanDetails, - WifiConfiguration wifiConfiguration) { - String ssid = WifiInfo.removeDoubleQuotes(wifiConfiguration.SSID); - String bssid = wifiConfiguration.BSSID; - boolean ignoreBssid = TextUtils.isEmpty(bssid) || "any".equals(bssid); - for (int i = 0; i < scanDetails.size(); i++) { - final ScanDetail scanDetail = scanDetails.get(i); - if (ssid.equals(scanDetail.getSSID()) - && (ignoreBssid || bssid.equals(scanDetail.getBSSIDString()))) { - return scanDetail; - } - } - - return null; - } - - private int addEphemeralNetwork(WifiConfiguration wifiConfiguration, ScanResult scanResult) { - if (wifiConfiguration.allowedKeyManagement.isEmpty()) { - ScanResultUtil.setAllowedKeyManagementFromScanResult(scanResult, - wifiConfiguration); - } - wifiConfiguration.ephemeral = true; - wifiConfiguration.BSSID = null; - NetworkUpdateResult networkUpdateResult = mWifiConfigManager - .addOrUpdateNetwork(wifiConfiguration, Process.WIFI_UID); - if (networkUpdateResult.isSuccess()) { - return networkUpdateResult.getNetworkId(); - } - mLocalLog.log("Failed to add ephemeral network for networkId: " - + WifiNetworkSelector.toScanId(scanResult)); - return WifiConfiguration.INVALID_NETWORK_ID; - } - - @Override - public String getName() { - return TAG; - } - - /** Cache for scores that have already been requested. */ - static class RequestedScoreCache extends INetworkScoreCache.Stub { - /** Number entries to be stored in the {@link LruCache} of requested {@link WifiKey}s. */ - private static final int MAX_CACHE_SIZE = 1000; - - private final long mCacheExpiryMillis; - @GuardedBy("mCache") - private final LruCache mCache = new LruCache<>(MAX_CACHE_SIZE); - @GuardedBy("mCache") - private long mCacheCreationTime; - - RequestedScoreCache(long cacheExpiryMillis) { - mCacheExpiryMillis = cacheExpiryMillis; - } - - /** Returns whether a score should be requested for a given {@code wifiKey}. */ - public boolean shouldRequestScore(WifiKey wifiKey) { - long nowMillis = SystemClock.elapsedRealtime(); - long oldestUsableCacheTimeMillis = nowMillis - mCacheExpiryMillis; - synchronized (mCache) { - if (mCacheCreationTime < oldestUsableCacheTimeMillis) { - mCache.evictAll(); - mCacheCreationTime = nowMillis; - } - boolean shouldRequest = mCache.get(wifiKey) == null; - mCache.put(wifiKey, this); // Update access time for wifiKey. - return shouldRequest; - } - } - - @Override - public void updateScores(List networks) throws RemoteException {} - - @Override - public void clearScores() throws RemoteException { - synchronized (mCache) { - mCache.evictAll(); - mCacheCreationTime = 0; - } - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - writer.println("RequestedScoreCache:"); - writer.println("mCacheExpiryMillis: " + mCacheExpiryMillis); - synchronized (mCache) { - writer.println("mCacheCreationTime: " + mCacheCreationTime); - writer.println("mCache size: " + mCache.size()); - } - } - } -} diff --git a/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java b/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java new file mode 100644 index 000000000..483da9936 --- /dev/null +++ b/service/java/com/android/server/wifi/ScoredNetworkEvaluator.java @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2017 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.Nullable; +import android.content.Context; +import android.database.ContentObserver; +import android.net.NetworkKey; +import android.net.NetworkScoreManager; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiNetworkScoreCache; +import android.os.Handler; +import android.os.Looper; +import android.os.Process; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.LocalLog; +import android.util.Log; +import android.util.Pair; + +import com.android.server.wifi.util.ScanResultUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * {@link WifiNetworkSelector.NetworkEvaluator} 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"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final NetworkScoreManager mNetworkScoreManager; + private final WifiConfigManager mWifiConfigManager; + private final LocalLog mLocalLog; + private final ContentObserver mContentObserver; + private boolean mNetworkRecommendationsEnabled; + private WifiNetworkScoreCache mScoreCache; + + ScoredNetworkEvaluator(final Context context, Looper looper, + final FrameworkFacade frameworkFacade, NetworkScoreManager networkScoreManager, + WifiConfigManager wifiConfigManager, LocalLog localLog, + WifiNetworkScoreCache wifiNetworkScoreCache) { + mScoreCache = wifiNetworkScoreCache; + mNetworkScoreManager = networkScoreManager; + mWifiConfigManager = wifiConfigManager; + mLocalLog = localLog; + mContentObserver = new ContentObserver(new Handler(looper)) { + @Override + public void onChange(boolean selfChange) { + mNetworkRecommendationsEnabled = frameworkFacade.getIntegerSetting(context, + Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1; + } + }; + frameworkFacade.registerContentObserver(context, + Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), + false /* notifyForDescendents */, mContentObserver); + mContentObserver.onChange(false /* unused */); + mLocalLog.log("ScoredNetworkEvaluator constructed. mNetworkRecommendationsEnabled: " + + mNetworkRecommendationsEnabled); + } + + @Override + public void update(List scanDetails) { + if (mNetworkRecommendationsEnabled) { + updateNetworkScoreCache(scanDetails); + } + } + + private void updateNetworkScoreCache(List scanDetails) { + ArrayList unscoredNetworks = new ArrayList(); + for (int i = 0; i < scanDetails.size(); i++) { + ScanResult scanResult = scanDetails.get(i).getScanResult(); + NetworkKey networkKey = NetworkKey.createFromScanResult(scanResult); + if (networkKey != null) { + // Is there a ScoredNetwork for this ScanResult? If not, request a score. + if (mScoreCache.getScoredNetwork(networkKey) == null) { + unscoredNetworks.add(networkKey); + } + } + } + + // Kick the score manager if there are any unscored network. + if (!unscoredNetworks.isEmpty()) { + NetworkKey[] unscoredNetworkKeys = + unscoredNetworks.toArray(new NetworkKey[unscoredNetworks.size()]); + mNetworkScoreManager.requestScores(unscoredNetworkKeys); + } + } + + @Override + public WifiConfiguration evaluateNetworks(List scanDetails, + WifiConfiguration currentNetwork, String currentBssid, boolean connected, + boolean untrustedNetworkAllowed, + List> connectableNetworks) { + if (!mNetworkRecommendationsEnabled) { + mLocalLog.log("Skipping evaluateNetworks; Network recommendations disabled."); + return null; + } + + final ScoreTracker scoreTracker = new ScoreTracker(); + for (int i = 0; i < scanDetails.size(); i++) { + ScanDetail scanDetail = scanDetails.get(i); + ScanResult scanResult = scanDetail.getScanResult(); + if (scanResult == null) continue; + if (mWifiConfigManager.wasEphemeralNetworkDeleted( + ScanResultUtil.createQuotedSSID(scanResult.SSID))) { + debugLog("Ignoring disabled ephemeral SSID: " + scanResult.SSID); + continue; + } + final WifiConfiguration configuredNetwork = + mWifiConfigManager.getSavedNetworkForScanDetailAndCache(scanDetail); + boolean untrustedScanResult = configuredNetwork == null || configuredNetwork.ephemeral; + + if (!untrustedNetworkAllowed && untrustedScanResult) { + continue; + } + + // Track scan results for open wifi networks + if (configuredNetwork == null) { + if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)) { + scoreTracker.trackUntrustedCandidate(scanResult); + } + continue; + } + + // Ignore non-ephemeral and non-externally scored networks + if (!configuredNetwork.ephemeral && !configuredNetwork.useExternalScores) { + continue; + } + + // Ignore externally scored or ephemeral networks that have been disabled for selection + if (!configuredNetwork.getNetworkSelectionStatus().isNetworkEnabled()) { + debugLog("Ignoring disabled SSID: " + configuredNetwork.SSID); + continue; + } + + // TODO(b/37485956): consider applying a boost for networks with only the same SSID + boolean isCurrentNetwork = currentNetwork != null + && currentNetwork.networkId == configuredNetwork.networkId + && TextUtils.equals(currentBssid, scanResult.BSSID); + if (configuredNetwork.ephemeral) { + scoreTracker.trackUntrustedCandidate( + scanResult, configuredNetwork, isCurrentNetwork); + } else { + scoreTracker.trackExternallyScoredCandidate( + scanResult, configuredNetwork, isCurrentNetwork); + } + if (connectableNetworks != null) { + connectableNetworks.add(Pair.create(scanDetail, configuredNetwork)); + } + } + + return scoreTracker.getCandidateConfiguration(); + } + + /** Used to track the network with the highest score. */ + class ScoreTracker { + private static final int EXTERNAL_SCORED_NONE = 0; + private static final int EXTERNAL_SCORED_SAVED_NETWORK = 1; + private static final int EXTERNAL_SCORED_UNTRUSTED_NETWORK = 2; + + private int mBestCandidateType = EXTERNAL_SCORED_NONE; + private int mHighScore = WifiNetworkScoreCache.INVALID_NETWORK_SCORE; + private WifiConfiguration mEphemeralConfig; + private WifiConfiguration mSavedConfig; + private ScanResult mScanResultCandidate; + + /** + * Returns the available external network score or null if no score is available. + * + * @param scanResult The scan result of the network to score. + * @param isCurrentNetwork Flag which indicates whether this is the current network. + * @return A valid external score if one is available or NULL. + */ + @Nullable + private Integer getNetworkScore(ScanResult scanResult, boolean isCurrentNetwork) { + if (mScoreCache.isScoredNetwork(scanResult)) { + int score = mScoreCache.getNetworkScore(scanResult, isCurrentNetwork); + if (DEBUG) { + mLocalLog.log(WifiNetworkSelector.toScanId(scanResult) + " has score: " + + score + " isCurrentNetwork network: " + isCurrentNetwork); + } + return score; + } + return null; + } + + /** Track an untrusted {@link ScanResult}. */ + void trackUntrustedCandidate(ScanResult scanResult) { + Integer score = getNetworkScore(scanResult, false /* isCurrentNetwork */); + if (score != null && score > mHighScore) { + mHighScore = score; + mScanResultCandidate = scanResult; + mBestCandidateType = EXTERNAL_SCORED_UNTRUSTED_NETWORK; + debugLog(WifiNetworkSelector.toScanId(scanResult) + + " becomes the new untrusted candidate."); + } + } + + /** + * Track an untrusted {@link ScanResult} that already has a corresponding + * ephemeral {@link WifiConfiguration}. + */ + void trackUntrustedCandidate( + ScanResult scanResult, WifiConfiguration config, boolean isCurrentNetwork) { + Integer score = getNetworkScore(scanResult, isCurrentNetwork); + if (score != null && score > mHighScore) { + mHighScore = score; + mScanResultCandidate = scanResult; + mBestCandidateType = EXTERNAL_SCORED_UNTRUSTED_NETWORK; + mEphemeralConfig = config; + mWifiConfigManager.setNetworkCandidateScanResult(config.networkId, scanResult, 0); + debugLog(WifiNetworkSelector.toScanId(scanResult) + + " becomes the new untrusted candidate."); + } + } + + /** Tracks a saved network that has been marked with useExternalScores */ + void trackExternallyScoredCandidate( + ScanResult scanResult, WifiConfiguration config, boolean isCurrentNetwork) { + // Always take the highest score. If there's a tie and an untrusted network is currently + // the best then pick the saved network. + Integer score = getNetworkScore(scanResult, isCurrentNetwork); + if (score != null + && (score > mHighScore + || (mBestCandidateType == EXTERNAL_SCORED_UNTRUSTED_NETWORK + && score == mHighScore))) { + mHighScore = score; + mSavedConfig = config; + mScanResultCandidate = scanResult; + mBestCandidateType = EXTERNAL_SCORED_SAVED_NETWORK; + mWifiConfigManager.setNetworkCandidateScanResult(config.networkId, scanResult, 0); + debugLog(WifiNetworkSelector.toScanId(scanResult) + + " becomes the new externally scored saved network candidate."); + } + } + + /** Returns the best candidate network tracked by this {@link ScoreTracker}. */ + @Nullable + WifiConfiguration getCandidateConfiguration() { + int candidateNetworkId = WifiConfiguration.INVALID_NETWORK_ID; + switch (mBestCandidateType) { + case ScoreTracker.EXTERNAL_SCORED_UNTRUSTED_NETWORK: + if (mEphemeralConfig != null) { + candidateNetworkId = mEphemeralConfig.networkId; + mLocalLog.log(String.format("existing ephemeral candidate %s network ID:%d" + + ", meteredHint=%b", + WifiNetworkSelector.toScanId(mScanResultCandidate), + candidateNetworkId, + mEphemeralConfig.meteredHint)); + break; + } + + mEphemeralConfig = + ScanResultUtil.createNetworkFromScanResult(mScanResultCandidate); + // Mark this config as ephemeral so it isn't persisted. + mEphemeralConfig.ephemeral = true; + mEphemeralConfig.meteredHint = mScoreCache.getMeteredHint(mScanResultCandidate); + NetworkUpdateResult result = + mWifiConfigManager.addOrUpdateNetwork(mEphemeralConfig, + Process.WIFI_UID); + if (!result.isSuccess()) { + mLocalLog.log("Failed to add ephemeral network"); + break; + } + if (!mWifiConfigManager.updateNetworkSelectionStatus(result.getNetworkId(), + WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE)) { + mLocalLog.log("Failed to make ephemeral network selectable"); + break; + } + candidateNetworkId = result.getNetworkId(); + mWifiConfigManager.setNetworkCandidateScanResult(candidateNetworkId, + mScanResultCandidate, 0); + mLocalLog.log(String.format("new ephemeral candidate %s network ID:%d, " + + "meteredHint=%b", + WifiNetworkSelector.toScanId(mScanResultCandidate), + candidateNetworkId, + mEphemeralConfig.meteredHint)); + break; + case ScoreTracker.EXTERNAL_SCORED_SAVED_NETWORK: + candidateNetworkId = mSavedConfig.networkId; + mLocalLog.log(String.format("new saved network candidate %s network ID:%d", + WifiNetworkSelector.toScanId(mScanResultCandidate), + candidateNetworkId)); + break; + case ScoreTracker.EXTERNAL_SCORED_NONE: + default: + mLocalLog.log("ScoredNetworkEvaluator did not see any good candidates."); + break; + } + return mWifiConfigManager.getConfiguredNetwork(candidateNetworkId); + } + } + + private void debugLog(String msg) { + if (DEBUG) { + mLocalLog.log(msg); + } + } + + @Override + public String getName() { + return TAG; + } +} diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index bd00b3f5b..010c6b294 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -124,7 +124,7 @@ public class WifiConnectivityManager { // Saved network evaluator priority private static final int SAVED_NETWORK_EVALUATOR_PRIORITY = 1; private static final int PASSPOINT_NETWORK_EVALUATOR_PRIORITY = 2; - private static final int RECOMMENDED_NETWORK_EVALUATOR_PRIORITY = 3; + private static final int SCORED_NETWORK_EVALUATOR_PRIORITY = 3; // Log tag for this class private static final String TAG = "WifiConnectivityManager"; @@ -512,7 +512,7 @@ public class WifiConnectivityManager { Looper looper, Clock clock, LocalLog localLog, boolean enable, FrameworkFacade frameworkFacade, SavedNetworkEvaluator savedNetworkEvaluator, - RecommendedNetworkEvaluator recommendedNetworkEvaluator, + ScoredNetworkEvaluator scoredNetworkEvaluator, PasspointNetworkEvaluator passpointNetworkEvaluator) { mStateMachine = stateMachine; mScanner = scanner; @@ -569,8 +569,8 @@ public class WifiConnectivityManager { mNetworkSelector.registerNetworkEvaluator(passpointNetworkEvaluator, PASSPOINT_NETWORK_EVALUATOR_PRIORITY); } - mNetworkSelector.registerNetworkEvaluator(recommendedNetworkEvaluator, - RECOMMENDED_NETWORK_EVALUATOR_PRIORITY); + mNetworkSelector.registerNetworkEvaluator(scoredNetworkEvaluator, + SCORED_NETWORK_EVALUATOR_PRIORITY); // Register for all single scan results mScanner.registerScanListener(mAllSingleScanListener); diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index c86bf1b93..758aed468 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -18,12 +18,14 @@ package com.android.server.wifi; import android.app.ActivityManager; import android.content.Context; +import android.net.NetworkKey; import android.net.NetworkScoreManager; import android.net.wifi.IApInterface; import android.net.wifi.IWifiScanner; import android.net.wifi.IWificond; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.net.wifi.WifiNetworkScoreCache; import android.net.wifi.WifiScanner; import android.os.BatteryStats; import android.os.HandlerThread; @@ -106,7 +108,8 @@ public class WifiInjector { private final WifiNetworkSelector mWifiNetworkSelector; private final SavedNetworkEvaluator mSavedNetworkEvaluator; private final PasspointNetworkEvaluator mPasspointNetworkEvaluator; - private final RecommendedNetworkEvaluator mRecommendedNetworkEvaluator; + private final ScoredNetworkEvaluator mScoredNetworkEvaluator; + private final WifiNetworkScoreCache mWifiNetworkScoreCache; private final NetworkScoreManager mNetworkScoreManager; private WifiScanner mWifiScanner; private final WifiPermissionsWrapper mWifiPermissionsWrapper; @@ -140,6 +143,9 @@ public class WifiInjector { mSettingsStore = new WifiSettingsStore(mContext); mWifiPermissionsWrapper = new WifiPermissionsWrapper(mContext); mNetworkScoreManager = mContext.getSystemService(NetworkScoreManager.class); + mWifiNetworkScoreCache = new WifiNetworkScoreCache(mContext); + mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, + mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE); mWifiPermissionsUtil = new WifiPermissionsUtil(mWifiPermissionsWrapper, mContext, mSettingsStore, UserManager.get(mContext), mNetworkScoreManager, this); mBatteryStats = IBatteryStats.Stub.asInterface(mFrameworkFacade.getService( @@ -198,11 +204,11 @@ public class WifiInjector { mConnectivityLocalLog = new LocalLog(ActivityManager.isLowRamDeviceStatic() ? 256 : 512); mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiConfigManager, mClock, mConnectivityLocalLog); - mSavedNetworkEvaluator = new SavedNetworkEvaluator(mContext, mWifiConfigManager, mClock, - mConnectivityLocalLog, mWifiConnectivityHelper); - mRecommendedNetworkEvaluator = new RecommendedNetworkEvaluator(context, - context.getContentResolver(), wifiStateMachineLooper, mFrameworkFacade, - mNetworkScoreManager, mWifiConfigManager, mConnectivityLocalLog); + mSavedNetworkEvaluator = new SavedNetworkEvaluator(mContext, + mWifiConfigManager, mClock, mConnectivityLocalLog, mWifiConnectivityHelper); + mScoredNetworkEvaluator = new ScoredNetworkEvaluator(context, wifiStateMachineLooper, + mFrameworkFacade, mNetworkScoreManager, mWifiConfigManager, mConnectivityLocalLog, + mWifiNetworkScoreCache); mSimAccessor = new SIMAccessor(mContext); mPasspointManager = new PasspointManager(mContext, mWifiNative, mWifiKeyStore, mClock, mSimAccessor, new PasspointObjectFactory(), mWifiConfigManager, mWifiConfigStore); @@ -409,7 +415,7 @@ public class WifiInjector { mWifiConfigManager, wifiInfo, mWifiNetworkSelector, mWifiConnectivityHelper, mWifiLastResortWatchdog, mWifiMetrics, mWifiStateMachineHandlerThread.getLooper(), mClock, mConnectivityLocalLog, hasConnectionRequests, mFrameworkFacade, - mSavedNetworkEvaluator, mRecommendedNetworkEvaluator, mPasspointNetworkEvaluator); + mSavedNetworkEvaluator, mScoredNetworkEvaluator, mPasspointNetworkEvaluator); } public WifiPermissionsUtil getWifiPermissionsUtil() { -- cgit v1.2.3