(九十八)Android O 探讨WiFi先打开后再打开WiFi热点继而改变配置的情况
发布日期:2021-06-30 15:25:23 浏览次数:2 分类:技术文章

本文共 8496 字,大约阅读时间需要 28 分钟。

1.场景

  1. 打开WiFi
  2. 打开WiFi热点(这时会把WiFi关闭)
  3. 改变WiFi热点的配置(这时会先关闭WiFi热点,再打开WiFi,最后再打开WiFi热点)

探讨下第3步WiFi和WiFi热点交替打开的逻辑实现。

 

2.流程梳理

TetherSettings.java

这个类是负责WiFi热点属性改变后的界面逻辑处理的,如下代码所示,改变配置点击保存后,这边会判断下如果mWifiConfig不为空并且当前WiFi热点为打开状态,那么先停止WiFi热点再打开WiFi热点,停止是在这个onClick里实现的,但重启WiFi热点这个onClick方法只是记了一个标志位。重启WiFi热点的逻辑是当接收到WiFi热点已关闭的广播后再判断下标志位再重启WiFi热点。

public void onClick(DialogInterface dialogInterface, int button) {        if (button == DialogInterface.BUTTON_POSITIVE) {            mWifiConfig = mDialog.getConfig();            if (mWifiConfig != null) {                /**                 * if soft AP is stopped, bring up                 * else restart with new config                 * TODO: update config on a running access point when framework support is added                 */                if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {                    Log.d("TetheringSettings",                            "Wifi AP config changed while enabled, stop and restart");                    mRestartWifiApAfterConfigChange = true;                    mCm.stopTethering(TETHERING_WIFI);                }                mWifiManager.setWifiApConfiguration(mWifiConfig);                int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig);                mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT),                        mWifiConfig.SSID,                        mSecurityType[index]));            }        }    }   private class TetherChangeReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context content, Intent intent) {            String action = intent.getAction();...            } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {                int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0);                if (state == WifiManager.WIFI_AP_STATE_DISABLED                        && mRestartWifiApAfterConfigChange) {                    mRestartWifiApAfterConfigChange = false;                    Log.d(TAG, "Restarting WifiAp due to prior config change.");                    startTethering(TETHERING_WIFI);                }            }

那么WiFi热点关闭时WiFi为何会自动打开呢?

WifiController

WiFi打开时所处状态

