`

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平台的移动学习系统的设计与实现(源码+文档).zip

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

    android系统学习

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

    Android系统化学习脑图

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

    Android教程之认识Android系统

    Android教程之认识Android系统,值得学习

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

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

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

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

    Android系统移植与平台开发

    Android系统移植与平台开发,将网络上面零散的连载文章整理合并成一个完整的文档,供Android系统开发人员学习与参考。

    构建嵌入式android系统

    《构建嵌入式Android系统》将告诉你Android是如何工作的,以及如何修改它以满足你的需求。你将会深入到Android的内部结构,并且学会如何阅读它的源码、修改它的各种组件、针对你的硬件设备创建你自己的Android版本。...

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

    基于Android在线考试系统的设计与实现,该系统主要使用JSP技术、MySQL数据库、Java编程语言和Android系统等,实现对考试信息的管理。系统主要分为三个模块,服务端管理员的功能有:个人中心、首页轮播图管理、资讯...

    (毕设)基于Android的学生在线学习平台(移动端+服务器端+数据库)

    博主毕业时自己开发的基于Android的学生在线学习APP,是一个相当完整的系统,该系统开发了移动端和服务器端两个系统。内附系统完整的源代码、开发运行环境说明、系统文档、数据库等等。此外压缩包中还包含博主在平时...

    android系统核心和原理

    本书全面介绍开放的移动电话平台android系统,包括android系统中的linux驱动、本地框架、java框架和java应用4个层次。本书内容以知识性内容为纲,重点关注开发要点,各个部分内容注重相互照应,按照清晰的思路向读者...

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

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

    android图形系统编程学习

    android图形系统编程学习 可以帮你刚好的学习android的学习

    Android系统定制之Android.mk和Android.bp语法详解(精通版).mp4

    1.Android系统源码定制和编译方法(Android7.0至Android12) 2.Android.mk和Android.bp语法大全及使用方法详解 3.Android.mk或Android.bp中引用Android的第三方(jar、aar、so)、Androidx的类库等的使用方法 4.Android....

    Android系统源代码情景分析.pdf

    Android系统源码情景分析pdf 1.源码驱动开发技巧 2.Android 源码查看技巧 3.Android高级技术学习

    Android基础学习系统图

    Android基础学习系统图

    android 点餐系统 综合代码

    android 点餐系统 综合代码 项目里有大量的android开发知识供android程序员学习使用

    android嵌入式系统学习总结.docx

    android嵌入式系统学习总结.docx

    android系统学习资源

    增加对系统的学习能力。android的新特性等等

    Android最佳学习路线图_androidpdf_android_two4fv_

    Android最佳学习路线图 pdf电子版,Android游戏与应用开发最佳学习路线图,为了帮助大家更好的学习Android,并快速入门特此我们为大家制定了以下学习路线图,希望能够帮助大家。

Global site tag (gtag.js) - Google Analytics