android-wifi(7.1)漫游部分逻辑
漫游说明:一个场所有若干台AP,相同的SSID不同的BSSID,STA可以在这个场所的不同地方自动连接信号好的AP.
协议规定:
相关类
WifiQualifiedNetworkSelector.java
WifiStateMachine.java
WifiConnectivityManager.handleScanResults
{
   WifiConfiguration candidate =
                mQualifiedNetworkSelector.selectQualifiedNetwork//根据扫描结果选择候选得分最高的网络
   //有得分较高的网络进行连接
   connectToNetwork(candidate)
}
WifiQualifiedNetworkSelector.SelectQualifiedNetwork
{
        <integer translatable="false" name="config_wifi_framework_RSSI_SCORE_OFFSET">85</integer>
        <integer translatable="false" name="config_wifi_framework_RSSI_SCORE_SLOPE">4</integer>
        mRssiScoreSlope = context.getResources().getInteger(
                R.integer.config_wifi_framework_RSSI_SCORE_SLOPE);//4
        mRssiScoreOffset = context.getResources().getInteger(
                R.integer.config_wifi_framework_RSSI_SCORE_OFFSET);//85
        mSameBssidAward = context.getResources().getInteger(
                R.integer.config_wifi_framework_SAME_BSSID_AWARD);
         //循环所有的扫描结果找到分数最高的候选网络
        //iterate all scan results and find the best candidate with the highest score
        for (ScanDetail scanDetail : mScanDetails) {
            ScanResult scanResult = scanDetail.getScanResult();
             //skip scan result with too weak signals
             //跳过信号小于最小值的结果
            if ((scanResult.is24GHz() && scanResult.level
                    < mWifiConfigManager.mThresholdMinimumRssi24.get())
                    || (scanResult.is5GHz() && scanResult.level
                    < mWifiConfigManager.mThresholdMinimumRssi5.get())) {
                
                continue;
            }
            int highestScore = Integer.MIN_VALUE;
            int score;
            //计算bssid的分数
            score = calculateBssidScore(scanResult, network, mCurrentConnectedNetwork,
                        (mCurrentBssid == null ? false : mCurrentBssid.equals(scanResult.BSSID)),
                        (lastUserSelectedNetwork == null ? false : lastUserSelectedNetwork.networkId
                         == network.networkId), scoreHistory);
           /*
                 //上面方法逻辑如下:
                 int score = 0;
                 //calculate the RSSI score
                 //1.第一个根据2.4和5G进行加分
                 int rssi = scanResult.level <= mWifiConfigManager.mThresholdSaturatedRssi24.get()
                            ? scanResult.level : mWifiConfigManager.mThresholdSaturatedRssi24.get();
                    score += (rssi + mRssiScoreOffset) * mRssiScoreSlope;//(rssi+85)*4
                 if (scanResult.is5GHz()) {//5G的情况
                    //5GHz band
                     score += mWifiConfigManager.mBandAward5Ghz.get();
                }
              //last user selection award
                //2.第一个根据上一次用户的选择进行减分
              if (sameSelect) {
                  long timeDifference = mClock.elapsedRealtime()
                    - mWifiConfigManager.getLastSelectedTimeStamp();
 
                 if (timeDifference > 0) {
                  int bonus = mLastSelectionAward - (int) (timeDifference / 1000 / 60);
                  score += bonus > 0 ? bonus : 0;
                  sbuf.append(" User selected it last time " + (timeDifference / 1000 / 60)
                        + " minutes ago, bonus:" + bonus);
                 }
                }
                //3.相同的网络进行加分
                //same network award
               if (network == currentNetwork || network.isLinked(currentNetwork)) {
                 score += mWifiConfigManager.mCurrentNetworkBoost.get();
               }
               //4.根据相同的BSSID来加分
               //same BSSID award
              if (sameBssid) {
               score += mSameBssidAward;
               sbuf.append(" Same BSSID with current association. Bonus: " + mSameBssidAward);
              }
              //5.根据是否是热点和加密方式设置加分点
                 if (network.isPasspoint()) {
                   score += mPasspointSecurityAward;
                 } else if (!mWifiConfigManager.isOpenNetwork(network)) {
                   score += mSecurityAward;
                 }
             //6.不能访问网络的惩罚进行减分
                 if (network.numNoInternetAccessReports > 0 && !network.validatedInternetAccess) {
                 score -= mNoIntnetPenalty;
                 }
            */
                //更新configurationCandidateForThisScan变量和highestScore 最高的那个网络network将会赋值给configurationCandidateForThisScan
                if (score > highestScore) {
                    highestScore = score;
                    configurationCandidateForThisScan = network;
                    potentialCandidate = network;
                }
                //update the cached candidate 更新候选网络缓存
                if (score > status.getCandidateScore() || (score == status.getCandidateScore()
                      && status.getCandidate() != null
                      && scanResult.level > status.getCandidate().level)) {
                    status.setCandidate(scanResult);
                    status.setCandidateScore(score);
                }
                //用currentHighestScore 来记录当前最高分 如果此次highestScore分和前面的最高分相等则要比较此次和前面最高分的网络的级别
                //把最高分的网络类型赋值给scanResultCandidate 并保存在最高分的WifiConfiguration文件中
                if (highestScore > currentHighestScore || (highestScore == currentHighestScore
                    && scanResultCandidate != null
                    && scanResult.level > scanResultCandidate.level)) {
                currentHighestScore = highestScore;
                scanResultCandidate = scanResult;
                networkCandidate = configurationCandidateForThisScan;
                networkCandidate.getNetworkSelectionStatus().setCandidate(scanResultCandidate);
            }
        }
        //循环体结束
        //其它一些简单步骤后返回networkCandidate
}

