因工作需要,对Android的Wifi模块做了些分析与跟踪,当前的源码版本是Android 4.4的,在Android 5以后已经发生了一些变化。

从Android的启动开始

      进入Android的入口是SystemServer,在这里面注册了许多的Service。这里主要看与Wifi相关的服务。

try {    Slog.i(TAG, "Wi-Fi Service");    wifi = new WifiService(context);    ServiceManager.addService(Context.WIFI_SERVICE, wifi);} catch (Throwable e) {    reportWtf("starting Wi-Fi Service", e);}try {    Slog.i(TAG, "Connectivity Service");    connectivity = new ConnectivityService(            context, networkManagement, networkStats, networkPolicy);    ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);    networkStats.bindConnectivityManager(connectivity);    networkPolicy.bindConnectivityManager(connectivity);    wifiP2p.connectivityServiceReady();    wifi.checkAndStartWifi();} catch (Throwable e) {    reportWtf("starting Connectivity Service", e);}

上述代码中,初始化了wifiService,并把这两个对象加到ServiceManager上,接着又创建了ConnectivityService对象,然后通过创建的WiFiService对象调用wifi.checkAndStartWifi();用于初始化开机时的wifi状态。

先说说WifiService

进入到WifiService.java的构造方法中,路径:
/frameworks/base/services/java/com/android/server/wifi/WifiService.java

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) {                    if (mSettingsStore.handleAirplaneModeToggled()) {                        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();}

这里可以看到,首先读取系统属性,获取系统wifi.interface,默认为wlan0。主要看这两句:

mWifiStateMachine =new WifiStateMachine(mContext,mInterfaceName);mWifiStateMachine.enableRssiPolling(true);

      可以看到,在实例化WifiService的时候,先创建了一个Wifi状态机对象,然后开始Rssi轮询。然后新建一个HandlerThread来处理所有的Message,并注册一些Broadcast的接收者。接着又创建了一个mWifiController 。(【注】:其实自己之前看到这里的时候也在想,为什么这么麻烦?先搞了一个Wifi状态机(哈哈,以前听到状态机,感觉感觉蛮高大上的样子),然后又弄了个WifiController又是干嘛的。)

      其实,WifiStateMachine用于控制整个Wifi的开启、关闭、连接和断开等各个状态的切换,这个感觉还是比较复杂的,后面再说吧。不过还是先看看它的构造方法做了些什么:源码路径在:/frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
这个构造方法太长了,截取一段比较关键的:

mWifiNative = new WifiNative(mInterfaceName);mWifiConfigStore = new WifiConfigStore(context, mWifiNative);mWifiMonitor = new WifiMonitor(this, mWifiNative);mWifiInfo = new WifiInfo();mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore, getHandler());mLinkProperties = new LinkProperties();mNetlinkLinkProperties = new LinkProperties();

这里初始化了一些对象,都是与wifi的控制相关的信息。

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);setLogRecSize(2000);setLogOnlyTransitions(false);if (DBG) setDbg(true);//start the state machinestart();

这里可以看到,WifiStateMachine在实例化的时候,往状态机中添加了许许多多的状态,在wifi连接与断开的整个流程中,都会与上述添加的状态息息相关。添加完这些状态后,先是设置了一下wifi状态机的最初始状态为InitialState。然后调用start()方法启动wifi状态机工作,这个start()方法的实现在WifiStateMachine的父类StateMachine中,所以状态机也叫层次状态机。
    由上面的分析,知道了在WifiService初始化的时候,实例化了一个WifiStateMachine,然后由WifiStateMachine接管了整个Wifi运行时期各种状态变化的管理。
      不过,在WifiService的构造方法中,还实例化了一个WifiController对象,这个又是在干嘛呢?来看看它在实例化的时候做了些什么:
/frameworks/base/services/java/com/android/server/wifi/WifiController.java

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);        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);        } else {            setInitialState(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);}

这段代码好长,感觉贴图上来好难看。。。
不过可以大致看到,在WifiService中把WifiStateMachine的实例传了进来。这里也注册了好几种状态,是的,WifiController也继承自StateMachine,并且在实例化的时候设置了初始状态。如下,当wifi被设置为一直可以扫描的话,初始状态会设置为mStaDisabledWithScanState,一般会走else分支。

if (mSettingsStore.isScanAlwaysAvailable()) {     setInitialState(mStaDisabledWithScanState);} else {     setInitialState(mApStaDisabledState);}

在WifiService中创建该实例后,立即调用了mWifiController.start();根据刚才对WiFiStateMachine的分析可知,这里调用的是状态机父类StateMachine中的start()方法。调用start方法后,WifiController首先进入mDefaultState状态,然后进入mApStaDisabledState状态(为什么呢?从addState(mApStaDisabledState, mDefaultState);可以看出,mDefaultState是mApStaDisabledState的父状态,执行的时候,会先进入父状态的enter(),然后再执行子状态。【层次状态机】),此时,WifiController状态机的状态为mApStaDisabledState状态,进入到该状态的enter()方法:

@Overridepublic void enter() {     mWifiStateMachine.setSupplicantRunning(false);     // Supplicant can't restart right away, so not the time we switched off     mDisabledTimestamp = SystemClock.elapsedRealtime();     mDeferredEnableSerialNumber++;     mHaveDeferredEnable = false;}

发现做了些配置,没有更多的动作,到这里WifiService的初始化大致做完了,还有一些细节,留到以后再分析吧。

回到SystemServer

在本文开始的时候,有贴过一段代码,其中在初始化完WifiService和ConnectivityService后,执行了如下代码:

    wifi.checkAndStartWifi();

这句代码才开始真正从开机状态完成真正的wifi监测与打开的动作。

public void checkAndStartWifi() {        //检查WiFi是否需要使能        boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();        Slog.i(TAG, "WifiService starting up with Wi-Fi " +                (wifiEnabled ? "enabled" : "disabled"));        // If we are already disabled (could be due to airplane mode), avoid changing persist        // state here        // MStar Android Patch Begin        if (wifiEnabled) {            setWifiEnabled(wifiEnabled);        } else {            //如果Wifi本身没有启动,测试softap是否需要启动            boolean wifiApEnabled = mSettingsStore.isWifiApToggleEnabled();            if (wifiApEnabled) {                Slog.d(TAG, "wifi ap start with enabled");                setWifiApEnabled(null, wifiApEnabled);            } else {                Slog.d(TAG, "wifi ap start with disabled");            }        }        // MStar Android Patch End        mWifiWatchdogStateMachine = WifiWatchdogStateMachine.makeWifiWatchdogStateMachine(mContext);}

上述实现WifiService.java中,首先来看这句:

 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();

先读取系统上次关机时的wifi开关状态,如果该值为true,证明上次是打开的,那么执行如下代码:

setWifiEnabled(wifiEnabled);

来看这句代码的实现:

public synchronized boolean setWifiEnabled(boolean enable) {        enforceChangePermission();        Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());        if (DBG) {            Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");        }        /*        * Caller might not have WRITE_SECURE_SETTINGS,        * only CHANGE_WIFI_STATE is enforced        */        long ident = Binder.clearCallingIdentity();        try {            if (! mSettingsStore.handleWifiToggled(enable)) {                // Nothing to do if wifi cannot be toggled                return true;            }        } finally {            Binder.restoreCallingIdentity(ident);        }        mWifiController.sendMessage(CMD_WIFI_TOGGLED);        return true;}

关键是最后一句:mWifiController.sendMessage(CMD_WIFI_TOGGLED);
给WifiController发了个消息:CMD_WIFI_TOGGLED。又转到了WifiController中 :)

刚才前面已经分析过,当wifiController的初始化状态为:ApStaDisabledState。所以,当前这个消息将由该状态来处理,来看它的processMessage()方法:

public boolean processMessage(Message msg) {    switch (msg.what) {        case CMD_WIFI_TOGGLED:        case CMD_AIRPLANE_TOGGLED:            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) {                    transitionTo(mDeviceActiveState);                } else {                    checkLocksAndTransitionWhenDeviceIdle();                }            }            break;        ....        default:            return NOT_HANDLED;    }    return HANDLED;}

这里可以看到,当系统wifi打开,并且mDeviceIdle == false,则会执行状态转换:

transitionTo(mDeviceActiveState);

addState(mDeviceActiveState, mStaEnabledState);可知,mStaEnabledState是mDeviceActiveState的父状态,所以先执行其enter()方法,

class StaEnabledState extends State {    @Override    public void enter() {        mWifiStateMachine.setSupplicantRunning(true);    }    ...}

这里执行了WifiStateMachine的setSupplicantRunning方法。

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

可以看到,这里又发了消息:CMD_START_SUPPLICANT。前面分析WiFiStateMachine初始化的时候,已经说过,其初始化状态为InitialState,所以这个消息将由它的processMessage()方法来处理:

case CMD_START_SUPPLICANT:    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)) {            setWifiState(WIFI_STATE_ENABLING);            if (DBG) log("Supplicant start successful");            mWifiMonitor.startMonitoring();            transitionTo(mSupplicantStartingState);        } else {            loge("Failed to start supplicant!");        }    } else {        loge("Failed to load driver");    }    break;

这一段代码还是比较关键的,可以看到首先通过mWifiNative.loadDriver()去加载驱动,当驱动加载成功后,重新加载固件:

mNwService.wifiFirmwareReload(mInterfaceName, "STA");mNwService.setInterfaceDown(mInterfaceName)...setWifiState(WIFI_STATE_ENABLING);mWifiMonitor.startMonitoring();transitionTo(mSupplicantStartingState);...

做了一系列的配置操作,设置wifi状态为WIFI_STATE_ENABLING正在打开,开始监管startMonitoring(),最后把状态转移到mSupplicantStartingState。

看完父状态的操作,再来看mDeviceActiveState的enter方法:

class DeviceActiveState extends State {    @Override    public void enter() {    mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);        mWifiStateMachine.setDriverStart(true);        mWifiStateMachine.setHighPerfModeEnabled(false);    }    ...}

可以看到,这里都是在通过wifi状态机去做一系列的操作,比如设置连接模式,启动driver等,来看看

mWifiStateMachine.setDriverStart(true);

看看它的实现:

public void setDriverStart(boolean enable) {    if (enable) {         sendMessage(CMD_START_DRIVER);    } else {         sendMessage(CMD_STOP_DRIVER);    }}

这里由刚才分析的结果,WiFiStateMachine进入了mSupplicantStartingState状态,所以,这个消息将由它的方法去处理,再经过几次状态转换到SupplicantStartedState,driver就启动了。

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. Android之view重绘
  5. android事件分发机制
  6. AsyncTask源码剖析(API 23)
  7. 【转】Android(安卓)虚拟机安装APK文件方法
  8. 新书内容连载(2):Android(安卓)Activity的生命周期
  9. [Android]实现静默安装APK的两种方法

随机推荐

  1. android AppWidget 支持ListView
  2. Android中获取文件路径的方法总结及对照
  3. 手动编译源码,打造自己的增量更新。
  4. Dalvik虚拟机是如何执行程序的
  5. android Dialog 背景问题
  6. Android 获取设备唯一号 unknown
  7. Android(安卓)api level对照表
  8. JavaEE还是Android?
  9. 2018 Android 框架汇总(转)
  10. Android 加速度传感器 (G-Sensor) 收