wifi

9 篇文章 0 订阅
2 篇文章 0 订阅

最近研究Wifi模块,查了不少的相关资料,但发现基本上是基于android2.0版本的的分析,而现在研发的android移动平台基本上都是2.3的版本,跟2.0版本的差别,在Wifi模块上也是显而易见的。2.3版本Wifi模块没有了WifiLayer,之前的WifiLayer主要负责一些复杂的Wifi功能,如AP选择等以提供给用户自定义,而新的版本里面的这块内容基本上被WifiSettings所代替。

       本文就是基于android2.3版本的Wifi分析,主要分为两部分来分别说明:

(1)    Wifi模块相关文件的解析

(2)    Wifi的启动流程(有代码供参考分析)

一,Wifi模块相关文件解析

1)      wifisettings.java

packages/apps/Settings/src/com/android/settings/wifi wifisettings.java

       该类数据部分主要定义了下面几个类的变量:

{

private final IntentFilter mFilter;

 

//广播接收器,用来接收消息并做响应的处理工作

private final BroadcastReceiver mReceiver;

 

//这是一个扫描类,会在用户手动扫描   AP时被调用

private final Scanner mScanner;               

private WifiInfo mLastInfo;

 

       //服务代理端,作为WifiService对外的接口类呈现

private WifiManager mWifiManager;

 

//这个类主要实现Wifi的开闭工作

private WifiEnabler mWifiEnabler;

 

//AP

private AccessPoint mSelected;

private WifiDialog mDialog;

……

}

       wifiSettings类的构造函数的主要工作:定义了一个IntentFilterIntent过滤器)变量,并添加了六个动作,(了解Androidintent机制的同学都知道什么意思,不明白的同学参考Intent机制的资料)接着定义一个广播接收器,并有相应的消息处理函数,下面是该构造函数的定义:

 

public WifiSettings() {

mFilter = new IntentFilter();

//intent机制中的intent消息过滤器,下面添加可以处理的动作

    mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);

      mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

    mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);

   mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);

        mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

    mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);

 

//注册了广播接收器,用来处理接收到的消息事件

        mReceiver = new BroadcastReceiver() {

            @Override

            public void onReceive(Context context, Intent intent) {

                handleEvent(intent); //事件处理函数

            }

        };

 

        mScanner = new Scanner();     //手动扫描类

}

       在广播接收器中的相应函数onReceive函数中有个handleEvent函数,它就是用来处理广播接收器接受到的intent消息的,它的功能是根据intent消息中的动作类型,来执行相应的操作,每一种动作对应了activity的一项消息处理能力。

       oncreate函数中实例化了mWifiManagermWifiEnabler两个类,这两个类对wifiSettings来说至关重要,它后面的定义的一系列函数都是通过调用这两个类的相应接口来实现的。

……

mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

mWifiEnabler = new WifiEnabler(this,

                    (CheckBoxPreference) findPreference("enable_wifi"));

……

       WifiSettings中还定义了显示菜单和响应菜单键的函数,即onCreateOptionsMenu()和onOptionsItemSelected();还有响应配置对话框中按键的onClick()函数;最后定义了Scanner类,它是一个handler的继承类,实现了消息处理函数,用于处理手动扫描的动作。

 

2)      WifiEnabler.java:

packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java

 

private final Context mContext;

private final CheckBoxPreference mCheckBox;

 

//两个重要成员

private final WifiManager mWifiManager;

private final IntentFilter mIntentFilter;

 

       wifienabler类中定义了四个成员变量很重要,mContextmCheckBoxmWifiManagermReceiver,其中mContext用于获取mwifiManager实例,mReceiver用来接收底层发来的消息,mCheckBox用来改变UI的状态。

该类中定义了几个重要的函数onPreferenceChangehandleWifiStateChangedhandleStateChangedonPreferenceChange用来处理按下的Enbler键,它会调用mWifiManager.setWifiEnabled(enable),另外两个用来处理接受的消息事件。

 

       在类的构造函数中,主要做了一下工作:初始化了mContext,mCheckBox,mWifimanager,并且初始化了一个mIntentFilter变量,添加了三个动作,在构造函数的上面定义了一个广播接收器,用来接收下层传来的消息,并根据intent动作的类型调用相应的处理函数,这个广播接收器在onResum函数中被注册。

