Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程
前置文章:
《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中。InCallActivity的显示则是由Call状态来决定的,Call的状态能够分为6种:ACTIVE、HOLDING、DIALING、ALERTING、INCOMING、WAITING。当发起MO流程而且对方还未接通这段时间。Call的状态是DIALING。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWlob25neXVlbGFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
Telephony Framework接收处理反馈
01-01 18:11:47.039 1061 1061 D RILJ : RIL(1) :[0147]> DIAL
... ...省略
01-01 18:11:47.044 682 692 D use-Rlog/RLOG-AT: AT> ATD13800138000;
01-01 18:11:47.044 682 696 I use-Rlog/RLOG-RIL: RIL_URC2_PROXY wakeup
01-01 18:11:47.044 682 692 D use-Rlog/RLOG-AT: ATD13800138000;
... ...省略
01-01 18:11:47.047 682 707 D use-Rlog/RLOG-AT: OK
01-01 18:11:47.047 682 707 D use-Rlog/RLOG-AT: AT< OK
01-01 18:11:47.047 682 707 D use-Rlog/RLOG-AT: RIL_CMD_READER_2:OK
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT:
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: +CIEV: 5, 1
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT:
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: +ECPI: 1,130,0,0,0,0,"13800138000",129,""
01-01 18:11:47.047 682 707 D use-Rlog/RLOG-AT: RIL_CMD_READER_2 Enter processLine
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: AT< +CIEV: 5, 1
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: RIL_URC_READER:+CIEV: 5, 1
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: RIL_URC_READER Enter processLine
01-01 18:11:47.047 682 707 I use-Rlog/RLOG-AT: AT read start
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-RIL: Nw URC:+CIEV: 5, 1
01-01 18:11:47.047 682 705 E use-Rlog/RLOG-RIL: Unhandled unsolicited result code: +CIEV: 5, 1
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: AT< +ECPI: 1,130,0,0,0,0,"13800138000",129,""
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: RIL_URC_READER:+ECPI: 1,130,0,0,0,0,"13800138000",129,""
01-01 18:11:47.047 682 692 D use-Rlog/RLOG-AT: response received on RIL_CMD_READER_2, tid:3086469296
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: RIL_URC_READER Enter processLine
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-RIL: Nw URC:+ECPI: 1,130,0,0,0,0,"13800138000",129,""
... ...省略
01-01 18:11:47.048 1061 1274 D RILJ : RIL(1) :[0147]< DIAL
01-01 18:11:47.048 1061 1274 V RILJ : RIL(1) :[UNSL RIL]< UNSOL_CALL_PROGRESS_INFO {1, 130, 0, 0, 0, 0, 13800138000, 129, }
这里简单的分析一下重要的log信息:
RIL(1) :[0147]> DIAL
这表示发起DIAL请求。紧接着运行ATD即AT拨号指令:
01-01 18:11:47.044 682 692 D use-Rlog/RLOG-AT: AT> ATD13800138000;
我们在《Android 4.4 Kitkat Phone工作流程浅析(四)__RILJ工作流程简析》文章中有讲过。能够依据serial号查看AT指令的配对。同一时候也提到了Log中的“>”和“<”所代表的含义。即“>”表示request,“<”表示response,上面两条log信息能够解释为RILJ发起了两次request请求。
依据第一条AT指令的serial号"0147"我们能够在后面找到相应的response:
01-01 18:11:47.048 1061 1274 D RILJ : RIL(1) :[0147]< DIAL
这表明整个拨号的request和response已经完毕,在此期间Modem主动返回了下面信息:
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: AT< +ECPI: 1,130,0,0,0,0,"13800138000",129,""
该条AT指令+ECPI是MTK加入的。在标准AT指令中查询不到,详细含义例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWlob25neXVlbGFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
相应着这个表我们来梳理一下
01-01 18:11:47.047 682 705 D use-Rlog/RLOG-AT: AT< +ECPI: 1,130,0,0,0,0,"13800138000",129,""
以上log重要信息例如以下:
01-01 18:11:47.048 1061 1274 V RILJ : RIL(1) :[UNSL RIL]< UNSOL_CALL_PROGRESS_INFO {1, 130, 0, 0, 0, 0, 13800138000, 129, }
这是一条UnSolicited response消息,处理方法是RIL.java中的processUnsolicited(),类型为:UNSOL_PROGRESS_INFO。
RIL.java将处理之后的消息通过notifyRegistrants()的方式传递给GsmCallTracker。在GsmCallTracker的handleCallProcessInfo()方法中能够看到是怎样定义Call状态为DIALING的。代码例如以下:
//... ... 省略部分代码
if (msgType == 132 || msgType == 6)
dc.state = DriverCall.State.ACTIVE;
else if (msgType == 131)
dc.state = DriverCall.State.HOLDING;
else if (msgType == 130 && callId != 254)
//从log中能够看到msgType=130,call_id=1
dc.state = DriverCall.State.DIALING;
else if (msgType == 2)
dc.state = DriverCall.State.ALERTING;
else if (msgType == 0)
{
for (j = 0; j < MAX_CONNECTIONS; j++) {
if (mConnections[j] != null) {
count ++;
}
}
if (mState == PhoneConstants.State.IDLE ||
(count == 0 && mForegroundCall.getState() == GsmCall.State.DIALING))
{
/* if the 2nd condition is true, that means we make a MO call, receiving +ECPI: 130,
* then receiving +ECPI: 133 immediately due to MT call (+ECPI: 0) is receiving*/
if (count == 0 && mForegroundCall.getState() == GsmCall.State.DIALING)
log("MO/MT conflict!!");
dc.state = DriverCall.State.INCOMING;
}
else
dc.state = DriverCall.State.WAITING;
}
当状态改变之后便会通过GsmPhone的notifyPreciseCallStateChanged()方法发起响应。例如以下:
if ((hasNonHangupStateChanged || newRinging != null) && crssAction != CrssAction.SWAP && !(hasPendingReplaceRequest && msgType == 133)) {
log("notify precise call state changed");
mPhone.notifyPreciseCallStateChanged();
}
之后会通过观察者模式方式调用到CallManager的handleMessage()方法中,case为EVENT_PRECISE_CALL_STATE_CHANGED。代码例如以下:
case EVENT_PRECISE_CALL_STATE_CHANGED:
//... ...省略部分代码
index = (msg.what - EVENT_PRECISE_CALL_STATE_CHANGED) / NOTIFICATION_ID_OFFSET;
mPreciseCallStateRegistrantsGemini[index].notifyRegistrants((AsyncResult) msg.obj);
mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
handle3GSwitchLock();
这里会有MTK的Gemini处理,即双卡处理,通过相同的观察者模式将状态改变信息通过notifyRegistrants()方法发送到TeleService中。整个流程例如以下图:
TeleService消息处理
同一时候CallNotifier和CallModeler均注冊了CallStateMonitor的状态改变回调。一旦Call状态改变便会通知CallNotifier和CallModeler。这里CallNotifier并没有做什么大的动作,仅仅是更新了近距离感应器的状态,推断是否接通假设接通则震动这类。跟界面相关的调用则在CallModeler中。
if (!ignoreUpdate()) {
if (updatedCalls.size() > 0) {
for (int i = 0; i < mListeners.size(); ++i) {
mListeners.get(i).onUpdate(updatedCalls);
}
}
}
这里会触发BluetoothManager、CallHandlerServiceProxy、DTMFTonePlayer三个类中的onUpdate()方法回调,这里我们查看CallHandlerServiceProxy中的onUpdate()方法就可以。对于上面的代码再多说几句,原生Android 4.4中,CallModeler的onPhoneStateChanged方法并没有ignoreUpdate()方法,这是MTK增加的主要目的是用于推断是否忽略本次界面更新。用于自己主动拒接和高速挂断正在响铃的电话两种场景。代码例如以下:
/*
* The function to judge whether should skip update calls to InCallUI,
* for auto reject case, or quick hang up ringing case.
* When 1A + 1R, if ringing call is hanged up while query(ringtone),
* CallNotifier will not notify InCallUI the onIncoming(), then we should ignore update calls to InCallUI;
* or will show callcard with ringing call information but no AnswerFragment shown.
*/
private boolean ignoreUpdate() {
boolean shouldIgnore = false;
final boolean hasActiveFgCall = mCallManager.hasActiveFgCall();
final boolean hasActiveBgCall = mCallManager.hasActiveBgCall();
shouldIgnore = (hasActiveFgCall || hasActiveBgCall) && PhoneGlobals.getInstance().notifier.hasPendingCallerInfoQuery();
Log.i(TAG, "ignoreUpdate()... shouldIgnore: " + shouldIgnore);
return shouldIgnore;
}
通过代码能够非常清楚的知道,当CallerInfo没有查询完成时hasPendingCallerInfoQuery()返回true,则忽略本次界面更新。
在CallHandlerServiceProxy的onUpdate()方法中,首先会去运行bindService操作也就是与InCallUI建立联系。代码例如以下:
@Override
public void onUpdate(List<Call> calls) {
synchronized (mServiceAndQueueLock) {
if (mCallHandlerServiceGuarded == null) {
//设置更新类型为METHOD_UPDATE
enqueueUpdate(calls);
//与CallHandlerService建立连接
setupServiceConnection();
return;
}
}
//运行更新
processUpdate(calls);
}
更新类型包含:
Android原生仅仅有前面三种类型,后面均由MTK加入。
InCallUI显示/更新
@Override
public void onUpdate(List<Call> calls) {
try {
Log.i(TAG, "onUpdate: " + calls);
//注意:这里的类型是ON_UPDATE_MULTI_CALL
mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_MULTI_CALL, calls));
} catch (Exception e) {
Log.e(TAG, "Error processing onUpdate() call.", e);
}
}
这里非常奇怪的一点是。类型竟然是ON_UPDATE_MULTI_CALL,而代码中也有ON_UPDATE_CALL类型。这是google原生的。MTK没有改过。不知道是何用意。
/**
* Sends a generic notification to all listeners that something has changed.
* It is up to the listeners to call back to determine what changed.
*/
private void notifyListenersOfChange() {
for (Listener listener : mListeners) {
listener.onCallListChange(this);
}
}
这里会运行listener的回调,分别在AnswerPresenter和InCallPresenter中。CallList仅仅是负责将状态改变通知到listener,是否处理则由listener们自己决定。AnswerPresenter仅仅有在incoming的时候才会处理。因此这里应该查看InCallPresenter的onCallListChange()方法:
@Override
public void onCallListChange(CallList callList) {
if (callList == null) {
return;
}
InCallState newState = getPotentialStateFromCallList(callList);
//这里去推断是否显示/关闭InCallActivity
newState = startOrFinishUi(newState);
//... ...省略部分代码
}
这里会跳转到startOrFinishUi()中进行推断,由于是第一次启动InCallActivity界面。最后会通过startActivity()的方式启动InCallActivity,到此整个InCallActivity的界面显示流程就结束了。兴许Modem側状态改变则依据该流程传递到InCallPresenter,由InCallPresenter来响应不同的状态所须要启动/关闭的界面。整个流程例如以下图:
小结
public void updateCalls() {
final List<Call> updatedCalls = Lists.newArrayList();
doUpdate(true, updatedCalls);
if (!ignoreUpdate()) {
if (updatedCalls.size() > 0) {
for (int i = 0; i < mListeners.size(); ++i) {
mListeners.get(i).onUpdate(updatedCalls);
}
}
}
}
注意:该方法是MTK自己加入的,原生AOSP并没有,假设想使用也能够仿照这样的方式加入。
Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程的更多相关文章
- Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析
本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 本文代码以MTK平台Android 4.4为分析对象.与Google原生AOSP有些许差异.请读者知悉. ...
- Android 4.4 Kitkat Phone工作流程浅析(七)__来电(MT)响铃流程
本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. ...
- 以太网驱动的流程浅析(四)-以太网驱动probe流程【原创】
以太网驱动的流程浅析(四)-以太网驱动probe流程 Author:张昺华 Email:920052390@qq.com Time:2019年3月23日星期六 此文也在我的个人公众号以及<Lin ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(六)---Recovery服务流程细节【转】
本文转载自:http://blog.csdn.net/mu0206mu/article/details/7465439 Android系统Recovery工作原理之使用update.zip升级过程分 ...
- Android 4.4(KitKat)中VSync信号的虚拟化
原文地址:http://blog.csdn.net/jinzhuojun/article/details/17293325 Android 4.1(Jelly Bean)引入了Vsync(Vertic ...
- Android 4.4 KitKat NotificationManagerService使用具体解释与原理分析(二)__原理分析
前置文章: <Android 4.4 KitKat NotificationManagerService使用具体解释与原理分析(一)__使用具体解释> 转载请务必注明出处:http://b ...
- Android 4.4 KitKat 新特性
New in Android 4.4 KitKat 本文是一个概览,关于KitKat,也即Android4.4的新东西,先是功能型的,之后是设计上的. 很多特性本文并没有提到,很多提到的特性也只是简短 ...
- 让你的短信应用迎接Android 4.4(KitKat)
原文地址:Getting Your SMS Apps Ready for KitKat 发送和接收短信是手机最基本的功能,很多的开发者也开发了很多成功的应用来增强Android这一方面的体验.你们当中 ...
- PHP容器--Pimple运行流程浅析
需要具备的知识点 闭包 闭包和匿名函数在PHP5.3.0中引入的. 闭包是指:创建时封装周围状态的函数.即使闭包所处的环境不存在了,闭包中封装的状态依然存在. 理论上,闭包和匿名函数是不同的概念.但是 ...
随机推荐
- Android UI布局之FrameLayout
一个FrameLayout对象就好比一块屏幕上提前预定好的空白区域.然后能够填充一些元素到里边.例如说一张图片等.须要注意的是,全部的元素都被放置在FrameLayout区域最左边上的区域.并且无法为 ...
- mac下显示隐藏文件
一.在终端中 ls -a就可以查看隐藏文件. 显示和隐藏的命令例如以下: 显示:defaults write com.apple.finder AppleShowAllFiles -bool true ...
- js转换ascii编码如中文友转换为编码友;可防止乱码
- 调起qq临时通话
1.在qq推广的网站上的推广工具中将个人或者公司的qq确认为推广qq 2. 选择好显示的图片,将代码拷贝到页面上就可以了
- 传输中文乱码js解决方法
encodeURI要编码两次 var a="我的"; //编译两次 //window.location.href = "http://127.0.0.1:8080/kab ...
- UML学习-时序图
时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的.顺序图中显示的是参与交互的对象及其对象之间消息交互的顺序.时序图中包括的建模元素主要有:对象(Actor) ...
- Glide的加载图片的帮助类,用来把图片圆角或者改成圆形图片
Glide虽然非常好用但是没找到把图片圆角的方法,所以百度了一个非常不错的加载类自己实现圆角图 感谢原文章作者:http://blog.csdn.net/weidongjian/article/det ...
- codeforces 340E Iahub and Permutations(错排or容斥)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Iahub and Permutations Iahub is so happy ...
- python单元测试--深入理解unittest
单元测试的重要性就不多说了,可恶的是python中有太多的单元测试框架和工具,什么unittest, testtools, subunit, coverage, testrepository, nos ...
- css元素隐藏(display:none和visibility:hidden)
在css中, display:none和visibility:hidden都能够使元素隐藏.但是两者所带来的效果完全不同. css display:none 当使用该样式的时候,HTML元素的宽高等 ...