(两百三十七)Android Q WiFi 校验带来的后续影响

目录

1.流程梳理

1.1 网络校验

1.1.1 网络校验失败

 1.1.2 网络校验成功

1.2 超时校验

2.总结


 

1.流程梳理

1.1 网络校验

ConnectivityService

                case EVENT_NETWORK_TESTED: {
                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                    if (nai == null) break;

                    final boolean wasPartial = nai.partialConnectivity;
                    nai.partialConnectivity = ((msg.arg1 & NETWORK_VALIDATION_RESULT_PARTIAL) != 0);
                    final boolean partialConnectivityChanged =
                            (wasPartial != nai.partialConnectivity);

                    final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0);
                    final boolean wasValidated = nai.lastValidated;
                    final boolean wasDefault = isDefaultNetwork(nai);
                    // Only show a connected notification if the network is pending validation
                    // after the captive portal app was open, and it has now validated.
                    if (nai.captivePortalValidationPending && valid) {
                        // User is now logged in, network validated.
                        nai.captivePortalValidationPending = false;
                        showNetworkNotification(nai, NotificationType.LOGGED_IN);
                    }

                    final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";

                    if (DBG) {
                        final String logMsg = !TextUtils.isEmpty(redirectUrl)
                                 ? " with redirect to " + redirectUrl
                                 : "";
                        log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg);
                    }
                    if (valid != nai.lastValidated) {
                        if (wasDefault) {
                            metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
                                    SystemClock.elapsedRealtime(), valid);
                        }
                        final int oldScore = nai.getCurrentScore();
                        nai.lastValidated = valid;
                        nai.everValidated |= valid;
                        updateCapabilities(oldScore, nai, nai.networkCapabilities);
                        // If score has changed, rebroadcast to NetworkFactories. b/17726566
                        if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
                        if (valid) {
                            handleFreshlyValidatedNetwork(nai);
                            // Clear NO_INTERNET, PARTIAL_CONNECTIVITY and LOST_INTERNET
                            // notifications if network becomes valid.
                            mNotifier.clearNotification(nai.network.netId,
                                    NotificationType.NO_INTERNET);
                            mNotifier.clearNotification(nai.network.netId,
                                    NotificationType.LOST_INTERNET);
                            mNotifier.clearNotification(nai.network.netId,
                                    NotificationType.PARTIAL_CONNECTIVITY);
                        }
                    } else if (partialConnectivityChanged) {
                        updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
                    }
                    updateInetCondition(nai);
                    // Let the NetworkAgent know the state of its network
                    Bundle redirectUrlBundle = new Bundle();
                    redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
                    // TODO: Evaluate to update partial connectivity to status to NetworkAgent.
                    nai.asyncChannel.sendMessage(
                            NetworkAgent.CMD_REPORT_NETWORK_STATUS,
                            (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
                            0, redirectUrlBundle);

                    // If NetworkMonitor detects partial connectivity before
                    // EVENT_PROMPT_UNVALIDATED arrives, show the partial connectivity notification
                    // immediately. Re-notify partial connectivity silently if no internet
                    // notification already there.
                    if (!wasPartial && nai.partialConnectivity) {
                        // Remove delayed message if there is a pending message.
                        mHandler.removeMessages(EVENT_PROMPT_UNVALIDATED, nai.network);
                        handlePromptUnvalidated(nai.network);
                    }

                    if (wasValidated && !nai.lastValidated) {
                        handleNetworkUnvalidated(nai);
                    }
                    break;
                }

