当前位置: 代码迷 >> Android >> Android4.4(MT8685)源码WIFI-起动
  详细解决方案

Android4.4(MT8685)源码WIFI-起动

热度:779   发布时间:2016-04-28 03:09:27.0
Android4.4(MT8685)源码WIFI--启动

系统启动时,会在SystemServer中创建一个WifiService的对象,并把这个对象保存在系统服务中

wifi = new WifiService(context);ServiceManager.addService(Context.WIFI_SERVICE, wifi);

看看WiFiService的构造方法

public WifiService(Context context) {        mContext = context;        mInterfaceName =  SystemProperties.get("wifi.interface", "wlan0");        mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);        mWifiStateMachine.enableRssiPolling(true);        mBatteryStats = BatteryStatsService.getService();        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);        mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);        mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);        mSettingsStore = new WifiSettingsStore(mContext);        HandlerThread wifiThread = new HandlerThread("WifiService");        wifiThread.start();        mClientHandler = new ClientHandler(wifiThread.getLooper());        mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());        mWifiController = new WifiController(mContext, this, wifiThread.getLooper());        mWifiController.start();        mBatchedScanSupported = mContext.getResources().getBoolean(                R.bool.config_wifi_batched_scan_supported);        registerForScanModeChange();        mContext.registerReceiver(                new BroadcastReceiver() {                    @Override                    public void onReceive(Context context, Intent intent) {                        ///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON                        boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);                        SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);                                                if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {                            mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);                        }                    }                },                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));        // Adding optimizations of only receiving broadcasts when wifi is enabled        // can result in race conditions when apps toggle wifi in the background        // without active user involvement. Always receive broadcasts.        registerForBroadcasts();        ///M:        initializeExtra();    }

这里初始化了一个WifiStateMachine和一个WifiController,并且调用了WifiController 的start方法,WifiController 继承至StateMachine状态机,这个start方法是父类的方法,表示启动一个状态机。我们先来看看WifiController这个状态机的构造方法

 WifiController(Context context, WifiService service, Looper looper) {        super(TAG, looper);        mContext = context;        mWifiStateMachine = service.mWifiStateMachine;        mSettingsStore = service.mSettingsStore;        mLocks = service.mLocks;        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);        Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);        mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);        ///M: add plugin         mWifiFwkExt = MediatekClassFactory.createInstance(IWifiFwkExt.class, mContext);        addState(mDefaultState);            addState(mApStaDisabledState, mDefaultState);            addState(mStaEnabledState, mDefaultState);                addState(mDeviceActiveState, mStaEnabledState);                addState(mDeviceInactiveState, mStaEnabledState);                    addState(mScanOnlyLockHeldState, mDeviceInactiveState);                    addState(mFullLockHeldState, mDeviceInactiveState);                    addState(mFullHighPerfLockHeldState, mDeviceInactiveState);                    addState(mNoLockHeldState, mDeviceInactiveState);            addState(mStaDisabledWithScanState, mDefaultState);            addState(mApEnabledState, mDefaultState);            addState(mEcmState, mDefaultState);        if (mSettingsStore.isScanAlwaysAvailable()) {            setInitialState(mStaDisabledWithScanState);			Log.e("dd","mStaDisabledWithScanState");        } else {            setInitialState(mApStaDisabledState);			Log.e("dd","mApStaDisabledState");        }        setLogRecSize(100);        setLogOnlyTransitions(false);        IntentFilter filter = new IntentFilter();        filter.addAction(ACTION_DEVICE_IDLE);        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);        mContext.registerReceiver(                new BroadcastReceiver() {                    @Override                    public void onReceive(Context context, Intent intent) {                        String action = intent.getAction();                        if (action.equals(ACTION_DEVICE_IDLE)) {                            sendMessage(CMD_DEVICE_IDLE);                        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {                            mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(                                    WifiManager.EXTRA_NETWORK_INFO);                        }                    }                },                new IntentFilter(filter));        initializeAndRegisterForSettingsChange(looper);    }

这里参数service就是WifiService,并且通过service得到了WifiService中的WifiStateMachine对象,然后添加了一些状态对象,设置了初始状态,调用start方法后,WifiController首先进入mDefaultState状态,然后进入mApStaDisabledState状态,此时,WifiController状态机的状态为mApStaDisabledState状态。

让我们回到WifiService的构造方法中,倒数第二行有个registerForBroadcasts方法

private void registerForBroadcasts() {        IntentFilter intentFilter = new IntentFilter();        intentFilter.addAction(Intent.ACTION_SCREEN_ON);        intentFilter.addAction(Intent.ACTION_USER_PRESENT);        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);        intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);        intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);        mContext.registerReceiver(mReceiver, intentFilter);    }
这个方法注册了一个广播,那我们看看接收到注册的这些action后,会有哪些处理

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            SXlog.d(TAG, "onReceive, action:" + action);            if (action.equals(Intent.ACTION_SCREEN_ON)) {                mWifiController.sendMessage(CMD_SCREEN_ON);            } else if (action.equals(Intent.ACTION_USER_PRESENT)) {                mWifiController.sendMessage(CMD_USER_PRESENT);            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {                mWifiController.sendMessage(CMD_SCREEN_OFF);            } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {                int pluggedType = intent.getIntExtra("plugged", 0);                mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);            } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,                        BluetoothAdapter.STATE_DISCONNECTED);                mWifiStateMachine.sendBluetoothAdapterStateChange(state);            } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {                boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);                mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);            }        }    };
当接收到的广播为ACTION_SCREEN_ON时,利用mWifiController对象发送一个CMD_SCREEN_ON消息,此时,mWifiController状态机的状态为mApStaDisabledState状态,我们看看这个状态实现类的processMessage方法

 @Override        public boolean processMessage(Message msg) {            SXlog.d(TAG, getName() + msg.toString() + "\n");            switch (msg.what) {                case CMD_WIFI_TOGGLED:                case CMD_AIRPLANE_TOGGLED:					Log.e("dd","1");                    ///M: add WifiIpoOff@{                    boolean wifiIpoOff = (msg.arg1==1) ? true: false;                    boolean ipoStateChange= false;                    if(mWifiIpoOff!=wifiIpoOff) ipoStateChange=true;                    mWifiIpoOff = wifiIpoOff;                    if(wifiIpoOff ==true){                        SXlog.d(TAG,"ipooff  don't enable wifi\n");                        break;                    }                    if (mSettingsStore.isWifiToggleEnabled()) {                    //@}                        if (doDeferEnable(msg)) {                            if (mHaveDeferredEnable) {                                //  have 2 toggles now, inc serial number an ignore both                                mDeferredEnableSerialNumber++;                            }                            mHaveDeferredEnable = !mHaveDeferredEnable;                            break;                        }                        if (mDeviceIdle == false) {							Log.e("dd","4");                            transitionTo(mDeviceActiveState);                        } else {                            checkLocksAndTransitionWhenDeviceIdle();                        }                    ///M: check scan always avaliable only when ipo change from ipo on to off                    }else if (ipoStateChange ==true && mSettingsStore.isScanAlwaysAvailable() && mSettingsStore.isAirplaneModeOn()==false ) {                        SXlog.d(TAG,"ipoStateChange = "+ipoStateChange + "isAirplaneModeOn= "+mSettingsStore.isAirplaneModeOn());                        transitionTo(mStaDisabledWithScanState);                    }                    break;                case CMD_SCAN_ALWAYS_MODE_CHANGED:                    if (mSettingsStore.isScanAlwaysAvailable()) {                        transitionTo(mStaDisabledWithScanState);                    }                    break;                case CMD_SET_AP:                    if (msg.arg1 == 1) {                        mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,                                true);                        transitionTo(mApEnabledState);                    }                    break;                case CMD_DEFERRED_TOGGLE:                    if (msg.arg1 != mDeferredEnableSerialNumber) {                        log("DEFERRED_TOGGLE ignored due to serial mismatch");                        break;                    }                    log("DEFERRED_TOGGLE handled");                    sendMessage((Message)(msg.obj));                    break;                default:                    return NOT_HANDLED;            }            return HANDLED;        }

注意,这里没有处理CMD_SCREEN_ON消息,根据状态机的机制,子状态没处理的消息,将由父状态处理,mApStaDisabledState的父状态为mDefaultState状态,看看它的processMessage方法

@Override        public boolean processMessage(Message msg) {            SXlog.d(TAG, getName() + msg.toString() + "\n");            switch (msg.what) {                case CMD_SCREEN_ON:                    mAlarmManager.cancel(mIdleIntent);                    mScreenOff = false;                    mDeviceIdle = false;					Log.e("dd","mDeviceIdle = false;");                    ///M: @{                    mWifiStateMachine.setDeviceIdle(mDeviceIdle);                    ///@}                    updateBatteryWorkSource();                    break;                case CMD_SCREEN_OFF:                    mScreenOff = true;                    /*                    * Set a timer to put Wi-Fi to sleep, but only if the screen is off                    * AND the "stay on while plugged in" setting doesn't match the                    * current power conditions (i.e, not plugged in, plugged in to USB,                    * or plugged in to AC).                    */                    if (!shouldWifiStayAwake(mPluggedType)) {                        //Delayed shutdown if wifi is connected                        if (mNetworkInfo.getDetailedState() ==                                NetworkInfo.DetailedState.CONNECTED) {                            if (DBG) Slog.d(TAG, "set idle timer: " + mIdleMillis + " ms");                            ///M: modify to use Exact alarm for accuracy                            mAlarmManager.setExact(AlarmManager.RTC_WAKEUP,                                    System.currentTimeMillis() + mIdleMillis, mIdleIntent);                        } else {                            sendMessage(CMD_DEVICE_IDLE);                        }                    }                    break;                case CMD_DEVICE_IDLE:                    mDeviceIdle = true;                    ///M: @{                    mWifiStateMachine.setDeviceIdle(mDeviceIdle);                    ///@}                                        updateBatteryWorkSource();                    break;                case CMD_BATTERY_CHANGED:                    /*                    * Set a timer to put Wi-Fi to sleep, but only if the screen is off                    * AND we are transitioning from a state in which the device was supposed                    * to stay awake to a state in which it is not supposed to stay awake.                    * If "stay awake" state is not changing, we do nothing, to avoid resetting                    * the already-set timer.                    */                    int pluggedType = msg.arg1;                    if (DBG) Slog.d(TAG, "battery changed pluggedType: " + pluggedType);                    if (mScreenOff && shouldWifiStayAwake(mPluggedType) &&                            !shouldWifiStayAwake(pluggedType)) {                        long triggerTime = System.currentTimeMillis() + mIdleMillis;                        if (DBG) Slog.d(TAG, "set idle timer for " + mIdleMillis + "ms");                        mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);                    }                    mPluggedType = pluggedType;                    break;                case CMD_SET_AP:                case CMD_SCAN_ALWAYS_MODE_CHANGED:                case CMD_LOCKS_CHANGED:                case CMD_WIFI_TOGGLED:                case CMD_AIRPLANE_TOGGLED:                case CMD_EMERGENCY_MODE_CHANGED:                    break;                case CMD_USER_PRESENT:                    mFirstUserSignOnSeen = true;                    break;                case CMD_DEFERRED_TOGGLE:                    log("DEFERRED_TOGGLE ignored due to state change");                    break;                default:                    throw new RuntimeException("WifiController.handleMessage " + msg.what);            }            return HANDLED;        }    }

果然,这里有处理CMD_SCREEN_ON消息,这里要注意的是 

mDeviceIdle = false;
稍后我们会用到这个flag,再一次回到WifiService的构造方法,其中有这么一段代码

mContext.registerReceiver(                new BroadcastReceiver() {                    @Override                    public void onReceive(Context context, Intent intent) {                        ///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON                        boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);                        SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);                                                if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {                            mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);                        }                    }                },                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));

这里注册了一个捕捉ACTION_AIRPLANE_MODE_CHANGED的广播,接收到这个广播后,通过mWifiController发送一个CMD_AIRPLANE_TOGGLED的消息,来看看接收到这个消息的地方,还是在WifiController的当前状态mApStaDisabledState实现类的 processMessage方法中

 @Override        public boolean processMessage(Message msg) {            SXlog.d(TAG, getName() + msg.toString() + "\n");            switch (msg.what) {                case CMD_WIFI_TOGGLED:                case CMD_AIRPLANE_TOGGLED:					Log.e("dd","1");                    ///M: add WifiIpoOff@{                    boolean wifiIpoOff = (msg.arg1==1) ? true: false;                    boolean ipoStateChange= false;                    if(mWifiIpoOff!=wifiIpoOff) ipoStateChange=true;                    mWifiIpoOff = wifiIpoOff;                    if(wifiIpoOff ==true){                        SXlog.d(TAG,"ipooff  don't enable wifi\n");                        break;                    }                    if (mSettingsStore.isWifiToggleEnabled()) {                    //@}                        if (doDeferEnable(msg)) {                            if (mHaveDeferredEnable) {                                //  have 2 toggles now, inc serial number an ignore both                                mDeferredEnableSerialNumber++;                            }                            mHaveDeferredEnable = !mHaveDeferredEnable;                            break;                        }                        if (mDeviceIdle == false) {							Log.e("dd","4");                            transitionTo(mDeviceActiveState);                        } else {                            checkLocksAndTransitionWhenDeviceIdle();                        }                    ///M: check scan always avaliable only when ipo change from ipo on to off                    }else if (ipoStateChange ==true && mSettingsStore.isScanAlwaysAvailable() && mSettingsStore.isAirplaneModeOn()==false ) {                        SXlog.d(TAG,"ipoStateChange = "+ipoStateChange + "isAirplaneModeOn= "+mSettingsStore.isAirplaneModeOn());                        transitionTo(mStaDisabledWithScanState);                    }                    break;                case CMD_SCAN_ALWAYS_MODE_CHANGED:                    if (mSettingsStore.isScanAlwaysAvailable()) {                        transitionTo(mStaDisabledWithScanState);                    }                    break;                case CMD_SET_AP:                    if (msg.arg1 == 1) {                        mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,                                true);                        transitionTo(mApEnabledState);                    }                    break;                case CMD_DEFERRED_TOGGLE:                    if (msg.arg1 != mDeferredEnableSerialNumber) {                        log("DEFERRED_TOGGLE ignored due to serial mismatch");                        break;                    }                    log("DEFERRED_TOGGLE handled");                    sendMessage((Message)(msg.obj));                    break;                default:                    return NOT_HANDLED;            }            return HANDLED;        }

当系统Wifi为开时,并且mDeviceIdle为false时,会把当前状态转换为mDeviceActiveState状态,mDeviceActiveState的父状态为mStaEnabledState状态,所以会先进入mStaEnabledState然后进入mDeviceActiveState状态,我们看看mStaEnabledState状态的实现类的enter方法

@Override        public void enter() {        	Log.e("dd","StaEnabledState");            if (DBG) log(getName() + "\n");                    mWifiStateMachine.setSupplicantRunning(true);        }

这里调用了WifiService中的WifiStateMachine对象的setSupplicantRunning方法

 public void setSupplicantRunning(boolean enable) {        if (enable) {            sendMessage(CMD_START_SUPPLICANT);        } else {            sendMessage(CMD_STOP_SUPPLICANT);        }    }

当参数为true时,发送一个CMD_START_SUPPLICANT消息,那么WifiStateMachine当前的状态是什么呢?看看它的构造方法吧,其中添加状态和初始状态的代码为

addState(mDefaultState);            addState(mInitialState, mDefaultState);            addState(mSupplicantStartingState, mDefaultState);            addState(mSupplicantStartedState, mDefaultState);                addState(mDriverStartingState, mSupplicantStartedState);                addState(mDriverStartedState, mSupplicantStartedState);                    addState(mScanModeState, mDriverStartedState);                    addState(mConnectModeState, mDriverStartedState);                        addState(mL2ConnectedState, mConnectModeState);                            addState(mObtainingIpState, mL2ConnectedState);                            addState(mVerifyingLinkState, mL2ConnectedState);                            addState(mCaptivePortalCheckState, mL2ConnectedState);                            addState(mConnectedState, mL2ConnectedState);                        addState(mDisconnectingState, mConnectModeState);                        addState(mDisconnectedState, mConnectModeState);                        addState(mWpsRunningState, mConnectModeState);                addState(mWaitForP2pDisableState, mSupplicantStartedState);                addState(mDriverStoppingState, mSupplicantStartedState);                addState(mDriverStoppedState, mSupplicantStartedState);            addState(mSupplicantStoppingState, mDefaultState);            addState(mSoftApStartingState, mDefaultState);            addState(mSoftApStartedState, mDefaultState);                addState(mTetheringState, mSoftApStartedState);                addState(mTetheredState, mSoftApStartedState);                addState(mUntetheringState, mSoftApStartedState);        setInitialState(mInitialState);

初始状态为mInitialState,看看它的实现类的processMessage方法

 @Override        public boolean processMessage(Message message) {            if (DBG) log(getName() + message.toString() + "\n");            switch (message.what) {                case CMD_START_SUPPLICANT:                    setWifiState(WIFI_STATE_ENABLING);                    if (mWifiNative.loadDriver()) {                        try {                            mNwService.wifiFirmwareReload(mInterfaceName, "STA");                        } catch (Exception e) {                            loge("Failed to reload STA firmware " + e);                            // continue                        }                        try {                            // A runtime crash can leave the interface up and                            // this affects connectivity when supplicant starts up.                            // Ensure interface is down before a supplicant start.                            mNwService.setInterfaceDown(mInterfaceName);                            // Set privacy extensions                            mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);                           // IPv6 is enabled only as long as access point is connected since:                           // - IPv6 addresses and routes stick around after disconnection                           // - kernel is unaware when connected and fails to start IPv6 negotiation                           // - kernel can start autoconfiguration when 802.1x is not complete                            mNwService.disableIpv6(mInterfaceName);                        } catch (RemoteException re) {                            loge("Unable to change interface settings: " + re);                        } catch (IllegalStateException ie) {                            loge("Unable to change interface settings: " + ie);                        }                       /* Stop a running supplicant after a runtime restart                        * Avoids issues with drivers that do not handle interface down                        * on a running supplicant properly.                        */                        mWifiMonitor.killSupplicant(mP2pSupported);                        if(mWifiNative.startSupplicant(mP2pSupported)) {                            if (DBG) log("Supplicant start successful");                            mWifiMonitor.startMonitoring();                            transitionTo(mSupplicantStartingState);                        } else {                            loge("Failed to start supplicant!");                        }                    } else {                        loge("Failed to load driver");                    }                    break;                case CMD_START_AP:                    if (mWifiNative.loadDriver()) {                        setWifiApState(WIFI_AP_STATE_ENABLING);                        transitionTo(mSoftApStartingState);                    } else {                        loge("Failed to load driver for softap");                    }                ///M: for Hotknot, enable wifi for p2p, sta mode should not connect@{                case WifiManager.SET_WIFI_DISCONNECT:                    if(message.arg1 == 1){                        mHotknotConnected.set(true);                    }else{                        mHotknotConnected.set(false);                    }                    sendMessage(M_CMD_UPDATE_BGSCAN);                    break;                    ///@}                default:                    return NOT_HANDLED;            }            return HANDLED;        }

接收到CMD_START_SUPPLICANT消息后,首先会调用mWifiNative的loadDriver方法,loadDriver是一个本地方法,其作用是加载相应的Wifi驱动,如果驱动加载成功,会调用mWifiMonitor的startMonitoring方法,并且把当前的 状态转为mSupplicantStartingState状态。我们来看看mWifiMonitor这个对象,mWifiMonitor是一个WifiMonitor对象,它负责从wpa_supplicant接收消息,运行在一个独立的线程中。看看构造方法

public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) {        if (DBG) Log.d(TAG, "Creating WifiMonitor");        mWifiNative = wifiNative;        mInterfaceName = wifiNative.mInterfaceName;        mWifiStateMachine = wifiStateMachine;        mMonitoring = false;        WifiMonitorSingleton.getMonitor().registerInterfaceMonitor(mInterfaceName, this);    }

这里传入了StateMachine对象和WifiNative对象,接着我们看看startMonitoring方法

public void startMonitoring() {        WifiMonitorSingleton.getMonitor().startMonitoring(mInterfaceName);    }
这里调用WifiMonitor内部类WifiMonitorSingleton的startMonitoring方法

 public synchronized void startMonitoring(String iface) {            WifiMonitor m = mIfaceMap.get(iface);            if (m == null) {                Log.e(TAG, "startMonitor called with unknown iface=" + iface);                return;            }            Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);            if (mConnected) {                m.mMonitoring = true;                m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);            } else {                if (DBG) Log.d(TAG, "connecting to supplicant");                int connectTries = 0;                while (true) {                    if (mWifiNative.connectToSupplicant()) {                        m.mMonitoring = true;                        m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);                        new MonitorThread(mWifiNative, this).start();                        mConnected = true;                        break;                    }                    if (connectTries++ < 5) {                        try {                            Thread.sleep(1000);                        } catch (InterruptedException ignore) {                        }                    } else {                    Log.d(TAG, "rmIfaceMap remove " + iface);                        mIfaceMap.remove(iface);                        ///M:@{                        if (!m.mInterfaceName.equals("ap0")) {                            m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);                        }                        ///@}                        Log.e(TAG, "startMonitoring(" + iface + ") failed! " );                        break;                    }                }            }        }

这里会启动一个MonitorThread线程,看看这个线程的构造方法

public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {            super("WifiMonitor");            mWifiNative = wifiNative;            mWifiMonitorSingleton = wifiMonitorSingleton;        }

没做什么,再看run方法

 public void run() {            //noinspection InfiniteLoopStatement            for (;;) {                String eventStr = mWifiNative.waitForEvent();                // Skip logging the common but mostly uninteresting scan-results event                if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {                    Log.d(TAG, "Event [" + eventStr + "]");                }                String iface = "p2p0";                WifiMonitor m = null;                mStateMachine = null;                if (eventStr.startsWith("IFNAME=")) {                    int space = eventStr.indexOf(' ');                    if (space != -1) {                        iface = eventStr.substring(7,space);                        Log.d(TAG, "iface " + iface);                        m = mWifiMonitorSingleton.getMonitor(iface);                        if(m==null)Log.d(TAG, "hcan get mm  " + iface);                        if (m == null && iface.startsWith("p2p-")) {                            // p2p interfaces are created dynamically, but we have                            // only one P2p state machine monitoring all of them; look                            // for it explicitly, and send messages there ..                            m = mWifiMonitorSingleton.getMonitor("p2p0");                        }                        eventStr = eventStr.substring(space + 1);                    }                } else {                    ///M: if ap0 exist, it could be hotspot event                                        m = mWifiMonitorSingleton.getMonitor("ap0");                    if(m!=null){                        if(m.mMonitoring){                            //we find hotspot active                        }else{                            //try p2p0                            m = mWifiMonitorSingleton.getMonitor("p2p0");                        }                     }else{                                            // events without prefix belong to p2p0 monitor                        m = mWifiMonitorSingleton.getMonitor("p2p0");                     }                                    }                if (m != null) {                    if (m.mMonitoring) {                        mStateMachine = m.mWifiStateMachine;                    } else {                        if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +                                            ") is stopped");                        continue;                    }                }                if (mStateMachine != null) {                    if (dispatchEvent(eventStr, m.mInterfaceName)) {                        //M: when dispatchEvent=true means break from waitForEvent                        //M: for hotspot clear hotspot data                        if(m.mInterfaceName.equals("ap0")){                            m.mMonitoring =false;                            mWifiNative.closeSupplicantConnection();                            Log.d(TAG, "ap0 get TEMINATING 1");                        }                        break;                    }                } else {                    if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id");                    boolean done = false;                    Iterator<Map.Entry<String, WifiMonitor>> it =                            mWifiMonitorSingleton.mIfaceMap.entrySet().iterator();                    while (it.hasNext()) {                        Map.Entry<String, WifiMonitor> e = it.next();                        m = e.getValue();                        mStateMachine = m.mWifiStateMachine;                        if (dispatchEvent(eventStr,null)) {                            done = true;                        }                    }                    if (done) {                                                //M: for hotspot clear hotspot data                        if(m.mInterfaceName.equals("ap0")){                            m.mMonitoring =false;                            mWifiNative.closeSupplicantConnection();                            Log.d(TAG, "ap0 get TEMINATING 2");                        }                        // After this thread terminates, we'll no longer                        // be connected to the supplicant                        if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");                        mWifiMonitorSingleton.mConnected = false;                        break;                    }                }            }        }

这里调用了mWifiNative的waitForEvent方法,这个方法通过jni调用本地方法读取wpa_supplicant的消息,接着转发出去
while (it.hasNext()) {                        Map.Entry<String, WifiMonitor> e = it.next();                        m = e.getValue();                        mStateMachine = m.mWifiStateMachine;                        if (dispatchEvent(eventStr,null)) {                            done = true;                        }                    }


看看dispatchEvent方法

 /* @return true if the event was supplicant disconnection */        private boolean dispatchEvent(String eventStr, String iface) {            if (!eventStr.startsWith(EVENT_PREFIX_STR)) {                if ((eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&                        0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR))                        ///M:@{                        || (eventStr.startsWith(AUTHENTICATION_TIMEOUT_PREFIX_STR)                            && 0 < eventStr.indexOf(AUTHENTICATION_TIMEOUT_STR))) {                        ///@}                    mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);                } else if (eventStr.startsWith(WPS_SUCCESS_STR)) {                    mStateMachine.sendMessage(WPS_SUCCESS_EVENT);                } else if (eventStr.startsWith(WPS_FAIL_STR)) {                    handleWpsFailEvent(eventStr);                } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {                    mStateMachine.sendMessage(WPS_OVERLAP_EVENT);                } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {                    mStateMachine.sendMessage(WPS_TIMEOUT_EVENT);                } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {                    handleP2pEvents(eventStr);                } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {                    handleHostApEvents(eventStr, iface);                ///M:@{                } else if (eventStr.startsWith(EAP_FAST_NEW_PAC_UPDATED)) {                    mStateMachine.sendMessage(NEW_PAC_UPDATED_EVENT);                ///M: whole chip reset fail                } else if (eventStr.startsWith(WHOLE_CHIP_RESET_FAIL_STRING)){                    mStateMachine.sendMessage(WHOLE_CHIP_RESET_FAIL_EVENT);                /** M: NFC Float II @{ */                } else if (eventStr.startsWith(WPS_ER_ENROLLEE_ADD_STR)) {                    mStateMachine.sendMessage(WPS_ER_ENROLLEE_ADD_EVENT, eventStr);                } else if (eventStr.startsWith(WPS_ER_AP_ADD_STR)) {                    mStateMachine.sendMessage(WPS_ER_AP_ADD_EVENT, eventStr);                /** } */                }                ///@}                else {                    if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);                }                return false;            }            String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);            int nameEnd = eventName.indexOf(' ');            if (nameEnd != -1)                eventName = eventName.substring(0, nameEnd);            if (eventName.length() == 0) {                if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name");                return false;            }            /*             * Map event name into event enum             */            int event;            if (eventName.equals(CONNECTED_STR))                event = CONNECTED;            else if (eventName.equals(DISCONNECTED_STR)) {                event = DISCONNECTED;                ///M: add                handleP2pEvents(eventStr);            } else if (eventName.equals(STATE_CHANGE_STR))                event = STATE_CHANGE;            else if (eventName.equals(SCAN_RESULTS_STR))                event = SCAN_RESULTS;            else if (eventName.equals(LINK_SPEED_STR))                event = LINK_SPEED;            else if (eventName.equals(TERMINATING_STR))                event = TERMINATING;            else if (eventName.equals(DRIVER_STATE_STR))                event = DRIVER_STATE;            else if (eventName.equals(EAP_FAILURE_STR))                event = EAP_FAILURE;            else if (eventName.equals(ASSOC_REJECT_STR))                event = ASSOC_REJECT;            ///M: @{                                    else if (eventName.equals(WAPI_NO_CERTIFICATION_STRING))                event = NO_CERTIFICATION;            ///@}            else                event = UNKNOWN;            String eventData = eventStr;            if (event == DRIVER_STATE || event == LINK_SPEED)                eventData = eventData.split(" ")[1];            else if (event == STATE_CHANGE || event == EAP_FAILURE) {                int ind = eventStr.indexOf(" ");                if (ind != -1) {                    eventData = eventStr.substring(ind + 1);                }            } else {                int ind = eventStr.indexOf(" - ");                if (ind != -1) {                    eventData = eventStr.substring(ind + 3);                }            }            if (event == STATE_CHANGE) {                handleSupplicantStateChange(eventData);            } else if (event == DRIVER_STATE) {                handleDriverEvent(eventData);            } else if (event == TERMINATING) {                Log.d(TAG, "event == TERMINATING " );                /**                 * Close the supplicant connection if we see                 * too many recv errors                 */                if (eventData.startsWith(WPA_RECV_ERROR_STR)) {                    if (++mRecvErrors > MAX_RECV_ERRORS) {                        if (DBG) {                            Log.d(TAG, "too many recv errors, closing connection");                        }                    } else {                        return false;                    }                }                // notify and exit                if(iface!=null && !iface.equals("ap0")){                    mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);                }                Log.d(TAG, "Exit because of receiving terminating for " + getName() + ", id:" + getId());                return true;            } else if (event == EAP_FAILURE) {                if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {                    mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);                }            } else if (event == ASSOC_REJECT) {                mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT);            } else {                handleEvent(event, eventData);            }            mRecvErrors = 0;            return false;        }

经过一系列处理调用handleEvent方法

 void handleEvent(int event, String remainder) {            switch (event) {                case DISCONNECTED:                    handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);                    break;                case CONNECTED:                    handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);                    break;                case SCAN_RESULTS:                    mStateMachine.sendMessage(SCAN_RESULTS_EVENT);                    break;                ///M: @{                case NO_CERTIFICATION:                    mStateMachine.sendMessage(WAPI_NO_CERTIFICATION_EVENT);                    break;                ///@}                case UNKNOWN:                    break;            }        }

以SCAN_RESULTS_EVENT为例,状态机发送一个SCAN_RESULTS_EVENT消息,这个状态机是WifiStateMachine对象,WifiStateMachine当前的状态为SupplicantStartedState(中间的过程暂时忽略),看看processMessage方法相关代码

case WifiMonitor.SCAN_RESULTS_EVENT:                    setScanResults();                    if (mWifiFwkExt.hasCustomizedAutoConnect()) {                        mShowReselectDialog = false;                        Xlog.d(TAG, "SCAN_RESULTS_EVENT, mScanForWeakSignal:" + mScanForWeakSignal);                        if (mScanForWeakSignal) {                            showReselectionDialog();                        }                        mDisconnectNetworkId = INVALID_NETWORK_ID;                    }                    sendScanResultsAvailableBroadcast();                    mScanResultIsPending = false;                    break;

这里会调用sendScanResultsAvailableBroadcast发送广播,把扫描到的Wifi热点信息发送给广播接收者

private void sendScanResultsAvailableBroadcast() {        noteScanEnd();        Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);        intent.putExtra(IWifiFwkExt.EXTRA_SHOW_RESELECT_DIALOG_FLAG, mShowReselectDialog);        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);    }

至此,Wifi启动的一个大概流程就先分析到这里!










1楼u010657219昨天 17:02
NB啊,膜拜。。
  相关解决方案