public WifiEnabler(Context context, CheckBoxPreference checkBox) {

        mContext = context;

        mCheckBox = checkBox;

        mOriginalSummary = checkBox.getSummary();

        checkBox.setPersistent(false);

 

        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

        mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);

        // The order matters! We really should not depend on this. :(

        mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);

        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

}

这里可以总结为:如果上层需要监听或收到下层的消息,那么就要通过定义一个BroadcastReciever,并将它注册,当然在接受到消息后应该有处理消息的函数,然后在onReciever函数中根据消息调用相应的处理函数,这里的消息通知机制是Intent,在BroadcastReciever类的onReciever函数的参数中可以看出。

该类成员函数的也是通过调用mWifimanager的接口来实现的。

 

 3) WifiManager:

       frameworks/base/wifi/java/android/net/wifi/WifiManager.java

       两个重要的数据成员:

//WifiService

IWifiManager mService;

    Handler mHandler;

IWifiManager mServiceHandler mHandler,这个类拥有了一个WifiService实例,就可以通过它进行一系列的调用;WifiManager中定义了的wifiap的状态,这些状态会在其他很多类中有使用;然后定义了大量的函数,这些函数几乎都是对WifiService接口函数的封装,直接调用WifiService的函数。

该类的构造函数很简单:

public WifiManager(IWifiManager service, Handler handler) {

        mService = service;

        mHandler = handler;

    }

该类中还定义了一个WifiLock类,这个类用来保证在有应用程序使用Wifi无线电传输数据时,wifi radio可用,即当一个应用程序使用wifiradio进行无线电数据传输时,就要先获得这个锁,如果该锁已被其他程序占有,就要等到该锁被释放后才能获得,只用当所有持有该锁的程序都释放该锁后,才能关闭radio功能。

 

 4) WifiService

frameworks/base/services/java/com/android/server/WifiService.java

private final WifiStateTracker mWifiStateTracker;

private Context mContext;

private WifiWatchdogService mWifiWatchdogService = null;

private final  WifiHandler mWifiHandler;

这是WifiService中的几个重要的数据成员。

在接下来的构造函数中初始化了mWifiStateTrackermContext,然后动态生成mWifiThread子线程并启动,在主线程里用mWifiThread调用getLooper()函数获得线程的looper,来初始化创建一个mWifiHandler对象,这个WifiHandlerWifiService类的后面有定义,并重载了Handler类的handlermessage()函数,这样消息就可以在主线程里被处理了,这是androidhandlerthread消息处理机制,可参考相关资料,这里不予详述。在构造函数的最后,注册了两个广播接收器,分别用来ACTION_AIRPLANE_MODE_CHANGEDACTION_TETHER_STATE_CHANGED这两个动作,这里是androidintent消息通知机制,请参考相关资料,代码如下:

 

mContext = context;

mWifiStateTracker = tracker;

mWifiStateTracker.enableRssiPolling(true);

……

HandlerThread wifiThread = new HandlerThread("WifiService");

wifiThread.start();

mWifiHandler = new WifiHandler(wifiThread.getLooper());

……

随后定义了一系列的函数,其中有服务器要发送的命令的系列函数,它通过mWifiStateTracker成员类调用自己的的发送命令的接口(其实就是对本地接口的一个封装),最后通过适配层发送命令给wpa_supplicant,而事件处理只到WifiStateTracker层被处理。

要注意的是,在WifiService中,定义了一些函数来创建消息,并通过mWifiHandler将消息发送到消息队列上,然后在mHandlerThread线程体run()分发\处理消息,在主线程中被mWifiHandlerhandlerMessage()函数处理,最后调用mWifiStateTracker的对应函数来实现的。这里我也不明白为什么WifiService不直接调用mWifiStateTracker对应的函数,还要通过消息处理机制,绕了一圈在调用,当然Google这么做肯定是有它道理的,忘高手指点。

 

 5) WifiStateTracker

frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

NetworkStateTracker继承了handler类,而WifiStateTracker继承了NetworkStateTracker类,就是说WifiStateTracker间接继承了handler类,属于一个事件处理类。