这边对WiFi的影响主要看,至于评分机制导致网络重新评分的之前梳理过了

                    nai.asyncChannel.sendMessage(
                            NetworkAgent.CMD_REPORT_NETWORK_STATUS,
                            (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
                            0, redirectUrlBundle);

这边可以看到会将网络校验成功或者失败通过asyncChannel发送出去

NetworkAgent会处理

            case CMD_REPORT_NETWORK_STATUS: {
                String redirectUrl = ((Bundle)msg.obj).getString(REDIRECT_URL_KEY);
                if (VDBG) {
                    log("CMD_REPORT_NETWORK_STATUS(" +
                            (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl);
                }
                networkStatus(msg.arg1, redirectUrl);
                break;
            }

对应到WiFi就看下WiFi的具体实现

    private class WifiNetworkAgent extends NetworkAgent {
        WifiNetworkAgent(Looper l, Context c, String tag, NetworkInfo ni,
                NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
            super(l, c, tag, ni, nc, lp, score, misc);
        }
        private int mLastNetworkStatus = -1; // To detect when the status really changes

        @Override
        protected void unwanted() {
            // Ignore if we're not the current networkAgent.
            if (this != mNetworkAgent) return;
            if (mVerboseLoggingEnabled) {
                log("WifiNetworkAgent -> Wifi unwanted score " + Integer.toString(mWifiInfo.score));
            }
            unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT);
        }

        @Override
        protected void networkStatus(int status, String redirectUrl) {
            if (this != mNetworkAgent) return;
            if (status == mLastNetworkStatus) return;
            mLastNetworkStatus = status;
            if (status == NetworkAgent.INVALID_NETWORK) {
                if (mVerboseLoggingEnabled) {
                    log("WifiNetworkAgent -> Wifi networkStatus invalid, score="
                            + Integer.toString(mWifiInfo.score));
                }
                unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED);
            } else if (status == NetworkAgent.VALID_NETWORK) {
                if (mVerboseLoggingEnabled) {
                    log("WifiNetworkAgent -> Wifi networkStatus valid, score= "
                            + Integer.toString(mWifiInfo.score));
                }
                mWifiMetrics.logStaEvent(StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK);
                doNetworkStatus(status);
            }
        }

1.1.1 网络校验失败

                    } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
                            || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) {
                        Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
                                ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN"
                                : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED"));
                        config = getCurrentWifiConfiguration();
                        if (config != null) {
                            // Disable autojoin
                            if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) {
                                mWifiConfigManager.setNetworkValidatedInternetAccess(
                                        config.networkId, false);
                                mWifiConfigManager.updateNetworkSelectionStatus(config.networkId,
                                        WifiConfiguration.NetworkSelectionStatus
                                        .DISABLED_NO_INTERNET_PERMANENT);
                            } else {
                                // stop collect last-mile stats since validation fail
                                removeMessages(CMD_DIAGS_CONNECT_TIMEOUT);
                                mWifiDiagnostics.reportConnectionEvent(
                                        WifiDiagnostics.CONNECTION_EVENT_FAILED);
                                mWifiConfigManager.incrementNetworkNoInternetAccessReports(
                                        config.networkId);
                                // If this was not the last selected network, update network
                                // selection status to temporarily disable the network.
                                if (mWifiConfigManager.getLastSelectedNetwork() != config.networkId
                                        && !config.noInternetAccessExpected) {
                                    Log.i(TAG, "Temporarily disabling network because of"
                                            + "no-internet access");
                                    mWifiConfigManager.updateNetworkSelectionStatus(
                                            config.networkId,
                                            WifiConfiguration.NetworkSelectionStatus
                                                    .DISABLED_NO_INTERNET_TEMPORARY);
                                }
                            }
                        }
                    }

若该网络不是用户最近选择的并且不认为是无网络的,则将其设置为临时无网络禁用,临时无网络禁用是不会触发断开的

