基于Android系统的G网(完整资料)_第1页
基于Android系统的G网(完整资料)_第2页
基于Android系统的G网(完整资料)_第3页
基于Android系统的G网(完整资料)_第4页
基于Android系统的G网(完整资料)_第5页
已阅读5页,还剩109页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于Android系统的G网(完整资料)(可以直接使用,可编辑优秀版资料,欢迎下载)

基于Android系统的G网(完整资料)(可以直接使用,可编辑优秀版资料,欢迎下载)JIUJIANGUNIVERSITY毕业论题目基于Android系统的3G网络功能开发英文题目The3GNetworkDevelopmentBasedonAndroidSystem院系信息科学与技术学院专业计算机科学与技术姓名黄盛华班级学号A081140指导教师于林峰二○一二年五月摘要随着Android系统在消费电子行业的份额不断加重,为满足用户对手持移动产品网络功能的要求,3G无线网络功能的开发是非常有必要的。主要针对中兴MG3732模块的开发。实现在FS_S5PC100开发板上连接MG3732模块后,可以在其搭载的Android2。2系统中实现3G无线网络的打电话、发短信和上网。首先搭建一个Android系统开发的环境,主要是安装编译工具链,和搭建Java平台。其次是实现电话、短信框架,主要是对RIL层的开发和MG3732模块驱动的调试,这是整个开发过程中的重点和难点,需要长时间调试和优化。然后是实现PPPD拨号上网,最后编译内核和Android源码,获得img镜像文件,烧录开发板后,插上MG3732模块,验证功能。关键词:安卓系统,第三代通信,网络功能AbstractWiththeAndroidsystemcomponentintheconsumerelectronicsindustryhasbeenincreasingtomeettherequirementsoftheusersofthenetworkfunctionalityofhandheldmobileproducts,thedevelopmentof3Gwirelessnetworkfunctionisverynecessary.ThedevelopmentworkismainlyforZTEMG3732moduledevelopment。OveralltoachievetheMG3732modules5pc100developmentboardconnectedAndroid2.2systemequippedwith3Gwirelessnetworks,phonecalls,textingandtheInternet。First,thedevelopmentistobuildanAndroidsystemdevelopmentenvironment,istoinstallthecompilertoolchain,andbuildtheJavaplatform.FollowedbyMG3732module-driventhedebuggingandAndroi2.2systemmiddlelayer(theFRAMEWORKlayer)isthedevelopmentofRIL,whichisthefocusthroughoutthedevelopmentprocessmoredifficult,afteralongperiodofdebuggingandoptimization。ThenthepreparationofthePPPdial-upscriptandATcommandscript,andfinallycompiledAdroidsourceliveimgfiles,andburndevelopmentboard,thecertificationfunction。Keywords:AndroidSystem,3rdGenerationCommunication,NetworkFunctions目录TOC\o"1—2”\h\z\u摘要 PAGEREF_Toc20736IHYPERLINK\l_Toc6265AbstractPAGEREF_Toc6265IIHYPERLINK\l_Toc229231绪论HYPERLINK\l_Toc83371.1系统概述(1)HYPERLINK\l_Toc314221.2研究的意义(1)HYPERLINK\l_Toc134801。3发展现状(1)HYPERLINK\l_Toc274001。4发展趋势(2)HYPERLINK\l_Toc90231。5本章小结(2)HYPERLINK\l_Toc44892需求分析2.1硬件需求分析(3)2。2软件需求分析(3)HYPERLINK\l_Toc190172.3用户需求分析(4)HYPERLINK\l_Toc159822。4可行性(5)HYPERLINK\l_Toc44942.5本章小结(6)3硬件与软件环境概述HYPERLINK\l_Toc292133。1硬件概述(7)152263。2软件环境概述(8)3。3本章小结(10)HYPERLINK\l_Toc242024基于Android系统的电话、短信功能框架的实现HYPERLINK\l_Toc253464。1Application层(12)HYPERLINK\l_Toc184644.2Framework层(13)4。3Native层(15)HYPERLINK\l_Toc28704.4Kernel层(26)149994。5本章小结(27)HYPERLINK\l_Toc155785基于Android系统的3G模块(MG3732)开发5。1RIL层的开发(28)5。2PPPD拨号上网(32)5.3本章小结(36)6功能验证HYPERLINK\l_Toc184066.1功能测试(37)6.2本章小结(39)HYPERLINK\l_Toc31055致谢(41)参考文献 (42)1绪论1.1系统概述此次开发目的为实现基于Android系统的3G网络功能,即利用3G网络实现打接电话、收发短信和无线上网.硬件部分主要采用三星FS_S5PC100开发平台和中兴MG32723G模块,以及一张联通3GSIM卡.系统软件部分采用Android2.2系统,主要包括Linux内核、UBOOT、Android文件系统.应用软件部分主要包括Android2.2系统自带的拨号输入、SMS软件及Browser软件,主要作用用于验证.1。2研究的意义3G是当今社会移动网络的主流,Android系统也在消费电子产品中占有极大的份额(特别是手机和平板电脑),所以研究3G在Android系统中的实现,具有较大的意义的。3G在Android系统上的实现,可以促使Android手机和Android平板电脑实现宽带上网,大大提升上网的速度,并且可以进行手机办公、手机商务等活动。其次手持移动产品(如手机和平板电脑)的视频通话和网络电视、音乐及其他一些只能在PC上实现的功能,都能因此而得到圆满的解决,这样就极大地方便了用户,也使基于Android系统的手持移动产品真正达到“手持电脑"的效果.1。3发展现状3G已经成为嵌入式领域的一个新热点,国内的移动通信三大巨头在08年相继宣布要重资发展3G业务,3G网络的WAP站点更是随处可见。特别是近几年,越来越多的消费者选择了Android系统的手机、平板电脑和其他设备。基于Android系统的3G网络功能必定会受到极大欢迎.1。4发展趋势近年来,随着计算机技术及相关技术的发展,嵌入式技术已成为后PC时代的主力,在通讯、网络、工控、医疗、电子、物联网、三网融合、3G等领域发挥着越来越重要的作用,嵌入式IT技术正在变得无处不在。如今,嵌入式IT系统开发无疑成为当今最热门、最有发展前途的领域之一。2010年开始,Android逐渐成为智能手机技术的主导,与iPhone同领潮流,改变人们的生活和工作。并且Android系统开放性会使其得到更大的发展。因此,基于Android系统的3G系统会得到更大的发展。1.5本章小结本章首先对包括硬件和软件在内的系统做了一个简单介绍,然后说明了该项目的意义和目的.接下来介绍了当前基于Android系统的3G技术应用这块的发展现状和未来发展趋势,说明当今和未来几年,基于Android系统的3G技术会是一项非常热门的技术。2需求分析需求分析是指开发人员要理解用户的要求,进行详细的市场调查,确定系统的新目标。为了满足用户的需要,回答系统要“做什么”的问题[1].2.1硬件需求分析好的硬件平台会发给软件开发带来许多便利,因此选择一个合适的硬件平台是非常重要的[2]。根据软件开发需求和硬件平台稳定性、价格等一系列因素,选择了FS_S5PC100开发板。该开发板采用三星SP5C100处理器,处理器采用64/32位内部总线结构,运算速度最大833MHZ,被广泛的应用于智能手机、平板电脑等产品.根据性价比,3G模块选择了中兴MG3732模块。MG3732模块是基于高通QSC6270平台开发的WCDMA3G无线通讯模块,引脚方式为36脚邮票孔,适用于WCDMA和GSM网络,支持850/900/1800/1900/2100频段。2.2软件需求分析据调查,这几年,系统源码开放的Android系统已经占用了智能手机市场36%的份额,并且Android系统还将得到更大的发展[3]。选择了Android2。2系统,其优点如下:(1)开放性Android平台首要优势就是其开放性[4]。开放的平台允许任何移动终端厂商加入到Android联盟中来.显著的开放性可以使其拥有更多的开发者,随着用户和应用的日益丰富,一个崭新的平台也将很快走向成熟[5]。(2)挣脱束缚在过去很长的一段时间,特别是在欧美地区,手机应用往往受到运营商制约,使用什么功能接入什么网络,几乎都受到运营商的控制。自从iPhone上市,用户可以更加方便地连接网络,运营商的制约减少。随着EDGE、HSDPA这些2G至3G移动网络的逐步过渡和提升,手机随意接入网络已不是运营商口中的笑谈[6].(3)丰富的硬件由于Android的开放性,同时Android的热火,致使众多的硬件生产厂商在第一时间专门针对Android生产出各具特色的产品。(4)开发商Android平台提供给第三方开发商一个十分宽泛、自由的环境.因此不会受到各种条条框框的阻挠,可想而知,会有无数新颖别致的软件诞生。(5)Google应用从搜索巨人到全面的互联网渗透,Google服务如地图、邮件、搜索等已经成为连接用户和互联网的重要纽带,而Android平台手机将无缝结合这些优秀的Google服务[7]。Android系统是开源的。这会为开发带来极大的方便。在互联网上,可以找到很多研究Android系统、研究3G网络功能实现的心得体会.这样可以通过查找资料,缩短开发的时间,明确开发方向。2。3用户需求分析根据调查,全球3G市场正在保持快速稳定的发展,并呈现以下趋势:(1)3G+技术将成增长主流截至2011年底,全球移动普及率已超过76%,市场将逐渐趋于饱和,移动用户增长将趋缓。中国、印度等发展中国家将是未来几年3G用户增长的主要来源,对整个移动通信市场的发展影响重大。3G+技术将成为3G市场主流。预计到2015年,HSPA用户占比将由2010年的6.3%迅速上升到25。6%,成为3G用户增长的重要来源[8]。(2)中低端智能终端市场份额不断提升,开放阵营将占据主流未来,智能终端的能力将呈现PC化,计算、处理和存储能力等方面都逐渐向PC性能水平靠拢。在价格方面,智能终端将整体走低,受众范围不断扩大。依靠产业分工合作、标准化、通用服务获得成本优势的中低端智能终端在市场中的份额将不断上升[9].(3)应用商店模式加快发展,浏览器成为其新载体未来,移动应用商店将继续处于快速发展阶段.随着智能终端种类和行业应用的增加,未来应用商店应用范围将持续扩大,成为覆盖手机、平板电脑、电子阅读器、笔记本电脑等移动终端设备的通用应用下载平台[10]。显而易见,基于Android系统的3G网络功能,会是一个非常热门的技术,并且拥有一个巨大的市场.越来越多的用户将会选择Android系统的移动终端设备,所以方便、快速、便宜,会是用户基本的选择条件。方便,即是携带方便,使用方便。3G模块的成品只有U盘大小,可以随身携带,使用时只需插入一张3G电话卡,连接上手机或是平板电脑就能直接使用。快速,即是上网速度快。MG3732模块的信号接收能力强,而且接收信号稳定。便宜,即是价格便宜.MG3732模块在同类型的3G模块中有明显的价格优势。综上所述,此项目今后必会受到用户的追捧,并且具有巨大的市场优势。2。4可行性2.4.1技术可行性基于Android的源代码的开放,使得在对Android做系统开发的时候可以很好的通过查看源代码来针对专门的问题进行解决[11].三星SP5C100的开发板有丰富的资源,在出现问题的时候在互联网中的各大论坛中都能够找到相应的解决方案。所以通过学习,查找相关的资料,开发本系统在技术方面没有任何的问题。2。4.2经济可行性经济可行性就是对开发成本进行分析,估计开发成本是否会超过项目的预期利润[7]。在这个系统的开发过程中,需要的只是开发板的购买,而且开发板是可以多次使用的,对于Android系统是完全自由的,不需要付出任何的代价。当项目结束的时候,可以直接把系统拿过去使用,或者针对相关的硬件进行相应的二次开发,所获得的效益是客观的.基于以上两点的分析,本次系统开发是很有价值的.2.5本章小结通过对软件和硬件的需求分析,说明所选择的硬件平台是非常合适的。加之Android系统在未来几年也是一个非常热门的方向,3G市场更是稳定快速发展,所以此次开发的项目,不仅紧靠市场的需求,而且在未来的几年内都是一个热门的方向。3硬件与软件环境概述3。1硬件概述开发板平台采用了FS_S5PC100开发平台,该开发平台用三星公司先进的基于Cortex—A8内核的S5PC100处理器设计而成。可以适应Android、Linux、Wince等智能操作系统的发展及市场需求[12].S5PC100处理器采用了64/32位的内部总线结构,运算速度最大833MHZ[13]。包括强大的硬件加速器,如:动态视频处理、显示控制和缩放。支持多种格式的硬件编解码:MPEF-1/2/4、H263/H264等。其视频解码能力很强大并且省电,编解码能力达到720p@30fps(1280x720),支持电视输出(NTSC/PAL/HDMI)。支持2D/3D加速.本处理器广泛应用于智能手机、平板电脑等产品。FS_S5PC100平台的外观,如图3-1所示。图3—1FS_S5PC100的外观图3.1.23G模块3G模块采用的是中兴MG3732模块,适用于WCDMA和GSM网络,支持850/900/1800/1900/2100频段[14]。ZTEMG37323G模块外观,如图3—2所示。图3-2MG3732外观图3.2软件环境概述3。2.1交叉开发环境的搭建(1)安装交叉编译工具链=1\*GB3①解压“Linux—Android\toolchain”目录下的“arm—none—eabi-4.2。2.tgz到根“/usr/local"目录下,在“/usr/local”目录下会生成“arm”目录。执行命令:#tarzxvfarm-none-eabi-4。2.2.tgz=2\*GB3②修改环境变量“PATH”。~$sudovim/etc/environment将路径添加到PATH变量的最后面,命令如下:PATH=”/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/arm/4.2。2—eabi/usr/bin保存退出后执行:source/etc/environment这样修改的环境变量会立即生效。(2)安装JDK=1\*GB3①安装“Linux-Android\toolchain”目录下的“jdk.bin”,jdk.bin是Jdk1.5,Jdk1。5是编译Android2。1必须的工具。把“jdk.bin”拷贝到“/usr"目录下,然后执行,按照提示安装即可.#sudo./jdk。bin=2\*GB3②安装结束后还要配置一下环境变量。~$sudovim/etc/environment将路径添加到PATH变量的最后面.PATH=”/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/arm/4。2.2-eabi/usr/bin:/usr/jdk1.5.0_21/bin保存退出后执行:source/etc/environment3.2。2搭建并配置Java环境(1)安装依赖包$sudoapt-getinstallbuild-essential$sudoapt-getinstalllibncurses5-dev$sudoapt-getinstallx11proto-core-dev$sudoapt-getinstallzlib1g-dev$sudoapt—getinstalllibx11-dev$sudoapt-getinstallgperf$sudoapt—getinstallbison$sudoapt—getinstallflex(2)搭建Java编译环境=1\*GB3①安装JDK下载jdk(JDK_1_5.BIN)并执行如下命令:$sudomkdir/usr/java$suodmvJDK_1_5。BIN/usr/java$sudochmod+xJDK_1_5.BIN$sudo。/JDK_1_5.BIN在执行以上命令后生成license文件,按q然后根据提示输入yes即可开始安装。=2\*GB3②配置java环境$sudogedit~/.bashrc在最后面加上:exportJAVA_HOME=/usr/java/jdk1.5.0_21//系统所用的jdk目录exportPATH=$JAVA_HOME/bin:$PATHexportANDROID_JAVA_HOME=$JAVA_HOME3。3本章小结本章主要介绍了开发系统中所需要的硬件及其参数,以及如何搭建好开发平台.良好的开发平台为一个系统开发不仅节约了开发成本,同时也缩短了开发周期[15]。4基于Android系统的电话、短信功能框架的实现基于Android系统的3G网络电话、短信框架分为如下四个部分:(1)Javaapplication层;(2)Javaframework层;(3)Nativeframework层;(4)Kernel层。第一层和第二层都属于Android应用层的代码使用的是JAVA语言开发,在此定义为Java-ril。第三层属于JNI层代码使用的是C/C++语言开发,从图4-1中可知,对于硬件的具体操作代码在第三层,一般情况下,Android框架代码中使用JNI的方式完成Java和C/C++代码的相互调用,再使用binder封装实现进程间通讯.电话框架没有使用这种方式,而是使用socket的方式,完成进程间通讯,rild进程作为服务器端,Java层代码作为客户端把用户的数据发送给rild进程去处理,3G的网络功能框架图如图4-1所示。图4—13G网络功能框架图4。1Application层4.1.1电话部分(1)通话部分拨打电话时,首先会调用onClick()方法,这个方法会通过myEditText.getText().toSTring()方法获取所拨打的电话号码,并会调用isPhoneNumberValid()方法判断这个电话号码是否符合格式,如果符合格式,则会触发Outgoingcallbroadcaster.java中的oncreate方法,如果号码是紧急号码则直接以startactivity方式处理。若不是紧急号码,则将该号码以sendorderedbroadcast(outgoingcallreceiver)方式处理,由OutgoingcallReceiver内部类去接收(doReceive)此号码,并在doreceive中启动InCallScreen类。IncallScreen类中,若第一次进入则调用oncreate函数;若通话中再拨打电话则调用onnewintent函数.oncreate函数中会调用internalResolveIntent方法--—〉调用placecall函数(建立一个我们需要拨打电话的Call)-—〉接着调用Phoneutil.java的placecall函数(传入phone对象和number参数),里面调用Connect=phone。dial(number)。phone类是个接口类,其中声明了dial这个方法,具体的结构如箭头所示:Phone(interface)〈-—-implements-—PhoneBase(abstractclass)<extends--——CDMAPhone,GSMPhone,SIPPhoneBase.其中GSMPhone与CDMAPhone都是由PhoneFactory来获取实例的.很明显这里是GSMPhone类在进行dial操作。(2)短信部分发送短信时,首先会通过mNumber。getText().toString()和mMessage。getText().toString()这两个方法获取短信号码和内容,然后会触发SmsManager.java中的sendTextMessage方法。该方法中有四个参数,分别是StringdesinationAddress、StringscAddrsss,Stringtext、PendingIntentsentIntent、PendingIntentdeliveryIntent,也就是收件人号码、发件人号码、信息内容、发送是否成功回执、接收是否成功回执。sendTextMessage方法是通过AIDL的方式,获得服务,再调用这个服务对象的sendText()方法.这个服务对象继承了ISms。Stub,所以SmsManager。sendTextMessage()方法调用了IccSmsInterfaceManager对象的sendText()方法。IccSmsInterfaceManager是一个继承了ISms.Stub的抽象类,IccSmsInterfaceManager对象的sendText()方法调用了SMSDispatcher类的sendText()方法,这个方法又调用了GsmSMSDispatcher。java中的sendSms()方法。sendSms()方法调用了CommandsInterface接口,CommandsInterface是一个特殊的接口,与RIL.java相关,于是进入了Framework层。4。2Framework层(1)通话部分进入GSMPhone的dial方法:其中有个mCT(GsmCallTracker类)。dial方法,深入其中有:cm.dial(pendingMO。address,clirMode,obtainCompleteMessage());cm为CommandsInterface(interface接口)的对象.因为RIL。java(在android/internal/telephony目录中)extendsBaseCommandsimplementsCommandsInterface接口,所以cm.dial就等同于RIL.dial。RIL.dial()方法中,创建RILRequest对象,并将此RILRequest对象放入messagequeue中。RIL中有个内部类叫RILSender:classRILSenderextendsHandlerimplementsRunnable,查看其handleMessage方法的核心代码如下:caseEVENT_SEND:s。getOutputStream()。write(dataLength);s.getOutputStream().write(data);s为mSocket,而文件中mSocket为LocalSocket对象,而在实例化中。s=newLocalSocket();l=newLocalSocketAddress(SOCKET_NAME_RIL,LocalSocketAddress.Namespace.RESERVED);s.connect(l);可以看到LocalSocket与SOCKET_NAME_RIL打上了交道,查看其SOCKET_NAME_RIL=”rild",可以得知s.getOutputStream()。write(data)是往rild的socket写数据。其实RILSender和RILReceiver都是共用的一个socket。也可以知道RIL中有RILD这个守护进程(负责控制RIL串口).这里总结下发送步骤:=1\*GB3①创建RILRequest,将请求数据及Msg放入到RILRequest中;=2\*GB3②利用Send方法(参数:EVENT_SEND)将RILRequest放入到消息队列中;=3\*GB3③RILSender类获取此消息,把RILRequest通过SOCKET方式发送到Rild并保存在mRequest中,以便消息的返回。(2)短信部分进入Framework层后,主要靠CommandsInterface对象的sendSMS()方法来做事情,sendSMS()方法源码如下:public