WifiStateTracker类首先定义了事件日志和事件码(这里包含了所有可能的事件类型),还定义了如下的重要成员数据:

          //几个重要的数据成员

private WifiMonitor mWifiMonitor;    //被启动用来监听supplicant传来的消息

private WifiInfo mWifiInfo;        

private WifiManager mWM;             //服务代理

private DhcpHandler mDhcpTarget;  //IP地址获取线程

private DhcpInfo mDhcpInfo;            //Dhcp的相关信息都在这里

               

类的构造函数中,初始化了系列成员变量,包括生成了WifiMonitor的实例,在构造函数中,因为WifiStateTracker是一个handler间接子类,所以他会自动调用handler的无参构造函数,获得looperQueue消息队列。

然后定义了一些设置supplicant和更新网络信息的辅助函数。

       startEventLoop()函数很重要,用来启动WifiMonitor线程,进入消息循环检测。接着定义了系列通知函数,被WifiMonitor调用来向WifiStateTracker传递从wpa_supplicant接收到的消息,他会调用消息发送函数到消息队列,并被WifiStateTrackerhandlermessage()函数处理。这个handlermessage()函数就是在随后被定义的,它主要是调用相应的辅助函数完成动作,并可能会将消息封装后,通过intent机制发送出去,被上层的UI活动接收处理。

这里也定义了很多的WfiNative接口函数,这是JNI的本地接口;类DhcpHandler extends Handler{}也是在该类中定义的,它也是一个handler的子类,用来处理DHCP相关的消息EVENT_DHCP_START,可以想到它和WifiStateTracker不是共用一个looper

       注意:handleMessage是在该文件中定义的,用来处理经WifiMonitor转换过的消息。

 

 6) WifiMonitor

       frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

声明了一个重要的成员变量:mWifiStateTracker,并在构造函数中由参数提供初始化,还定义了一系列的可能从wpa_supplicant层接收的事件类型及其名字,这些是消息处理机制的基础。

startMonitoring()函数,这是一个线程启动的封装函数,WifiStateTracker就是通过这个函数启动的WifiThread

这个重要的类classMonitorThread extends Thread{};它是一个监控进程类,里面有一系列的事件处理函数和一个重要的Run()函数,run函数主要流程:connectToSupplicant()连接精灵进程wpa_supplicant,这里有一个mWifiStateTracker.notifySupplicantXXX()的调用,通知上层是否连接成功,然后就是一个轮询过程,其中调用了WifiNative.waitForEvent()本地轮询函数接口,并从返回的事件字符串类型中提取事件的名称,最后通过事件的名称调用相应的事件处理函数,并将事件转换成mWifiStateTracker能识别的类型上报。

       注意:这里的每个事件的捕获(由wifimonitor完成),最终都会调用相应的mWifiStateTracker的消息通知函数上报消息;轮询和事件处理都是在Monitor线程类中实现的。

 

 7) WifiNative

       frameworks/base/wifi/java/android/net/wifi/WifiNative.java

里面定义了一个类WifiNative:其中声明了许多本地接口,可由native的标志看出,这是Java代码和本地库之间的联系接口;

 

 8) android_net_wifi_Wifi.cpp

frameworks/base/core/jni/

       里面定义了许多的JNI的本地代码实现,每个实现中都会调用wpa_supplicant适配层的接口,通过包含适配层的头文件wifi.h获取适配层定义的接口;后面是一个JNINativeMethod数组,定义了每个本地接口和本地实现的对应关系;最后有一个注册函数regester_XXX_XX(),用以把上面的方法类数组注册到系统中。

       该类实现了本地接口的相关功能,并通过调用wpa的适配层的相关函数和wpa_supplicant通信,所以JNI是连接Java框架层和wpa适配层的桥梁.

 

 9) wpa_supplicant适配层,wifi.c:目录libhardware/wifi/

       里面定义很多字符串变量和适配层的接口实现,是对wpa_supplicant程序通信的接口封装,用来完成上层和wpa_supplicant的通信,头文件在libhardware/include/hardware下,这里的函数用来向JNI的本地实现提供调用接口。

       这里的函数,我把它们分为三类函数:

一类是命令相关的(控制)函数,就是在JNIandroid_XXX_Command()函数所调用的::Wifi_Command()函数,调用流程:android_XXX_command()=>docommand()=>wifi_command()=>wifi_send_command()=>wpa_ctrl_require()

二类是监听函数,即Wifi_wait_for_event()函数,调用流程:android_net_wifi_Waitforevent()=>wifi_wait_for_event()=>wpa_ctrl_recv()

三类是剩下的函数。

 

10wpa_supplicant与上层的接口,wpa_ctrl.cexternal/wpa_supplicant

定义了三类套接字,并分别实现了和wpa_supplicant的通信,因此wpa_supplicant适配层和wpa_supplicant层是通过socket通讯的。

要是从wifi.c中真的很难看出它和wpa_supplicant有什么关系,和它联系密切的是wpa_ctrl.h文件,这里面定义了一个类wpa_ctrl,这个类中声明了两个Socket套接口,一个是本地一个是要连接的套接口,wpa_ctrlwpa_supplicant的通信就需要socket来帮忙了,而wpa_supplicant就是通过调用wpa_ctrl.h中定义的函数和wpa_supplicant进行通讯的,wpa_ctrl类(其实是其中的两个socket)就是他们之间的桥梁。

 

 11)wpa_supplicantdriver_wext驱动接口的联系:

       driver.h:该文件定义了系列结构,首先是一个wpa_scan_result结构,这是一个扫描结果的通用格式,里面包含了扫描的所有信息(如BSSIDSSID,信号质量,噪音水平,支持的最大波特率等等信息),每个驱动接口实现负责将从驱动中上传的扫描信息的格式转换到该通用的扫描信息格式;然后是一些宏定义和枚举定义,最后也是最重要的是wpa_driver_ops结构,该结构是wpa driver的操作函数集合,里面有驱动接口的名称和很多的函数指针。

       drviers.c:该文件很简单,首先是一些外部变量的引用声明,都是不同驱动操作接口的集合wpa_driver_XXX_ops变量;然后就是定义一个驱动操作接口集合的数组,根据宏定义添加对应的驱动操作接口集合的变量。

       drvier_XXX.h:这是不同驱动接口头文件,主要声明了操作接口

       drvier_XXX.c:实现操作接口,定义一个操作集合变量,并用上面定义的函数初始化其中的函数指针

       注意:下面要搞清楚wpa_supplicant守护进程是如何操作,最后调用驱动接口集合中的函数的;要知道wpa_supplicant是为不同驱动和操作系统具有更好移植性而被设计的,以便在wpa_supplicant层不用实现驱动的具体接口就可以添加新的驱动程序;在wpa_supplicant结构中有一个wpa_drv_ops类型的drvier成员,在wpa_supplicant进程中,经常通过Wpa_supplicant_XXX函数传递wpa_supplicant实例指针wpa_s参数给wpa_drv_XXX函数来调用它,在wpa_drv_XX中会通过wpa_s->driver->XXX()的流程来调用通用驱动接口,简单才是生活的真相,可android始终让我感到真相还是遥不可及。

 

 12)WifiWatchdogService

首先声明了两个主要变量mWifiStateTrackermWifiManager,需要这两个类对象来完成具体的控制工作,在WifiWatchdogService的构造函数中,创建了这两个类,并通过regesterForWifiBroadcasts()注册了BroadcastReceiverBroadcastReceiver是用来获取网络变化的,然后启动了一个WatchdogTread线程,用来处理从WifiStateTracker接收到的消息。

 

frameworks/base/services/java/com/android/server/WifiWatchdogService.java

WifiWatchdogService(Context context, WifiStateTracker wifiStateTracker) {

        mContext = context;

        mContentResolver = context.getContentResolver();

        mWifiStateTracker = wifiStateTracker;

        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

       

        createThread();

       

        // The content observer to listen needs a handler, which createThread creates

        registerForSettingsChanges();

        if (isWatchdogEnabled()) {

            registerForWifiBroadcasts();

        }

       

        if (V) {

            myLogV("WifiWatchdogService: Created");

        }

    }

       WifiWatchdogHandler继承了handler类,成为一个消息处理类,定义handlemessage()函数,处理消息队列上的消息。



