Wi-Fi PNO扫描流程(Android P)

简介:当手机灭屏情况下,有保存网络时,若已连接,不扫描,否则,PNO扫描,即只扫描已保存的网络。最小间隔min=20s,最大间隔max=20s*3=60s

PNO 即Preferred Network Offload,用于系统在休眠的时候连接WiFi

Wi-Fi PNO扫描流程

WifiConnectivityManager.java
灭屏时,WifiConnectivityManager中handleScreenStateChanged函数会判断是否触发PNO扫描。并且进行PNO扫描列表设置、PNO扫描间隔(20s)设置等PNO扫描的参数设置。所以先从处理屏幕状态改变开始。

public void handleScreenStateChanged(boolean screenOn) {
    localLog("handleScreenStateChanged: screenOn=" + screenOn);

    mScreenOn = screenOn;

    mOpenNetworkNotifier.handleScreenStateChanged(screenOn);
    mCarrierNetworkNotifier.handleScreenStateChanged(screenOn);

    startConnectivityScan(SCAN_ON_SCHEDULE);
}

开始连接扫描。 扫描方式根据当前的屏幕状态和WiFi状态选择。这里会选择PNO扫描。

private void startConnectivityScan(boolean scanImmediately) {
    localLog("startConnectivityScan: screenOn=" + mScreenOn
            + " wifiState=" + stateToString(mWifiState)
            + " scanImmediately=" + scanImmediately
            + " wifiEnabled=" + mWifiEnabled
            + " wifiConnectivityManagerEnabled="
            + mWifiConnectivityManagerEnabled);

    if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) {
        return;
    }
    if (mWifiState != WIFI_STATE_CONNECTED && mWifiState != WIFI_STATE_DISCONNECTED) {
        return;
    }

    if (mScreenOn) {
        startPeriodicScan(scanImmediately);
    } else {
        if (mWifiState == WIFI_STATE_DISCONNECTED && !mPnoScanStarted) {
            startDisconnectedPnoScan();
        }
    }

}

当屏幕关闭且WiFI未连接时,开启PNO扫描,初始化scan的设置。
可以看到扫描间隔为20s:scanSettings.periodInMs = DISCONNECTED_PNO_SCAN_INTERVAL_MS

private static final int DISCONNECTED_PNO_SCAN_INTERVAL_MS = 20 * 1000; // 20 seconds
private void startDisconnectedPnoScan() {
    // Initialize PNO settings
    PnoSettings pnoSettings = new PnoSettings();
    List<PnoSettings.PnoNetwork> pnoNetworkList = mConfigManager.retrievePnoNetworkList();
    int listSize = pnoNetworkList.size();
    
    pnoSettings.networkList = new PnoSettings.PnoNetwork[listSize];
    pnoSettings.networkList = pnoNetworkList.toArray(pnoSettings.networkList);
    pnoSettings.min5GHzRssi = mMin5GHzRssi;
    pnoSettings.min24GHzRssi = mMin24GHzRssi;
    pnoSettings.initialScoreMax = mInitialScoreMax;
    pnoSettings.currentConnectionBonus = mCurrentConnectionBonus;
    pnoSettings.sameNetworkBonus = mSameNetworkBonus;
    pnoSettings.secureBonus = mSecureBonus;
    pnoSettings.band5GHzBonus = mBand5GHzBonus;

    // Initialize scan settings
    ScanSettings scanSettings = new ScanSettings();
    scanSettings.band = getScanBand();
    scanSettings.reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH;
    scanSettings.numBssidsPerScan = 0;
    scanSettings.periodInMs = DISCONNECTED_PNO_SCAN_INTERVAL_MS;

    mPnoScanListener.clearScanDetails();

    mScanner.startDisconnectedPnoScan(scanSettings, pnoSettings, mPnoScanListener);
    mPnoScanStarted = true;
}

WifiScanner.java
startDisconnectedPnoScan --> startPnoScan 开启PNO扫描

