1.目录架构(20101215的git版本):
其中include/telephony目录下面的ril.h文件,定义了104个如下的宏:
RIL_Request_XXX这些宏代表客户进程向Android telephony发送的命令,包括SIM卡相关的功能,打电话,发短信,网络信号查询等等。
2.目录hardware/ril/libril
本目录下代码负责与客户进程进行交互。在接收客户进程命令后,调用相应函数进行处理,然后将命令响应结果传回客户进程。在收到来自网络端的事件后,也传给客户进程。
RIL_register函数:打开监听端口,接收来自客户进程的命令请求 (s_fdListen =android_get_control_socket(SOCKET_NAME_RIL);),当与某客户进程连接建立时,调
用 listenCallback函数;创建一单独线程监视并处理所有事件源(通过ril_event_loop)
processCommandsCallback函数:具体处理来自客户进程的命令请求。对每一个命令,ril_commands.h中都规定了对应的命令处理函数(dispatchXXX),
processCommandsCallback会调用这个命令处理函数进行处理。
response系列函数:对每一个命令,都规定了一个对应的response函 数来处理命令的最终响应;对每一个网络端的事件,也规定了一个对应的response函数来处理此事
件。response函数可被 onUnsolicitedResponse或者onRequestComplete调用。
3. 目录hardware/ril/reference-ril分析:
本目录下代码主要负责与modem进行交互。onRequest 函数:在这个函数里,对每一个 RIL_REQUEST_XXX请求,都转化成相应的ATcommand,发送给modem,然后睡眠等待。当收到此ATcommand的最终响应
后,线 程被唤醒,将响应传给客户进程(RIL_onRequestComplete-> sendResponse)。
onUnsolicited函数:这个函数处理modem从网络端收到的各种事件,如网络信号变化,拨入的电话,收到短信等。然后将时间传给客户进程
(RIL_onUnsolicitedResponse -> sendResponse)
at_send_command_full_nolock函数:运行在主线程里面。将一个ATcommand命令写入modem后进入睡眠状态(使用pthread_cond_wait或类似函数),直到modem读
线程将其唤醒。唤醒后此函数获得了ATcommand的最终响应并返回。
readerLoop函数: 运行在一个单独的读线程里面,负责从modem中读取数据。读到的数据可分为三种类型:网络端传入的事件;modem对当前ATcommand的部分响 应;
modem对当前AT command的全部响应。对第三种类型的数据(ATcommand的全部响应),读线程唤醒(pthread_cond_signal)睡眠状态的主线 程。
第二部分, Java代码
Android中,telephony相关的java代码主要在下列目录中:目录telephony/java/com/android/internal/telephony和services/java/com/android/server中的代码提供一系列内部接口,目前第三方应用还不能使用。当前似乎
只有packages/apps/Phone能够使用
目录 packages/apps/Phone是一个特殊应用,或者理解为一个平台内部进程。其他应用通过intent方式调用这个进程的服务。1. ITelephony, 提供与telephony进行操作,交互的接口,在packages/apps/Phone中由PhoneInterfaceManager.java实现。
2. ITelephonyRegistry,提供登记telephony事件的接口。由frameworks/base/services/java/com/android/server/TelephonyRegistry.java实现。
classBaseCommands是CommandsInterface的直接派生类,实现了电话事件的处理(发送message给对应的handler)。
classRIL又派生自BaseCommands。 RIL负责实际实现CommandsInterface中的接口方法。RIL通过Socket和rild守护进程进行通讯。对于每一个命令接口方法,
如 acceptCall,或者状态查询,将它转换成对应的RIL_REQUEST_XXX,发送给rild。线程RILReceiver监听socket, 当有数据上报时,读取该数据并处理。读取的数据有两种,
1. 电话事件,RIL_UNSOL_xxx, RIL读取相应数据后,发送message给对应的handler(详见函数processUnsolicited)2. 命令的异步响应。(详见函数processSolicited)
interface Phone描述了对电话的所有操作接口。 PhoneBase直接从Phone派生而来。而另外两个类,CDMAPhone和GSMPhone,又从PhoneBase派生而来,分别代表对
CDMA和GSM的操作。
PhoneProxy也从Phone直接派生而来。当当前不需要区分具体是CDMA Phone还是GSMPhone时,可使用PhoneProxy。DefaultPhoneNotifier从PhoneNotifier派生而来。在其方法实现中,通过调用serviceITelephonyRegistry来发布电话事件。
serviceITelephonyRegistey由frameworks/base/services/java/com/android/server/TelephonyRegistry.java实现。这个类通过广播intent,从而触发对应的
broadcastreceiver。
在PhoneApp创建时,
sPhoneNotifier = newDefaultPhoneNotifier(); ... sCommandsInterface = newRIL(context, networkMode, cdmaSubscription);
然后根据当前phone是cdma还是gsm,创建对应的phone,如
sProxyPhone = newPhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier));下面我们来研究一个电话打出去的流程。
TwelveKeyDialer.java, onKeyUp() TwelveKeyDialer.java, placeCall() OutgoingCallBroadcaster.java, onCreate() sendOrderedBroadcast(broadcastIntent, PERMISSION, new OutgoingCallReceiver(), null, Activity.RESULT_OK, number,null); OutgoingCallBroadcaster.java, OutgoingCallReceiver doReceive-> context.startActivity(newIntent); InCallScreen.java, onCreate/onNewIntent InCallScreen.java, placeCall PhoneUtils.java, placeCall GSMPhone.java, dial GsmCallTracker.java, dial RIL.java, dialRIL::getCurrentCalls RILRequestrr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS,result); ... send(rr);下面来研究一个incoming call的流程:
1. 创建GsmPhone时:
mCT = new GsmCallTracker(this);2. 创建GsmCallTracker时:
cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE,null); mCallStateRegistrants.add(r);3. RIL中的RILReceiver线程首先读取从rild中传来的数据:
processResponse-> processUnsolicited4. 对应于incoming call,RIL收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息,触发mCallStateRegistrants中的所有记录。
5.GsmCallTracker处理EVENT_CALL_STATE_CHANGE,调用pollCallsWhenSafe
6. 函数pllCallsWhenSafe 处理:
lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT); cm.getCurrentCalls(lastRelevantPoll);7.RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); ... send(rr);8.接着RIL调用processSolicited处理RIL_REQUEST_GET_CURRENT_CALLS的返回结果
9.GsmCallTracker的handleMessage被触发,处理事件EVENT_POLL_CALLS_RESULT,调用函数 handlePollCalls
10. handlPollCalls 调用
phone.notifyNewRingingConnection(newRinging);11. PhoneApp中创建CallNotifier
12. CallNotifier注册:
registerForNewRingingConnection ->mNewRingingConnectionRegistrants.addUnique(h, what, obj);