1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.networkrecommendation.wakeup; 17 18 import android.content.res.Resources; 19 import android.net.RecommendationRequest; 20 import android.net.RecommendationResult; 21 import android.net.wifi.ScanResult; 22 import android.net.wifi.WifiConfiguration; 23 import android.support.annotation.Nullable; 24 import android.util.ArraySet; 25 import com.android.networkrecommendation.R; 26 import com.android.networkrecommendation.SynchronousNetworkRecommendationProvider; 27 import com.android.networkrecommendation.util.RoboCompatUtil; 28 import com.android.networkrecommendation.util.ScanResultUtil; 29 import com.android.networkrecommendation.util.WifiConfigurationUtil; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.Map; 33 import java.util.Set; 34 35 /** This class determines which network the framework would connect to if Wi-Fi was enabled. */ 36 public class WifiWakeupNetworkSelector { 37 private final int mThresholdQualifiedRssi24; 38 private final int mThresholdQualifiedRssi5; 39 private final int mRssiScoreSlope; 40 private final int mRssiScoreOffset; 41 private final int mPasspointSecurityAward; 42 private final int mSecurityAward; 43 private final int mBand5GHzAward; 44 private final int mThresholdSaturatedRssi24; 45 private final SynchronousNetworkRecommendationProvider mNetworkRecommendationProvider; 46 47 public WifiWakeupNetworkSelector( 48 Resources resources, 49 SynchronousNetworkRecommendationProvider networkRecommendationProvider) { 50 mThresholdQualifiedRssi24 = 51 resources.getInteger(R.integer.config_netrec_wifi_score_low_rssi_threshold_24GHz); 52 mThresholdQualifiedRssi5 = 53 resources.getInteger(R.integer.config_netrec_wifi_score_low_rssi_threshold_5GHz); 54 mRssiScoreSlope = resources.getInteger(R.integer.config_netrec_RSSI_SCORE_SLOPE); 55 mRssiScoreOffset = resources.getInteger(R.integer.config_netrec_RSSI_SCORE_OFFSET); 56 mPasspointSecurityAward = 57 resources.getInteger(R.integer.config_netrec_PASSPOINT_SECURITY_AWARD); 58 mSecurityAward = resources.getInteger(R.integer.config_netrec_SECURITY_AWARD); 59 mBand5GHzAward = resources.getInteger(R.integer.config_netrec_5GHz_preference_boost_factor); 60 mThresholdSaturatedRssi24 = 61 resources.getInteger(R.integer.config_netrec_wifi_score_good_rssi_threshold_24GHz); 62 mNetworkRecommendationProvider = networkRecommendationProvider; 63 } 64 65 /** Returns the network that the framework would most likely connect to if Wi-Fi was enabled. */ 66 @Nullable 67 public WifiConfiguration selectNetwork( 68 Map<String, WifiConfiguration> savedNetworks, List<ScanResult> scanResults) { 69 Set<WifiConfiguration> openOrExternalConfigs = new ArraySet<>(); 70 List<ScanResult> openOrExternalScanResults = new ArrayList<>(); 71 WifiConfiguration candidateWifiConfiguration = null; 72 ScanResult candidateScanResult = null; 73 int candidateScore = -1; 74 for (int i = 0; i < scanResults.size(); i++) { 75 ScanResult scanResult = scanResults.get(i); 76 WifiConfiguration wifiConfiguration = savedNetworks.get(scanResult.SSID); 77 if (wifiConfiguration == null) { 78 continue; 79 } 80 if ((ScanResultUtil.is5GHz(scanResult) && scanResult.level < mThresholdQualifiedRssi5) 81 || (ScanResultUtil.is24GHz(scanResult) 82 && scanResult.level < mThresholdQualifiedRssi24)) { 83 continue; 84 } 85 if (!ScanResultUtil.doesScanResultMatchWithNetwork(scanResult, wifiConfiguration)) { 86 continue; 87 } 88 if (WifiConfigurationUtil.isConfigForOpenNetwork(wifiConfiguration) 89 || RoboCompatUtil.getInstance().useExternalScores(wifiConfiguration)) { 90 // All open and externally scored networks should defer to network recommendations. 91 openOrExternalConfigs.add(wifiConfiguration); 92 openOrExternalScanResults.add(scanResult); 93 continue; 94 } 95 int score = calculateScore(scanResult, wifiConfiguration); 96 if (candidateScanResult == null 97 || calculateScore(scanResult, wifiConfiguration) > candidateScore) { 98 candidateScanResult = scanResult; 99 candidateWifiConfiguration = wifiConfiguration; 100 candidateScore = score; 101 } 102 } 103 if (candidateWifiConfiguration == null && !openOrExternalConfigs.isEmpty()) { 104 // TODO(netrec): Add connectableConfigs after next SystemApi drop 105 RecommendationRequest request = 106 new RecommendationRequest.Builder() 107 .setScanResults(openOrExternalScanResults.toArray(new ScanResult[0])) 108 .build(); 109 RecommendationResult result = 110 mNetworkRecommendationProvider.requestRecommendation(request); 111 return result.getWifiConfiguration(); 112 } 113 return candidateWifiConfiguration; 114 } 115 116 private int calculateScore(ScanResult scanResult, WifiConfiguration wifiConfiguration) { 117 int score = 0; 118 // Calculate the RSSI score. 119 int rssi = 120 scanResult.level <= mThresholdSaturatedRssi24 121 ? scanResult.level 122 : mThresholdSaturatedRssi24; 123 score += (rssi + mRssiScoreOffset) * mRssiScoreSlope; 124 125 // 5GHz band bonus. 126 if (ScanResultUtil.is5GHz(scanResult)) { 127 score += mBand5GHzAward; 128 } 129 130 // Security award. 131 if (RoboCompatUtil.getInstance().isPasspoint(wifiConfiguration)) { 132 score += mPasspointSecurityAward; 133 } else if (!WifiConfigurationUtil.isConfigForOpenNetwork(wifiConfiguration)) { 134 score += mSecurityAward; 135 } 136 137 return score; 138 } 139 } 140