public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
        PnoScanListener listener) {
    Preconditions.checkNotNull(listener, "listener cannot be null");
    Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
    int key = addListener(listener);
    if (key == INVALID_KEY) return;
    validateChannel();
    pnoSettings.isConnected = false;
    startPnoScan(scanSettings, pnoSettings, key);
}

startPnoScan发送PNO扫描(CMD_START_PNO_SCAN)的消息,由WifiScanningServiceImpl处理。

private void startPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, int key) {
    // Bundle up both the settings and send it across.
    Bundle pnoParams = new Bundle();
    // Set the PNO scan flag.
    scanSettings.isPnoScan = true;
    pnoParams.putParcelable(PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
    pnoParams.putParcelable(PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
    mAsyncChannel.sendMessage(CMD_START_PNO_SCAN, 0, key, pnoParams);
}

WifiScanningServiceImpl.java
从StartedState状态开始,获取到PNO扫描的设置以后,进入HwPnoScanState状态。

class StartedState extends State {
         .......
    @Override
    public boolean processMessage(Message msg) {
        ClientInfo ci = mClients.get(msg.replyTo);
        switch (msg.what) {
            case WifiScanner.CMD_START_PNO_SCAN:
                ........
                pnoParams.setDefusable(true);
                PnoSettings pnoSettings =
                        pnoParams.getParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY);
                if (mScannerImpl.isHwPnoSupported(pnoSettings.isConnected)) {
                    deferMessage(msg);
                    transitionTo(mHwPnoScanState);
                } else {
                    replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "not supported");
                }
                .................
        }
        return HANDLED;
    }
}

如果已经有PNO扫描,则进入StartedState。如果没有,则addHwPnoScanRequest。
注意:这里的StartedState是WifiBackgroundScanStateMachine中的StartedState。

class HwPnoScanState extends State {
    @Override
    public boolean processMessage(Message msg) {
        ClientInfo ci = mClients.get(msg.replyTo);
        switch (msg.what) {
            case WifiScanner.CMD_START_PNO_SCAN:
                Bundle pnoParams = (Bundle) msg.obj;
                if (pnoParams == null) {
                    replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "params null");
                    return HANDLED;
                }
                pnoParams.setDefusable(true);
                PnoSettings pnoSettings =
                        pnoParams.getParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY);
                ScanSettings scanSettings =
                        pnoParams.getParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY);
                if (addHwPnoScanRequest(ci, msg.arg2, scanSettings, pnoSettings)) {
                    replySucceeded(msg);
                } else {
                    replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request");
                    transitionTo(mStartedState);
                }
                break;
            ...........
        return HANDLED;
    }
}

addHwPnoScanRequest --> addPnoScanRequest

private boolean addHwPnoScanRequest(ClientInfo ci, int handler, ScanSettings scanSettings,
        PnoSettings pnoSettings) {
    if (ci == null) {
        Log.d(TAG, "Failing scan request ClientInfo not found " + handler);
        return false;
    }
    if (!mActivePnoScans.isEmpty()) {
        loge("Failing scan request because there is already an active scan");
        return false;
    }
    WifiNative.PnoSettings nativePnoSettings =
            convertSettingsToPnoNative(scanSettings, pnoSettings);
    if (!mScannerImpl.setHwPnoList(nativePnoSettings, mPnoScanStateMachine)) {
        return false;
    }
    logScanRequest("addHwPnoScanRequest", ci, handler, null, scanSettings, pnoSettings);
    addPnoScanRequest(ci, handler, scanSettings, pnoSettings);

    return true;
}
private void addPnoScanRequest(ClientInfo ci, int handler, ScanSettings scanSettings,
        PnoSettings pnoSettings) {
    mActivePnoScans.addRequest(ci, handler, WifiStateMachine.WIFI_WORK_SOURCE,
            Pair.create(pnoSettings, scanSettings));
    addInternalClient(ci);
}

WifiBackgroundScanStateMachine --> StartedState

未完待续。。。。

发布了67 篇原创文章 · 获赞 62 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43804080/article/details/103605390
今日推荐