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方法更新界面。

远程挂断电话流程分析相关推荐

  1. Android 7.0 挂断电话流程分析

    1.图形显示 挂断电话分为本地挂断和远程对方挂断 2.本地挂断 1).点击按钮 先看按键的监听事件 CallCardFragment.java 中有对按钮的监听事件 @Overridepublic v ...

  2. Android 5.1 Phone 挂断电话流程分析

    写在前面的话 本文主要分析Android挂断电话的流程,研究的代码是Android 5.1的,以CDMA为例,GSM同理. 挂断电话主要分两种情况: 本地主动挂断电话 \color{red}{本地主动 ...

  3. android6.0 挂断电话流程分析(一)

    下面是android 6.0挂断电话的流程分析图: 后继续更新挂断回调...........................!

  4. Android挂断电话流程

    近期在友盟上看到许多关于挂断电话导致崩溃的问题,如下异常 java.lang.NoSuchMethodError: No interface method endCall()Z in class Lc ...

  5. android蓝牙耳机来电铃声,Android蓝牙耳机接听挂断电话流程

    一.alps/packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java image.png proc ...

  6. Android挂断电话以及Java Class Loader

    Android中,要自己实现一个挂断电话方法时,很久之前可以endCall().不过现在已经不行了,要应用反射机制,获取到 "android.os.ServiceManager" ...

  7. 安卓隐藏摄像_【快讯:诺基亚发布三款安卓机;全面屏手机的最终形态,目标是去掉摄像头;iPhone 打电话不息屏或挂断电话后不亮屏是什么问题?】...

    资讯一 [诺基亚发布三款安卓新机:带来了可拆后盖设计] 2月25日,诺基亚在MWC 2019正式召开发布会,发布了诺基亚4.2.诺基亚3.2.诺基亚1 Plus三款全新安卓机型. 其中诺基亚4.2是三 ...

  8. 挂断电话的实现(即类似于电话号码黑名单)

    在文章的开头先列出以下需要注意的地方: 1.需要用到的权限如下: <uses-permission android:name="android.permission.READ_PHON ...

  9. 黑名单挂断电话及删除电话记录

    黑名单挂断电话及删除电话记录 挂断电话 挂断电话需要申请权限android.permission.CALL_PHONE 对于黑名单号码的来电如何挂断,由于监听来电时在TelephonyManager中 ...

最新文章

  1. 《主算法》作者Pedro Domingos:做机器学习硬件不能只考虑深度学习
  2. POJ 3225 Help with Intervals(线段树)
  3. LSTM之父,现已加入鬼畜全明星,“他为啥没得图灵奖,太不公平了!”
  4. 新概念英语(1-137)A pleasant dream
  5. 应用存储和持久化数据卷:核心知识
  6. communication with respect to scholars
  7. idea点击表单按钮不做post反应
  8. SAP Spartacus 电商云 UI Shipping Method 在单元测试环境下没有显示的问题
  9. php最新图片漏洞,2018最新PHP漏洞利用技巧
  10. 作者:杨丽彬,华侨大学信息管理系讲师。
  11. 一文快速理解23种经典设计模式
  12. 西工大18秋《C语言程序设计》平时作业,西工大18秋C语言程序设计平时作业答案...
  13. python爬虫什么意思-python的爬虫是什么意思
  14. python实现深度优先搜索_python 递归深度优先搜索与广度优先搜索算法模拟实现...
  15. 生物学软件大汇总!史上最全
  16. 【数学建模常用模型】分类专题
  17. 三星android安装到sd卡,三星怎么安装sd卡 三星手机怎么安装sim卡
  18. centos7环境下编译bitcoin
  19. 《黑匣子思维:我们如何更理性地犯错》ipad部分
  20. Leetcode:347. 前 K 个高频元素(C++)

热门文章

  1. influxDB的group by time(intervals)
  2. 纽约警察局反恐负责人:苹果这是在给绑匪、强盗提供帮助
  3. 第二届南京六合创业大赛参赛流程|创成汇
  4. [bzoj5018][dp]英雄联盟
  5. KeyShot 10新版本安装操作指南
  6. 【游戏逆向】】游戏全屏捡物的分析实现
  7. 这两部剧,至少99.9%的人都看过,KOOCAN还看了不止3遍
  8. Microsoft edge 浏览器打开是360导航解决方法
  9. 英语语言教学4c,如何进行七年级英语语音教学
  10. js判断运行环境是手机还是 PC