class StaEnabledState extends State {        @Override        public void enter() {            mWifiStateMachine.setSupplicantRunning(true);        }        @Override        public boolean processMessage(Message msg) {            switch (msg.what) {...                case CMD_SET_AP:                    if (msg.arg1 == 1) {                        // remeber that we were enabled                        mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_ENABLED);                        deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));                        transitionTo(mApStaDisabledState);                    }                    break;

这时候如果打开WiFi热点,那么WifiController就会记住当前WiFi状态为打开状态,并将打开WiFi热点的消息委托给ApStaDisabledState,就和WiFi没打开时逻辑一样,当然进入到ApStaDisabledState状态会将supplicant干掉,也就是WiFi会先关闭。

class ApStaDisabledState extends State {        private int mDeferredEnableSerialNumber = 0;        private boolean mHaveDeferredEnable = false;        private long mDisabledTimestamp;        @Override        public void enter() {            mWifiStateMachine.setSupplicantRunning(false);            // Supplicant can't restart right away, so not the time we switched off            mDisabledTimestamp = SystemClock.elapsedRealtime();            mDeferredEnableSerialNumber++;            mHaveDeferredEnable = false;            mWifiStateMachine.clearANQPCache();        }

WiFi热点打开以后会进入如下ApEnabledState状态,表示WiFi热点已打开

/**     * Only transition out of this state when AP failed to start or AP is stopped.     */    class ApEnabledState extends State {        /**         * Save the pending state when stopping the AP, so that it will transition         * to the correct state when AP is stopped.  This is to avoid a possible         * race condition where the new state might try to update the driver/interface         * state before AP is completely torn down.         */        private State mPendingState = null;        /**         * Determine the next state based on the current settings (e.g. saved         * wifi state).         */        private State getNextWifiState() {            if (mSettingsStore.getWifiSavedState() == WifiSettingsStore.WIFI_ENABLED) {                return mDeviceActiveState;            }            if (mSettingsStore.isScanAlwaysAvailable()) {                return mStaDisabledWithScanState;            }            return mApStaDisabledState;        }        @Override        public boolean processMessage(Message msg) {            switch (msg.what) {                ...                case CMD_SET_AP:                    if (msg.arg1 == 0) {                        mWifiStateMachine.setHostApRunning(null, false);                        mPendingState = getNextWifiState();                    }                    break;                case CMD_AP_STOPPED:                    if (mPendingState == null) {                        /**                         * Stop triggered internally, either tether notification                         * timed out or wifi is untethered for some reason.                         */                        mPendingState = getNextWifiState();                    }                    if (mPendingState == mDeviceActiveState && mDeviceIdle) {                        checkLocksAndTransitionWhenDeviceIdle();                    } else {                        // go ahead and transition because we are not idle or we are not going                        // to the active state.                        transitionTo(mPendingState);                    }                    break;

这时候再接收到关闭WiFi热点的消息,这时会先将WiFi热点关掉,然后判断一下后续切换的状态。

/**         * Determine the next state based on the current settings (e.g. saved         * wifi state).         */        private State getNextWifiState() {            if (mSettingsStore.getWifiSavedState() == WifiSettingsStore.WIFI_ENABLED) {                return mDeviceActiveState;            }            if (mSettingsStore.isScanAlwaysAvailable()) {                return mStaDisabledWithScanState;            }            return mApStaDisabledState;        }

由于最开始WiFi是处于打开状态并且已经记录了,所以这时候状态会切换到mDeviceActiveState。

切换流程是接收到WiFi热点已关闭的广播,然后发出CMD_AP_STOPPED消息并完成切换

mContext.registerReceiver(                new BroadcastReceiver() {                    @Override                    public void onReceive(Context context, Intent intent) {                        String action = intent.getAction();...                        } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {                            int state = intent.getIntExtra(                                    WifiManager.EXTRA_WIFI_AP_STATE,                                    WifiManager.WIFI_AP_STATE_FAILED);                            if (state == WifiManager.WIFI_AP_STATE_FAILED) {                                loge(TAG + "SoftAP start failed");                                sendMessage(CMD_AP_START_FAILURE);                            } else if (state == WifiManager.WIFI_AP_STATE_DISABLED) {                                sendMessage(CMD_AP_STOPPED);                            }
case CMD_AP_STOPPED:                    if (mPendingState == null) {                        /**                         * Stop triggered internally, either tether notification                         * timed out or wifi is untethered for some reason.                         */                        mPendingState = getNextWifiState();                    }                    if (mPendingState == mDeviceActiveState && mDeviceIdle) {                        checkLocksAndTransitionWhenDeviceIdle();                    } else {                        // go ahead and transition because we are not idle or we are not going                        // to the active state.                        transitionTo(mPendingState);                    }                    break;

切换到DeviceActiveState的enter方法,这边就开始了WiFi开启流程了。

/* Parent: StaEnabledState */    class DeviceActiveState extends State {        @Override        public void enter() {            mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);            mWifiStateMachine.setHighPerfModeEnabled(false);        }

 

3.总结

1代表打开WiFi热点,从WiFi打开状态先切换到热点关闭状态,打开WiFi热点的操作留给第2步

2代表处理打开WiFi热点的逻辑,从热点关闭状态切换到热点打开状态

3代表关闭WiFi热点,从热点打开状态切换到WiFi打开状态。

 

转载地址:https://jiatai.blog.csdn.net/article/details/83035808 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:(九十九) Android O wps 流程简单梳理
下一篇:(九十七)Android O WiFi热点 开启流程梳理续(二)

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月14日 08时57分27秒