void

sendSMS

(String

smscPDU,

String

pdu,

Message

result)

RILRequest

rr=RILRequest。obtain(RIL_REQUEST_SEND_SMS,

result);rr。mp。writeInt(2);rr.mp。writeString(smscPDU);rr.mp。writeString(pdu);if

(RILJ_LOGD)riljLog(rr.serialString()

+

">

+

requestToString(rr.mRequest));send(rr);}

在sendSMS()方法中,把上面传下来的短信相关的数据写入到了Parcel中,协同一个特殊的RILRequest写入到Socket的输出流中,进而将数据传递到RIL层.4.3Native层RIL(RadioInterfaceLayer)层,主要是基于AT命令的操作,也就是把上层的传递下来的数据包(电话数据或是短信数据)分解,并转化为可以让3G模块识别的AT命令,最后把3G模块处理完数据返回的response解析,再传递回上层。4。3.1AndroidRIL概念AndroidRIL是基于telephony服务和raido硬件层的抽象层,Android的Rild库介于硬件抽象层HAL接口与基于Modem之间,它同样提供了语音、数据、短信、SIM卡管理以及STK应用的功能,实现思路跟微软的RIL有异曲同工之妙,也是把标准的GSM27.007中常用的如Dial这些做主动请求的操作称之为request,一共75个;另外一类信息是GSM模块主动上报的例如信号强度、基站信息等,称之为unsolicitedresponse,一共17个。其开发模式是跟微软RIL开发差不多,需要针对不同的GSM模块进行不同的GSM驱动开发,公用的部分google已经做好了,特定的部分需要用户自己去定制,这样做可以大大地提高开发效率.以下是RIL交互图,如图4-2所示.图4-2RIL交互图4.3.2本地代码RIL支持的本地代码包括RIL库和守护进程.hardware/ril/includehardware/ril/librilhardware/ril/rildhardware/ril/reference—ril编译结果是:/system/bin/rild:守护进程/system/lib/libril。so:RIL的库/system/lib/libreference-ril。so:RIL参考库Android的RIL驱动模块,在hardware/ril目录下,一共分rild,libril。so以及librefrence_ril。so三个部分,另外radiooptions可供自动或手动调试使用.它们都依赖于include目录中ril。h头文件.目前cupcake分支上带的是gsm的支持,另有一个cdma分支,3G通信模块MG3732用到的是gsm驱动。rild与libril.so以及librefrence_ril。so的关系=1\*GB3①rild仅以main函数作为整个RIL层的入口点,负责完成初始化。在rild.c文件中,将完成RIL的加载过程,它会执行如下操作:首先动态加载VendorRIL的。so文件;其次执行RIL_startEventLoop()开启消息队列以进行事件监听;最后通过执行VendorRIL的rilInit()方法来进行VendorRIL与libril的关系建立。=2\*GB3②libril.so与rild结合紧密,是其共享库。编译时就已经建立了这一关系(其实也可以编译成可执行程序,作为守护进程运行)。组成部分为ril.cpp和ril_event。cpp。libril.so驻留在rild这一守护进程中,主要完成同上层通信的工作,接受RIL请求并传递给librefrence_ril.so,同时把来自librefrence_ril.so的反馈回传给调用进程。编译时,libril被链入rild,它为rild提供了event处理功能,还提供了在rild与VendorRIL之间传递请求和响应消息的能力。Libril提供的主要功能分布在两个主要方法中:一个是RIL_startEventLoop()方法;另一个是RIL_register()方法。RIL_startEventLoop()方法所提供的功能就是启用eventLoop线程,执行RIL消息队列;RIL_register()方法的功能是启动名为rild的监听端口。=3\*GB3③librefrence_ril.sorild通过手动的dlopen方式加载,结合稍微松散,这主要是因为librefrence.so负责跟Modem硬件通信。这样做更方便替换或修改加载的方式,以适配更多种类的Modem。它将来自libril。so的请求转换为AT命令,同时监控Modem的反馈信息,并传递回libril.so。在初始化时,rild通过符号RIL_Init获取一组函数指针并以此与之建立联系。reference—ril会接收调用者传来的参数,参数内容为与radio的通信方式。如通过串口连接radio,那么参数形式为:-d/dev/ttySx,如图4—3所示.图4-3Rild、Libril。so及Librefrence。so关系图=4\*GB3④radiootionsradiooptiongs通过获取启动参数,利用socket与rild通信,其作用是通过串口将一些与radio相关的参数直接传给rild。可用于调试时配置Modem参数的配置.(2)初始化流程rild是一个守护进程,在这里定义宏RIL_SHLIB.执行的过程为:获取参数—〉打开功能库->建立事件循环—〉执行RIL_Init—>RIL_register。主入口是rild.c中的main函数,主要完成三个任务:=1\*GB3①任务一:开启libril。so中的event机制.在RIL_startEventLoop中,最核心的是由多路I/O驱动的消息循环。=2\*GB3②任务二:初始化librefrence_ril。so。也就是跟硬件或模拟硬件modem通信的部分(后面统一称硬件),通过RIL_Init函数完成。=3\*GB3③任务三:通过RIL_Init获取一组函数指针RIL_RadioFunctions,并通过RIL_register完成注册,并打开接受上层命令的socket通道。初始化流程分析如下:=1\*GB3①任务一:也就是RIL_startEventLoop函数。RIL_startEventLoop在ril.cpp中实现,它的主要目的是通过pthread_create(&s_tid_dispatch,&attr,eventLoop,NULL)建立一个dispatch线程,入口点在eventLoop。而eventLoop中,会调用ril_event。cpp中的ril_event_loop()函数,建立起消息(event)队列机制.这一消息队列的机制讨论如下:voidril_event_init();//初始化消息队列voidril_event_set(structril_event*ev,intfd,boolpersist,ril_event_cbfunc,void*param);//设置消息队列相关的属性voidril_event_add(structril_event*ev);//增加消息voidril_timer_add(structril_event*ev,structtimeval*tv);//增加时间计时器voidril_event_del(structril_event*ev);//删除消息voidril_event_loop();//通过多路复用I/O机制循环调用消息队列structril_event{structril_event*next;//下一个消息structril_event*prev;//前一个消息intfd;//事件相关设备句柄。例如对于串口数据事件,fd就是相关串口的设备句柄boolpersist;//如果是保持的,则不从watch_list中删除structtimevaltimeout;ril_event_cbfunc;//回调事件处理函数void*param;//回调时参数};每个ril_event结构,与一个fd句柄绑定(可以是文件、socket、管道等),并且带一个func指针去执行指定的操作。具体流程是:ril_event_init完成后,通过ril_event_set来配置一个新ril_event,并通过ril_event_add加入到队列之中(实际通常用rilEventAddWakeup来添加)。add会把队列里所有ril_event的fd,放入一个fd集合readFds中。这样ril_event_loop能通过一个多路复用I/O的机制(select)来等待这些fd.如果任何一个fd有数据写入,则进入分析流程processTimeouts(),processReadReadies(&rfds,n)和firePending()(后面会详细分析这些流程)。另外可以看到,在进入ril_event_loop之前,已经通过pipe机制挂入了s_wakeupfd_event.目的是为了可以在一些情况下能够内部唤醒ril_event_loop的多路复用阻塞,比如一些带timeout的命令到期的时候。至此第一个任务分析完毕,这样便建立起了基于event队列的消息循环,稍后便可以接受上层发来的的请求了(上层请求的event对象建立,在第三个任务中)。=2\*GB3②任务二:这个任务的入口是RIL_Init,RIL_Initreference—ril。c首先通过参数获取(p/d/s)硬件接口的设备文件或模拟硬件接口的socket。接下来便新创建一个线程pthread_create(&s_tid_mainloop,&attr,mainLoop,NULL)继续初始化,即mainLoop。mainLoop的主要任务是建立起与硬件的通信,然后通过read方法阻塞等待硬件的主动上报或响应。在注册一些基础回调(timeout、readerclose)后,mainLoop首先打开硬件设备文件,建立起与硬件的通信,s_device_path和s_port是前面获取的设备路径参数,将其打开(两者可以同时打开并拥有各自的reader,这里也很容易添加双卡双待等支持)。接下来通过at_open(fd,onUnsolicited)函数建立起这一设备文件上的reader等待循环,这也是通过新建一个线程完成,ret=pthread_create(&s_tid_reader,&attr,readerLoop,&attr),入口点为readerLoop。AT命令都是以/r/n或/n/r的换行符来作为分隔符的,所以readerLoop是line驱动的,除非出错、超时等,否则会读到一行完整的响应或主动上报,才会返回.这个循环启动以后,基本的AT响应机制就已经建立了起来。对它的具体分析,包括at_open中挂接的ATUnsolHandler,放到后面的response分析里去。SMS(短信)的收发if(isSMSUnsolicited(line))判断也在readerLoop中。有了响应的机制(当然,能与硬件通信也已经可以发请求了),通过RIL_requestTimedCallback(initializeCallback,NULL,&TIMEVAL_0),跑到initializeCallback中,执行一些以AT命令为主的Modem初始化命令。关于AT命令发送的流程,详见request分析.这里可以看到,主要完成一些参数配置,以及网络状态的检查等.硬件已经可以访问了.=3\*GB3③任务三:由RIL_Init的返回值funcs=rilInit(&s_rilEnv,argc,rilArgv)开始,这是一个RIL_RadioFunctions结构的指针.typedefstruct{intversion;/*settoRIL_VERSION*/RIL_RequestFunconRequest;RIL_RadioStateRequestonStateRequest;RIL_Supportssupports;RIL_CancelonCancel;RIL_GetVersiongetVersion;}RIL_RadioFunctions;其中最重要的是onRequest域,来自上层的请求都由这个函数进行映射后转换成对应的AT命令并发给硬件。Rild通过RIL_register注册这一指针.RIL_register中要完成的另外一个任务,就是打开跟上层通信的socket接口(s_fdListen是主接口,s_fdDebug供调试时使用)。然后将这两个socket接口使用任务一中实现的机制进行注册(仅列出s_fdListen)。ril_event_set(&s_listen_event,s_fdListen,false,listenCallback,NULL);rilEventAddWakeup(&s_listen_event);这样将两个socket加到任务一中建立起来多路复用I/O的检查句柄集合中,一旦有上层来的(调试)请求,event机制便能响应处理了.(3)Request流程对Dial而言,CommandInfo包含了所有的AT命令。所以CommandInfo结构应该这样进行初始化:{RIL_REQUEST_DIAL,dispatchDial,responseVoid}这里执行dispatchFunction,也就是dispatchDial这一函数。其实有很多种类的dispatchfunction,比如dispatchVoid,dispatchStrings,dispatchSIM_IO等等,这些函数的区别在于解析传入的参数形式,void就是不带参数的,Strings是以string[]做参数,又如Dial等,有自己的参数解析方式,以此类推.Request号和参数具备后,就可以进行具体的request函数调用了。利用s_callbacks。onRequest(pRI—〉pCI—〉requestNumber,xxx,len,pRI)完成这一操作。s_callbacks的作用是获取前文中提到的来自libreference-ril的RIL_RadioFunctions结构指针.request请求在这里转入底层的libreference-ril处理,handler是reference-ril.c中的onRequest。onRequest进行一个简单的switch分发。RIL_REQUEST_DIAL流程是:onRequest-->requestDial--〉at_send_command——>at_send_command_full——>at_send_command_full_nolock--〉writeline。requestDial中将命令和参数转换成对应的AT命令,调用公共sendcommand接口at_send_command。除了这个接口之外,还有如下命令:at_send_command_singleline、at_send_command_sms、at_send_command_multiline等,这是根据at返回值,以及发命令流程的类型来区别的。比如at_csq类型,需要at_send_command_singleline,而发送短信,因为有prompt提示符“>”,传送数据、结束符等一系列操作,需要专门用at_send_command_sms来实现.然后执行at_send_command_full,前面几个接口都会最终到这里,再通过一个互斥的at_send_command_full_nolock调用,完成最终的写出操作,在writeline中,写出到初始化时打开的设备中。前面提到RILSender将请求呼叫的字节流传给了rild的socket.这时,ril_event_loop方法的select检测到了有请求的信号,导致被挂入pending_list,并执行ev->func(ev—>fd,0,ev->param),即调用staticvoidlistenCallback(intfd,shortflags,void*param)方法。在该方法中,首先通过accept()接收上层的socket,然后通过record_stream_new()建立一个record_stream,并联系上s_fdCommand,到目前为止s_fdCommand已经有了上层数据,于是调用processCommandsCallback(intfd,shortflags,void*param)方法,processCommandsCallback会保证收到一个完整的request(由recordStream决定),并调用processCommandBuffer方法,这是命令的下发流程。每个命令以RequestInfo的形式存在(实例:pRI),并且将pRI挂在了s_pendingRequests中,并执行dispatchFunction方法,即dispatchDial.dispatchDial方法中,里面核心代码如下:s_callbacks。onRequest(pRI->pCI-〉requestNumber,&dial,sizeOfDial,pRI);而s_callbacks是前文提到说的RIL_RadioFunctions结构的指针,RIL_RadioFunction中有个重要的域是onRequest,详情可参照reference-ril.c文件中onrequest方法的实现。onrequest中主要是用switch..case判断发送过来的命令是什么(如:拨打电话、SIM卡状态、挂断电话、等待状态等),这里当然是拨打电话。大致的流程为:onrequest--〉requestDial——>at_send_command—->at_send_command_full-—〉at_send_command_full_nolock.nolock方法中关键性的一句为writeLine(。..).查看writeline方法,written=write(s_fd,s+cur,len—cur)。能够看得出是往硬件中写入命令。其实质都是at_send_command_full方法,执行write之后便等待硬件那边给过来的响应,于是进入response阶段。(4)Response流程前文对Request的分析,中止在at_send_command_full_nolock里的writeline操作.因为这里完成命令写出到硬件设备的操作,接下来就是等待硬件响应,也就是response过程。后继分析从此处开始。response信息的获取,是初始化分析中提到的readerLoop中,由readline函数以“行”为单位接收上来.AT的response有两种,一是主动上报的,比如网络状态、短信、来电等都不需要经过请求,有一个unsolicited词语专门描述;另一种才是真正意义上的response,也就是命令的响应。所有的行,首先经过sms的自动上报筛选。因为短信的AT处理通常比较麻烦,无论收发都单独列出。这里是因为要即时处理这条短信消息(两行、标志+pdu),而不能拆开处理。处理函数为onUnsolicited(由s_unsolHandler指向)。除sms特例外,所有的line都要经过processLine,该处理流程如下:nocmd—-->handleUnsolicited//主动上报isFinalResponseSuccess-—-〉handleFinalResponse//成功,标准响应isFinalResponseError--—>handleFinalResponse//失败,标准响应get'>'——->sendsmspdu//收到>符号,发送sms数据再继续等待响应switchs_type-——>具体响应//命令有具体的响应信息需要对应分析需要关注的是handleUnsolicited自动上报功能以及switchs_type具体响应信息。具体响应需要handleFinalResponse这样的标准响应来最终完成。=1\*GB3①onUnsolicite(主动上报响应)staticvoidonUnsolicited(constchar*s,constchar*sms_pdu);短信的AT设计难度较高。response的主要的解析过程由at_tok。c中的函数完成,其本质就是字符串按块解析,具体的解析方式由每条命令或上报信息自行决定.此处不再详述。onUnsolicited只解析出头部(一般是+XXXX的形式),然后按类型决定下一步操作,操作为RIL_onUnsolicitedResponse和RIL_requestTimedCallback两种。第一,RIL_onUnsolicitedResponse:solicite的信息直接返回给上层。通过Parcel传递,将RESPONSE_UNSOLICITED,unsolResponse(request号)先写入Parcel,然后通过s_unsolResponses数组,查找到对应的responseFunction完成进一步的的解析,存入Parcel中。最终通过sendResponse将其传递回原进程.流程如下:sendResponse—->sendResponseRaw-->blockingWrite-->writetos_fdCommand(前面建立起来的和上层框架的socket连接)。第二,RIL_requestTimedCallback:通过event机制实现的timer机制,回调对应的内部处理函数.通过internalRequestTimedCallback将回调添加到event循环,最终完成callback上挂的函数的回调。比如pollSIMState,onPDPContextListChanged等回调,不用返回上层,内部处理就可以。=2\*GB3②switchs_type(命令的具体响应)及handleFinalResponse(标准响应)命令的类型(s_type)在sendcommand时设置。有NO_RESULT、NUMERIC、SINGLELINE、MULTILINE几种,供不同的AT使用.比如AT+CSQ是singleline,返回at+csq=xx,xx,再加一行OK,比如一些设置命令,就是no_result,只有一行OK或ERROR.这几个类型的解析都很相似,通过一定的判断(如比较AT头标记等),如果是对应的响应,就通过addIntermediate挂到一个临时结果。sp_response—>p_intermediates队列中,如果不是对应响应,则其应该是穿插其中的自动上报,用onUnsolicite来处理。具体响应只起一个获取响应信息到临时结果、等待具体分析的作用。无论有无具体响应,最终都会以标准响应handleFinalResponse来处理,也就是接受到OK,ERROR等标准response来结束,这是大多数AT命令的规范。handleFinalResponse会设置s_commandcond这一object,也就是at_send_command_full_nolock等待的对象。至此,响应的完整信息已经完全获得,sendcommand可以进一步处理返回的信息(临时结果、以及标准返回的成功或失败都在sp_response中)。pp_outResponse参数将sp_response返回给调用at_send_command_full_nolock的函数。p_response如果返回失败(也就是标准响应的ERROR等造成),则通过RIL_onRequestComplete发送返回数据给上层,结束命令;如果成功,则进一步分析p_response—>p_intermediates,同样是通过at_tok.c里的函数进行分析,并同样将结果通过RIL_onRequestComplete返回。RIL_onRequestComplete和RIL_onUnsolicitedResponse很相似,功能也一致.通过Parcel来传递回上层,同样是先写入RESPONSE_SOLICITED(区别于RESPONSE_UNSOLICITED),pRI->token(上层传下的request号),错误码(sendcommand的错误,不是AT响应).如果有AT响应,通过访问pRI-〉pCI->responseFunction来完成具体response的解析,并写入Parcel。然后通过同样的途径:sendResponse--〉sendResponseRaw—->blockingWrite-->writetos_fdCommandﻫ完成最终的响应传递,如图4—4所示。图4—4Response流程图Readloop要解决的问题是:解析从Modem发过来的回应。如果遇到主动上报消息则通过handleUnsolicited上报的java-ril;如果是命令的应答,则通过handleFinalResponse通知send_at_command有应答结果。Rild层初始化时获取reference-ril.c提供的函数列表结构体.Eventloop将根据不同的命令类型获取java-ril消息,解析出需要的参数,并调用onRequest函数进行分发处理。send_at_command是同步的,命令发送后,send_at_command将等待在命令处理完成。=3\*GB3③RIL跟上层通讯主要采用两种方式:一种是通过Socket发送与接收消息的方式来实现,C方面,这个Socket在ril.cpp里面可以找到它的创建代码:s_fdListen=android_get_control_socket(SOCKET_NAME_RIL);JAVA方面,在RIL。java中:s=newLocalSocket();l=newLocalSocketAddress(SOCKET_NAME_RIL,LocalSocketAddress.Namespace。RESERVED);s.connect(l);另外一种方式就是直接通过TCP/IP直接访问内核中的sharedmemory,进行RPC调用,这种方式主要应用在数据模式上,一是因为Android的每个Activity随时都会有可能需要网络连接接收发送数据,因此必须提供一种实时性较高的访问方式,二是因为可以提高通讯效率。4.4Kernel层此处主要是对usbserialdriver的加载,这里使用的usbserialdriver是来自linux内核下的通用usbserial驱动。Usbserial驱动控制插入其中的usb3G(ZTEMG3732)设备,提供虚拟的串口,如ttyUSB0,ttyUSB1。为了让usbserial驱动为3G模块所使用,需要修改驱动源码,使内核能够识别设备。主要是在内核/driver/usb/serial/option.c中,增加设备的vid和pid,也就是产品号和出厂号。代码如下所示:{USB_DEVICE(0x19d2,0xffff)},{USB_DEVICE(0x19d2,0xffec)},并且还需要配置内核:DeviceDrivers--->[*]USBsupport—-—>〈*>SupportforHos-sideUSB//<*〉OHCIHCDsupport〈*〉USBSerialConvertersupport——-><*>USBdriverforGSMandCDMAmodems这样内核就支持ZTEMG37323G模块了。当驱动成功加载后,插入3G模块后,在/dev/目录下就可以看到ttyUSB0,ttyUSB1等字符设备文件。4.5本章小结本章对APP层、Framework层进行了简单的分析,重点介绍了RIL层和Kernel层的实现。对App层、Framework层的分析是为了实现RIL层,知道RIL层从上层接收到什么.RIL层主要实现了两个流程,即Request流程和Response流程。Request流程就是接收上层的事件转化为AT命令传输到硬件。Response流程就是把硬件响应的命令再解析,然后返回给上层。5基于Android系统的3G模块(MG3732)开发5.1RIL层的开发为了使RIL层支持该3G模块,首先要在RIL层添加对该模块的支持。代码如ril/reference—ril/Android.mk中:LOCAL_CFLAGS+=-DZTE_MG3732MG3732模块Response的数据与普通的模块有所区别,所以获取Response信息的代码有所不同.这里需要获取Response信息代码,具体代码在ril/reference-ril/atchannel.c中:staticconstchar*urc_readline()//读取Response信息{ssize_tcount;char*p_read=NULL;char*p_eol=NULL;char*ret;if(*s_URCBufferCur==’\0’){s_URCBufferCur=s_URCBuffer;*s_URCBufferCur=’\0';p_read=s_URCBuffer;}else{while(*s_URCBufferCur=='\r'||*s_URCBufferCur=='\n')s_URCBufferCur++;p_eol=findNextEOL(s_URCBufferCur);if(p_eol==NULL){size_tlen;len=strlen(s_URCBufferCur);memmove(s_URCBuffer,s_URCBufferCur,len+1);p_read=s_URCBuffer+len;s_URCBufferCur=s_URCBuffer;}}while(p_eol==NULL){if(0==MAX_AT_RESPONSE—(p_read—s_URCBuffer)){LOGE("ERROR:Inputlineexceededbuffer\n");s_URCBufferCur=s_URCBuffer;*s_URCBufferCur='\0';p_read=s_URCBuffer;}do{count=read(urc_fd,p_read,MAX_AT_RESPONSE-(p_read-s_URCBuffer));}while(count<0&&errno==EINTR);if(count>0){AT_DUMP(”<〈",p_read,count)s_readCount+=count;p_read[count]='\0';while(*s_URCBufferCur=='\r'||*s_URCBufferCur=='\n')s_URCBufferCur++;p_eol=findNextEOL(s_URCBufferCur);p_read+=count;}elseif(count<=0){if(count==0){LOGD("atchannel:EOFreached”);}else{LOGD(”atchannel:readerror%s",strerror(errno));}returnNULL;}}ret=s_URCBufferCur;*p_eol='\0';s_URCBufferCur=p_eol+1;LOGD("AT<%s\n”,ret);returnret;}staticvoid*urc_readerLoop(void*arg)//循环读取Response信息{for(;;){constchar*line;line=urc_readline();if(line==NULL){break;}if(isSMSUnsolicited(line)){//如果是短信,则用readline读取,否则用processLine(line)读取char*line1;constchar*line2;line1=strdup(line);line2=readline();if(line2==NULL){break;}if(s_unsolHandler!=NULL){s_unsolHandler(line1,line2);}free(line1);}else{processLine(line);}}onReaderClosed();returnNULL;};MG3732模块读取Response信息,所以在AT命令解析函数at_open中需要有对MG3732模块的宏控制,具体代码在ril/reference-ril/atchannel.cat_open函数中:#ifdefZTE_MG3732//发现ZTE_MG3732模块intfd2=-1;while(fd2<0){fd2=open("/dev/ttyUSB2",O_RDWR);//打开硬件设备if(fd2〈0){perror("openingURCinterface.retrying。..”);sleep(10);}}if(fd2>0){urc_fd=fd2;structtermiosios;tcgetattr(fd2,&ios);ios.c_lflag=0;tcsetattr(fd2,TCSANOW,&ios);}ret=pthread_cr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论