(两百八十九)Android R supplicant的恢复机制

1.简介

我无聊试了下用命令把supplicant杀了,但是supplicant后来又自己启动起来了,看下流程

 

2.流程梳理

WifiNative

    /** Helper method invoked to start supplicant if there were no STA ifaces */
    private boolean startSupplicant() {
        synchronized (mLock) {
            if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) {
                if (!startAndWaitForSupplicantConnection()) {
                    Log.e(TAG, "Failed to connect to supplicant");
                    return false;
                }
                if (!mSupplicantStaIfaceHal.registerDeathHandler(
                        new SupplicantDeathHandlerInternal())) {
                    Log.e(TAG, "Failed to register supplicant death handler");
                    return false;
                }
            }
            return true;
        }
    }


    /**
     * Death handler for the supplicant daemon.
     */
    private class SupplicantDeathHandlerInternal implements SupplicantDeathEventHandler {
        @Override
        public void onDeath() {
            synchronized (mLock) {
                Log.i(TAG, "wpa_supplicant died. Cleaning up internal state.");
                onNativeDaemonDeath();
                mWifiMetrics.incrementNumSupplicantCrashes();
            }
        }
    }



    /**
     * Helper method invoked to trigger the status changed callback after one of the native
     * daemon's death.
     */
    private void onNativeDaemonDeath() {
        synchronized (mLock) {
            for (StatusListener listener : mStatusListeners) {
                listener.onStatusChanged(false);
            }
            for (StatusListener listener : mStatusListeners) {
                listener.onStatusChanged(true);
            }
        }
    }

supplicant在启动的时候注册了个DeathHandler,然后如果它死亡的时候会有个回调,告知AcitveModeWarden注册的listener

ActiveModeWarden

        wifiNative.registerStatusListener(isReady -> {
            if (!isReady && !mIsShuttingdown) {
                mHandler.post(() -> {
                    Log.e(TAG, "One of the native daemons died. Triggering recovery");
                    wifiDiagnostics.captureBugReportData(
                            WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE);

                    // immediately trigger SelfRecovery if we receive a notice about an
                    // underlying daemon failure
                    // Note: SelfRecovery has a circular dependency with ActiveModeWarden and is
                    // instantiated after ActiveModeWarden, so use WifiInjector to get the instance
                    // instead of directly passing in SelfRecovery in the constructor.
                    mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
                });
            }
        });

这边然后就会调用到WiFi的SelfRecovery的流程

    /**
     * Trigger recovery.
     *
     * This method does the following:
     * 1. Checks reason code used to trigger recovery
     * 2. Checks for sta iface down triggers and disables wifi by sending {@link
     * ActiveModeWarden#recoveryDisableWifi()} to {@link ActiveModeWarden} to disable wifi.
     * 3. Throttles restart calls for underlying native failures
     * 4. Sends {@link ActiveModeWarden#recoveryRestartWifi(int)} to {@link ActiveModeWarden} to
     * initiate the stack restart.
     * @param reason One of the above |REASON_*| codes.
     */
    public void trigger(@RecoveryReason int reason) {
        if (!(reason == REASON_LAST_RESORT_WATCHDOG || reason == REASON_WIFINATIVE_FAILURE
                  || reason == REASON_STA_IFACE_DOWN)) {
            Log.e(TAG, "Invalid trigger reason. Ignoring...");
            return;
        }
        if (reason == REASON_STA_IFACE_DOWN) {
            Log.e(TAG, "STA interface down, disable wifi");
            mActiveModeWarden.recoveryDisableWifi();
            return;
        }

        Log.e(TAG, "Triggering recovery for reason: " + REASON_STRINGS[reason]);
        if (reason == REASON_WIFINATIVE_FAILURE) {
            int maxRecoveriesPerHour = mContext.getResources().getInteger(
                    R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour);
            if (maxRecoveriesPerHour == 0) {
                Log.e(TAG, "Recovery disabled. Disabling wifi");
                mActiveModeWarden.recoveryDisableWifi();
                return;
            }
            trimPastRestartTimes();
            if (mPastRestartTimes.size() >= maxRecoveriesPerHour) {
                Log.e(TAG, "Already restarted wifi " + maxRecoveriesPerHour + " times in"
                        + " last 1 hour. Disabling wifi");
                mActiveModeWarden.recoveryDisableWifi();
                return;
            }
            mPastRestartTimes.add(mClock.getElapsedSinceBootMillis());
        }
        mActiveModeWarden.recoveryRestartWifi(reason);
    }

reason是REASON_WIFINATIVE_FAILURE,然后会判断当前每小时最大恢复次数(2次),大于的话就关闭WiFi,否则打开WiFi。

ActiveModeWarden

EnabledState

                    case CMD_RECOVERY_RESTART_WIFI:
                        final String bugTitle;
                        final String bugDetail;
                        if (msg.arg1 < SelfRecovery.REASON_STRINGS.length && msg.arg1 >= 0) {
                            bugDetail = SelfRecovery.REASON_STRINGS[msg.arg1];
                            bugTitle = "Wi-Fi BugReport: " + bugDetail;
                        } else {
                            bugDetail = "";
                            bugTitle = "Wi-Fi BugReport";
                        }
                        if (msg.arg1 != SelfRecovery.REASON_LAST_RESORT_WATCHDOG) {
                            mHandler.post(() -> mClientModeImpl.takeBugReport(bugTitle, bugDetail));
                        }
                        log("Recovery triggered, disable wifi");
                        deferMessage(obtainMessage(CMD_DEFERRED_RECOVERY_RESTART_WIFI));
                        shutdownWifi();
                        // onStopped will move the state machine to "DisabledState".
                        break;

先记录当前的bugreport,关闭WiFi,等状态机走到DisabledState的时候,再打开WiFi

                    case CMD_RECOVERY_RESTART_WIFI:
                        log("Recovery triggered, already in disabled state");
                        // intentional fallthrough
                    case CMD_DEFERRED_RECOVERY_RESTART_WIFI:
                        // wait mRecoveryDelayMillis for letting driver clean reset.
                        sendMessageDelayed(CMD_RECOVERY_RESTART_WIFI_CONTINUE,
                                readWifiRecoveryDelay());
                        break;
                    case CMD_RECOVERY_RESTART_WIFI_CONTINUE:
                        if (shouldEnableSta()) {
                            startClientModeManager();
                            transitionTo(mEnabledState);
                        }
                        break;

延迟2s让WiFi驱动得以clean(最大延迟4s)

 

3.总结

supplicant恢复机制其实很简单,就是supplicant挂了后触发的一个回调,然后再重启下WiFi就好了

相关推荐
©️2020 CSDN 皮肤主题: 鲸 设计师:meimeiellie 返回首页