WifiConnectivityManager.connectToNetwork
{
    //获取当前得分最高的网络
    ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate();
    String targetBssid = scanResultCandidate.BSSID;
    String targetAssociationId = candidate.SSID + " : " + targetBssid;
    //漫游状态下networkId是否相同???
    if (currentConnectedNetwork != null
                && (currentConnectedNetwork.networkId == candidate.networkId
                || currentConnectedNetwork.isLinked(candidate))) {
            localLog("connectToNetwork: Roaming from " + currentAssociationId + " to "
                        + targetAssociationId);
            mStateMachine.autoRoamToNetwork(candidate.networkId, scanResultCandidate);
        } else {
            localLog("connectToNetwork: Reconnect from " + currentAssociationId + " to "
                        + targetAssociationId);
            mStateMachine.autoConnectToNetwork(candidate.networkId, scanResultCandidate.BSSID);
        }
}
WifiStateMachine.connectToNetwork()
{
    //获取候选网络 得分较高的网络
    ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate();
        if (scanResultCandidate == null) {
            Log.e(TAG, "connectToNetwork: bad candidate - "  + candidate
                    + " scanResult: " + scanResultCandidate);
            return;
        }
}

WifiStateMachine.autoRoamToNetwork(int networkId, ScanResult scanResult) 
{
        sendMessage(CMD_AUTO_ROAM, networkId, 0, scanResult);
}

在ConnectedState会接收和处理此消息
ConnectedState
{
   case CMD_AUTO_ROAM:
       setTargetBssid(config, bssid);//设置需要漫游到目标的bssid
       mTargetNetworkId = netId;//保存漫游网络ID
       /* Determine if this is a regular roam (between BSSIDs sharing the same SSID),
          or a DBDC roam (between 2.4 & 5GHz networks on different SSID's, but with
          matching 16 byte BSSID prefixes):
        */
       //确定是正常的漫游-不同的bssid相同的网络名称还是 双频同步-DBDC
       WifiConfiguration currentConfig = getCurrentWifiConfiguration();
                    if (currentConfig != null && currentConfig.isLinked(config)) {
                        // This is dual band roaming
                        mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID,
                                WifiMetricsProto.ConnectionEvent.ROAM_DBDC);//双频同步记录信息
                    } else {
                        // This is regular roaming
                        mWifiMetrics.startConnectionEvent(config, mTargetRoamBSSID,
                                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);//正常的漫游记录信息
                    }

       if (mLastNetworkId != netId) {
              //进行漫游连接
              if (mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ false,
                     WifiConfiguration.UNKNOWN_UID) && mWifiNative.reconnect()) {
                      ret = true;
              }
       } else {
                     ret = mWifiNative.reassociate();//重新关联
              }
       if (ret) {
             lastConnectAttemptTimestamp = System.currentTimeMillis();
             targetWificonfiguration = mWifiConfigManager.getWifiConfiguration(netId);
             // replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED);
             mAutoRoaming = true;
             transitionTo(mRoamingState);//连接成功后转换到漫游状态

       }
}

更多推荐