Android Wi-Fi源码分析之WifiService操作Wi-Fi(二):WifiStateMachine.java中的SUP_CONNECTION_EVENT分析

来源:互联网 发布:淘宝上的迪奥是真的吗 编辑:程序博客网 时间:2024/05/16 08:28

Wi-Fi源码分析之WifiService操作Wi-Fi(二)

一. SupplicantStartingState中的的processMessage方法分析

        public boolean processMessage(Message message) {            switch(message.what) {                case WifiMonitor.SUP_CONNECTION_EVENT:                    if (DBG) log("Supplicant connection established");                    setWifiState(WIFI_STATE_ENABLED);/*发送WIFI_STATE_CHANGED_ACTION广播*/                    mSupplicantRestartCount = 0;                    /* Reset the supplicant state to indicate the supplicant                     * state is not known at this time */                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);/*发送消息给SupplicantStateTracker状态机*/                    /* Initialize data structures */                    mLastBssid = null;                    mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;                    mLastSignalLevel = -1;                    /*设置本机IP地址*/                    mWifiInfo.setMacAddress(mWifiNative.getMacAddress());                    mWifiConfigStore.loadAndEnableAllNetworks();                    initializeWpsDetails();                    /*初始化WPS相关*/                    /*发送SUPPLICANT_CONNECTION_CHANGE_ACTION广播*/                    sendSupplicantConnectionChangedBroadcast(true);                    transitionTo(mDriverStartedState);/*转到DriverStartedState*/                    break;                case WifiMonitor.SUP_DISCONNECTION_EVENT:                    if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {                        loge("Failed to setup control channel, restart supplicant");                        mWifiMonitor.killSupplicant(mP2pSupported);                        transitionTo(mInitialState);                        sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);                    } else {                        loge("Failed " + mSupplicantRestartCount +                                " times to start supplicant, unload driver");                        mSupplicantRestartCount = 0;                        setWifiState(WIFI_STATE_UNKNOWN);                        transitionTo(mInitialState);                    }                    break;                case CMD_START_SUPPLICANT:                case CMD_STOP_SUPPLICANT:                case CMD_START_AP:                case CMD_STOP_AP:                case CMD_START_DRIVER:                case CMD_STOP_DRIVER:                case CMD_SET_OPERATIONAL_MODE:                case CMD_SET_COUNTRY_CODE:                case CMD_SET_FREQUENCY_BAND:                case CMD_START_PACKET_FILTERING:                case CMD_STOP_PACKET_FILTERING:                    deferMessage(message);                    break;                default:                    return NOT_HANDLED;            }            return HANDLED;        }

DriverStarted的父状态是SupplicantStarted(涉及到的HSM和各个状态层的关系以后再说), 所以transitionTo(mDriverStartedState)会导致DriverStarted和SupplicantStarted里的enter被调用.下面逐个分析.

二. SupplicantStartedState里的enter方法分析

 class SupplicantStartedState extends State {        @Override        public void enter() {            /* Wifi is available as long as we have a connection to supplicant */            mNetworkInfo.setIsAvailable(true);            /*config_wifi_supplicant_scan_interval:控制扫描间隔,默认15000毫秒*/            int defaultInterval = mContext.getResources().getInteger(                    R.integer.config_wifi_supplicant_scan_interval);            mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),                    Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,                    defaultInterval);            /*向WPAS发送"SCAN_INTERVAL 扫描间隔时间"命令*/            mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000);        }   ...} 

