(二)Android Q WiFi 启动流程分析二

ClientModeImpl 状态机分析

ClientModeImpl 是ClientMode的状态机,是用于控制WiFi 连接,获取IP ,设置网络配置。上一篇我们说到启动后,发送消息使得ClientModeImpl 状态机切换到DisconnectedState 状态;调用DisconnectedState enter 方法;enter主要是调用 WifiConnectivityManager
的handleConnectionStateChanged 方法处理WiFi 网络状态的改变。

     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);
            
        }

WifiConnectivityManager WiFi 网络连接管理类

WifiConnectivityManager 是管理WiFi 连接管理的类,主要管理者WiFi 网络的评分及网络选择,和扫描。handleConnectionStateChanged 实现如下,在上文中我们知道,传进来的参数为 WifiConnectivityManager.WIFI_STATE_DISCONNECTED ,所以我们调用startConnectivityScan(SCAN_IMMEDIATELY) 触发一次快速的连接扫描。

   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);
        }
    }

startConnectivityScan(SCAN_IMMEDIATELY) 方法的实现如下,SCAN_IMMEDIATELY 参数定义是true,首先判断当前WiFi的状态,如果WiFi 不是Enable 状态则退出。然后停止之前的连接扫描,根据当前屏幕的状态;如果是亮屏状态,则启动周期性的扫描,如果是灭屏状态则启动PNO 扫描(背景扫描)

 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();
            }
        }
    }

我们先看周期性的扫描startPeriodicScan 设置周期扫描的周期为PERIODIC_SCAN_INTERVAL_MS ;PERIODIC_SCAN_INTERVAL_MS 为20s ,调用startPeriodicSingleScan

   // 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();
    }

startPeriodicSingleScan 实现如下,
由于是第一次打开WiFi ,所以mWifiState 为WIFI_STATE_DISCONNECTED ,所以isScanNeeded 和isFullBandScan 都为true;更新最后单次扫描的时间,启动单次扫描。更新扫描的周期,以2的指数增加,最大160s;然后在启动定时器,时间到了再触发一次扫描

  // 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);
        }
    }

startSingleScan 方法实现构造一个ScanSettings 对象,然后调用Scanner 去触发一次扫描,扫描完成后会返回一个扫描结果。在得到扫描结果的时候会回调之前注册到wifiscanserver 的函数来处理扫描结果。

   // 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();
    }

当扫描结束,wifiscanserver 获取到扫描结果会回调WifiConnectivityManager 的handleScanResults 方法来处理扫描结果,首先调用selectNetwork 对各类WiFi 网络进行评分,选择出最好的WiFi 网络,然后调用connectToNetwork 来连接该网络

 * 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;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值