`

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学习笔记 完整版

    Android学习笔记是Android开发者的必读书籍,书中涵盖了Android系统架构、Activity、Intent、资源管理等多方面的知识。本笔记对应的学习资源《第一行代码》是Android开发者的入门必读书籍,书中系统地介绍了Android...

    Android基础学习笔记

    Android基础学习笔记主要涵盖了一系列关于Android开发的基本概念和关键组件,以下是这些知识点的详细解析: 1. **Activity**: 是Android应用程序的基本单元,它代表用户在屏幕上看到的一个界面。每个Activity都必须...

    Android Studio 学习笔记-新手入门-(1)第一个案例

    这篇学习笔记将引导新手入门,通过创建第一个简单的案例来了解Android Studio的基本操作。 首先,让我们了解一下Android Studio的核心功能。它基于IntelliJ IDEA,具备代码自动补全、重构、调试等强大的开发特性。...

    Android Activity学习笔记

    Android Activity学习笔记 Android Activity是Android系统中最基本的组件之一,它负责处理用户交互和显示用户界面。本文将深入讲解Activity的生命周期、Activity之间的数据交互、Activity启动模式、Task和BackStack...

    Android学习新手笔记

    - Android系统基于Linux系统开发,拥有开放源码。 - Android系统框架由多个组件构成,其中包括Activity、Intent、Service、ContentProvider、View和BroadcastReceiver。 - Activity作为组件容器,主要负责用户...

    java学习细节 android学习笔记

    根据给定的信息,我们可以从Java和Android学习笔记中提取出一系列重要的知识点,下面将逐一进行详细解释。 ### Java基础知识 #### 1. 命令行基础操作 - **`javacmd`**: 这个命令是Java命令行工具的一部分,用于...

    Android+学习笔记

    ### Android学习笔记知识点详解 #### 一、简介与背景 Android作为全球最受欢迎的移动操作系统之一,自2007年谷歌发布以来,迅速占领市场并持续引领移动技术的发展。随着移动互联网的兴起和发展,Android应用开发...

    Android_学习笔记

    ### Android学习笔记——从HelloWorld开始 #### 一、Google的Android SDK介绍 自从Google发布了Android SDK以来,这款开源移动操作系统迅速吸引了众多开发者的关注。Android SDK为开发者提供了丰富的工具和API,...

    android全程学习笔记

    Android全程学习笔记旨在提供一个详尽且全面的指南,涵盖了Android开发中的关键技术点和实践案例。以下是关于Android开发的一些核心知识点: 1. **第一个Android应用**:开发Android应用的起点通常是从创建并运行你...

    Android 学习笔记

    这篇学习笔记主要涵盖了关于布局的一些基本概念,特别是`fill_parent`和`wrap_content`这两种尺寸指定方式,以及如何通过XML布局文件来精确控制组件的位置。 首先,`fill_parent`和`wrap_content`是Android布局中的...

    Android_学习笔记.zip

    这个"Android_学习笔记.zip"文件很可能包含了一个详细的Android开发学习路径和关键知识点的总结。下面将基于这个主题,详细讲解Android开发的一些核心概念和技术。 首先,Android是Google开发的一款开源操作系统,...

    Android 系统相关学习笔记.zip

    在Android系统相关学习笔记中,我们可以深入探讨这个广泛而复杂的移动操作系统的核心概念和技术。Android以其开源性和灵活性,吸引了大量的开发者和爱好者。以下是一些关键的知识点: 1. **Android架构**:Android...

    android 很好的学习笔记

    【Android学习笔记详解】 在移动应用开发领域,Android操作系统占据着重要的地位,为开发者提供了...通过系统学习并实践其中的内容,你将能够逐步掌握Android开发的核心技能,为你的Android开发者之路打下坚实的基础。

    Android PreferenceActivity 学习笔记

    这篇学习笔记将深入探讨PreferenceActivity的使用方法、功能以及与源码相关的知识。 首先,PreferenceActivity是Android SDK提供的一种特殊类型的Activity,它允许开发者快速构建具有可配置选项的界面,类似于系统...

    Android开发学习笔记

    ### Android开发学习笔记知识点梳理 #### 一、Android概述与架构 - **定义与发布**:Android是由Google在2007年11月5日宣布的基于Linux平台的开源手机操作系统。它不仅用于智能手机,还广泛应用于平板电脑、可穿戴...

    Android入门学习笔记

    Android入门学习笔记主要涵盖了Android开发的基础知识,包括平台概述、环境搭建、基本概念以及实际应用开发的各个方面。这里我们将深入探讨这些关键知识点。 一、Android平台概述 Android是由Google主导开发的一款...

Global site tag (gtag.js) - Google Analytics