三. DriverStartedState里的enter方法分析

    class DriverStartedState extends State {        @Override        public void enter() {            mIsRunning = true;            mInDelayedStop = false;            mDelayedStopCounter++;            updateBatteryWorkSource(null);            /**             * Enable bluetooth coexistence scan mode when bluetooth connection is active.             * When this mode is on, some of the low-level scan parameters used by the             * driver are changed to reduce interference with bluetooth             * 蓝牙是运行在2.4GHz频段上,所以为了避免wlan和蓝牙互相干扰,下面这个函数将告知             * wlan driver蓝牙是否启用. 如果是 wlan芯片会做适当调整*/            mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);            /* 设置国家代码和频段             * 其内部是通过发送消息的方式来出发WifiNative             * setCountryCode和setBand函数被调用.在WifiNative中,这个两个函数都会发送形如             * "DRIVER XXX"命令给WPAS. DRIVER命令是Android平台特有的, 用于给wlan driver发送一些定制的命令.             * hardware\broadcom\wlan\bcmdhd\wpa_supplicant_8_lib\driver_cmd_nl80211.c中有wlan driver的"DRIVER XXX"命令             */            setCountryCode();            setFrequencyBand();            /* initialize network state */            setNetworkDetailedState(DetailedState.DISCONNECTED);            /*下面的三个函数都和WPAS中的"DRIVER XXX"命令有关*/            /* Remove any filtering on Multicast v6 at start */            mWifiNative.stopFilteringMulticastV6Packets();            /* Reset Multicast v4 filtering state */            if (mFilteringMulticastV4Packets.get()) {                mWifiNative.startFilteringMulticastV4Packets();            } else {                mWifiNative.stopFilteringMulticastV4Packets();            }            mDhcpActive = false;            startBatchedScan();            if (mOperationalMode != CONNECT_MODE) {                mWifiNative.disconnect();                mWifiConfigStore.disableAllNetworks();                if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {                    setWifiState(WIFI_STATE_DISABLED);                }                transitionTo(mScanModeState);            } else {                /* Driver stop may have disabled networks, enable right after start */                mWifiConfigStore.enableAllNetworks();                if (DBG) log("Attempting to reconnect to wifi network ..");                mWifiNative.reconnect();/*发送"RECONNECT"命令给wpas*/                // Status pulls in the current supplicant state and network connection state                // events over the monitor connection. This helps framework sync up with                // current supplicant state                mWifiNative.status();/*发送"STATUS"命令给WPAS*/                transitionTo(mDisconnectedState);/*进入mDisconnectedState*/            }            // We may have missed screen update at boot            if (mScreenBroadcastReceived.get() == false) {                PowerManager powerManager = (PowerManager)mContext.getSystemService(                        Context.POWER_SERVICE);                handleScreenStateChanged(powerManager.isScreenOn());            } else {                // Set the right suspend mode settings                /*发送"DRIVER SETSUSPENDMODE"命令.该命令由Driver厂商提供的库来实现*/                mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0                        && mUserWantsSuspendOpt.get());            }            mWifiNative.setPowerSave(true);/*和P2P PowerSave有关*/            /*如果支持P2P,则通过mWifiP2pChannel向WifiP2p模块发送消息*/            if (mP2pSupported) {                if (mOperationalMode == CONNECT_MODE) {                    mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);                } else {                    // P2P statemachine starts in disabled state, and is not enabled until                    // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to                    // keep it disabled.                }            }            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);            intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);        }        @Override        public boolean processMessage(Message message) {            switch(message.what) {                case CMD_START_SCAN:                    noteScanStart(message.arg1, (WorkSource) message.obj);                    startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);                    break;                case CMD_SET_BATCHED_SCAN:                    if (recordBatchedScanSettings(message.arg1, message.arg2,                            (Bundle)message.obj)) {                        startBatchedScan();                    }                    break;                case CMD_SET_COUNTRY_CODE:                    String country = (String) message.obj;                    if (DBG) log("set country code " + country);                    if (country != null) {                        country = country.toUpperCase(Locale.ROOT);                        if (mLastSetCountryCode == null                                || country.equals(mLastSetCountryCode) == false) {                            if (mWifiNative.setCountryCode(country)) {                                mLastSetCountryCode = country;                            } else {                                loge("Failed to set country code " + country);                            }                        }                    }                    break;                case CMD_SET_FREQUENCY_BAND:                    int band =  message.arg1;                    if (DBG) log("set frequency band " + band);                    if (mWifiNative.setBand(band)) {                        mFrequencyBand.set(band);                        // flush old data - like scan results                        mWifiNative.bssFlush();                        //Fetch the latest scan results when frequency band is set                        startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);                    } else {                        loge("Failed to set frequency band " + band);                    }                    break;                case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:                    mBluetoothConnectionActive = (message.arg1 !=                            BluetoothAdapter.STATE_DISCONNECTED);                    mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);                    break;                case CMD_STOP_DRIVER:                    int mode = message.arg1;                    /* Already doing a delayed stop */                    if (mInDelayedStop) {                        if (DBG) log("Already in delayed stop");                        break;                    }                    /* disconnect right now, but leave the driver running for a bit */                    mWifiConfigStore.disableAllNetworks();                    mInDelayedStop = true;                    mDelayedStopCounter++;                    if (DBG) log("Delayed stop message " + mDelayedStopCounter);                    /* send regular delayed shut down */                    Intent driverStopIntent = new Intent(ACTION_DELAYED_DRIVER_STOP, null);                    driverStopIntent.putExtra(DELAYED_STOP_COUNTER, mDelayedStopCounter);                    mDriverStopIntent = PendingIntent.getBroadcast(mContext,                            DRIVER_STOP_REQUEST, driverStopIntent,                            PendingIntent.FLAG_UPDATE_CURRENT);                    mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()                            + mDriverStopDelayMs, mDriverStopIntent);                    break;                case CMD_START_DRIVER:                    if (mInDelayedStop) {                        mInDelayedStop = false;                        mDelayedStopCounter++;                        mAlarmManager.cancel(mDriverStopIntent);                        if (DBG) log("Delayed stop ignored due to start");                        if (mOperationalMode == CONNECT_MODE) {                            mWifiConfigStore.enableAllNetworks();                        }                    }                    break;                case CMD_DELAYED_STOP_DRIVER:                    if (DBG) log("delayed stop " + message.arg1 + " " + mDelayedStopCounter);                    if (message.arg1 != mDelayedStopCounter) break;                    handleStopDriverCmd();                    if (mP2pSupported) {                        transitionTo(mWaitForP2pDisableState);                    } else {                        transitionTo(mDriverStoppingState);                    }                    break;                case CMD_START_PACKET_FILTERING:                    if (message.arg1 == MULTICAST_V6) {                        mWifiNative.startFilteringMulticastV6Packets();                    } else if (message.arg1 == MULTICAST_V4) {                        mWifiNative.startFilteringMulticastV4Packets();                    } else {                        loge("Illegal arugments to CMD_START_PACKET_FILTERING");                    }                    break;                case CMD_STOP_PACKET_FILTERING:                    if (message.arg1 == MULTICAST_V6) {                        mWifiNative.stopFilteringMulticastV6Packets();                    } else if (message.arg1 == MULTICAST_V4) {                        mWifiNative.stopFilteringMulticastV4Packets();                    } else {                        loge("Illegal arugments to CMD_STOP_PACKET_FILTERING");                    }                    break;                case CMD_SET_SUSPEND_OPT_ENABLED:                    if (message.arg1 == 1) {                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true);                        mSuspendWakeLock.release();                    } else {                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false);                    }                    break;                case CMD_SET_HIGH_PERF_MODE:                    if (message.arg1 == 1) {                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false);                    } else {                        setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true);                    }                    break;                case CMD_ENABLE_TDLS:                    if (message.obj != null) {                        String remoteAddress = (String) message.obj;                        boolean enable = (message.arg1 == 1);                        mWifiNative.startTdls(remoteAddress, enable);                    }                    break;                default:                    return NOT_HANDLED;            }            return HANDLED;        }        @Override        public void exit() {            mIsRunning = false;            updateBatteryWorkSource(null);            mScanResults = new ArrayList<ScanResult>();            stopBatchedScan();            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);            intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);            noteScanEnd(); // wrap up any pending request.            mLastSetCountryCode = null;        }    }

WifiStateMachine将转入DisconnectedState. 由于DisconnectedState的父状态是ConnectModeState, 所以它的enter函数没有做任何有意义的工作.

四. 分析DisconnectedState中的enter方法

        public void enter() {            // We dont scan frequently if this is a temporary disconnect            // due to p2p            if (mTemporarilyDisconnectWifi) {                mWifiP2pChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_RESPONSE);                return;            }            mFrameworkScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),                    Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,                    mDefaultFrameworkScanIntervalMs);            /*             * We initiate background scanning if it is enabled, otherwise we             * initiate an infrequent scan that wakes up the device to ensure             * a user connects to an access point on the move             * 当系统支持后台扫描时,如果手机屏幕关闭,则设置mEnableBackgroundScan为true启动后台扫描             */            if (mEnableBackgroundScan) {                /* If a regular scan result is pending, do not initiate background                 * scan until the scan results are returned. This is needed because                 * initiating a background scan will cancel the regular scan and                 * scan results will not be returned until background scanning is                 * cleared                 * mScanResultIsPending用于表示WifiService是否在等待普通扫描的结果.                 * 因为启动后台扫描的时候会取消上一次扫描的请求,所以如果mScanResultIsPending                 * 为ture的话,就先不启用后台扫描.                 */                if (!mScanResultIsPending) {                    mWifiNative.enableBackgroundScan(true);                }            } else {                /*设置定时扫描任务.到时间后,AlarmManager将发送一个"ACTION_START_SCAN"Intent                 * 而WifiStateMachine对Intent的处理就是调用startScan函数*/                setScanAlarm(true);            }            /**             * If we have no networks saved, the supplicant stops doing the periodic scan.             * The scans are useful to notify the user of the presence of an open network.             * Note that these are not wake up scans.             * 如果当前没有P2P连接,并且没有之前保存的AP信息,则发送CMD_NO_NETWORKS_PERIODIC_SCAN消息出发扫描             */            if (!mP2pConnected.get() && mWifiConfigStore.getConfiguredNetworks().size() == 0) {                sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,                            ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);            }        }
阅读全文
0 0
原创粉丝点击