远程挂断电话流程分析
3,远程挂断电话流程分析
3.1 services Telephony
当远程挂断/拒接电话时,GsmCallTracker的handlePollCalls 方法有关代码如下,
if (mDroppedDuringPoll.size() > 0) {mCi.getLastCallFailCause(obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE));
}
由于不是主动发起的挂断流程,因此会向RIL发送消息获取通话断开的cause,
RIL的getLastCallFailCause方法如下,
public void getLastCallFailCause (Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
注意,此时封装了EVENT_GET_LAST_CALL_FAIL_CAUSE消息。
向ril库发送RIL_REQUEST_LAST_CALL_FAIL_CAUSE消息,ril处理查询完成之后,返回上报结果, processSolicited方法中
对该消息处理如下,
1,读取消息处理结果,
case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: ret = responseFailCause(p); break;
responseFailCause方法如下,
private Object responseFailCause(Parcel p) {LastCallFailCause failCause = new LastCallFailCause();failCause.causeCode = p.readInt();if (p.dataAvail() > 0) {failCause.vendorCause = p.readString();}return failCause;
}
返回的是LastCallFailCause对象。
2,分发消息给对应的注册类处理,
if (rr.mResult != null) {AsyncResult.forMessage(rr.mResult, ret, null);rr.mResult.sendToTarget();
}
GsmCallTracker的handleMessage方法中对EVENT_GET_LAST_CALL_FAIL_CAUSE消息处理如下,
1,首先获取结果,也就是断开的原因,
LastCallFailCause failCause = (LastCallFailCause)ar.result;
causeCode = failCause.causeCode;
vendorCause = failCause.vendorCause;
2,调用GsmConnection的onRemoteDisconnect继续处理,
for (int i = 0, s = mDroppedDuringPoll.size(); i < s ; i++ ) {GsmConnection conn = mDroppedDuringPoll.get(i);conn.onRemoteDisconnect(causeCode, vendorCause);
}updatePhoneState();//更新phone状态
mPhone.notifyPreciseCallStateChanged();
mDroppedDuringPoll.clear();
GsmConnection的onRemoteDisconnect方法调用流程图如下,
onRemoteDisconnect方法如下,
void onRemoteDisconnect(int causeCode, String vendorCause) {this.mPreciseCause = causeCode;this.mVendorCause = vendorCause;onDisconnect(disconnectCauseFromCode(causeCode));
}
在onDisconnect方法中,又会调用GSMPhone的notifyDisconnect方法,该方法如下,
void notifyDisconnect(Connection cn) {mDisconnectRegistrants.notifyResult(cn);mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause());
}
在父类PhoneBase中注册mDisconnectRegistrants的方法为registerForDisconnect,
public void registerForDisconnect(Handler h, int what, Object obj) {checkCorrectThread(h);mDisconnectRegistrants.addUnique(h, what, obj);
}
同样的, TelephonyConnection的setOriginalConnection方法中调用了PhoneBase的registerForDisconnect方法,
getPhone().registerForDisconnect(mHandler, MSG_DISCONNECT, null);
TelephonyConnection的内部变量mHandler的handleMessage方法对该消息处理如下,
case MSG_DISCONNECT:updateState();break;
调用带参数的updateState方法,
void updateState() {updateState(false);
}
updateState方法如下,
1,获取当前的Call状态,
Call.State newState = mOriginalConnection.getState();
2,根据状态分别进行处理,
switch (newState) {case IDLE:break;
case ACTIVE:
•••
如果是断开状态,调用setDisconnected方法进一步处理,
setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(mOriginalConnection.getDisconnectCause(),mOriginalConnection.getVendorDisconnectCause()));
3,更新信息已经相关状态,
updateStatusHints();
updateConnectionCapabilities();
updateAddress();
updateMultiparty();
setDisconnected方法在父类Connection中实现,如下,
public final void setDisconnected(DisconnectCause disconnectCause) {checkImmutable();mDisconnectCause = disconnectCause;setState(STATE_DISCONNECTED);Log.d(this, "Disconnected with cause %s", disconnectCause);for (Listener l : mListeners) {l.onDisconnected(this, disconnectCause);}
}
mListeners变量中保存了所有注册的监听器,
private final Set<Listener> mListeners = Collections.newSetFromMap(new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
并且是在addConnectionListener方法中添加监听器的,
public final Connection addConnectionListener(Listener l) {mListeners.add(l);return this;
}
再看ConnectionService的addConnection方法,
private void addConnection(String callId, Connection connection) {mConnectionById.put(callId, connection);mIdByConnection.put(connection, callId);connection.addConnectionListener(mConnectionListener);connection.setConnectionService(this);
}
调用了Connection的addConnectionListener方法注册mConnectionListener变量,
因此当Connection中的setDisconnected调用监听器的onDisconnected方法时,会调用ConnectionService的
mConnectionListener的onDisconnected方法。
在此注意的是, ConnectionService只是一个抽象类,其实运行的是子类TelephonyConnectionService。还是在
services Telephony进程中,并没有跨进程调用。
ConnectionService的mConnectionListener变量是一个匿名内部类,
private final Connection.Listener mConnectionListener = new Connection.Listener() {
其onDisconnected方法如下,
public void onDisconnected(Connection c, DisconnectCause disconnectCause) {String id = mIdByConnection.get(c);Log.d(this, "Adapter set disconnected %s", disconnectCause);mAdapter.setDisconnected(id, disconnectCause);
}
ConnectionServiceAdapter的setDisconnected方法如下,
void setDisconnected(String callId, DisconnectCause disconnectCause) {for (IConnectionServiceAdapter adapter : mAdapters) {try {adapter.setDisconnected(callId, disconnectCause);} catch (RemoteException e) {}}
}
Adapter其实是一个跨进程调用, adapter 指services telecom进程中的ConnectionServiceWrapper的内部类Adapter。
3.2 services telecom
ConnectionServiceWrapper的内部类Adapter定义如下,
private final class Adapter extends IConnectionServiceAdapter.Stub {
调用流程图如下,
Adapter的setDisconnected方法如下,
if (call != null) {mCallsManager.markCallAsDisconnected(call, disconnectCause);
}
CallsManager的setCallState方法如下,
if (mCalls.contains(call)) {for (CallsManagerListener listener : mListeners) {if (Log.SYSTRACE_DEBUG) {Trace.beginSection(listener.getClass().toString() + " onCallStateChanged");}listener.onCallStateChanged(call, oldState, newState);if (Log.SYSTRACE_DEBUG) {Trace.endSection();}}updateCallsManagerState();
}
调用监听器的onCallStateChanged方法更新界面。
远程挂断电话流程分析相关推荐
- Android 7.0 挂断电话流程分析
1.图形显示 挂断电话分为本地挂断和远程对方挂断 2.本地挂断 1).点击按钮 先看按键的监听事件 CallCardFragment.java 中有对按钮的监听事件 @Overridepublic v ...
- Android 5.1 Phone 挂断电话流程分析
写在前面的话 本文主要分析Android挂断电话的流程,研究的代码是Android 5.1的,以CDMA为例,GSM同理. 挂断电话主要分两种情况: 本地主动挂断电话 \color{red}{本地主动 ...
- android6.0 挂断电话流程分析(一)
下面是android 6.0挂断电话的流程分析图: 后继续更新挂断回调...........................!
- Android挂断电话流程
近期在友盟上看到许多关于挂断电话导致崩溃的问题,如下异常 java.lang.NoSuchMethodError: No interface method endCall()Z in class Lc ...
- android蓝牙耳机来电铃声,Android蓝牙耳机接听挂断电话流程
一.alps/packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java image.png proc ...
- Android挂断电话以及Java Class Loader
Android中,要自己实现一个挂断电话方法时,很久之前可以endCall().不过现在已经不行了,要应用反射机制,获取到 "android.os.ServiceManager" ...
- 安卓隐藏摄像_【快讯:诺基亚发布三款安卓机;全面屏手机的最终形态,目标是去掉摄像头;iPhone 打电话不息屏或挂断电话后不亮屏是什么问题?】...
资讯一 [诺基亚发布三款安卓新机:带来了可拆后盖设计] 2月25日,诺基亚在MWC 2019正式召开发布会,发布了诺基亚4.2.诺基亚3.2.诺基亚1 Plus三款全新安卓机型. 其中诺基亚4.2是三 ...
- 挂断电话的实现(即类似于电话号码黑名单)
在文章的开头先列出以下需要注意的地方: 1.需要用到的权限如下: <uses-permission android:name="android.permission.READ_PHON ...
- 黑名单挂断电话及删除电话记录
黑名单挂断电话及删除电话记录 挂断电话 挂断电话需要申请权限android.permission.CALL_PHONE 对于黑名单号码的来电如何挂断,由于监听来电时在TelephonyManager中 ...
最新文章
- 《主算法》作者Pedro Domingos:做机器学习硬件不能只考虑深度学习
- POJ 3225 Help with Intervals(线段树)
- LSTM之父,现已加入鬼畜全明星,“他为啥没得图灵奖,太不公平了!”
- 新概念英语(1-137)A pleasant dream
- 应用存储和持久化数据卷:核心知识
- communication with respect to scholars
- idea点击表单按钮不做post反应
- SAP Spartacus 电商云 UI Shipping Method 在单元测试环境下没有显示的问题
- php最新图片漏洞,2018最新PHP漏洞利用技巧
- 作者:杨丽彬,华侨大学信息管理系讲师。
- 一文快速理解23种经典设计模式
- 西工大18秋《C语言程序设计》平时作业,西工大18秋C语言程序设计平时作业答案...
- python爬虫什么意思-python的爬虫是什么意思
- python实现深度优先搜索_python 递归深度优先搜索与广度优先搜索算法模拟实现...
- 生物学软件大汇总!史上最全
- 【数学建模常用模型】分类专题
- 三星android安装到sd卡,三星怎么安装sd卡 三星手机怎么安装sim卡
- centos7环境下编译bitcoin
- 《黑匣子思维:我们如何更理性地犯错》ipad部分
- Leetcode:347. 前 K 个高频元素(C++)
热门文章
- influxDB的group by time(intervals)
- 纽约警察局反恐负责人:苹果这是在给绑匪、强盗提供帮助
- 第二届南京六合创业大赛参赛流程|创成汇
- [bzoj5018][dp]英雄联盟
- KeyShot 10新版本安装操作指南
- 【游戏逆向】】游戏全屏捡物的分析实现
- 这两部剧,至少99.9%的人都看过,KOOCAN还看了不止3遍
- Microsoft edge 浏览器打开是360导航解决方法
- 英语语言教学4c,如何进行七年级英语语音教学
- js判断运行环境是手机还是 PC