`

android系统学习八

阅读更多

Android的联接部分

 

 

Wifi部分

Wifi的基本架构

自上而下包括的一些内容:

Linux内核的标准wifi驱动程序和协议

Wap_supplicant可执行程序(WAP应用层认证客户端)

WifiHAL

WIFIJNI接口

Wifijava框架

Wifi的相关应用

 

Wifi的结构图如下:

 

 

 

 

 

Wifi的本地实现(主要包括wap_supplicantwap_supplicant适配层)

WAPwifiprotectedAccess

 

Wap_supplicantWAP应用层认证客户端,负责认证完成相关的登陆和加密工作,他是一个开源的

代码路径为:\external\wpa_supplicant文件名为:wpq_ctrl.c

部分代码如下:

 

 

最终生成动态库libwap_client.so

Wap_supplicant是一个独立的守护进程,其通信是通过socket协议定完成

 

Wap_supplicantwext驱动接口的联系

driver.h头文件中,部分代码如下:

//该结构体是扫描结果的通用格式

structwpa_scan_result{

u8bssid[ETH_ALEN];

u8ssid[32];

size_tssid_len;

u8wpa_ie[SSID_MAX_WPA_IE_LEN];

size_twpa_ie_len;

u8rsn_ie[SSID_MAX_WPA_IE_LEN];

size_trsn_ie_len;

intfreq;

u16caps;

intqual;

intnoise;

intlevel;

intmaxrate;

};

 

 

//操作函数集合,所有驱动类型的一个接口封装包

structwpa_driver_ops{

constchar*name;

constchar*desc;

int(*get_bssid)(void*priv,u8*bssid);

 

}

Driver_wext.h:声明了该驱动的一些对应驱动API接口的函数

Driver_wext.c:最后初始化了一个wpa_drv_pos变量

Drivers.c文件:主要定义了不同驱动操作接口的集合

Driver_xxx.h:是不同驱动接口头文件声明了操作接口

Driver_xxx.c:实现操作接口

 

Wpq_supplicant守护进程是为不同驱动和操作系统具有更好的移植性而设计的,以便在wpa_supplicant层不用实现驱动的具体接口就可以添加新的驱动程序

 

Wpa_supplicant_xxx函数传递wpa_supplicant实例指针wpa_s参数给wpa_drv_xxx来调用他,

Wpa_drv_xx会通过wpa_s->driver->xxx()来调用通用驱动接口

Wpa_ctrl.h:声明了几个用于socket通信的函数接口

Wpq_ctrl.c:定义了一个wpa_ctrl结构

//根据UDPUNIX和命名管道三种domain类型来定义通信实体

structwpa_ctrl*wpa_ctrl_open(constchar*ctrl_path)

{

structwpa_ctrl*ctrl;

staticintcounter=0;

 

ctrl=os_malloc(sizeof(*ctrl));

if(ctrl==NULL)

returnNULL;

os_memset(ctrl,0,sizeof(*ctrl));

 

ctrl->s=socket(PF_UNIX,SOCK_DGRAM,0);

if(ctrl->s<0){

os_free(ctrl);

returnNULL;

}

 

ctrl->local.sun_family=AF_UNIX;

os_snprintf(ctrl->local.sun_path,sizeof(ctrl->local.sun_path),

#ifdefANDROID

"%s/%s%d-%d",local_socket_dir,local_socket_prefix,

getpid(),counter++);

#else/*ANDROID*/

"/tmp/wpa_ctrl_%d-%d",getpid(),counter++);

#endif

if(bind(ctrl->s,(structsockaddr*)&ctrl->local,

sizeof(ctrl->local))<0){

close(ctrl->s);

os_free(ctrl);

returnNULL;

}

 

 

Wpa_supplicant.h:

部分代码如下:

//wpa的事件类型

typedefenumwpa_event_type{}

Wpa_supplicant_i.h:

Wpq_suppliant.c文件中定义的很多函数是在该头文件中声明的,而不是在wpa_supplicant.h

 

Wap_supplicant的结构如下:

 

 

 

 

Wpa-_supplicant适配层

android中作为wifi部分的硬件抽像层来使用,主要用于封装与wpa_supplicant守护进程的通信(加载、控制、消息监控)

 

Wpa_supplicant适配层的头文件路径为:

\hardware\libhardware_legacy\include\hardware_legacy\wifi.h

头文件中定义了以下几个重要的方法:

//事件的进入通道,这个函数被阻塞,直到收到一个wifi事件,并以字符串的形式返回

intwifi_wait_for_event(char*buf,size_tlen);

//将命令发送到wifi系统下层的功能,

intwifi_command(constchar*command,char*reply,size_t*reply_len);

实现文件路径为:\hardware\libhardware_legacy\wifi

在实现文件中

//

intwifi_wait_for_event(char*buf,size_tbuflen)

{

size_tnread=buflen-1;

intfd;

fd_setrfds;

intresult;

structtimevaltval;

structtimeval*tptr;

 

if(monitor_conn==NULL){

LOGD("Connectionclosed\n");

strncpy(buf,WPA_EVENT_TERMINATING"-connectionclosed",buflen-1);

buf[buflen-1]='\0';

returnstrlen(buf);

}

//调用此方法来接收一次wpa_supplication

result=wpa_ctrl_recv(monitor_conn,buf,&nread);

if(result<0){

LOGD("wpa_ctrl_recvfailed:%s\n",strerror(errno));

strncpy(buf,WPA_EVENT_TERMINATING"-recverror",buflen-1);

buf[buflen-1]='\0';

returnstrlen(buf);

}

buf[nread]='\0';

/*LOGD("wait_for_event:result=%dnread=%dstring=\"%s\"\n",result,nread,buf);*/

/*CheckforEOFonthesocket*/

if(result==0&&nread==0){

/*Fabricateaneventtopassup*/

LOGD("ReceivedEOFonsupplicantsocket\n");

strncpy(buf,WPA_EVENT_TERMINATING"-signal0received",buflen-1);

buf[buflen-1]='\0';

returnstrlen(buf);

}

/*

*Eventsstringsareintheformat

*

*<N>CTRL-EVENT-XXX

*

*whereNisthemessagelevelinnumericalform(0=VERBOSE,1=DEBUG,

*etc.)andXXXistheeventname.Thelevelinformationisnotuseful

*tous,sostripitoff.

*/

if(buf[0]=='<'){

char*match=strchr(buf,'>');

if(match!=NULL){

nread-=(match+1-buf);

memmove(buf,match+1,nread+1);

}

}

returnnread;

}

 

 

//wifi_commandwifi_send_command的封装

intwifi_send_command(structwpa_ctrl*ctrl,constchar*cmd,char*reply,size_t*reply_len)

{

intret;

 

if(ctrl_conn==NULL){

LOGV("Notconnectedtowpa_supplicant-\"%s\"commanddropped.\n",cmd);

return-1;

}

//通过此方法发送命令给wpa_supplicant

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

if(ret==-2){

LOGD("'%s'commandtimedout.\n",cmd);

return-2;

}elseif(ret<0||strncmp(reply,"FAIL",4)==0){

return-1;

}

if(strncmp(cmd,"PING",4)==0){

reply[*reply_len]='\0';

}

return0;

}

 

WIFI的适配层是libhardware_legacy.so的一部分

 

 

Wifijava部分jni部分

JNI部分的源程代码路径为下:

\frameworks\base\core\jni\android_net_wifi_wifi.cpp

在这里实现的本地函数,都是通过调用wpa_supplicant适配层的接口实现的

 

 

 

 

Java部分实现代码路径为:

\frameworks\base\services\java\com\android\server//wifi服务层的内容
\frameworks\base\wifi\java\android\net\wifi//wifi服务的接口

 

 

 

 

 

 

 

 

 

由上图可以看出:wifiNative.java类提供wifiService类、wifiStateTracker类和wifiMonitor类的底层操作支持

Wifi系统的核心部分是根据IWifiManager接口所创建的Binder服务器端(wifiService)和客户端(wifiManager)

 

IWifiManager.aidl编译后生成IWifiManager.java。并生成IWifiManager.Stub(服务器端抽象类)IWifiManager.Stub.Proxy(客户端代理类)

wifiService通过继承IWifiManager.Stub实现,
客户端通过getService()取得IWifiManager.Stub.Proxy,将其作为参数传递给wifiManager

 

wifiManagerwifi部分与外界的接口wifiwatchDogService也是使用wifiManager来进行具体操作

wifiService是服务器端的实现,处理实际的驱动加载\、扫描,连接,断开

根据客户端的不同命令,调用相应的nativeWifi底层实现 当接收到客户端消息命令后,转换成对应的自身消息加入消息队列,方便客户端调用,在wifiHandlerhandlerMessage中来处理对应的消息

 

对于底层上报的事件,wifiService一般调用wifiStateTracker

 

wifiStateTracker负责电源控制,设置电源管理模式,其核心是wifiMonitor所实现的事件轮询机制(关键函数是wifiNative..waitForEvent阻塞式函数),该类也是与外部的接口,通过发送广播来完成消息的传递

 

wifiMontor的通知机制是将底层事件转换成wifistateTracker能识别的消息

 

 

wifiWatchDogServiceconnectivityService启动的服务,它的作用是监控同一网络内的接入点(AccessPoint),如果当前接入点的DNS无法ping通,就自动切入到下一个接入点

在初始化时,通过registerForWifiBroadcasts注册广播接收,捕获wifiStateTracker发出的通知,

开启一个wifiWatchdogThread线程来处理消息

 

 

 

Settings中的wifi设置

 

 

原代码的路径为:\packages\apps\Settings\src\com\android\settings\wifi

网络设置的实际功能还是调用wifiManager来实现的,同样注册一个广播接收者来接收wifistateTracker发出的消息

wifiEnable是用来设置wifi的开关

 

 

Wifi工作流程实例

例;一个AP的联接流程

1开启wifi

wifiEnable中调用wifiManagersetwifiEnagled(null,true);

wifimanager.setwifiEnable()通过Binder机制调用wifiService.setWifiEnabled

wifiService.setWifiService.setWifiEnabledMESSAGE_ENABLE_WIFI消息发送到自已的消息队列

wifiService通过wifHandlerhandleMessage处理MESSAGE_ENABLE_WIFI

调用setWifiEnableBlocking

setWifiEnableBlocking调用setWifiEnabledState,向外发送WIFI_STATE_CHANGED_ACTIONT通知消息

另外一些初始化工作

设置当前状态、加载wifi驱动、开启wpa_supplicant、开启wifiStateTracker、注册广播接收者接收wifiStateTracker的消息

 

wifiService.java的代码路径为:\frameworks\base\services\java\com\android\server

部分代码如下:

privatebooleansetWifiEnabledBlocking(booleanenable,booleanpersist,intuid){

finalinteventualWifiState=enable?WIFI_STATE_ENABLED:WIFI_STATE_DISABLED;

finalintwifiState=mWifiStateTracker.getWifiState();

 

if(wifiState==eventualWifiState){

returntrue;

}

if(enable&&isAirplaneModeOn()&&!mAirplaneModeOverwridden){

returnfalse;

}

 

/**

*MultiplecallstounregisterReceiver()causeexceptionandasystemcrash.

*Thiscanhappenifasupplicantislost(orfirmwarecrashoccurs)anduserindicates

*disablewifiatthesametime.

*AvoiddoingadisablewhenthecurrentWifistateisUNKNOWN

*TODO:Handledriverloadfailandsupplicantlostasseperatestates

*/

if((wifiState==WIFI_STATE_UNKNOWN)&&!enable){

returnfalse;

}

 

/**

*FailWifiifAPisenabled

*TODO:DeprecateWIFI_STATE_UNKNOWNandrenameit

*WIFI_STATE_FAILED

*/

if((mWifiApState==WIFI_AP_STATE_ENABLED)&&enable){

setWifiEnabledState(WIFI_STATE_UNKNOWN,uid);

returnfalse;

}

 

setWifiEnabledState(enable?WIFI_STATE_ENABLING:WIFI_STATE_DISABLING,uid);

 

if(enable){

//调用JNI,加载wifi驱动

if(!mWifiStateTracker.loadDriver()){

Slog.e(TAG,"FailedtoloadWi-Fidriver.");

setWifiEnabledState(WIFI_STATE_UNKNOWN,uid);

returnfalse;

}

//调用JNI层开启supplicant

if(!mWifiStateTracker.startSupplicant()){

mWifiStateTracker.unloadDriver();

Slog.e(TAG,"Failedtostartsupplicantdaemon.");

setWifiEnabledState(WIFI_STATE_UNKNOWN,uid);

returnfalse;

}

 

registerForBroadcasts();

mWifiStateTracker.startEventLoop();

 

}else{

 

mContext.unregisterReceiver(mReceiver);

//Removenotification(itwillno-opifitisn'tvisible)

mWifiStateTracker.setNotificationVisible(false,0,false,0);

 

booleanfailedToStopSupplicantOrUnloadDriver=false;

 

if(!mWifiStateTracker.stopSupplicant()){

Slog.e(TAG,"Failedtostopsupplicantdaemon.");

setWifiEnabledState(WIFI_STATE_UNKNOWN,uid);

failedToStopSupplicantOrUnloadDriver=true;

}

 

/**

*Resetconnectionsanddisableinterface

*beforeweunloadthedriver

*/

mWifiStateTracker.resetConnections(true);

 

if(!mWifiStateTracker.unloadDriver()){

Slog.e(TAG,"FailedtounloadWi-Fidriver.");

if(!failedToStopSupplicantOrUnloadDriver){

setWifiEnabledState(WIFI_STATE_UNKNOWN,uid);

failedToStopSupplicantOrUnloadDriver=true;

}

}

 

if(failedToStopSupplicantOrUnloadDriver){

returnfalse;

}

}

 

//Success!

 

if(persist){

persistWifiEnabled(enable);

}

setWifiEnabledState(eventualWifiState,uid);

returntrue;

}

 

2wifi开启完成后,接下就是搜索AP

启动supplient守护进程,启动MonitorThread开始监听supplient的事件。

 

****SettingwifiLayer.attemptScan()调用wifiManager.startScan();*****

wifi2.3之后就没有wifiLayer类了,取而代之的是wifiSettingwifiSetting中有一个扫描类,Scanner,用于扫搜索AP

wifimanager.startScan()通过Binder机制调用wifiService.starScan();

首先MonitorThread会收到DRIVER_STATE事件,wifiNative.scanCommand()supplient发送搜索AP的命令给wpa_supplicant,中间经过JNI实现的doCommand,最终调用wap_supplicant适配层的wifiCommand来完成发送过程

命令的最终响应由wpa_supplicant上报"SCAN-RESULT"消息,wifiStateTracker开启的wifiMonitormonitorThread可以获取此消息,

handlerEvent的处理方式是调用wifiStateTracker.notifyScanResultsAvailable;

发送广播:mContext.sendBroadcast(newIntent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

wifiSetting中会得到这个消息.作相关的处理操作

连接AP

supplient搜索AP结束时,monitorThread会收到SCAN_RESULTS

接下来会调用wifiNative.setScanResultHandlingCommand(normalMode)来让supplient自行去连接哪个AP,首先会去挑选信号强并没有密码的AP进行联接

wifiSettings会收到wifiManager.SCAN_RESULTE_AVAILABLE_ACTION广播

 

supplient联接到一个AP时,monitorThread会收到CONNECTED事件,配置IP地址,

如果配置成功会发送EVENT_STATE_CHANGED,ConnectivityService就会根据网络优先级决定关掉以太网,android为了省电会将之前的网络设为desable

mWifiManager.enableNetwork(networkId,false);

分享到:
评论

相关推荐

    安卓Android源码——安卓Android系统日历日程操作.rar

    总结,通过解析和学习"安卓Android源码——安卓Android系统日历日程操作.rar"中的CalendarDemo,我们可以了解到Android系统日历API的使用,包括添加、查询、更新和删除日历事件的方法,以及权限处理和数据操作的流程...

    基于Android平台的移动学习系统的设计与实现(源码+文档).zip

    Android内核基于Linux平台,有着较快的处理速度和较好的系统性能,使用平台无关的Java语言作为其开发语言,可移植性好,可以广泛支持智能手机、平板电脑等移动设备,是移动学习软件研究和开发的首选平台。...

    安卓Android商品销售管理系统毕业源码案例设计.zip

    Android 项目是使用 Android 操作系统和相关开发工具开发的一款移动应用程序。Android 平台提供了丰富的功能和接口,开发人员可以使用 Java 或 Kotlin 等编程语言编写 Android 应用程序。Android 项目也可以是针对...

    android系统学习

    Android系统源代码情景分析 [罗升阳著][电子工业出版社][2012.10][840页].pdf Android官方API文档完整版.chm ANDROID的设计与实现 卷1_13259533.pdf Android(卷2)(带全目录完整版)邓凡平.pdf Android源码设计模式...

    安卓Android源码——android相册系统(用Matrix实现).rar

    在安卓Android系统中,开发一个相册应用是常见的任务,涉及到图像处理、UI设计以及数据管理等多个方面。这个压缩包“安卓Android源码——android相册系统(用Matrix实现).rar”显然提供了一个使用Matrix类来实现相册...

    安卓Android精品课程在线学习系统app设计毕业源码案例设计

    安卓Android精品课程在线学习系统app设计 系统开发环境: Windows + Myclipse(服务器端) + Eclipse(手机客户端) + mysql数据库 服务器也可以用Eclipse或者idea等工具,客户端也可以采用android studio工具! 系统...

    毕业设计-基于安卓Android销售管理系统

    【毕业设计-基于安卓Android销售管理系统】是一款专为学习者和开发者设计的实践项目,它提供了全面的课程指导以及源代码,旨在帮助学生和新手掌握Android平台上的销售管理系统的开发技术。这个系统能够帮助企业或...

    Android系统学习文档

    Android系统学习文档

    安卓android开发学习文档API.CHM

    【安卓Android开发学习文档API.CHM】是一份针对Android应用开发者的重要参考资料,它包含了全面的Android SDK信息,帮助开发者深入理解和实践Android平台的开发工作。这份文档主要由两个CHM(Compiled HTML Help)...

    安卓Android源码——安卓Android学习——数据存储.rar

    本压缩包文件"安卓Android源码——安卓Android学习——数据存储.rar"显然是针对安卓数据存储机制的学习资料,其中可能包含了相关的源代码示例和讲解。下面我们将深入探讨安卓中的数据存储方法。 1. **Shared ...

    Android系统化学习脑图

    高质量Android系统化技术学习脑图,是作者多年Android开发经验的结晶,你值得拥有!

    安卓Android商品销售管理系统源码.zip

    "安卓Android商品销售管理系统源码.zip" 这个标题表明这是一个与安卓应用开发相关的项目,特别是一个商品销售管理系统的源代码。在Android平台上,开发人员经常使用Java或Kotlin语言编写应用程序,而这个系统可能...

    android系统函数大全.rar_android_android系统_安卓函数大全_安卓系统函数_系统函数

    在“android系统函数大全”文档中,你可能会找到这些领域的详细函数解析和示例代码,对于深入学习Android编程非常有帮助。开发者应根据实际需求,结合文档,灵活运用这些函数,构建高效且功能丰富的Android应用。

    安卓Android源码——安卓Android系统访问串口设备源码.rar

    这份"安卓Android源码——安卓Android系统访问串口设备源码.rar"压缩包提供了相关的源代码和资料,帮助开发者理解和实现这一功能。 首先,我们需要了解的是Android系统对串口的支持。在Linux内核的基础上构建的...

    深入理解Android系统张元亮.rar

    总之,《深入理解Android系统》是一本全面覆盖Android系统各层次的书籍,不仅适合有经验的Android开发者进行深入学习,也适合初学者作为理解Android系统原理的入门教材。通过阅读这本书,读者可以提升自己的Android...

    安卓Android新闻发布系统app源码.zip

    本源码是一个基于Android平台的新闻发布系统,旨在提供一个集新闻浏览、分类筛选、文章详情展示等功能于一体的移动应用程序。通过分析这个源码,我们可以深入理解Android开发中的关键技术和设计模式。 1. **...

    android系统原理及开发要点详解

     Android中、高级开发者:通过本书的引导,学习系统架构,关注开发要点,并尽量使用手机系统的通用设计思想、软件工程思想、系统工程思想来指导Android系统学习。  嵌入式Linux系统学习者:将Android作为一个集...

    基于Android在线考试系统的设计与实现

    摘要中的内容提到了一个基于Android的在线考试系统的设计与实现,该系统利用JSP技术、MySQL数据库、Java编程语言和Android系统,旨在管理和处理考试相关信息。系统分为三个主要模块,分别对应服务端管理员、客户端...

    Android系统原理及开发要点详解(超清)

    《Android系统原理及开发要点详解》全面介绍开放的移动电话平台Android系统,包括Android...《Android系统原理及开发要点详解》既适合从事Android各个层次开发的工程师阅读,也适合通用嵌入式Linux系统的学习者使用。

Global site tag (gtag.js) - Google Analytics