`

android系统学习笔记七

阅读更多

Android电话部分综述

主要部分:

呼叫

短信

数据连接

SIM

电话本

电话部分分为以下几层:

Modem驱动

RIL(radiointerfacelayer)

电话服务框架

应用层

 

 

Modem通信模块

 

Chip-on-board
Modem硬件上一般使用两个渠道:

一个是用于AT命令:一般使用UARTUSB方式,AT命令由Hayes公司发明

AT开头,用于完成调制解调器之间的交互

另一个用于数据传输:通过usb方式传输数据

如果基带与应用处理器集成一般通过共享内存方式传输

 

本地的RIL代码
本地代码的路径:\hardware\ril

部分文件;

include:RIL头文件

Libril:RIL,最终生成libril.so是一个辅助库

Rild:守护进程安装在system/bin目录下

Rdference-ril:参考库,生成动态库libreference-ril.so

Include目录中ril.h头文件是RIL框架结构和接口

 

 

Rild守护进程

Rild是一个可执行程序:获取参数------->r打开功能库------->建立事件循环----------->执行RIL-Init------>register

 

ril.c

staticstructRIL_Envs_rilEnv={

RIL_onRequestComplete,//RIL请求完成

RIL_onUnsolicitedResponse,//主动上报的响应

RIL_requestTimedCallback//用户定义响应的回调函数

};

 

 

主函数部分代码如下:

intmain(intargc,char**argv)

{

...

//获取参数并解析

dlHandle=dlopen(rilLibPath,RTLD_NOW);

//启动线程进入事件循环

RIL_startEventLoop();

rilInit=(constRIL_RadioFunctions*(*)(conststructRIL_Env*,int,char**))dlsym(dlHandle,"RIL_Init");

//处理参数

funcs=rilInit(&s_rilEnv,argc,rilArgv);

RIL_register(funcs);

 

...

}

通过select多路复用机制,读取来自上层的Socket接口的具体操作命令

init.rc中启动这个守护进程,如果使用-l则可以指定所使用的功能库

 

Libril

Libril.so主要提供了用于注册的RIL_register(),

几个回调函数

RIL_onRequestComplete(RIL_Tokent,RIL_Errnoe,void*response,size_tresponselen){}

voidRIL_onUnsolicitedResponse(intunsolResponse,void*data,size_tdatalen){}

staticUserCallbackInfo*internalRequestTimedCallback(RIL_TimedCallbackcallback,void*param,

conststructtimeval*relativeTime){}

字符串转换函数

extern"C"constchar*requestToString(intrequest);

extern"C"constchar*failCauseToString(RIL_Errno);

extern"C"constchar*callStateToString(RIL_CallState);

extern"C"constchar*radioStateToString(RIL_RadioState);

 

 

 

 

RIL的实现库ReferenceRIL

libreference-ril.so功能库的一个参考实现,完成从具体电话服务命令到实际的AT命令之间的转换

 

Request请求流程

首先由java层通过socket将命令发送到RIL层的RILD守护进程,负责监听的ril_event_loop消息循环中

RILDSocket有了请求链接信号,会建立起一个record_system,打通与上层的数据通道开始接收请求数据

数据通道的回调函数processCommandsCallback()会保证收到一个完整的Request(Request包的完整性由record_stream的机制保证),将其送达processCommandBuffer()函数,

staticint

processCommandBuffer(void*buffer,size_tbuflen){

Parcelp;

status_tstatus;

int32_trequest;

int32_ttoken;

RequestInfo*pRI;

intret;

 

p.setData((uint8_t*)buffer,buflen);

 

//statuscheckedatend

status=p.readInt32(&request);

status=p.readInt32(&token);

 

if(status!=NO_ERROR){

LOGE("invalidrequestblock");

return0;

}

 

if(request<1||request>=(int32_t)NUM_ELEMS(s_commands)){

LOGE("unsupportedrequestcode%dtoken%d",request,token);

//FIXMEthisshouldperhapsreturnaresponse

return0;

}

 

 

pRI=(RequestInfo*)calloc(1,sizeof(RequestInfo));

 

pRI->token=token;

pRI->pCI=&(s_commands[request]);

 

//互斥量上锁

ret=pthread_mutex_lock(&s_pendingRequestsMutex);

assert(ret==0);

 

pRI->p_next=s_pendingRequests;

s_pendingRequests=pRI;

 

//互斥量解锁

ret=pthread_mutex_unlock(&s_pendingRequestsMutex);

assert(ret==0);

 

/*sLastDispatchedToken=token;*/

 

//调用分派函数

pRI->pCI->dispatchFunction(p,pRI);

 

return0;

}

processCommandBuffer()函数正式进入命令的解析流程它从socket中序列化的数据流里还原信息,将其组织到RequestInfo,每个命令将以下形式存在

typedefstructRequestInfo{

int32_ttoken;//thisisnotRIL_Token

CommandInfo*pCI;

structRequestInfo*p_next;

charcancelled;

charlocal;//responsestolocalcommandsdonotgobacktocommandprocess

}RequestInfo;

在还原出来的信息中,最重要的是request号它在RIL层和上层之间,ril_commands.h中定义

/**Index==requestNumber*/

staticCommandInfos_commands[]={

#include"ril_commands.h"

};

RIL层中采用表驱动方式分派请求,分派的基础是ruquest,头文件按以下方式被包含

 

commandInfo结枸表示命令信息,关联了request号和实际的请求函数,及响应函数之间的关系

typedefstruct{

intrequestNumber;

void(*dispatchFunction)(Parcel&p,structRequestInfo*pRI);

int(*responseFunction)(Parcel&p,void*response,size_tresponselen);

}CommandInfo;

 

接下来的分发流程,

s_callbacks.onReauest()完成这一操作,s-callbacks是获取libreference-rilRILRadioFunctions的结构指针,请求在这里转入底层libreference-ril处理,handlerreferece-ril.cRequest

例如:RIL——REQUEST——DIAL请求流程如下

onRequest()---->requestDial()-这里将命令和参数转换成对应的AT命令----------->at_send_connand------->at_command_full()------>at_send_command_full_nolock()---->writeline()

 

 

Response流程

 

RIL的移植工作

当宏RIL——SHLIB被定义时,将使用库的行式,

没有被定义时,将使用守护进程的方式

移植需要考虑的问题:

RIL设备所使用的不同端口

RIL_RadioFunctionsonRequest函数中需要处理的不同命令(差异部分在数据连接和呼叫状态查询等方面)

 

 

电话部分Java框加及应用

代码路径为:\frameworks\base\telephony\java

 

Java层与RIL本地代码的接口,是一个名为rildsocket接口

RIL.java中的几个类

RILRequest代表一个电话服务命令请求

RILSender负责命令的发送

RILReceiver处理信命令响应和主动上报信息的响应

 

RILConstants.java定义了电话报务的具体命令

 

classRILRequest{

staticRILRequestobtain(intrequest,Messageresult){}

voidrelease(){}

StaticvoidresetSerial(){}

StringserialString(){}

voidonError(interror,Objectret){}

}

 

RILRIL.RIL_SenderRIL.RILReceiver几个类的关系

publicfinalclassRILextendsBaseCommandsimplementsCommandsInterface{}

Connamds为命令响应或主动上报提供回调函数的注册机制

commandInterface提供具体的电话服务接口

RILJava中一个命令的发送标准流程是:

RILRequest.obtain--->复制参数----->通过send()函数发送EVENT_SEND----->RILSender线程中处理EVENT_SEND------>将命令写到outstream(socket)

 

Socket的取得,是在RILReceiver中建立

staticfinalStringSOCKET_NAME_RIL="rild";

s=newLocalSocket();

l=newLocalSocketAddress(SOCKET_NAME_RIL,

LocalSocketAddress.Namespace.RESERVED);

s.connect(l);

响应和主动上报消息的流程:

RILReceiver线程监视mSocketinput------>readRilMessage(读取完整响应)---------->processResponse---------->分别处理RESPONSE_UNSOLICITEDRESPONSE_SOLICITED(前者为主动上报,后者为命令响应)

 

注:sendprocessResponse是异步的,电话服务的发送和响应是异步的

RIL直接同RIL本地代码打交道,对上层应用来说他并不是直接的接口,GSMPhone.java他继承了PhoneBase,phoneBase实现了phone接口,GSMPhoneRIL进行了一层封装,通过phone接口来实现功能

 

Phone应用程式序中:

通过PhoneFactory来获取GSMPhone

流程是:

PhoneFactory.makeDefaultPhones------>PhoenFactory.useNewRIL------>PhoneFactory.registerPhone

然后Phone就可以获取GSMPhone的实例(Phone接口)

 

拔打电话和获取网络状态,是由telephonyManager来完成

TelephoneManager通过两个IBander接口ITelephonyITelephonyRegistry来完成

ITelephony是电话服务的用户主动进行RIL访问的路径(如拔打电话),它的服务实现类不在框架代码中,而在phone应用中phoneInterfaceManager.java

ITelephonyRegistry提供一个通知机制,将底层状态或变更通知给电话服务如网络状态/信号强弱

底层通知的来源是GSMPhone通过PhoneNotifier的实现者DefaultPhoneNotifier.java

telephonyRegistry通过两种方式通知用户

一种是Broadcast

另一种是在TelephoneRegistry.java中注册的IPhoneStateListener接口实现回调机制

interfaceITelephonyRegistry{

voidlisten(Stringpkg,IPhoneStateListenercallback,intevents,booleannotifyNow);

}

传递的是IPhoneStateListenercallback参数

呼叫

 

ITelephony接口实现在Phone应用中的phone服务,通过TelephonyManager提供访问接口

服务内部通过PhoneFactory获取GSMPhone来访问URI提供如拔号/接通/挂断

在呼叫部分中,GSMPhoneRIL的路径中用到的几个数据结构如下:

GSMCall基本的呼叫控制结构,每个接通的GSMCall都拥有一个GSMConnection结构

GSMConnection该结构用于存放呼叫时长等信息

CallTracker是呼叫模块的核心它提供与呼叫相关的接口

GSMPhone拥有CallTracker的实例,通过调用CommandsInterface实现

 

维护当前的GSMCall,实现追踪的方法为:pollCallsWhenSafe

getCurrentCalls取得当前活动的呼叫列表

 

 

 

短信部分

 

 

 

 

SMSManager实现短信的发送与sim卡短信相关的操作通过ISms接口实现对应操作

ISms的服务端实现是:simsmsInterfaceManager

SMSDispatacher是短信的核心部分,负责发送接收短信,同样也集成在GSMPhone

发送方面

提供了textpdu两种方式.SmsTracker跟踪短信的发送过程

发送结果根据PendingIntent回传

接收方面

SMSDispatcher启动时会通过CommandInterface注册新短信和返回报告的回调接口

mCm.setOnNewSMS(this,EVENT_NEW_SMS,null);

mCm.setOnSmsStatus(this,EVENT_NEW_SMS_STATUS_REPORT,null);

mCm.setOnIccSmsFull(this,EVENT_ICC_FULL,null);

mCm.registerForOn(this,EVENT_RADIO_ON,null);

 

有新消息上来时,相应的消息会被发送到SMSDispatcher的消息处理函数

dispatchMessage会读取SMSHeader分析是否需要拼接,完在后由dispatchPdus通过

Intentintent=newIntent(Intents.SMS_REJECTED_ACTION);

intent.putExtra("result",result);

mWakeLock.acquire(WAKE_LOCK_TIMEOUT);

mContext.sendBroadcast(intent,"android.permission.RECEIVE_SMS");

广播出去

 

 

数据联接

Android数据联接是通过ppp方式实现的

数据联接分两个步骤:

首先是通过AT命令激活PDP联接

pppd通过数据端口完成拔号联接

GSMPhone拥有其实例,基入口点是:

DataConnectionTrackr.trySetupData------>setupData------->pdpConnection.connect------>commandsInterface.setupDefaultPDP

数据连接部分的结构

 

注:pppd是一个单独的进程,需要在init.rc里注册此服务

 

 

 

 

 

分享到:
评论

相关推荐

    Android 系统相关学习笔记.zip

    Android 系统相关学习笔记.zip

    android系统模块之Contacts的学习笔记

    android系统模块之Contacts的学习笔记

    android开发学习笔记

    本人做android也有两年了,主要做智能机系统级开发,期间也承包了一些项目,对于如何学好android,以及学好android后如何开启自己的致富之门也能起到抛砖引玉的作用,欢迎大家加入,积极发言讨论,积极解决他人的...

    Android学习笔记.doc Android学习笔记.doc

    Android platform是一个用于开发移动程序的软件包,它包括了操作系统、中间件及一些关键应用。开发者能使用android SDK为Android platform开发应用,这些应用使用JAVA语言书写,运行在虚拟机Dalvik(一个专为手机程序...

    Pro Android学习:Menu

    是Pro Android学习笔记Menu系统的例子代码

    android入门学习笔记-永远不变的helloworld、初识activity

    本资源是上课时的笔记,系统的讲述了android。想学习andorid的新手可以载下来供参考使用

    Android知识系统总结+最佳学习线路图+实例+全程开发笔记

    Android知识系统总结+最佳学习线路图+实例+全程开发笔记Android知识系统总结+最佳学习线路图+实例+全程开发笔记

    Android学习笔记.doc

    Android platform是一个用于开发移动程序的软件包,它包括了操作系统、中间件及一些关键应用。开发者能使用android SDK为Android platform开发应用,这些应用使用JAVA语言书写,运行在虚拟机Dalvik(一个专为手机程序...

    android 系统笔记.zip

    操作系统:LInux、IOS、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络...

    android 学习笔记

    使用系统自带意图对象完成: Intent intent=new Intent(); intent.setAction("android.intent.action.Call"); intent.setData(Uri.parse("tel:"+i)); startActivity(Intent); 权限: &lt;uses-permission ...

    黑马程序员之android学习笔记--用户界面 View(一).docx

    黑马程序员之android学习笔记--用户界面 View(一).docx

    Android知识系统总结

    里面包含7个常见android应用程序源代码,android学习笔记,开发入门实践,入门书籍等很有用的资料。

    Android Map开发基础知识学习笔记

    本教程适用于Android Map学习的初学者,这是一本很平易近人的Android入门书籍,也是开发者及非开发者两相宜的实务书籍,它能陪伴你顺利入门,并驰骋于无限宽广的Android系统和应用领域

    第一行代码—Android第二版学习笔记

    Android 第一行代码学习笔记第一章 概述1.1安卓系统架构1.2Android四大组件1.3项目结构1.4app目录结构1.5 项目运行原理1.6 res目录详解1.7日志工具的使用第二章 活动2.1 创建基本活动2.2 使用Intent在活动之间跳转...

    Android学习笔记之——Content Providers

    之前博文《 Android学习笔记之——Android Studio的安装(3.6版本)、Java的基本语法及Android的概述 》曾经介绍过android有四大组件。本博文学习一下Content Providers(内容提供器) 目录 Android运行时 ...

    2021-学习相关-Android 局域网简易云端笔记系统源码.zip

    2021-学习相关-Android 局域网简易云端笔记系统源码.zip

    AOSP Android系统定制裁剪笔记.zip

    操作系统:LInux、IOS、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络...

    android移植到特定平台学习笔记

    android移植到Cortex-A8平台,手把手开发步骤,从安装编译器,配置环境变量,编译uboot,kernel,android文件系统详细步骤和修改的文件。最后是将镜像烧入SD卡等详细步骤!好东西不容错过

    Android代码-Android_Learning_Notes

    这是我的安卓学习笔记。 开始时间:2016-9-11 计划:一个半月 文章目录: 基础知识 1、Android01--搭建Android开发环境 2、Android02--认识Activity 3、Android03--Context和Application 4、Android04--Android服务 ...

Global site tag (gtag.js) - Google Analytics