当SystemServer启动后会加载一系列的Service其中init2启动的就有ConnectivityService,这在我的前面《Android 启动过程分析》中已经提到过。ConnectivityService.java (frameworks\base\services\java\com\android\server) 会管理所有的Connectivity相关的比如APN,WiFi。看看是怎么启动WiFi Service的:

       if (DBG) Log.v(TAG, "Starting Wifi Service.");

        WifiStateTracker wst = new WifiStateTracker(context, mHandler);

        WifiService wifiService = new WifiService(context, wst);

        ServiceManager.addService(Context.WIFI_SERVICE, wifiService);

WifiStateTracker会创建WifMonitor来接受来自底层的事件。WifiService和WifiMonitor是整个模块的核心部分,WifiService负责启动关闭wpa_supplicant,发命令给wpa_supplicant,WiFiMonitor负责从wpa_supplicant接收事件。

整个流程是

SystemServer -> ServerThread -> ConnectivityService -> ConnectivityThread -> WifiTracker->WifiService -> WifiMonitor

WiFi 的启动过程

用户在设置界面下开启了WiFi,调用应用程序Settings中的setWifiEnabler的onPerferenceChange,再由WifiEnable调用WifiService,发送MESSAGE_ENABLE_WIFI,首先装载wifi内核模块wlan.ko然后启动wpa_supplicant(用/data/misc/wifi/wpa_supplicant.conf配置),再通过WifiStateTracker来启动WifiMonitor监视线程。

WifiSettings.java (packages\apps\settings\src\com\android\settings\wifi)启动

           mWifiEnabled = (CheckBoxPreference) preferenceScreen.findPreference(KEY_WIFI_ENABLED);

           mWifiEnabler = new WifiEnabler(this, (WifiManager) getSystemService(WIFI_SERVICE), mWifiEnabled);

这样就启动WifiEnabler

WifiEnabler.java (packages\apps\settings\src\com\android\settings\wifi)通过WifiManager调用WifiManager.java (frameworks\base\wifi\java\android\net\wifi) setWifiEnabled 中的IWifiManager来启动wifiservice[mService.setWifiEnabled(enabled);]

WifiService.java (frameworks\base\services\java\com\android\server)又setWifiEnabled()这个里面的sendEnableMessage(enable, true, Binder.getCallingUid());来发送一则消息。

Message msg = Message.obtain(mWifiHandler,

                                     (enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),

                                     (persist ? 1 : 0), uid);

        msg.sendToTarget();发送给自身的消息。

通过WifiHandler的 handleMessage来维护这些消息,enable的时候会调用setWifiEnabledBlocking这个函数,这个函数会做setWifiEnabledState  然后做两件事: 1. 调用wifi 本地方法JNI的WifiNative.loadDriver。

下面说本地方法WifiNative.loadDriver函数WifiNative.java (frameworks\base\wifi\java\android\net\wifi) Android的WIFI系统的JNI的部分:

frameworks/base/core/jni/android_net_wifi_Wifi.cpp 中的android_net_wifi_loadDriver()可以把wifi驱动模块装载

Wifi.c (hardware\libhardware_legacy\wifi) 内核模块/system/lib/modules/wlan.ko中的wifi_load_driver()

设置wlan.driver.status属性为ok,至此wifi模块加载完毕。

2. 再来看看启动,同样是在WifiService 中的setWifiEnabledBlocking这个函数会调用startSupplicant 通过WifiNative.java (frameworks\base\wifi\java\android\net\wifi)的startSupplicant来启动JNI:frameworks/base/core/jni/android_net_wifi_Wifi.cpp的android_net_wifi_startSupplicant调用驱动模块Wifi.c (hardware\libhardware_legacy\wifi) wlan.ko中的wifi_start_supplicant, Wifi 启动完毕。

成功启动wifi之后setWifiEnabledBlocking运行mWifiStateTracker.startEventLoop();事件循环,来监视事件mWifiMonitor.startMonitoring(); à MonitorThread().start();一直在线程里循环调用WifiNative.waitForEvent();最后调用

setWifiEnabledState(eventualWifiState, uid); 

intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);