WifiConnectivityManager

    private class OnSavedNetworkUpdateListener implements
            WifiConfigManager.OnSavedNetworkUpdateListener {
        @Override
        public void onSavedNetworkAdded(int networkId) {
            updatePnoScan();
        }
        @Override
        public void onSavedNetworkEnabled(int networkId) {
            updatePnoScan();
        }
        @Override
        public void onSavedNetworkRemoved(int networkId) {
            updatePnoScan();
        }
        @Override
        public void onSavedNetworkUpdated(int networkId) {
            // User might have changed meteredOverride, so update capabilties
            mStateMachine.updateCapabilities();
            updatePnoScan();
        }
        @Override
        public void onSavedNetworkTemporarilyDisabled(int networkId, int disableReason) {
            if (disableReason == DISABLED_NO_INTERNET_TEMPORARY) return;
            mConnectivityHelper.removeNetworkIfCurrent(networkId);
        }

 1.1.2 网络校验成功

                case CMD_NETWORK_STATUS:
                    if (message.arg1 == NetworkAgent.VALID_NETWORK) {
                        // stop collect last-mile stats since validation pass
                        removeMessages(CMD_DIAGS_CONNECT_TIMEOUT);
                        mWifiDiagnostics.reportConnectionEvent(
                                WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED);
                        mWifiScoreCard.noteValidationSuccess(mWifiInfo);
                        config = getCurrentWifiConfiguration();
                        if (config != null) {
                            // re-enable autojoin
                            mWifiConfigManager.updateNetworkSelectionStatus(
                                    config.networkId,
                                    WifiConfiguration.NetworkSelectionStatus
                                            .NETWORK_SELECTION_ENABLE);
                            mWifiConfigManager.setNetworkValidatedInternetAccess(
                                    config.networkId, true);
                        }
                    }
                    break;

和无网络临时禁用是相对的,会enable当前的ap config

 

1.2 超时校验

ConnectivityService还有个8s的超时校验

    private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
        if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
        mHandler.sendMessageDelayed(
                mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
                PROMPT_UNVALIDATED_DELAY_MS);
    }

   // How long to wait before putting up a "This network doesn't have an Internet connection,
    // connect anyway?" dialog after the user selects a network that doesn't validate.
    private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;


    private void handlePromptUnvalidated(Network network) {
        if (VDBG || DDBG) log("handlePromptUnvalidated " + network);
        NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);

        if (nai == null || !shouldPromptUnvalidated(nai)) {
            return;
        }

        // Stop automatically reconnecting to this network in the future. Automatically connecting
        // to a network that provides no or limited connectivity is not useful, because the user
        // cannot use that network except through the notification shown by this method, and the
        // notification is only shown if the network is explicitly selected by the user.
        nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);

        // TODO: Evaluate if it's needed to wait 8 seconds for triggering notification when
        // NetworkMonitor detects the network is partial connectivity. Need to change the design to
        // popup the notification immediately when the network is partial connectivity.
        if (nai.partialConnectivity) {
            showNetworkNotification(nai, NotificationType.PARTIAL_CONNECTIVITY);
        } else {
            showNetworkNotification(nai, NotificationType.NO_INTERNET);
        }
    }

看这一句

        // Stop automatically reconnecting to this network in the future. Automatically connecting
        // to a network that provides no or limited connectivity is not useful, because the user
        // cannot use that network except through the notification shown by this method, and the
        // notification is only shown if the network is explicitly selected by the user.
        nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);

NetworkAgent会处理

            case CMD_PREVENT_AUTOMATIC_RECONNECT: {
                preventAutomaticReconnect();
                break;
            }

对应到WiFi

        @Override
        protected void preventAutomaticReconnect() {
            if (this != mNetworkAgent) return;
            unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN);
        }


                    } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
                            || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) {
                        Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
                                ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN"
                                : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED"));
                        config = getCurrentWifiConfiguration();
                        if (config != null) {
                            // Disable autojoin
                            if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) {
                                mWifiConfigManager.setNetworkValidatedInternetAccess(
                                        config.networkId, false);
                                mWifiConfigManager.updateNetworkSelectionStatus(config.networkId,
                                        WifiConfiguration.NetworkSelectionStatus
                                        .DISABLED_NO_INTERNET_PERMANENT);
                            } 

设置为无网络并且永久禁用,同样无网络永久禁用并不会断开

        @Override
        public void onSavedNetworkPermanentlyDisabled(int networkId, int disableReason) {
            // For DISABLED_NO_INTERNET_PERMANENT we do not need to remove the network
            // because supplicant won't be trying to reconnect. If this is due to a
            // preventAutomaticReconnect request from ConnectivityService, that service
            // will disconnect as appropriate.
            if (disableReason == DISABLED_NO_INTERNET_PERMANENT) return;
            mConnectivityHelper.removeNetworkIfCurrent(networkId);
            updatePnoScan();
        }

 

 

2.总结

WiFi若在8s内校验不通过则会被永久禁用并将网络设置为无网络;

若校验未通过,则会被设置为临时禁用;

若校验通过,则会设置为enable并且网络可用

待研究一个问题:

若永久禁用后又被网络校验失败,会变成临时禁用么?从代码来看会的呀

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值