您的位置:首页 > 移动开发 > Android开发

Android WIFI框架分析

2013-01-14 23:01 513 查看
转自/article/8001807.html

趁做Android WIFI驱动移植,对Android WIFI框架做了深刻的分析,并做此文档共同学习。

对上层WIFI的应用,基本流程为:(1)WIFI初始化(2)Wifi启动(3)开始扫描AP(4)显示扫描的AP
(5)配置AP(6)连接AP(7)获取IP地址(8)上网

一、Android WIFI模块初始化

上文Android系统启动分析讲到在SystemServer中实例化了ConnectivityService,接着的便是WIFI初始化:

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

ConnectivityService 的构造函数会创建WifiService,

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 会创建WifiMonitor 接收来自底层的事件,WifiService 和WifiMonitor 是整个模块的核心。WifiService 负责启动关闭wpa_supplicant、启动关闭WifiMonitor 监视线程和把命令下发给wpa_supplicant,而WifiMonitor 则负责从wpa_supplicant 接收事件通知。

具体流程图如下:



二、WIFI模块启动

WirelessSettings 在初始化的时候配置了由WifiEnabler 来处理Wifi 按钮 WirelessSettings 在初始化的时候配置了由WifiEnabler 来处理Wifi 按钮

Packages\apps\settings\src\com\android\settings\WirelessSettings.java

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

addPreferencesFromResource(R.xml.wireless_settings);

initToggles();

mAirplaneModePreference = (CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE);

}

private void initToggles() {

…………

mWifiEnabler = new WifiEnabler(

this, (WifiManager) getSystemService(WIFI_SERVICE),

(CheckBoxPreference) wifiPreference);

…………

}



当用户按下Wifi 按钮后,Android 会调用WifiEnabler 的onPreferenceChange,再由WifiEnabler调用WifiManager 的setWifiEnabled 接口函数,通过AIDL,实际调用的是WifiService 的setWifiEnabled 函数,WifiService 接着向自身发送一条MESSAGE_ENABLE_WIFI 消息,在处理该消息的代码中做真正的使能工作:

首先装载WIFI 内核模块(该模块的位置硬编码为"/system/lib/modules/libertas_sdio.ko" ),

然后启动wpa_supplicant ( 配置文件硬编码为"/data/misc/wifi/wpa_supplicant.conf"),再通过WifiStateTracker 来启动WifiMonitor 中的监视线程。

WifiEnabler.java

public boolean onPreferenceChange(Preference preference, Object value) {

// Turn on/off Wi-Fi

setWifiEnabled((Boolean) value);

}

private void setWifiEnabled(final boolean enable) {

if (!mWifiManager.setWifiEnabled(enable)) {

}

}

WifiManager.java

public boolean setWifiEnabled(boolean enabled) {

return mService.setWifiEnabled(enabled);

}

IWifiManager mService;

interface IWifiManager{

…………

boolean startScan(boolean forceActive);

boolean setWifiEnabled(boolean enable);

…………

}

IWifiManger.aidl编译后生成了IWifiManger.java,并生成IWifiManger.Stub(服务器端抽象类)和IWifiManger.Stub.Proxy(客户端代理实现类)。WifiService通过继承IWifiManger.Stub实现,而客户端通过getService()函数获取IWifiManger.Stub.Proxy(即Service的代理类),将其作为参数传递给WifiManger,供其与WifiService通信时使用。

WifiService.java

public boolean setWifiEnabled(boolean enable) {

…………

sendEnableMessage(enable, true, Binder.getCallingUid());

…………

}

private void sendEnableMessage(boolean enable, boolean persist, int uid) {

Message msg = Message.obtain(mWifiHandler,

(enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),

(persist ? 1 : 0), uid);

msg.sendToTarget();

}

public void handleMessage(Message msg) {

switch (msg.what) {

case MESSAGE_ENABLE_WIFI:

setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);

case MESSAGE_START_WIFI:

mWifiStateTracker.restart();

case MESSAGE_DISABLE_WIFI:

setWifiEnabledBlocking(false, msg.arg1 == 1, msg.arg2);

case MESSAGE_STOP_WIFI:

mWifiStateTracker.disconnectAndStop();

break;

}

}

}

private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) {

if (enable) {

if (!WifiNative.loadDriver()) {

setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

}

if (!WifiNative.startSupplicant()) {

WifiNative.unloadDriver();

setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

}

registerForBroadcasts();

mWifiStateTracker.startEventLoop();

} else {

………………

}

// Success!

setWifiEnabledState(eventualWifiState, uid);

}