广播消息向外界通知wifi已经成功启动了。

查找热点AP

上面说了WifiManager发送广播WIFI_STATE_CHANGED_ACTION,只要Android应用注册了接受该Action的就接受,我们的WifiLayer注册了接收到该Action WifiSettings.java (packages\apps\settings\src\com\android\settings\wifi)中有mWifiLayer.onCreate();(这个函数创建WifiLayer指定接受的Action) WifiLayer.java (packages\apps\settings\src\com\android\settings\wifi)中的BroadcastReceiver 有一句话else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {                 handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,                         WifiManager.WIFI_STATE_UNKNOWN)); 这个函数会调用loadConfiguredAccessPoints和attemptScan来开始扫描,调用WifiManager的mWifiManager.startScanActive,WifiManager.java中的mService.startScan通过WifiService中的startScan通过本地方法WifiNative.setScanResultHandlingCommand启动JNI android_net_wifi_Wifi.cpp (frameworks\base\core\jni) 中的android_net_wifi_setScanResultHandlingCommand的命令“AP_SCAN 模式” Wifi.c ::wifi_command(cmd)开始扫描wifi_send_command发出SCAN命令调用wpa_supplicant开始扫描 扫描完成之后会发送SCAN_RESULT 在WifiMonitor的HandleEvent里处理调用mWifiStateTracker.notifyScanResultsAvailable(); à sendEmptyMessage(EVENT_SCAN_RESULTS_AVAILABLE); mWifiStateTracker中的 handleMessage接收到case EVENT_SCAN_RESULTS_AVAILABLE:之后发送广播mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); WiFiLayer接收到这个消息在mReceiver = new BroadcastReceiver()中处理handleScanResultsAvailable();

WiFi 连接流程

用户在AccessPointDialog中输入密码之后点击连接按钮,Android调用顺序如下:

AccessPointDialog.java (packages\apps\settings\src\com\android\settings\wifi) -> onClick -> handleConnect(); -> mWifiLayer.connectToNetwork ->通过WifiConfiguration config = findConfiguredNetwork(state);查看是不是配置过的,如果是就直接使用了,如果不是config = addConfiguration(state, 0); -> managerEnableNetwork -> mWifiManager.enableNetwork -> mService.enableNetwork -> WifiService. enableNetwork -> WifiNative.enableNetworkCommand -> JNI: android_net_wifi_Wifi.cpp android_net_wifi_enableNetworkCommand 调用wpa_suppcant发送相关命令返回之后由WiFiMonitor处理跟以前类似,连接的中间流程与查找AP的流程类似,都经过了WifiMonitor对“CONNECTED”消息响应的捕获,以及WifiStateTracker对EVENT_SUPPLICANT_STATE_ CHANGED的处理。还有一个比较重

要的步骤是WifiStateTracker通过对DHCP服务器的申请进行了IP地址分配。最终会广播NETWORK_STATE_CHANGED_ ACTION消息,由WifiLayer响应。

IP地址分配

由上面继续说IP地址分配,因为当wpa_supplicant链接AP成功之后,它会发出事件从而wifi_for_event函数会接收到该事件,由WifiMonitor中的MonitorThread执行。

执行这个事件handleEvent-> case CONNECTED: handleNetworkStateChange -> mWifiStateTracker.notifyStateChange  -> EVENT_NETWORK_STATE_CHANGED -> handleMessage 下的:case EVENT_SUPPLICANT_STATE_CHANGED: -> intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); Wi-Fi supplicant state changed:

SettingsObserver专门是观察该类变化的

if (changed) {

                resetInterface(true);

                configureInterface();

                if (mUseStaticIp) {

                    mTarget.sendEmptyMessage(EVENT_CONFIGURATION_CHANGED);

                }

            }

mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);

DhcpHandler的handleMessage函数case EVENT_DHCP_START: NetworkUtils.runDhcp获取DHCP的IP地址,成功之后发送EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:

event通过WifiStateTracker的HandleMessage函数case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:会调用sendNetworkStateChangeBroadcast Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);发送全局Intent Action 完成网络切换。

上文中暗红色的部分都是ICS Settings里面的内容(也就是可以注意下android自带的UI是如何使用wifi的)~~



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值