- 浏览: 535498 次
-
文章分类
最新评论
android wifi模块分析
声明:本文纯属网上资料收集,版权归源作者所有,转载时请标明为转载文章
现在对android平台的wifi模块了解了一段时间,现在做一些简要总结,以便以后查阅和与修正,上正文。
【Wifi模块学习流程】
最近研究Wifi模块,查了不少的相关资料,但发现基本上是基于android2.0版本的的分析,而现在研发的android移动平台基本上都是2.3的版本,跟2.0版本的差别,在Wifi模块上也是显而易见的。2.3版本Wifi模块没有了WifiLayer,之前的WifiLayer主要负责一些复杂的Wifi功能,如AP选择等以提供给用户自定义,而新的版本里面的这块内容基本上被WifiSettings所代替
本文就是基于android2.3版本的Wifi分析,主要分为两部分来分别说明:
(a) Wifi的启动流程(有代码供参考分析)
(b) Wifi模块相关文件的解析
(c) Wpa_supplicant解析
【A】wifi的基本运行流程(针对代码而言)
首先给一张我网上down下来的图,针对2.3版本之前的,由于不怎么擅长画这些,大家也就将就点,只要能助理解就可以了
(一)初始化
a.流程
1.在SystemServer启动的时候会生成一个ConnectivityService的实例
2.ConnectivityService的构造函数会创建WifiService
3.WifiStateTracker会创建WifiMonitor接受来自底层的事件,WifiService和WifiMonitor是整个wifi模块的核心,WifiService负责启动和关闭wpa_supplicant,启动和关闭WifiMonitor监视线程和把命令下方给wpa_supplicant,而WifiMonitor则负责从wpa_supplicant接受事件通知
b.代码分析
要想使用Wifi模块,必须首先使能Wifi,当你第一次按下Wifi使能按钮时,WirelessSettings会实例化一个WifiEnabler对象,实例化代码如下:
packages/apps/settings/src/com/android/settings/WirelessSettings.java
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); …… CheckBoxPreferencewifi = (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI); mWifiEnabler= new WifiEnabler(this, wifi); …… }WifiEnabler类的定义大致如下,它实现了一个监听接口,当WifiEnabler对象被初始化后,它监听到你按键的动作,会调用响应函数 onPreferenceChange(),这个函数会调用WifiManager的setWifiEnabled()函数。
public class WifiEnabler implementsPreference.OnPreferenceChangeListener { …… public boolean onPreferenceChange(Preference preference,Object value) { booleanenable = (Boolean) value; …… if (mWifiManager.setWifiEnabled(enable)) { mCheckBox.setEnabled(false); …… } …… }我们都知道Wifimanager只是个服务代理,所以它会调用WifiService的setWifiEnabled()函数,而这个函数会调用 sendEnableMessage()函数,了解android消息处理机制的都知道,这个函数最终会给自己发送一个 MESSAGE_ENABLE_WIFI的消息,被WifiService里面定义的handlermessage()函数处理,会调用 setWifiEnabledBlocking()函数。下面是调用流程:
mWifiEnabler.onpreferencechange()===>mWifiManage.setWifienabled()===>mWifiService.setWifiEnabled()===>mWifiService.sendEnableMessage()
===>mWifiService.handleMessage()===>mWifiService.setWifiEnabledBlocking().
在setWifiEnabledBlocking()函数中主要做如下工作:加载Wifi驱动,启动wpa_supplicant,注册广播接收器,启动WifiThread监听线程。代码如下:…… if (enable) { if (!mWifiStateTracker.loadDriver()) { Slog.e(TAG, "Failed toload Wi-Fi driver."); setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; } if (!mWifiStateTracker.startSupplicant()) { mWifiStateTracker.unloadDriver(); Slog.e(TAG, "Failed tostart supplicant daemon."); setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; } registerForBroadcasts(); mWifiStateTracker.startEventLoop(); ……至此,Wifi使能(开启)结束,自动进入扫描阶段。
(二)扫描AP
当驱动加载成功后,如果配置文件的AP_SCAN = 1,扫描会自动开始,WifiMonitor将会从supplicant收到一个消息EVENT_DRIVER_STATE_CHANGED,调用 handleDriverEvent(),然后调用mWifiStateTracker.notifyDriverStarted(),该函数向消息队列添加EVENT_DRIVER_STATE_CHANGED,handlermessage()函数处理消息时调用scan()函数,并通过 WifiNative将扫描命令发送到wpa_supplicant。
看代码Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java
private void handleDriverEvent(Stringstate) { if (state == null) { return; } if (state.equals("STOPPED")) { mWifiStateTracker.notifyDriverStopped(); } else if (state.equals("STARTED")) { mWifiStateTracker.notifyDriverStarted(); } else if (state.equals("HANGED")) { mWifiStateTracker.notifyDriverHung(); } }Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
... case EVENT_DRIVER_STATE_CHANGED: switch(msg.arg1) { case DRIVER_STARTED: /** *Set the number of allowed radio channels according *to the system setting, since it gets reset by the *driver upon changing to the STARTED state. */ setNumAllowedChannels(); synchronized (this) { if (mRunState == RUN_STATE_STARTING) { mRunState = RUN_STATE_RUNNING; if (!mIsScanOnly) { reconnectCommand(); } else { // In somesituations, supplicant needs to be kickstarted to // start thebackground scanning scan(true); } } } break; ...上面是启动Wifi时,自动进行的AP的扫描,用户当然也可以手动扫描AP,这部分实现在WifiService里面,WifiService通过startScan()接口函数发送扫描命令到supplicant。
看代码:Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
public boolean startScan(booleanforceActive) { enforceChangePermission(); switch (mWifiStateTracker.getSupplicantState()) { case DISCONNECTED: case INACTIVE: case SCANNING: case DORMANT: break; default: mWifiStateTracker.setScanResultHandling( WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY); break; } return mWifiStateTracker.scan(forceActive); }然后下面的流程同上面的自动扫描,我们来分析一下手动扫描从哪里开始的。我们应该知道手动扫描是通过菜单键的扫描键来响应的,而响应该动作的应该是 WifiSettings类中Scanner类的handlerMessage()函数,它调用WifiManager的 startScanActive(),这才调用WifiService的startScan()。
如代码:packages/apps/Settings/src/com/android/settings/wifiwifisettings.java
public boolean onCreateOptionsMenu(Menu menu) { menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan) .setIcon(R.drawable.ic_menu_scan_network); menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced) .setIcon(android.R.drawable.ic_menu_manage); return super.onCreateOptionsMenu(menu); }当按下菜单键时,WifiSettings就会调用这个函数绘制菜单。如果选择扫描按钮,WifiSettings会调用onOptionsItemSelected()。
packages/apps/Settings/src/com/android/settings/wifiwifisettings.java
public booleanonOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_ID_SCAN: if(mWifiManager.isWifiEnabled()) { mScanner.resume(); } return true; case MENU_ID_ADVANCED: startActivity(new Intent(this,AdvancedSettings.class)); return true; } return super.onOptionsItemSelected(item); }Handler类:
private class Scanner extends Handler { private int mRetry = 0; void resume() { if (!hasMessages(0)) { sendEmptyMessage(0); } } void pause() { mRetry = 0; mAccessPoints.setProgress(false); removeMessages(0); } @Override public void handleMessage(Message message) { if (mWifiManager.startScanActive()){ mRetry = 0; } else if (++mRetry >= 3) { mRetry = 0; Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show(); return; } mAccessPoints.setProgress(mRetry != 0); sendEmptyMessageDelayed(0, 6000); } }这里的mWifiManager.startScanActive()就会调用WifiService里的startScan()函数,下面的流程和上面的一样,这里不赘述。
当supplicant完成了这个扫描命令后,它会发送一个消息给上层,提醒他们扫描已经完成,WifiMonitor会接收到这消息,然后再发送给WifiStateTracker。
Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java
void handleEvent(int event, String remainder) { switch (event) { caseDISCONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder); break; case CONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder); break; case SCAN_RESULTS: mWifiStateTracker.notifyScanResultsAvailable(); break; case UNKNOWN: break; } }WifiStateTracker将会广播SCAN_RESULTS_AVAILABLE_ACTION消息:
代码如:Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
public voidhandleMessage(Message msg) { Intent intent; …… case EVENT_SCAN_RESULTS_AVAILABLE: if(ActivityManagerNative.isSystemReady()) { mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); } sendScanResultsAvailable(); /** * On receiving the first scanresults after connecting to * the supplicant, switch scanmode over to passive. */ setScanMode(false); break; …… }由于WifiSettings类注册了intent,能够处理SCAN_RESULTS_AVAILABLE_ACTION消息,它会调用handleEvent(),调用流程如下所示。
WifiSettings.handleEvent()
====>WifiSettings.updateAccessPoints() ====> mWifiManager.getScanResults()====> mService.getScanResults()====>
mWifiStateTracker.scanResults() ====> WifiNative.scanResultsCommand()……
将获取AP列表的命令发送到supplicant,然后supplicant通过Socket发送扫描结果,由上层接收并显示。这和前面的消息获取流程基本相同。
(3)配置,连接AP
当用户选择一个活跃的AP时,WifiSettings响应打开一个对话框来配置AP,比如加密方法和连接AP的验证模式。配置好AP后,WifiService添加或更新网络连接到特定的AP。
代码如:packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java
public booleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference) { if (preference instanceof AccessPoint) { mSelected = (AccessPoint) preference; showDialog(mSelected, false); } else if (preference == mAddNetwork) { mSelected = null; showDialog(null, true); } else if (preference == mNotifyOpenNetworks) { Secure.putInt(getContentResolver(), Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, mNotifyOpenNetworks.isChecked() ? 1 : 0); } else { return super.onPreferenceTreeClick(screen, preference); } return true; }配置好以后,当按下“Connect Press”时,WifiSettings通过发送LIST_NETWORK命令到supplicant来检查该网络是否配置。如果没有该网络或没有配置它,WifiService调用addorUpdateNetwork()函数来添加或更新网络,然后发送命令给supplicant,连接到这个网络。下面是从响应连接按钮到WifiService发送连接命令的代码:
packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java
public void onClick(DialogInterfacedialogInterface, int button) { if (button == WifiDialog.BUTTON_FORGET && mSelected != null) { forget(mSelected.networkId); } else if (button == WifiDialog.BUTTON_SUBMIT && mDialog !=null) { WifiConfiguration config = mDialog.getConfig(); if (config == null) { if (mSelected != null&& !requireKeyStore(mSelected.getConfig())) { connect(mSelected.networkId); } } else if (config.networkId != -1) { if (mSelected != null) { mWifiManager.updateNetwork(config); saveNetworks(); } } else { int networkId =mWifiManager.addNetwork(config); if (networkId != -1) { mWifiManager.enableNetwork(networkId, false); config.networkId =networkId; if (mDialog.edit || requireKeyStore(config)){ saveNetworks(); } else { connect(networkId); } } } } }Frameworks\base\wifi\java\android\net\wifi\WifiManager.java
public intupdateNetwork(WifiConfiguration config) { if(config == null || config.networkId < 0) { return -1; } return addOrUpdateNetwork(config); } private intaddOrUpdateNetwork(WifiConfiguration config) { try { return mService.addOrUpdateNetwork(config); } catch (RemoteException e) { return -1; } }WifiService.addOrUpdateNetwork()通过调用mWifiStateTracker.setNetworkVariable()将连接命令发送到Wpa_supplicant。
(4)获取IP地址
当连接到supplicant后,WifiMonitor就会通知WifiStateTracker。
代码如:Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java
Public void Run(){ if (connectToSupplicant()) { // Send a message indicatingthat it is now possible to send commands // to the supplicant mWifiStateTracker.notifySupplicantConnection(); } else { mWifiStateTracker.notifySupplicantLost(); return; } …… }WifiStateTracker发送EVENT_SUPPLICANT_CONNECTION消息到消息队列,这个消息有自己的handlermessage()函数处理,它会启动一个DHCP线程,而这个线程会一直等待一个消息事件,来启动DHCP协议分配IP地址。
frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
void notifySupplicantConnection() { sendEmptyMessage(EVENT_SUPPLICANT_CONNECTION); } public void handleMessage(Message msg) { Intent intent; switch (msg.what) { case EVENT_SUPPLICANT_CONNECTION: …… HandlerThread dhcpThread = newHandlerThread("DHCP Handler Thread"); dhcpThread.start(); mDhcpTarget = newDhcpHandler(dhcpThread.getLooper(), this); …… ……case EVENT_NETWORK_STATE_CHANGED: …… configureInterface(); ……
}}private void configureInterface() { checkPollTimer(); mLastSignalLevel = -1; if(!mUseStaticIp) { //使用DHCP线程动态IP if(!mHaveIpAddress && !mObtainingIpAddress) { mObtainingIpAddress = true; //发送启动DHCP线程获取IP mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START); } } else { //使用静态IP,IP信息从mDhcpInfo中获取 intevent; if(NetworkUtils.configureInterface(mInterfaceName, mDhcpInfo)) { mHaveIpAddress = true; event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED; if (LOCAL_LOGD) Log.v(TAG, "Static IP configurationsucceeded"); }else { mHaveIpAddress = false; event = EVENT_INTERFACE_CONFIGURATION_FAILED; if (LOCAL_LOGD) Log.v(TAG, "Static IP configuration failed"); } sendEmptyMessage(event); //发送IP获得成功消息事件 } }
当Wpa_supplicant连接到AP后,它会发送一个消息给上层来通知连接成功,WifiMonitor会接受到这个消息并上报给WifiStateTracker。Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java
void handleEvent(int event, String remainder) { switch (event) { case DISCONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder); break; case CONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder); break; …… } private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) { StringBSSID = null; intnetworkId = -1; if(newState == NetworkInfo.DetailedState.CONNECTED) { Matcher match = mConnectedEventPattern.matcher(data); if(!match.find()) { if (Config.LOGD) Log.d(TAG, "Could not find BSSID in CONNECTEDevent string"); }else { BSSID = match.group(1); try { networkId = Integer.parseInt(match.group(2)); } catch (NumberFormatException e) { networkId = -1; } } } mWifiStateTracker.notifyStateChange(newState,BSSID, networkId); } void notifyStateChange(DetailedState newState, StringBSSID, int networkId) { Messagemsg = Message.obtain( this, EVENT_NETWORK_STATE_CHANGED, newNetworkStateChangeResult(newState, BSSID, networkId)); msg.sendToTarget(); }DhcpThread获取EVENT_DHCP_START消息事件后,调用handleMessage()函数,启动DHCP获取IP地址的服务。frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
public void handleMessage(Message msg) { intevent; switch (msg.what) { case EVENT_DHCP_START: …… Log.d(TAG, "DhcpHandler: DHCP requeststarted"); //启动一个DHCPclient的精灵进程,为mInterfaceName请求分配一个IP地//址 if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) { event= EVENT_INTERFACE_CONFIGURATION_SUCCEEDED; if(LOCAL_LOGD) Log.v(TAG, "DhcpHandler: DHCP request succeeded"); } else { event= EVENT_INTERFACE_CONFIGURATION_FAILED; Log.i(TAG,"DhcpHandler: DHCP request failed: " + NetworkUtils.getDhcpError()); } …… } }这里调用了一个NetworkUtils.runDhcp()函数,NetworkUtils类是一个网络服务的辅助类,它主要定义了一些本地接口,这些接口会通过他们的JNI层android_net_NetUtils.cpp文件和DHCP client通信,并获取IP地址。至此,IP地址获取完毕,Wifi启动流程结束。
待续(b) Wifi模块相关文件的解析
(c) Wpa_supplicant解析
相关推荐
对Android 下的WIFI 模块进行了分析和测试
以下是对Android WIFI模块的深入分析: **WIFI模块框图** WIFI模块通常包括以下几个层次:应用程序层、框架层、JNI(Java Native Interface)层、硬件抽象层和内核驱动层。在框图中,我们可以看到WirelessSettings...
本文将深入探讨Android Wi-Fi源码分析,特别是如何连接到一个接入点(Access Point,简称AP)的过程。 首先,当用户在AcessPointDialog中选择加密方式并点击连接按钮后,Android系统会执行连接操作。关键代码在于`...
Android WIFI模块分析 Wifi 模块框图 Wifi核心模块 Wifi工作步骤 Wifi模块代码总结
Android WIFI 模块分析 Android WIFI 模块分析是 Android 操作系统中负责 WIFI 连接的模块。该模块主要由 WifiService、WifiMonitor、Wpa_supplicant、Wifi 驱动模块、Wifi 电源管理模块等组件组成。 Wifi 模块...
在Android平台上,与WIFI模块进行数据传输是一个常见的任务,特别是在物联网(IoT)设备的交互中。本项目中,开发者被要求创建一个Android应用程序,用于配置HLK-RM04 WIFI模块,进行数据读取、参数设置以及系统时间...
在Android平台上,WIFI模块测试是一项关键任务,涉及到多个方面,确保设备能够稳定、高效地接入无线网络。下面将详细阐述Android WIFI模块测试涉及的知识点。 首先,WIFI是一种无线连接技术,基于IEEE802.11标准,...
在这个特定的主题中,我们聚焦于Android Studio中的WiFi模块,包括如何连接到WiFi网络以及如何进行WiFi热点搜索。这些功能涉及到Android系统的网络权限管理,这对于构建具有网络功能的应用至关重要。 1. **WiFi连接...
《深入理解Android:WiFi模块 NFC和GPS卷》是由邓凡平编著的一本技术书籍,主要探讨了Android系统中三个重要的无线通信技术:WiFi、NFC(近场通信)和GPS(全球定位系统)。这本书以文字版的形式,深入浅出地讲解了...
Android Q WIFI 模块移植指南 随着 Android 系统的不断发展和更新,WIFI 模块的移植成为 Android 设备开发中一个非常重要的步骤。T507 Android Q WIFI 模块移植说明文档提供了将 WIFI 模块移植到 Android Q 系统上...
Android WIFI 应用层框架分析是从应用程序的角度描述 Android WIFI 的工作流程,主要介绍了各个控制接收模块的数据走向,具体数据传输流程和所调用到的方法介绍。本文将从 WIFI 初始化、WIFI 启动、开始扫描 AP、...
Android 11 WiFi 模块 WiFi 打开函数调用流程图 Android 11 中的 WiFi 模块是如何打开的?下面是 WiFi 打开函数调用流程图的详细解释。 首先,用户打开 WiFi 时,系统会调用 WifiServiceImpl.java 中的 ...
在Android系统中,WiFi模块是实现无线网络连接的关键部分,对于开发者来说,理解和掌握如何进行Android WiFi开发至关重要。本文将深入探讨Android WiFi的模块程序、初始化过程、连接AP的步骤,以及WiFi SLAM...
首先,Android Wi-Fi模块的核心代码主要位于Android源码树的`frameworks/base/services/core/java/com/android/server/wifi`目录下。这部分代码包含了Wi-Fi服务(WifiService)的实现,它是系统服务,负责管理Wi-Fi...
其中,WiFi模块负责WiFi连接和数据传输,WiFi Display模块负责WiFi Display功能的控制和数据传输,而显示模块负责显示 WiFi Display的内容。 二、代码分析 WiFi Display功能的代码分析可以参考博客...
在Android 8.0平台上实现双Wi-Fi模块的STA(Station)+AP(Access Point)模式,是一项技术挑战,涉及到Android系统的网络堆栈、Wi-Fi驱动以及框架层的深度定制。这种模式允许设备同时作为Wi-Fi客户端连接到一个网络...
在Android环境下进行WiFi模块编程,主要是利用Android系统提供的API来操控设备的WiFi功能,包括开启/关闭WiFi,扫描可用的WiFi网络,连接指定的网络,以及处理WiFi状态变化等。以下将详细介绍相关知识点: 1. **...
总结来说,本资料“深入理解Android WiFi模块 NFC和GPS卷”将涵盖这些关键领域的基本概念、API使用、以及实践应用案例,是初学者学习Android开发中不可或缺的一部分。通过阅读这份文档,你将能够建立起对这些技术的...