Android Q-wifi启动流程(三)

9 篇文章 0 订阅
7 篇文章 2 订阅

4、ClientModeImpl 状态机分析
    ClientModeImpl 是ClientMode的状态机,是用于控制WiFi 连接,获取IP ,设置网络配置。上一篇我们说到启动后,发送消息使得ClientModeImpl 状
    态机切换到DisconnectedState 状态;调用DisconnectedState enter 方法;enter主要是调用 WifiConnectivityManager的
    handleConnectionStateChanged 方法处理WiFi 网络状态的改变。
        enter源码:
        public void enter() {
                Log.i(TAG, "disconnectedstate enter");
                // We don't scan frequently if this is a temporary disconnect
                // due to p2p
                if (mTemporarilyDisconnectWifi) {
                    p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
                    return;
                }

                if (mVerboseLoggingEnabled) {
                    logd(" Enter DisconnectedState screenOn=" + mScreenOn);
                }

                /** clear the roaming state, if we were roaming, we failed */
                mIsAutoRoaming = false;
                mIpReachabilityMonitorActive = false;
                removeMessages(CMD_IP_REACHABILITY_SESSION_END);

                
                    mWifiConnectivityManager.handleConnectionStateChanged(
                            WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
                
            }
5、WifiConnectivityManager WiFi 网络连接管理类
    5.1 WifiConnectivityManager 是管理WiFi 连接管理的类,主要管理者WiFi 网络的评分及网络选择,和扫描。handleConnectionStateChanged 实现
        如下,在上文中我们知道,传进来的参数为 WifiConnectivityManager.WIFI_STATE_DISCONNECTED ,所以我们调用startConnectivityScan(
        SCAN_IMMEDIATELY) 触发一次快速的连接扫描。
        handleConnectionStateChanged源码:
            public void handleConnectionStateChanged(int state) {
                localLog("handleConnectionStateChanged: state=" + stateToString(state));
            
                mWifiState = state;

                // Reset BSSID of last connection attempt and kick off
                // the watchdog timer if entering disconnected state.
                if (mWifiState == WIFI_STATE_DISCONNECTED) {
                    mLastConnectionAttemptBssid = null;
              
                    startConnectivityScan(SCAN_IMMEDIATELY);
                } else {
                    startConnectivityScan(SCAN_ON_SCHEDULE);
                }
            }
    5.2 startConnectivityScan(SCAN_IMMEDIATELY) 方法的实现如下,SCAN_IMMEDIATELY 参数定义是true,首先判断当前WiFi的状态,如果WiFi 不是
        Enable状态则退出。然后停止之前的连接扫描,根据当前屏幕的状态;如果是亮屏状态,则启动周期性的扫描,如果是灭屏状态则启动PNO 扫描

        (背景扫描)
        startConnectivityScan源码:
            private void startConnectivityScan(boolean scanImmediately) {
                localLog("startConnectivityScan: screenOn=" + mScreenOn
                        + " wifiState=" + stateToString(mWifiState)
                        + " scanImmediately=" + scanImmediately
                        + " wifiEnabled=" + mWifiEnabled
                        + " wifiConnectivityManagerEnabled="
                        + mWifiConnectivityManagerEnabled);

                if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) {
                    return;
                }
                // Always stop outstanding connecivity scan if there is any
                stopConnectivityScan();
                // Don't start a connectivity scan while Wifi is in the transition
                // between connected and disconnected states.
                if (mWifiState != WIFI_STATE_CONNECTED && mWifiState != WIFI_STATE_DISCONNECTED) {
                    return;
                }
                if (mScreenOn) {
                        startPeriodicScan(scanImmediately);
                    }
                } else {
                    if (mWifiState == WIFI_STATE_DISCONNECTED && !mPnoScanStarted) {
                        startDisconnectedPnoScan();
                    }
                }
            }
    5.3 我们先看周期性的扫描startPeriodicScan 设置周期扫描的周期为PERIODIC_SCAN_INTERVAL_MS ;PERIODIC_SCAN_INTERVAL_MS 为20s ,调用
        startPeriodicSingleScan
        startPeriodicScan源码如下:
            // Start a periodic scan when screen is on
            private void startPeriodicScan(boolean scanImmediately) {
                mPnoScanListener.resetLowRssiNetworkRetryDelay();
                // No connectivity scan if auto roaming is disabled.
                if (mWifiState == WIFI_STATE_CONNECTED && !mEnableAutoJoinWhenAssociated) {
                    return;
                }
                // Due to b/28020168, timer based single scan will be scheduled
                // to provide periodic scan in an exponential backoff fashion.
                if (scanImmediately) {
                    resetLastPeriodicSingleScanTimeStamp();
                }
                mPeriodicSingleScanInterval = PERIODIC_SCAN_INTERVAL_MS;
                startPeriodicSingleScan();
            }
    5.4 startPeriodicSingleScan 实现如下,由于是第一次打开WiFi ,所以mWifiState 为WIFI_STATE_DISCONNECTED ,所以isScanNeeded 和
        isFullBandScan 都为true;更新最后单次扫描的时间,启动单次扫描。更新扫描的周期,以2的指数增加,最大160s;然后在启动定时器,时间
        到了再触发一次扫描

        startPeriodicSingleScan源码:
            // Start a single scan and set up the interval for next single scan.
            private void startPeriodicSingleScan() {
                long currentTimeStamp = mClock.getElapsedSinceBootMillis();
                if (mLastPeriodicSingleScanTimeStamp != RESET_TIME_STAMP) {
                    long msSinceLastScan = currentTimeStamp - mLastPeriodicSingleScanTimeStamp;
                    if (msSinceLastScan < PERIODIC_SCAN_INTERVAL_MS) {
                        localLog("Last periodic single scan started " + msSinceLastScan
                                + "ms ago, defer this new scan request.");
                        schedulePeriodicScanTimer(PERIODIC_SCAN_INTERVAL_MS - (int) msSinceLastScan);
                        return;
                    }
                }

                boolean isScanNeeded = true;
                boolean isFullBandScan = true;
                boolean isTrafficOverThreshold = mWifiInfo.txSuccessRate > mFullScanMaxTxRate
                        || mWifiInfo.rxSuccessRate > mFullScanMaxRxRate;
                // If the WiFi traffic is heavy, only partial scan is proposed.
                if (mWifiState == WIFI_STATE_CONNECTED && isTrafficOverThreshold) {
                    // If only partial scan is proposed and firmware roaming control is supported,
                    // we will not issue any scan because firmware roaming will take care of
                    // intra-SSID roam.
                    if (mConnectivityHelper.isFirmwareRoamingSupported()) {
                        localLog("No partial scan because firmware roaming is supported.");
                        isScanNeeded = false;
                    } else {
                        localLog("No full band scan due to ongoing traffic");
                        isFullBandScan = false;
                    }
                }

                if (isScanNeeded) {
                    mLastPeriodicSingleScanTimeStamp = currentTimeStamp;
                    startSingleScan(isFullBandScan, WIFI_WORK_SOURCE);
                    schedulePeriodicScanTimer(mPeriodicSingleScanInterval);

                    // Set up the next scan interval in an exponential backoff fashion.
                    mPeriodicSingleScanInterval *= 2;
                    if (mPeriodicSingleScanInterval >  MAX_PERIODIC_SCAN_INTERVAL_MS) {
                        mPeriodicSingleScanInterval = MAX_PERIODIC_SCAN_INTERVAL_MS;
                    }
                } else {
                    // Since we already skipped this scan, keep the same scan interval for next scan.
                    schedulePeriodicScanTimer(mPeriodicSingleScanInterval);
                }
            }
    5.5 startSingleScan 方法实现构造一个ScanSettings 对象,然后调用Scanner 去触发一次扫描,扫描完成后会返回一个扫描结果。在得到扫描结果
        的时候会回调之前注册到wifiscanserver 的函数来处理扫描结果。

        startSingleScan源码:
            // Start a single scan
            private void startSingleScan(boolean isFullBandScan, WorkSource workSource) {
                if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) {
                    return;
                }
                // Any scans will impact wifi performance including WFD performance,
                // So at least ignore scans triggered internally by ConnectivityManager
                // when WFD session is active. We still allow connectivity scans initiated
                // by other work source.
                if (WIFI_WORK_SOURCE.equals(workSource) &&
                    (mMiracastMode == WifiP2pManager.MIRACAST_SOURCE ||
                    mMiracastMode == WifiP2pManager.MIRACAST_SINK)) {
                    Log.d(TAG,"ignore connectivity scan, MiracastMode:" + mMiracastMode);
                    return;
                }
                mPnoScanListener.resetLowRssiNetworkRetryDelay();

                ScanSettings settings = new ScanSettings();
                if (!isFullBandScan) {
                    if (!setScanChannels(settings)) {
                        isFullBandScan = true;
                    }
                }
                settings.type = WifiScanner.TYPE_HIGH_ACCURACY; // always do high accuracy scans.
                settings.band = getScanBand(isFullBandScan);
                settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT
                                    | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
                settings.numBssidsPerScan = 0;
                // retrieve the list of hidden network SSIDs from saved network to scan for
                List<ScanSettings.HiddenNetwork> hiddenNetworkList =
                        new ArrayList<>(mConfigManager.retrieveHiddenNetworkList());
                // retrieve the list of hidden network SSIDs from Network suggestion to scan for
                hiddenNetworkList.addAll(
                        mWifiInjector.getWifiNetworkSuggestionsManager().retrieveHiddenNetworkList());
                settings.hiddenNetworks =
                        hiddenNetworkList.toArray(new ScanSettings.HiddenNetwork[0]);

                SingleScanListener singleScanListener =
                        new SingleScanListener(isFullBandScan);
                mScanner.startScan(settings, singleScanListener, workSource);
                mWifiMetrics.incrementConnectivityOneshotScanCount();
            }
    5.6 当扫描结束,wifiscanserver 获取到扫描结果会回调WifiConnectivityManager 的handleScanResults 方法来处理扫描结果,首先调用
        selectNetwork 对各类WiFi 网络进行评分,选择出最好的WiFi 网络,然后调用connectToNetwork 来连接该网络

        handleScanResults源码如下:
             * Handles 'onResult' callbacks for the Periodic, Single & Pno ScanListener.
             * Executes selection of potential network candidates, initiation of connection attempt to that
             * network.
             *
             * @return true - if a candidate is selected by WifiNetworkSelector
             *         false - if no candidate is selected by WifiNetworkSelector
             */
            private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName) {
                // Check if any blacklisted BSSIDs can be freed.
                refreshBssidBlacklist();

                if (mStateMachine.isSupplicantTransientState()) {
                    localLog(listenerName
                            + " onResults: No network selection because supplicantTransientState is "
                            + mStateMachine.isSupplicantTransientState());
                    return false;
                }

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

                List<ScanDetail> filteredScans = mStateMachine.qtiGetFilteredScan(scanDetails);

                WifiConfiguration candidate =
                        mNetworkSelector.selectNetwork(filteredScans, 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());
                        if (mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()) {
                            mCarrierNetworkNotifier.handleScanResults(
                                    mNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
                                            mCarrierNetworkConfig));
                        }
                    }
                    return false;
                }
            }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值