Wifi自动连接评分机制

2020-07-15 10:33:12 浏览数 (1)

今天了解了一下Wifi自动连接时的评分机制,总结如下: WifiConnectivityManager的初始化: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

代码语言:javascript复制
    class SupplicantStartedState extends State {
            if (mWifiScanner == null) {
                mWifiScanner = mWifiInjector.getWifiScanner();

                synchronized (mWifiReqCountLock) {
                    mWifiConnectivityManager =
                            mWifiInjector.makeWifiConnectivityManager(mWifiInfo,
                                                                      hasConnectionRequests());
                    mWifiConnectivityManager.setUntrustedConnectionAllowed(mUntrustedReqCount > 0);
                    mWifiConnectivityManager.handleScreenStateChanged(mScreenOn);
                }
            }

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiInjector.java

代码语言:javascript复制
    public WifiConnectivityManager makeWifiConnectivityManager(WifiInfo wifiInfo,
                                                               boolean hasConnectionRequests) {
        return new WifiConnectivityManager(mContext, mWifiStateMachine, getWifiScanner(),
                mWifiConfigManager, wifiInfo, mWifiNetworkSelector, mWifiConnectivityHelper,
               mWifiLastResortWatchdog, mOpenNetworkNotifier, mWifiMetrics,
                mWifiStateMachineHandlerThread.getLooper(), mClock, mConnectivityLocalLog,
                hasConnectionRequests, mFrameworkFacade, mSavedNetworkEvaluator,
                mScoredNetworkEvaluator, mPasspointNetworkEvaluator);
    }

WifiConnectivityManager中会注册三个Evaluator。 /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConnectivityManager.java

代码语言:javascript复制
        mNetworkSelector.registerNetworkEvaluator(savedNetworkEvaluator,
                SAVED_NETWORK_EVALUATOR_PRIORITY);
        if (hs2Enabled) {
            mNetworkSelector.registerNetworkEvaluator(passpointNetworkEvaluator,
                    PASSPOINT_NETWORK_EVALUATOR_PRIORITY);
        }
        mNetworkSelector.registerNetworkEvaluator(scoredNetworkEvaluator,
                SCORED_NETWORK_EVALUATOR_PRIORITY);

继续看下注册方法,其实就是初始化一个NetworkEvaluator数组,大小为6,即优先级从高到低0-5。 /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNetworkSelector.java

代码语言:javascript复制
    public static final int EVALUATOR_MIN_PRIORITY = 6;

    private final NetworkEvaluator[] mEvaluators = new NetworkEvaluator[MAX_NUM_EVALUATORS];

    public boolean registerNetworkEvaluator(NetworkEvaluator evaluator, int priority) {
        if (priority < 0 || priority >= EVALUATOR_MIN_PRIORITY) {
            localLog("Invalid network evaluator priority: "   priority);
            return false;
        }

        if (mEvaluators[priority] != null) {
            localLog("Priority "   priority   " is already registered by "
                      mEvaluators[priority].getName());
            return false;
        }

        mEvaluators[priority] = evaluator;
        return true;
    }

WifiConnectivityManager的网络评估

代码语言:javascript复制
    private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName) {
        if (mSupportCMCC && mWifiManagerEx.isAutoConnect() == false) {
            Log.i(TAG, "WifiManagerEx isAutoConnect false,  "   mWifiManagerEx.isAutoConnect());
            return false;
        }
        
        if (!mP2pWifiCoexistSupported && WifiP2pServiceImpl.mP2pConnectingOrConnected) {
            Log.i(TAG, "Do not auto connect when wifi and p2p should not coexsit");
            return false;
        }
    
        refreshBssidBlacklist();

        if (mStateMachine.isLinkDebouncing() || mStateMachine.isSupplicantTransientState()) {
            localLog(listenerName   " onResults: No network selection because linkDebouncing is "
                      mStateMachine.isLinkDebouncing()   " and supplicantTransient is "
                      mStateMachine.isSupplicantTransientState());
            return false;
        }

        localLog(listenerName   " onResults: start network selection");

        WifiConfiguration candidate =
                mNetworkSelector.selectNetwork(scanDetails, buildBssidBlacklist(), mWifiInfo,
                mStateMachine.isConnected(), mStateMachine.isDisconnected(),
                mUntrustedConnectionAllowed);
        mWifiLastResortWatchdog.updateAvailableNetworks(
                mNetworkSelector.getConnectableScanDetails());
        mWifiMetrics.countScanResults(scanDetails);
        if (candidate != null) {
            localLog(listenerName   ":  WNS candidate-"   candidate.SSID);
            connectToNetwork(candidate);
            return true;
        } else {
            if (mWifiState == WIFI_STATE_DISCONNECTED) {
                mOpenNetworkNotifier.handleScanResults(
                        mNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
            }
            return false;
        }
    }

如api注释所述,对周期性、单次和pno扫描的结果进行潜在网络候选者的选择,如果有合适的网络,则进行连接

看下candiate是如何产生的:

代码语言:javascript复制
    public WifiConfiguration selectNetwork(List<ScanDetail> scanDetails,
            HashSet<String> bssidBlacklist, WifiInfo wifiInfo,
        boolean connected, boolean disconnected, boolean untrustedNetworkAllowed) 
        mFilteredNetworks.clear();
       mConnectableNetworks.clear();
        if (scanDetails.size() == 0) {
           localLog("Empty connectivity scan result");
            return null;
        WifiConfiguration currentNetwork =
                mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
        String currentBssid = wifiInfo.getBSSID();
        if (!isNetworkSelectionNeeded(scanDetails, wifiInfo, connected, disconnected)) {
            return null;
        }
        for (NetworkEvaluator registeredEvaluator : mEvaluators) {
            if (registeredEvaluator != null) {
                registeredEvaluator.update(scanDetails);
            }
        }
        mFilteredNetworks = filterScanResults(scanDetails, bssidBlacklist,
                connected, currentBssid);
        if (mFilteredNetworks.size() == 0) {
            return null;
        }
        WifiConfiguration selectedNetwork = null;
        for (NetworkEvaluator registeredEvaluator : mEvaluators) {
            if (registeredEvaluator != null) {
                localLog("About to run "   registeredEvaluator.getName()   " :");
                selectedNetwork = registeredEvaluator.evaluateNetworks(
                        new ArrayList<>(mFilteredNetworks), currentNetwork, currentBssid, connected,
                        untrustedNetworkAllowed, mConnectableNetworks);
                if (selectedNetwork != null) {
                    localLog(registeredEvaluator.getName()   " selects "
                              WifiNetworkSelector.toNetworkString(selectedNetwork)   " : "
                              selectedNetwork.getNetworkSelectionStatus().getCandidate().BSSID);
                    break;
                }
        if (selectedNetwork != null) {
         selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork);
            mLastNetworkSelectionTimeStamp = mClock.getElapsedSinceBootMillis();
       }
        return selectedNetwork;
    }

看下是否可以进行网络选择: 1、 当前网络无效时 2、 当前没有连接网络时

代码语言:javascript复制
    private boolean isNetworkSelectionNeeded(List<ScanDetail> scanDetails, WifiInfo wifiInfo,
                        boolean connected, boolean disconnected) {
        if (scanDetails.size() == 0) {
            localLog("Empty connectivity scan results. Skip network selection.");
            return false;
        }

        if (connected) {
            if (isCurrentNetworkSufficient(wifiInfo, scanDetails)) {
                localLog("Current connected network already sufficient. Skip network selection.");
                return false;
            } else {
                localLog("Current connected network is not sufficient.");
                return true;
            }
        } else if (disconnected) {
            return true;
        } else {

判断网络是否有效,主要是看以下几点要素: 1、rssi(区分2.4G还是5G) 2、packet rate 3、ephemeral(短暂的) 4、open network 5、5G优先级>2.4G

代码语言:javascript复制
    private boolean isCurrentNetworkSufficient(WifiInfo wifiInfo, List<ScanDetail> scanDetails) {
        WifiConfiguration network =
                   mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
        int currentRssi = wifiInfo.getRssi();
        boolean hasQualifiedRssi =
                (wifiInfo.is24GHz() && (currentRssi > mThresholdQualifiedRssi24))
                        || (wifiInfo.is5GHz() && (currentRssi > mThresholdQualifiedRssi5));
        boolean hasActiveStream = (wifiInfo.getTxSuccessRatePps() > mStayOnNetworkMinimumTxRate)
                || (wifiInfo.getRxSuccessRatePps() > mStayOnNetworkMinimumRxRate);
        if (hasQualifiedRssi && hasActiveStream) {
            localLog("Stay on current network because of good RSSI and ongoing traffic");
            return true;
        }
        if (network.ephemeral) {
            localLog("Current network is an ephemeral one.");
            return false;
        }
        if (WifiConfigurationUtil.isConfigForOpenNetwork(network)) {
            localLog("Current network is a open one.");
            return false;
        }
        if (wifiInfo.is24GHz()) {
            if (is5GHzNetworkAvailable(scanDetails)) {
                localLog("Current network is 2.4GHz. 5GHz networks available.");
                return false;
            }
        }
        if (!hasQualifiedRssi) {
            localLog("Current network RSSI["   currentRssi   "]-acceptable but not qualified.");
            return false;
        }

        return true;
    }

SavedNetworkEvaluator的筛选 首先遍历扫描结果:

代码语言:javascript复制
  for (ScanDetail scanDetail : scanDetails) {
            ScanResult scanResult = scanDetail.getScanResult();
            int highestScoreOfScanResult = Integer.MIN_VALUE;
      int candidateIdOfScanResult = WifiConfiguration.INVALID_NETWORK_ID;

过滤passpoint和ephemeral,如api所述这类网络交由PasspointNetworkEvaluator和ScoredNetworkEvaluator进行评估
                if (network.isPasspoint() || network.isEphemeral()) {
                    continue;
                }

接着过滤没有enabled的,scan bssid和config对不上的和eap-sim之类的网络但是没插卡的。

代码语言:javascript复制
                if (!status.isNetworkEnabled()) {
                    continue;
                } else if (network.BSSID != null &&  !network.BSSID.equals("any")
                        && !network.BSSID.equals(scanResult.BSSID)) {
  localLog("Network "   WifiNetworkSelector.toNetworkString(network)  " has specified BSSID "   network.BSSID   ". Skip "   scanResult.BSSID);
                    continue;
                } else if (TelephonyUtil.isSimConfig(network)
                        && !mWifiConfigManager.isSimPresent()) {
                    localLog("isSimPresent");
                    continue;
                }

网络评分的关键:计算BSSID的分数,评分几大要素如下: 1、 RSSI 2、 5G 3、 lastUserSelectedNetworkId 4、 currentNetwork 5、 isFirmwareRoamingSupported 6、 isConfigForOpenNetwork

代码语言:javascript复制
    private int calculateBssidScore(ScanResult scanResult, WifiConfiguration network,
                        WifiConfiguration currentNetwork, String currentBssid,
                        StringBuffer sbuf) {
        int score = 0;
        boolean is5GHz = scanResult.is5GHz();

        sbuf.append("[ ").append(scanResult.SSID).append(" ").append(scanResult.BSSID)
                .append(" RSSI:").append(scanResult.level).append(" ] ");

        int rssiSaturationThreshold = is5GHz ? mThresholdSaturatedRssi5 : mThresholdSaturatedRssi24;
        int rssi = scanResult.level < rssiSaturationThreshold ? scanResult.level
                : rssiSaturationThreshold;
        score  = (rssi   mRssiScoreOffset) * mRssiScoreSlope;
        sbuf.append(" RSSI score: ").append(score).append(",");

如果是5G频段,会有奖励。
        if (is5GHz) {
            score  = mBand5GHzAward;
            sbuf.append(" 5GHz bonus: ").append(mBand5GHzAward).append(",");
        }
之前连接过也有奖励
       int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork();
        if (lastUserSelectedNetworkId != WifiConfiguration.INVALID_NETWORK_ID
                && lastUserSelectedNetworkId == network.networkId) {
            long timeDifference = mClock.getElapsedSinceBootMillis()
                    - mWifiConfigManager.getLastSelectedTimeStamp();
            if (timeDifference > 0) {
                int bonus = mLastSelectionAward - (int) (timeDifference / 1000 / 60);
                score  = bonus > 0 ? bonus : 0;
                sbuf.append(" User selection ").append(timeDifference / 1000 / 60)
                        .append(" minutes ago, bonus: ").append(bonus).append(",");
            }
        }

如果是当前正在连接的网络,也会加分
        if (currentNetwork != null
                && (network.networkId == currentNetwork.networkId
  
                /* || network.isLinked(currentNetwork) */)) {
            score  = mSameNetworkAward;
            sbuf.append(" Same network bonus: ").append(mSameNetworkAward).append(",");
支持漫游也会有奖励
            if (mConnectivityHelper.isFirmwareRoamingSupported()
                    && currentBssid != null && !currentBssid.equals(scanResult.BSSID)) {
                score  = mSameBssidAward;
                sbuf.append(" Equivalent BSSID bonus: ").append(mSameBssidAward).append(",");
            }
        }

BSSID相同也会有奖励
        if (currentBssid != null && currentBssid.equals(scanResult.BSSID)) {
            score  = mSameBssidAward;
            sbuf.append(" Same BSSID bonus: ").append(mSameBssidAward).append(",");
        }

不是开放的网络,也会有奖励
        if (!WifiConfigurationUtil.isConfigForOpenNetwork(network)) {
            score  = mSecurityAward;
            sbuf.append(" Secure network bonus: ").append(mSecurityAward).append(",");
        sbuf.append(" ## Total score: ").append(score).append("n");

        return score;
    }

0 人点赞