前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Wifi自动连接评分机制

Wifi自动连接评分机制

作者头像
用户7557625
发布2020-07-15 10:33:12
1.2K0
发布2020-07-15 10:33:12
举报
文章被收录于专栏:程序猿的那点事

今天了解了一下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;
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档