我们通常看到WiFi的守护进程wpa_supplicant在我们的ps的进程列表中,这个就是我们的wifi守护进程。wpa_supplicant在external/wpa_supplicant里实现
wpa_supplicant适配层是通用的wpa_supplicant的封装,在Android中作为WIFI部分的硬件抽象层来使用。wpa_supplicant适配层主要用于封装与wpa_supplicant守护进程的通信,以提供给Android框架使用。它实现了加载,控制和消息监控等功能。
wpa_supplicant适配层的头文件如下所示:
hardware/libhardware_legacy/include/hardware_legacy/wifi.h
我们看它的加载过程
Init会在系统启动首先加载init.rc这个文件会加载所有service,这是linux启动的第一个用户空间的应用(属于linux进程,不属于Android应用)。
Servicewpa_supplicant/system/bin/wpa_supplicant–Dwext–iwlan0–d–c/data/misc/wifi/wpa_supplicant.conf
#userwifi
#groupwifisystem
Socketwpa_eth0dgram0660wifisystem
Disabled
Oneshot
Serivedhcpcd/system/bin/dhcpcd–f/system/etc/dhcpcd/dhcpcd.conf–deth0
Onshot
Onproperty:init.svc.wpa_supplicant=stopped
Stopdhcpcd
添加/system/etc/wifi/wpa_supplicant.conf
Update_config=1
Ctrl_interface=/data/system/wpa_supplicant//和IFACE_DIR对应
Eapol_verison=1
Ap_scan=1
Fast_reauth=1
通过linux内核模块/system/lib/modules/wlan.ko这个wifi模块定义在/hardware/libhardware_legacy/wifi/wifi.c
if(DBG)Log.v(TAG,"StartingWifiService.");
WifiStateTrackerwst=newWifiStateTracker(context,mHandler);
WifiServicewifiService=newWifiService(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=newWifiEnabler(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());来发送一则消息
Messagemsg=Message.obtain(mWifiHandler,
(enableMESSAGE_ENABLE_WIFI:MESSAGE_DISABLE_WIFI),
(persist1: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=newIntent(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有一句话elseif(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启动JNIandroid_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接收到caseEVENT_SCAN_RESULTS_AVAILABLE:之后发送广播mContext.sendBroadcast(newIntent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
WiFiLayer接收到这个消息在mReceiver=newBroadcastReceiver()中处理handleScanResultsAvailable();
WiFi连接流程
用户在AccessPointDialog中输入密码之后点击连接按钮,Android调用顺序如下:
要的步骤是WifiStateTracker通过对DHCP服务器的申请进行了IP地址分配。最终会广播NETWORK_STATE_CHANGED_ACTION消息,由WifiLayer响应。
IP地址分配
由上面继续说IP地址分配,因为当wpa_supplicant链接AP成功之后,它会发出事件从而wifi_for_event函数会接收到该事件,由WifiMonitor中的MonitorThread执行执行这个事件handleEvent->caseCONNECTED:handleNetworkStateChange->mWifiStateTracker.notifyStateChange->EVENT_NETWORK_STATE_CHANGED->handleMessage下的:caseEVENT_SUPPLICANT_STATE_CHANGED:->intent=newIntent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);Wi-Fisupplicantstatechanged:
èSettingsObserver专门是观察该类变化的
if(changed){
resetInterface(true);
configureInterface();
if(mUseStaticIp){
mTarget.sendEmptyMessage(EVENT_CONFIGURATION_CHANGED);
}
è
mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
->
DhcpHandler的handleMessage函数caseEVENT_DHCP_START:NetworkUtils.runDhcp获取DHCP的IP地址,成功之后发送EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
event通过WifiStateTracker的HandleMessage函数caseEVENT_INTERFACE_CONFIGURATION_SUCCEEDED:会调用sendNetworkStateChangeBroadcastIntentintent=newIntent(WifiManager.NETWORK_STATE_CHANGED_ACTION);发送全局IntentAction完成网络切换。
-------------------------------------------------------------------WIFI启动代码流程走读
---------------------------------------------------------------------------------android网络连接管理
###C++代码走读意见与开发注意事项####内存管理与安全性在软件开发过程中,尤其是使用C++这类提供底层内存操作的语言时,代码质量和安全性尤为重要。本篇将基于给定的“C++代码走读意见--开发注意事项”文件中...
代码走读记录表模板代码走读记录表模板代码走读记录表模板
DPDKL2fwd代码走读报告(代码流程分析)DPDK(DataPlaneDevelopmentKit)是一种高性能的网络数据包处理平台,能够在通用x86服务器上实现高速网络数据包转发。该平台通过使用hugepage、uio、zerocopy、cpu...
代码走读记录,又称代码审查记录,包含C++代码走读,JAVA代码走读,C#代码走读
在软件开发过程中,代码走读是一项重要的质量保证活动,它能帮助团队成员理解代码逻辑,发现潜在的问题,以及确保代码遵循既定的设计原则和最佳实践。以下是对代码走读检查列表的一些关键点的详细说明:1.**设计...
Android平台中的广播机制是一种非常重要的组件间通信方式,它能够实现跨应用的数据共享与事件通知功能。本文将深入解析广播分发的过程,从源码层面逐步拆解广播的传递路径。####二、广播分发流程广播分发大致...
代码走读是软件开发中的一种重要技术,旨在通过检查代码是否符合编程规范、寻找编译器中的设计陷阱、快速理解源代码、对原有代码的重构等步骤,提高代码的质量和可维护性。代码走读可以分为四个层次:检查是否符合...
【单元测试PCLint代码走读重点】是一个关于软件质量保证和缺陷预防的主题,主要讨论如何在软件开发过程中,通过代码审查和单元测试工具PCLint来发现并消除潜在的编程错误。潜在缺陷是指那些在常规测试过程中难以察觉...
###SPEEDX代码走读笔记知识点解析####LMS算法详解在文本中提到了LMS(LeastMeanSquares)算法的基本公式与参数调整方法。LMS算法是一种用于自适应滤波器的设计方法,主要用于噪声抑制、回声消除等场景。-...
本文档是关于Storm源码的详细走读笔记,主要分析了Storm的启动场景、Topology提交过程、worker进程中的线程使用情况、消息传递机制以及TridentTopology的创建和ack机制等多个方面。首先,文档提到了Storm集群中的...
本资料包聚焦于FFmpeg的开发学习,特别是通过一系列的代码走读报告来深入理解其内部工作原理。首先,我们可以看到一系列的教程源码文件,如`tutorial01.c`到`tutorial08.c`。这些文件很可能是逐步介绍FFmpegAPI...
ffmpeg播放m3u8网络视频文件的流程,详细描述了整个播放过程的代码流程。
1.创建SparkContext实例:用户在SparkShell中输入的代码会首先创建SparkContext,这个实例是与集群进行交互的入口点,负责提交作业和获取资源。2.创建RDD(弹性分布式数据集):通过SparkContext实例,用户可以...
本文将通过代码走读和注释的方式,详细解读Activity的启动流程,帮助开发者更清晰地理解这一难点。首先,当一个Activity想要启动另一个Activity时,会调用startActivity方法。这个方法会触发一系列事件,最终导致...
###ApacheSpark源码走读:如何进行代码跟读####概述本文旨在探讨如何有效地进行ApacheSpark源码的阅读与理解。ApacheSpark作为一款高性能的分布式计算框架,在大数据处理领域占据着重要地位。其核心由Scala...
单元测试是软件开发过程中的重要环节,它主要目的是确保代码的正确性和稳定性。代码走读是一种审查技术,通过检查代码的各个部分来发现潜在的问题。以下是对这些测试项的详细解释:1.**J1下标变量越界**:确保...
代码走读,也称为代码审查,是软件开发过程中的一个重要环节,它有助于发现潜在的错误、提高代码质量、促进团队间的知识共享以及确保代码符合既定的设计规范和标准。以下是一份详细的代码走读检查列表,它涵盖了从...