前置文章:
《 Android 4.4 Kitkat Phone工作流程浅析(一)__概要和学习计划 》《Android 4.4 Kitkat Phone工作流程浅析(二)__UI结构分析》
《Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析》
《Android 4.4 Kitkat Phone工作流程浅析(四)__RILJ工作流程简析》
《Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析》
《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》
概述
本系列文章以MT/MO为主线流程,并对其中的细枝末节进行补充说明,比如来电响铃流程。在MT流程的分析中已经涵盖了流程的发起与终止,本文所描述的响铃流程始于MT流程的发起,如对MT流程不熟悉的童鞋请查看文章《Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析》以及《Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程》。
Android 4.4对于响铃流程有所改动,把响铃触发放到了TeleService中,这也符合4.4 Phone的设计风格即UI和Logic分离。当来电流程发起时,抓取radio_log进行分析后,可以看到整个来电过程状态改变如下:
- handleMessage (EVENT_VOICE_CALL_INCOMING_INDICATION) //设置voice call的标志
- handleMessage (EVENT_NEW_RINGING_CONNECTION) //新来电标志
- handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED) //状态改变
- handleMessage (EVENT_INCOMING_RING) //响铃
- handleMessage (EVENT_CRSS_SUPP_SERVICE_NOTIFICATION) //收到AT指令CLIP后,更新通话信息(CLIP即来电显示作用)
- handleMessage (EVENT_INCOMING_RING)
- handleMessage (EVENT_CRSS_SUPP_SERVICE_NOTIFICATION)
- handleMessage (EVENT_INCOMING_RING)
- handleMessage (EVENT_CRSS_SUPP_SERVICE_NOTIFICATION)
- handleMessage (EVENT_INCOMING_RING)
- handleMessage (EVENT_CRSS_SUPP_SERVICE_NOTIFICATION)
- handleMessage (EVENT_INCOMING_RING)
- handleMessage (EVENT_CRSS_SUPP_SERVICE_NOTIFICATION)
- handleMessage (EVENT_DISCONNECT) //断开连接
- handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED) //状态改变
- handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)
当Modem侧收到来电消息后所做的操作如下:
1. 根据来电类型设置INCOMING_INDICATION;
2. 发起NEW_RINGING_CONNECTION,新来电标志;
3. 触发CALL_STATE_CHANGED状态,状态改变促使界面更新;
4. 发起响铃通知INCOMING_RING,响铃流程由此发起;
5. 根据CLIP返回信息触发CRSS_SUPP_SERVICE_NOTIFICATION,这是由MTK加入的,其作用是根据CLIP的返回更新Call的信息;
6. 循环上面4和5步,持续响铃;
7. 断开连接DISCONNECT,本次MT流程结束(未接听);
8. 触发CALL_STATE_CHANGED状态,状态改变促使界面更新;
Telephony Framework处理响铃事件
RILJ
在MT流程发起后,会有相关的unsolicited信息反馈到RILJ中,这里主要关注响铃流程(ringing_flow),因此可以找到以下AT指令返回的log信息:
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT: +CRING: VOICE
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT:
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT: +CLIP: "13800138000",0,"",0,"",0
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT:
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT: +ECPI: 1,4,0,1,1,0,"13800138000",129,""
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT: AT< +CRING: VOICE
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT: RIL_URC_READER:+CRING: VOICE
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-AT: RIL_URC_READER Enter processLine
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-RIL: Nw URC:+CRING: VOICE
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-RIL: receiving RING!!!!!!
- 01-01 02:46:01.154 4753 4768 D use-Rlog/RLOG-RIL: receiving first RING!!!!!!
整个radio_log中每隔3877ms便会打印一次+CRING: VOICE的log,通话挂断前一共有5次。根据AT返回信息可以知道,来电类型为Voice,并且是一次响铃事件。紧接着在RILJ中收到了与之对应的事件RIL_UNSOL_CALL_RING:
- 01-01 02:46:02.155 1443 1837 D RILJ : RIL(2) :[UNSL RIL]< UNSOL_CALL_RING [C@422899d0
这里是UnSolicited事件,触发processUnsolicited方法,并执行到以下代码处:
- case RIL_UNSOL_CALL_RING:
- if (RILJ_LOGD) unsljLogRet(response, ret);
- if (mRingRegistrant != null) {
- //观察者模式
- mRingRegistrant.notifyRegistrant(
- new AsyncResult (null, ret, null));
- }
首先查看到mRingRegistrant的定义在SourceCode/frameworks/opt/telephony/src/java/com/android/internal/telephony/BaseCommands.java中,且赋值在setOnCallRing方法中,如下:
- @Override
- public void setOnCallRing(Handler h, int what, Object obj) {
- mRingRegistrant = new Registrant (h, what, obj);
- }
- mCi.setOnCallRing(this, EVENT_CALL_RING, null);
需要注意两点:
(1). PhoneBase extends Handler,因此setOnCallRing中的this即代表了PhoneBase本身。换句话说,当触发notifyRegistrant时,便会回调到PhoneBase的handleMessage中;
(2). setOnCallRing中的EVENT_CALL_RING表示当触发notifyRegistrant时,回调handleMessage中的相应case;
mRingRegistrant注册流程
当Phone第一次启动时便会执行PhoneFactory中的makeDefaultPhone()方法,用于完成Phone的初始化,在初始化过程中即完成了mRingRegistrant的注册。
PhoneBase
当执行mRingRegistrant.notifyRegistrant()方法后,跳转到PhoneBase的handleMessage方法中,代码如下:
- case EVENT_CALL_RING:
- ar = (AsyncResult)msg.obj;
- if (ar.exception == null) {
- PhoneConstants.State state = getState();
- if ((!mDoesRilSendMultipleCallRing)
- && ((state == PhoneConstants.State.RINGING) ||
- (state == PhoneConstants.State.IDLE))) {
- mCallRingContinueToken += 1;
- sendIncomingCallRingNotification(mCallRingContinueToken);
- } else {
- //执行这里
- notifyIncomingRing();
- }
- }
- break;
- private void notifyIncomingRing() {
- if (!mIsVoiceCapable)
- return;
- AsyncResult ar = new AsyncResult(null, this, null);
- mIncomingRingRegistrants.notifyRegistrants(ar);
- }
- @Override
- public void registerForIncomingRing(
- Handler h, int what, Object obj) {
- checkCorrectThread(h);
- mIncomingRingRegistrants.addUnique(h, what, obj);
- }
- if (FeatureOption.MTK_GEMINI_SUPPORT == true && !(phone instanceof SipPhone)) {
- if(phone instanceof GeminiPhone) {
- int offset; <span style="white-space:pre"> </span>
- int count = (MAXIMUM_SIM_COUNT < PhoneConstants.GEMINI_SIM_NUM) ? MAXIMUM_SIM_COUNT : PhoneConstants.GEMINI_SIM_NUM;
- Phone targetPhone;
- for (int i = 0; i < count; i++) {
- offset = i * NOTIFICATION_ID_OFFSET;
- targetPhone = ((GeminiPhone)phone).getPhonebyId(PhoneConstants.GEMINI_SIM_1 + i);
- //... ...省略
- targetPhone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING + offset, null);
通过上面CallManager中的代码可以知道:
(1). mHandler在CallManager中定义,相关handleMessage即可找到;
(2). case对应事件为:EVENT_INCOMING_RING;
mIncomingRingRegistrants注册流程
mIncomingRingRegistrants的注册流程始于Phone启动并初始化时,需要关注的一点是CallManager中的registerForPhoneStates()方法。为什么这里直接从CallManager跳转到PhoneBase呢?实际上targetPhone对象是通过PhoneProxy传递过来的,而PhoneProxy是GSMPhone和CDMAPhone的代理,GSMPhone和CDMAPhone都继承自PhoneBase,最终的实现也在PhoneBase中,这里省略了部分跳转,请读者知悉。
CallManager
根据前面的分析,在PhoneBase的notifyIncomingRing()方法中会调用mIncomingRingRegistrants.notifyRegistrants()方法,可以找到在CallManager中对应的handleMessage方法以及对应的处理事件EVENT_INCOMING_RING:
- @Override
- public void handleMessage(Message msg) {
- int index;
- switch (msg.what) {
- //... ...省略
- case EVENT_INCOMING_RING:
- case EVENT_INCOMING_RING + NOTIFICATION_ID_OFFSET:
- case EVENT_INCOMING_RING + (NOTIFICATION_ID_OFFSET * 2):
- case EVENT_INCOMING_RING + (NOTIFICATION_ID_OFFSET * 3):
- if (!hasActiveFgCall()) {
- index = (msg.what - EVENT_INCOMING_RING) / NOTIFICATION_ID_OFFSET;
- mIncomingRingRegistrantsGemini[index].notifyRegistrants((AsyncResult) msg.obj);
- mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
- }
- break;
- //mIncomingRingRegistrantsGemini的registe方法
- public void registerForIncomingRingEx(Handler h, int what, Object obj, int simId){
- int index = getRegistrantsArrayIndex(simId);
- if (index != -1) {
- mIncomingRingRegistrantsGemini[index].addUnique(h, what, obj);
- }
- }
- //mIncomingRingRegistrants的registe方法
- public void registerForIncomingRing(Handler h, int what, Object obj){
- mIncomingRingRegistrants.addUnique(h, what, obj);
- }
- public static void registerForIncomingRing(Handler handler, int what, Object obj) {
- if (GeminiUtils.isGeminiSupport()) {
- final int[] geminiSlots = GeminiUtils.getSlots();
- for (int geminiSlot : geminiSlots) {
- <span style="white-space:pre"> </span> //双卡
- CallManager.getInstance().registerForIncomingRingEx(handler, what, obj,
- geminiSlot);
- }
- } else {
- <span style="white-space:pre"> </span>//单卡
- CallManager.getInstance().registerForIncomingRing(handler, what, obj);
- }
- }
- public static void registerForIncomingRing(Handler handler, int what) {
- registerForIncomingRing(handler, what, null);
- }
- CallManagerWrapper.registerForIncomingRing(this, PHONE_INCOMING_RING);
通过以上分析我们可以知道:
(1). 在CallStateMonitor中注册了来电响铃回调,也就是这里的this。CallStateMonitor继承自Handler,那么CallManager中的notifyRegistrants()方法会跳转到CallStateMonitor中;
(2). 对应的case事件为:PHONE_INCOMING_RING;
mIncomingRingRegistrantsGemini注册流程
整个注册流程是从TeleService启动时开始的,TeleService有监听BOOT_COMPLETE的广播,在随机启动之后便开始了整个注册流程。在第8步需要注意,双卡执行CallManager.getInstance().registerForIncomingRingEx(),单卡则执行CallManager.getInstance().registerForIncomingRing()。
TeleService处理响铃
CallStateMonitor
- @Override
- public void handleMessage(Message msg) {
- for (Handler handler : registeredHandlers) {
- handler.handleMessage(msg);
- }
- }
CallNotifier
- @Override
- public void handleMessage(Message msg) {
- //... ...省略
- case CallStateMonitor.PHONE_INCOMING_RING:
- log("PHONE_INCOMING_RING !");
- if (msg.obj != null && ((AsyncResult) msg.obj).result != null) {
- //... ...省略
- if (provisioned && !isRespondViaSmsDialogShowing()) {
- mRinger.ring();
- }
- } else {
- if (DBG) log("RING before NEW_RING, skipping");
- }
- }
- break;
Ringer
- void ring() {
- synchronized (this) {
- //... ...省略
- //创建Looper线程,用于播放/停止铃声,通过handleMessage接收播放/停止请求
- makeLooper();
- //如果是第一次播放则mFirstRingEventTime = -1
- if (mFirstRingEventTime < 0) {
- //这里获取系统开机后经过的时间,包括休眠
- mFirstRingEventTime = SystemClock.elapsedRealtime();
- if (mRingHandler != null) {
- //发起播放铃声的请求
- mRingHandler.sendEmptyMessage(PLAY_RING_ONCE);
- }
- } else {
- //如果不是第一次播放
- if (mFirstRingStartTime > 0) {
- if (mRingHandler != null) {
- //延迟发送播放请求,延迟时间为第一次启动播放时间减去第一次发送PLAY_RING_ONCE的时间(133ms)
- mRingHandler.sendEmptyMessageDelayed(PLAY_RING_ONCE,
- mFirstRingStartTime - mFirstRingEventTime);
- }
- } else {
- mFirstRingEventTime = SystemClock.elapsedRealtime();
- }
- }
- }
- }
makeLooper()方法主要创建一个ringer的线程,用于播放/停止铃声,代码如下:
- private void makeLooper() {
- //如果第一响铃mRingThread==null
- if (mRingThread == null) {
- //Worker实现了Runnable接口,在其构造方法Worker(String name)
- //中创建并启动了名为"ringer"的工作线程
- mRingThread = new Worker("ringer");
- //若还未获取到ringer线程的Looper对象则返回
- if (mRingThread.getLooper() == null) {
- return ;
- }
- //创建Handler并依附于ringer线程的Looper对象
- mRingHandler = new Handler(mRingThread.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- Ringtone r = null;
- switch (msg.what) {
- case PLAY_RING_ONCE:
- if (DBG) log("mRingHandler: PLAY_RING_ONCE...");
- if (mRingtone == null && !hasMessages(STOP_RING)) {
- // create the ringtone with the uri
- if (DBG) log("creating ringtone: " + mCustomRingtoneUri);
- r = RingtoneManager.getRingtone(mContext, mCustomRingtoneUri);
- synchronized (Ringer.this) {
- if (!hasMessages(STOP_RING)) {
- mRingtone = r;
- }
- }
- }
- r = mRingtone;
- if (r != null && !hasMessages(STOP_RING) && !r.isPlaying()) {
- PhoneLog.d(LOG_TAG, "play ringtone... ");
- PhoneUtils.setAudioMode();
- //播放铃声
- r.play();
- synchronized (Ringer.this) {
- //将第一次播放时间(开机后的时间包括休眠)赋值给mFirstRingStartTime
- if (mFirstRingStartTime < 0) {
- mFirstRingStartTime = SystemClock.elapsedRealtime();
- }
- }
- }
- break;
- case STOP_RING:
- if (DBG) log("mRingHandler: STOP_RING...");
- r = (Ringtone) msg.obj;
- if (r != null) {
- //停止播放铃声
- r.stop();
- } else {
- if (DBG) log("- STOP_RING with null ringtone! msg = " + msg);
- }
- //退出Looper循环
- getLooper().quit();
- break;
- private class Worker implements Runnable {
- //创建mLock锁
- private final Object mLock = new Object();
- private Looper mLooper;
- Worker(String name) {
- //创建并启动名为"name"的线程
- Thread t = new Thread(null, this, name);
- t.start();
- synchronized (mLock) {
- while (mLooper == null) {
- try {
- //阻塞直到前面的"name"线程已成功运行(执行了run方法),最大阻塞时间5s
- mLock.wait(5000);
- } catch (InterruptedException ex) {
- }
- }
- }
- }
- public Looper getLooper() {
- //返回"name"线程的Looper对象
- return mLooper;
- }
- public void run() {
- synchronized (mLock) {
- //启用Looper
- Looper.prepare();
- //返回当前线程(也就是这里的子线程"name")的Looper对象
- mLooper = Looper.myLooper();
- //唤醒锁,不再阻塞
- mLock.notifyAll();
- }
- //开启Looper循环
- Looper.loop();
- }
- public void quit() {
- //退出Looper循环
- mLooper.quit();
- }
- }