150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu/* 250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * Copyright (C) 2016 The Android Open Source Project 350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * 450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * Licensed under the Apache License, Version 2.0 (the "License"); 550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * you may not use this file except in compliance with the License. 650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * You may obtain a copy of the License at 750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * 850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * http://www.apache.org/licenses/LICENSE-2.0 950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * 1050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * Unless required by applicable law or agreed to in writing, software 1150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * distributed under the License is distributed on an "AS IS" BASIS, 1250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * See the License for the specific language governing permissions and 1450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * limitations under the License. 1550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu */ 1650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 1750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiupackage com.android.server.wifi.hotspot2; 1850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 1950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport android.net.wifi.WifiConfiguration; 2050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport android.os.Process; 2150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport android.text.TextUtils; 2250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport android.util.LocalLog; 2350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport android.util.Pair; 2450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 2550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport com.android.server.wifi.NetworkUpdateResult; 2650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport com.android.server.wifi.ScanDetail; 2750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport com.android.server.wifi.WifiConfigManager; 2850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport com.android.server.wifi.WifiNetworkSelector; 2950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport com.android.server.wifi.util.ScanResultUtil; 3050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 3150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport java.util.ArrayList; 3250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiuimport java.util.List; 3350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 3450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu/** 3550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * This class is the WifiNetworkSelector.NetworkEvaluator implementation for 3650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * Passpoint networks. 3750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu */ 3850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiupublic class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator { 3950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu private static final String NAME = "PasspointNetworkEvaluator"; 4050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 4150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu private final PasspointManager mPasspointManager; 4250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu private final WifiConfigManager mWifiConfigManager; 4350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu private final LocalLog mLocalLog; 4450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 45d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu /** 46d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu * Contained information for a Passpoint network candidate. 47d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu */ 48d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu private class PasspointNetworkCandidate { 49d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu PasspointNetworkCandidate(PasspointProvider provider, PasspointMatch matchStatus, 50d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu ScanDetail scanDetail) { 51d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu mProvider = provider; 52d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu mMatchStatus = matchStatus; 53d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu mScanDetail = scanDetail; 54d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu } 55d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu PasspointProvider mProvider; 56d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu PasspointMatch mMatchStatus; 57d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu ScanDetail mScanDetail; 58d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu } 59d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu 6050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu public PasspointNetworkEvaluator(PasspointManager passpointManager, 6150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu WifiConfigManager wifiConfigManager, LocalLog localLog) { 6250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu mPasspointManager = passpointManager; 6350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu mWifiConfigManager = wifiConfigManager; 6450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu mLocalLog = localLog; 6550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 6650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 6750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu @Override 6850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu public String getName() { 6950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu return NAME; 7050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 7150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 7250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu @Override 7350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu public void update(List<ScanDetail> scanDetails) {} 7450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 7550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu @Override 7650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails, 7750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu WifiConfiguration currentNetwork, String currentBssid, 7850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu boolean connected, boolean untrustedNetworkAllowed, 7950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) { 80ec28f863c5e46c0a75e8bdb92283304b875ee0f2Peter Qiu // Sweep the ANQP cache to remove any expired ANQP entries. 81ec28f863c5e46c0a75e8bdb92283304b875ee0f2Peter Qiu mPasspointManager.sweepCache(); 82ec28f863c5e46c0a75e8bdb92283304b875ee0f2Peter Qiu 8350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu // Go through each ScanDetail and find the best provider for each ScanDetail. 84d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu List<PasspointNetworkCandidate> candidateList = new ArrayList<>(); 8550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu for (ScanDetail scanDetail : scanDetails) { 8650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu // Skip non-Passpoint APs. 8750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu if (!scanDetail.getNetworkDetail().isInterworking()) { 8850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu continue; 8950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 9050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 9150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu // Find the best provider for this ScanDetail. 9250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu Pair<PasspointProvider, PasspointMatch> bestProvider = 93b54f07e01c9daef8883c85e09f61436f2c06cc72Peter Qiu mPasspointManager.matchProvider(scanDetail.getScanResult()); 9450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu if (bestProvider != null) { 95d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu candidateList.add(new PasspointNetworkCandidate( 96d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu bestProvider.first, bestProvider.second, scanDetail)); 9750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 9850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 9950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 100d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu // Done if no candidate is found. 101d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu if (candidateList.isEmpty()) { 10250bc1e851d073d4a986f5b32072f94bbaba86a95Peter Qiu localLog("No suitable Passpoint network found"); 10350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu return null; 10450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 10550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 106d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu // Find the best Passpoint network among all candidates. 107d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu PasspointNetworkCandidate bestNetwork = 108d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu findBestNetwork(candidateList, currentNetwork == null ? null : currentNetwork.SSID); 10950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 11050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu // Return the configuration for the current connected network if it is the best network. 11150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu if (currentNetwork != null && TextUtils.equals(currentNetwork.SSID, 112d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu ScanResultUtil.createQuotedSSID(bestNetwork.mScanDetail.getSSID()))) { 11350bc1e851d073d4a986f5b32072f94bbaba86a95Peter Qiu localLog("Staying with current Passpoint network " + currentNetwork.SSID); 114d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu connectableNetworks.add(Pair.create(bestNetwork.mScanDetail, currentNetwork)); 11550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu return currentNetwork; 11650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 11750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 118d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu WifiConfiguration config = createWifiConfigForProvider(bestNetwork); 119d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu connectableNetworks.add(Pair.create(bestNetwork.mScanDetail, config)); 12050bc1e851d073d4a986f5b32072f94bbaba86a95Peter Qiu localLog("Passpoint network to connect to: " + config.SSID); 12150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu return config; 12250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 12350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 12450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu /** 12550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * Create and return a WifiConfiguration for the given ScanDetail and PasspointProvider. 12650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * The newly created WifiConfiguration will also be added to WifiConfigManager. 12750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * 128d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu * @param networkInfo Contained information for the Passpoint network to connect to 12950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * @return {@link WifiConfiguration} 13050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu */ 131d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu private WifiConfiguration createWifiConfigForProvider(PasspointNetworkCandidate networkInfo) { 132d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu WifiConfiguration config = networkInfo.mProvider.getWifiConfig(); 133d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu config.SSID = ScanResultUtil.createQuotedSSID(networkInfo.mScanDetail.getSSID()); 134d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu if (networkInfo.mMatchStatus == PasspointMatch.HomeProvider) { 135d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu config.isHomeProviderNetwork = true; 136d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu } 13750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 13850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu // Add the newly created WifiConfiguration to WifiConfigManager. 13950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu NetworkUpdateResult result = 14050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID); 14150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu if (!result.isSuccess()) { 14250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu localLog("Failed to add passpoint network"); 14350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu return null; 14450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 14567a4541372684c5d0a3f834f8be76bd8d29ca7acPeter Qiu mWifiConfigManager.enableNetwork(result.getNetworkId(), false, Process.WIFI_UID); 14650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu mWifiConfigManager.setNetworkCandidateScanResult(result.getNetworkId(), 147d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu networkInfo.mScanDetail.getScanResult(), 0); 148d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu mWifiConfigManager.updateScanDetailForNetwork( 149d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu result.getNetworkId(), networkInfo.mScanDetail); 15050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu return mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); 15150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 15250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 15350f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu /** 15450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * Given a list of Passpoint networks (with both provider and scan info), find and return 15550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * the one with highest score. The score is calculated using 15650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * {@link PasspointNetworkScore#calculateScore}. 15750f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * 15850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * @param networkList List of Passpoint networks 15950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu * @param currentNetworkSsid The SSID of the currently connected network, null if not connected 160d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu * @return {@link PasspointNetworkCandidate} 16150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu */ 162d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu private PasspointNetworkCandidate findBestNetwork( 163d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu List<PasspointNetworkCandidate> networkList, String currentNetworkSsid) { 164d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu PasspointNetworkCandidate bestCandidate = null; 16550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu int bestScore = Integer.MIN_VALUE; 166d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu for (PasspointNetworkCandidate candidate : networkList) { 167d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu ScanDetail scanDetail = candidate.mScanDetail; 168d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu PasspointMatch match = candidate.mMatchStatus; 16950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 17050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu boolean isActiveNetwork = TextUtils.equals(currentNetworkSsid, 17150f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu ScanResultUtil.createQuotedSSID(scanDetail.getSSID())); 17250f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu int score = PasspointNetworkScore.calculateScore(match == PasspointMatch.HomeProvider, 173ec28f863c5e46c0a75e8bdb92283304b875ee0f2Peter Qiu scanDetail, mPasspointManager.getANQPElements(scanDetail.getScanResult()), 174ec28f863c5e46c0a75e8bdb92283304b875ee0f2Peter Qiu isActiveNetwork); 17550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 17650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu if (score > bestScore) { 177d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu bestCandidate = candidate; 17850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu bestScore = score; 17950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 18050f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 181d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu localLog("Best Passpoint network " + bestCandidate.mScanDetail.getSSID() + " provided by " 182d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu + bestCandidate.mProvider.getConfig().getHomeSp().getFqdn()); 183d6ba42b153a41a19c9ce4fb8e63abbe859ad67e9Peter Qiu return bestCandidate; 18450f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 18550f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu 18650f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu private void localLog(String log) { 18717c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan mLocalLog.log(log); 18850f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu } 18950f36ec6fe906445db996bf3918e5cb3f170bc79Peter Qiu} 190