智能电话会议系统(11)---Android 6.0 Phone 多方通话流程
Android 6.0 Phone 多方通话流程
写在前面的话
本文主要分析Voice Call多方通话的流程,分析GSM和CDMA在多方通话不同的地方,研究的代码是Android 6.0的,目前只关注framework层。
1. 多方通话的概念
下面引用来自《百度百科》的一段文字:
多方通话的发起流程是:主席方用户A先呼叫参与方用户B,B用户接通呼叫,形成一个典型的两人通话的基本呼叫场景,此后A用户通过终端菜单发起保持B用户呼叫的请求,此时B用户会听到一段背景音乐,并且与A用户的通话暂时断开,主席方A用户紧接着呼叫另一个参与方C用户,在与C用户建立了一个基本通话之后,由A用户发起建立多方通话的业务请求,此时B用户听到的背景音乐将会取消,A、B、C三方加入到一个多方通话中来,他们每个人都可以听到其他两人的话音。其他的四方通话、五方通话的建立过程与此类似。
在明确了多方通话的概念之后,下面我们就来分析多方通话的整个过程吧
本文来自本文来自http://blog.csdn.net/linyongan ,转载请务必注明出处。,转载请务必注明出处。
2. 多方通话的流程(GSM)
如果图片看不清的话,可以右键选择在新标签中打开图片
多方通话主要分成四个部分:
- A呼叫B,B接电话,A与B开始通话。
- A再呼叫C,A与B的通话变成HOLDING,C接电话。
- 点击“合并”按钮,建立多方通话。
- 挂断电话。
2.1 A呼叫B,B接通电话
拨打电话的流程,在Android 5.1 Phone MO(去电)流程分析(应用层) 和《 Android 5.1 Phone MO(去电)流程分析(Framework层) 》 里已经详细介绍过了,如果还没有看过这两篇文章的童鞋,建议先看看这两篇文章啦。
2.2 A呼叫C,并且Hold住B
2.2小节又可以细分成三部分:
- 用户输入C的号码,点击拨号按钮,流程从应用层一直走到Framework层(即来到GsmCallTracker.java的dial()方法里,步骤2~5)。
- 将A与B的通话switch成HOLDING状态。
- 调用RIL.java的dial()方法发起RIL_REQUEST_DIAL请求(步骤12~15)。
其中第一部分和第三部分跟上面说的MO(去电)流程是一样的,所以这里重点讲解第二部分(步骤6~11)
在GsmCallTracker.java的dial()方法里
/* The new call must be assigned to the foreground call.That call must be idle, so place anything that'sthere on hold */
if (mForegroundCall.getState() == GsmCall.State.ACTIVE) {/* this will probably be done by the radio anywaybut the dial might fail before this happensand we need to make sure the foreground call is clearfor the newly dialed connection */switchWaitingOrHoldingAndActive();/* This is a hack to delay DIAL so that it is sent out to RIL only afterEVENT_SWITCH_RESULT is received. We've seen failures when adding a new call tomulti-way conference calls due to DIAL being sent out before SWITCH is processed */try {Thread.sleep(500);} catch (InterruptedException e) {// do nothing}/* Fake local state so thata) foregroundCall is empty for the newly dialed connectionb) hasNonHangupStateChanged remains false in thenext poll, so that we don't clear a failed dialing call */fakeHoldForegroundBeforeDial();
}
上面的代码做了两件事:
1.当发现ForegroundCall正处于ACTIVE状态,用户又要发起DIAL请求,则调用switchWaitingOrHoldingAndActive()方法把当前的ForegroundCall变成Holding状态。
2.并且让线程休眠500毫秒,目的是延迟DIAL请求的下发,等待RIL上报REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(但是,即便延迟了500毫秒,但是并不能确保在RIL上报REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE之后才下发DIAL请求)
其实第三部分(步骤12~15)还有些值得注意的地方,就是Call的状态变化。ID为1的Call一直都处于HOLDING状态,而ID为2的Call就从DIALING—->ALERTING—->ACTIVE变化。等待A与C的通话建立,就变成id=1,HOLDING;id=2,ACTIVE
状态(步骤15),此时Foreground Call是A与C,Background Call就是A与B,此时B是听不到A与C对话的。
2.3 建立多方通话merge as a conference call
用户点击建立多方通话的按钮之后,流程一直走,从应用层走到PhoneUtils.java的mergeCalls()方法里
static void mergeCalls(CallManager cm) {int phoneType = cm.getFgPhone().getPhoneType();if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {省略...} else {try {log("mergeCalls(): calling cm.conference()...");cm.conference(cm.getFirstActiveBgCall());} catch (CallStateException ex) {Log.w(LOG_TAG, "mergeCalls: caught " + ex, ex);}}}
在这里会对Phone的类型做判断,这里分析的是GSM多方通话流程,所以走进else语句,依次调CallManager.java—->GSMPhone.java—->GsmCallTracker.java的conference()方法(步骤16~19),最后调用RIL.java的conference()方法向RILC发送RIL_REQUEST_CONFERENCE请求建立多方通话(步骤20)。
2.4 挂断电话
对于GSM的话,多方通话中的电话是可以一通一通地挂断的;而CDMA的话,点击挂断按钮,就把所有电话都挂断。
3. 多方通话的流程(CDMA)
如果图片看不清的话,可以右键选择在新标签中打开图片
3.1 A呼叫B,B接通电话
同2.1节。
3.2 A呼叫C,并且Hold住B
拨号流程从应用层走到framework层,
在CdmaCallTracker.javaCdmaCallTracker.java的dial 方法里的流程就有点不一样了(步骤5)
Connection dial (String dialString, int clirMode) throws CallStateException { ...// The new call must be assigned to the foreground call.// That call must be idle, so place anything that's// there on holdif (mForegroundCall.getState() == CdmaCall.State.ACTIVE) {return dialThreeWay(dialString);}...
}private Connection dialThreeWay (String dialString) {if (!mForegroundCall.isIdle()) {// Check data calldisableDataCallInEmergencyCall(dialString);// Attach the new connection to foregroundCallmPendingMO = new CdmaConnection(mPhone,checkForTestEmergencyNumber(dialString), this, mForegroundCall);// Some network need a empty flash before sending the normal onem3WayCallFlashDelay = mPhone.getContext().getResources().getInteger(com.android.internal.R.integer.config_cdma_3waycall_flash_delay);if (m3WayCallFlashDelay > 0) {mCi.sendCDMAFeatureCode("", obtainMessage(EVENT_THREE_WAY_DIAL_BLANK_FLASH));} else {mCi.sendCDMAFeatureCode(mPendingMO.getAddress(),obtainMessage(EVENT_THREE_WAY_DIAL_L2_RESULT_CDMA));}return null;
}
如果发现当前ForegroundCall的状态是ACTIVE,则进入dialThreeWay()方法里,然后调用RIL.java的sendCDMAFeatureCode()方法发出RIL_REQUEST_CDMA_FLASH请求(注意,这次拨号并没有发出RIL_REQUEST_DIAL请求,也没有switch A与B那通电话的状态)
3.3 merge call
建立多方通话,从PhoneUtils.java的mergeCallsmergeCalls方法开始
static void mergeCalls(CallManager cm) {int phoneType = cm.getFgPhone().getPhoneType();if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {log("mergeCalls(): CDMA...");PhoneGlobals app = PhoneGlobals.getInstance();if (app.cdmaPhoneCallState.getCurrentCallState()== CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) {// Set the Phone Call State to conferenceapp.cdmaPhoneCallState.setCurrentCallState(CdmaPhoneCallState.PhoneCallState.CONF_CALL);// Send flash cmd// TODO: Need to change the call from switchHoldingAndActive to// something meaningful as we are not actually trying to swap calls but// instead are merging two calls by sending a Flash command.log("- sending flash...");switchHoldingAndActive(cm.getFirstActiveBgCall());}}else {try {log("mergeCalls(): calling cm.conference()...");cm.conference(cm.getFirstActiveBgCall());} catch (CallStateException ex) {Log.w(LOG_TAG, "mergeCalls: caught " + ex, ex);}}}
依次调PhoneUtils.java—->CallManager.java—->CDMAPhone.java的switchHoldingAndActive()方法(步骤14~16)。
接着调CdmaCallTracker.java的switchWaitingOrHoldingAndActive()方法(步骤17)
void switchWaitingOrHoldingAndActive() throws CallStateException {// Should we bother with this check?if (mRingingCall.getState() == CdmaCall.State.INCOMING) {throw new CallStateException("cannot be in the incoming state");} else if (mForegroundCall.getConnections().size() > 1) {flashAndSetGenericTrue();} else {// Send a flash command to CDMA network for putting the other party on hold.// For CDMA networks which do not support this the user would just hear a beep// from the network. For CDMA networks which do support it will put the other// party on hold.mCi.sendCDMAFeatureCode("", obtainMessage(EVENT_SWITCH_RESULT));}
}
最后还是调用RIL.java的sendCDMAFeatureCode()方法发出RIL_REQUEST_CDMA_FLASH请求(步骤20)。(最后把两通电话合并成一通电话?这个问题还需继续深究。根据挂断电话时一次性把所有通话都挂断,可推测只有一通电话)
3.4 挂断电话
对于CDMA的话,与GSM不同。点击挂断按钮,就把所有电话都挂断。
4 扩展的问题
假如多方通话已建立,那么这时候再拨打紧急电话会怎样?紧急电话能拨通吗?
PS:GSM网络下,iphone5S是把多方通话挂断,然后再拨紧急电话;安卓如果想实现这样的效果,还需自己修改代码。
智能电话会议系统(11)---Android 6.0 Phone 多方通话流程相关推荐
- Android 6.0 Phone 多方通话流程
写在前面的话 本文主要分析Voice Call多方通话的流程,分析GSM和CDMA在多方通话不同的地方,研究的代码是Android 6.0的,目前只关注framework层. 1. 多方通话的概念 下 ...
- 基于感应器的智能求救系统----以android为例实现
基于感应器的智能求救系统----以android为例实现 基于感应器的智能求救系统是由android实验小组研发的一款基于android手机系统以及汽车硬件的能够通过感应外界温度.压力.初速度就可 ...
- Android 9.0 SIM卡初始化流程
转载:https://blog.csdn.net/linyongan/article/details/51406123 本文主要讲述Android 9.0 SIM卡初始化流程,这个过程也涉及到UICC ...
- Android 最新 ios 11,差异性越来越小!iOS 11/Android 8.0最新系统对比
北京时间9月13日凌晨1点,苹果在他的新飞船总部举办新品发布会.会上除了发布了一系列的智能设备外,更是发布了iOS 11操作系统的正式版本.iOS 11版本在今年6月份的苹果开发者大会正式亮相,但是之 ...
- 联想K系引领智能电视潮流,Android 4.0将成行业标配
现在,随着智能电视的普及,电视机正从平板时代向互联网时代甚至向目前的智能时代跨越,电视正在成为家庭的智能娱乐终端.笔者上周撰写的<联想完成PC+战略布局,K系智能电视打响"家庭争夺战& ...
- android 7.0电视,将智能电视升级到Android 7.0有什么经验?为索尼用户祝福
尽管Android 7.0系统很早以前就已正式发布,但实际上,由于Android设备的严重碎片化,并不是所有的Android设备都可以在第一时间进行升级,因此,实际上现在已经安装了Android 7. ...
- android 4.0系统,全新Android 4.0系统_手机Android频道-中关村在线
与搭载Android 2.3系统的OPPO R807不同,OPPO R817搭载了Android 4.0系统.不过这款手机仍旧舍弃了Android系统的原生界面,因此两款手机在界面上的变化其实并不非常 ...
- Android 系统(11)---android 系统权限大全
收集到的android权限都很实用的(permission)大全 1.android.permission.WRITE_USER_DICTIONARY 允许应用程序向用户词典中写入新词 2.andro ...
- android改变系统语言,Android 9.0设置系统语言
1.系统权限 android:sharedUserId="android.uid.system" 2.签名 通过手动签名的方式,用系统的签名文件为程序签名解决签名的问题,将程序加入 ...
最新文章
- SqlSessionFactoryBean的构建流程
- 什麽样的资料集不适合用深度学习?
- 《FusionCharts学习及使用笔记》之 第一篇
- “拼图”化解智慧城市“碎片化”难题
- kdj指标主要看哪个值_终于有人把KDJ指标总结全了,值得收藏
- 激光雷达的KPI与技术方案
- 计算机基础与C语言程序设计书籍,C语言程序设计(21世纪高等学校计算机基础实用规划教材)...
- Selenium TestNG Java环境搭建过程中所遇问题汇总
- 基于C#的学生选课管理系统
- 为啥外包喜欢php,为什么要面向对象?
- 13.SpringBoot学习(十三)——JDBC之 Spring Boot Jpa多数据源
- EtherCAT从站协议栈代码笔记之ecat_def.h
- 一叶知秋:“安全“的野指针、 static函数、成员函数、this 指针、gcc编译器、name mangling...
- 数字健康-共建共享 火绒安全将亮相2021中华医院信息网络大会(CHINC)
- 【JHOK-ZBZ201型智能型剩余电流继电器】
- 【2016年第4期】基于仿真大数据的效能评估指标体系构建方法
- Unity-URP 实现遮挡高亮
- 批量删除 txt 记事本文本文件中的某一行或一些行
- 无人驾驶1——自动驾驶硬件、软件概述
- WPS中设置参考文献自动插入和更新