private void setWifiEnabledState(int wifiState, int uid) {

// Broadcast

final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);

}

JNI android_net_wifi_wifi.cpp

// ----------------------------------------------------------------------------

/*

* JNI registration.

*/

static JNINativeMethod gWifiMethods[] = {

/* name, signature, funcPtr */

{ "loadDriver", "()Z", (void *)android_net_wifi_loadDriver },

{ "startSupplicant", "()Z", (void *)android_net_wifi_startSupplicant },

{ "scanResultsCommand", "()Ljava/lang/String;", (void*) android_net_wifi_scanResultsCommand },

{ "reconnectCommand", "()Z", (void *)android_net_wifi_reconnectCommand },

{ "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand },

}

1)static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject clazz)

{

return (jboolean)(::wifi_load_driver() == 0);

}

2)static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject clazz)

{

return (jboolean)(::wifi_start_supplicant() == 0);

}

3)WifiStateTracker.java

mWifiStateTracker.startEventLoop();

public void startEventLoop() {

mWifiMonitor.startMonitoring();

}

//WifiMonitor.java

public void startMonitoring() {

new MonitorThread().start();

}

当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION 这个Intent 通知外界WIFI已经成功使能了。// Success!后广播的。

上文讲到WIFI的启动流程,当然接着便扫描热点(AP),然后显示扫描到的AP、配置AP(填写IP地址等信息)、连接AP、获取IP地址、最后就是想要的上网咯!

一、扫描热点(AP)

上文启动WIFI成功后:// Success!

setWifiEnabledState(eventualWifiState, uid);

private void setWifiEnabledState(int wifiState, int uid) {

// Broadcast

final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);

}

当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION 这个Intent 通知外界WIFI已经成功使能了。WifiLayer 创建的时候就会向Android 注册接收WIFI_STATE_CHANGED_ACTION,因此它会收到该Intent,从而开始扫描。

WifiSetting.java:

protected void onCreate(Bundle savedInstanceState) {

mWifiLayer.onCreate();

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

WifiLayer.java:

public void onCreate() {

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

mIntentFilter = new IntentFilter();

mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);

}

public void onResume() {

mContext.registerReceiver(mReceiver, mIntentFilter);

if (isWifiEnabled()) {

// Kick start the continual scan

queueContinuousScan();

}

}

以上就是WifiLayer.java注册接收的部分事件。接收部分事件处理有:

private BroadcastReceiver mReceiver = new BroadcastReceiver() {

private BroadcastReceiver mReceiver = new BroadcastReceiver() {

public void onReceive(Context context, Intent intent) {

final String action = intent.getAction();

if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {

handleNetworkStateChanged(

(NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO),

intent.getStringExtra(WifiManager.EXTRA_BSSID));

} else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {

handleScanResultsAvailable();

} ……

else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {

handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,

WifiManager.WIFI_STATE_UNKNOWN));

}

}

};

从可接受的事件看,当WIFI_STATE_CHANGED_ACTION时,对应的处理函数有:

handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,

WifiManager.WIFI_STATE_UNKNOWN));

private void handleWifiStateChanged(int wifiState) {

attemptScan();

…………

}

public void attemptScan() {

if (!mWifiManager.startScanActive()) {

postAttemptScan();

}

}

WifiManager.java:

public boolean startScanActive() {

return mService.startScan(true);

}

-------AIDL-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

WifiService.java:

public boolean startScan(boolean forceActive) {

…………

return WifiNative.scanCommand(forceActive);

}

---------JNI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

android_net_wifi_wifi.cpp:

{ "scanCommand", "(Z)Z", (void*)
android_net_wifi_scanCommand },

static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive)

{

…………

result = doBooleanCommand("SCAN", "OK");

}

static jboolean doBooleanCommand(const char *cmd, const char *expect)

{

if (doCommand(cmd, reply, sizeof(reply)) != 0) {

return (jboolean)JNI_FALSE;

}

}

static int doCommand(const char *cmd, char *replybuf, int replybuflen)

{

if (::wifi_command(cmd, replybuf, &reply_len) != 0)

return -1;

…………

}

-------HAL------------------------------------------------------------------------------------------------------------------------------------------------------------------------

wifi.c:

int wifi_command(const char *command, char *reply, size_t *reply_len)

{

return wifi_send_command(ctrl_conn, command, reply, reply_len);

}

int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len)

{

ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);

…………

}

wpa_ctrl.c:

int wpa_ctrl_request()在wpa_ctrl.c中其实就是执行SCAN命令。

二、显示扫描的AP

当扫描成后,WifiMonitor 中的MonitorThread 会被执行来出来这个事件:

void handleEvent(int event, String remainder) {

switch (event) {

case SCAN_RESULTS:

mWifiStateTracker.notifyScanResultsAvailable();

->sendEmptyMessage(EVENT_SCAN_RESULTS_AVAILABLE);

break;

}

WifiStateTracker.java

public void handleMessage(Message msg) {

switch (msg.what) {

case EVENT_SCAN_RESULTS_AVAILABLE:

if (ActivityManagerNative.isSystemReady()) {

mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

}

}

WifiLayer注册接收SCAN_RESULTS_AVAILABLE_ACTION这个Intent:

private BroadcastReceiver mReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))

{

handleScanResultsAvailable();

}

handleScanResultsAvailable();

-> list = mWifiManager.getScanResults();

-> mCallback.onAccessPointSetChanged(ap, true);

handleScanResultsAvailable()中首先会去拿到SCAN的结果(最终是往wpa_supplicant中发送SCAN_RESULT命令并读取返回值来实现的),对每一个扫描返回的AP,WifiLayer会回调WifiSetting的onAccessPointSetChanged函数,从而最终把该AP加到GUI显示列表中。

三、配置AP

当用户在 WifiSettings 界面上选择了一个AP 后,会显示配置AP 参数的一个对话框:

public boolean onPreferenceTreeClick()

->showAccessPointDialog(state, AccessPointDialog.MODE_INFO);

->AccessPointDialog dialog =

new AccessPointDialog(this, mWifiLayer);

showDialog(dialog);

当用户在AccessPointDialog中选择好加密方式和输入密钥之后,再点击连接按钮,Android就会去连接这个AP。

四、连接AP

在AccessPointDialog.java中点击连接后会执行:

public void onClick(DialogInterface dialog, int which) {

handleConnect();

-> mWifiLayer.connectToNetwork(mState);

-> // Need WifiConfiguration for the AP

WifiConfiguration config = findConfiguredNetwork(state);

config = addConfiguration(state, 0);

managerEnableNetwork(state, false)

->mWifiManager.enableNetwork()

->mService.enalbeNetwork()

->WifiNative.enableNetworkCommand()

接下去就JNI { "enableNetworkCommand", "(IZ)Z", (void*)android_net_wifi_enableNetworkCommand},最终就是向wpa_supplicant发送连接命令

五、获取IP地址

当wpa_supplicant成功连接上AP之后,它会向控制通道发送事件通知连接上AP了,从而wifi_wait_for_event函数会接收到该事件,由此WifiMonitor中的MonitorThread会被执行来出来这个事件:

void handleEvent(int event, String remainder) {

switch (event) {

case CONNECTED:

handleNetworkStateChange();

-> mWifiStateTracker.notifyStateChange(newState, BSSID, networkId);

->msg.sendToTarget();

break;

}

WifiStateTracker.java

public void handleMessage(Message msg) {

switch (msg.what) {

case EVENT_NETWORK_STATE_CHANGED:

sendNetworkStateChangeBroadcast(mWifiInfo.getBSSID());

}

}

WifiStateTracker中注册的对Wifi相关数据库的观察者if(changed) 则启动:

private void configureInterface()

-> mDhcpTarget.sendEmptyMessage();

private class DhcpHandler extends Handler

handleMessage()

->switch (msg.what) {

case EVENT_DHCP_START:

Target.sendEmptyMessage(event);

DhcpHandler会发送EVENT_DHCP_START消息启动DHCP去获取IP地址,当DHCP拿到IP地址之后,会发送EVENT_INTERFACE_CONFIGURATION_SUCCEEDED的消息,然后WifiStateTacker中的handleMessage会处理这样的消息

case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:

sendNetworkStateChangeBroadcast(mWifiInfo.getBSSID());

-> Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);

-> mContext.sendStickyBroadcast(intent);

这次带上完整的IP地址信息。WifiLayer中注册了此Intent的接受者,会调用handleNetworkStateChanged进行处理。最后就可以自由的上网了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: