概述
VoiceCall就是我们通常所说的打电话是基于系统中Telephony框架的具体应用情景,Telephony中涉及的其他通讯功能有ServiceState(服务状态)、DataConnection(数据链接)、SMS(短信),这篇文章重点讲解Call(通话)
1.MO(Mobile Origination Call)主叫,操作流程:拨号,启动UI界面,更新通话状态;
2.MT(Mobile Termination Call)被叫,操作流程:响铃,启动UI界面,更新通话状态。
VoiceCall框架
VoiceCall是一个可以通话的手机功能,Android系统中的VoiceCall的组成结构主要由下面几部分构成
1.Dialer(IncallUI) 为用户交互操作提供UI界面
2.Telephony Service 封装了控制,查询Telephony等功能
3.Telephony Framework 提供通话各种功能调用和状态查询,负责上层和Modem的通信
4.RIL 负责拨号,Sip,package收发等基本操作
具体个模块详细信息请查看下表:
| 模块名称 | 模块路径 | 模块功能 |
|---|---|---|
| Dialpad | packages/apps/Dialer/ | 拨号盘 |
| CallLog | packages/apps/Dialer/ | 通话记录。其中显示的信息是从数据库中读出来的。在通话结束时,会将Call的信息存储到CallLog数据库中。 |
| InCallUI | packages/apps/Dialer/ | 通话中的画面显示,在Android原生设计中,该模块只处理界面相关的内容。 |
| TeleService | packages/services/Telephony | TeleService Framework 和 TeleCom Framework沟通的介质。 |
| CallSettings | packages/services/Telephony | 里面多数是增值服务(SS)的设置,设置的过程中,会向MODEM侧发请求。比如:呼叫转移(CF)。 |
| TeleCom | packages/services/Telecomm | App侧维护Call,call的相关处理都在TeleCom中进行。 |
| TeleService FW | frameworks/opt/telephony | 和RIL通信,完成Call的基本通话功能以及其他相关业务。 |
| Telecom FW | frameworks/base/telecom | 确保TeleCom的独立性,减少TeleCom和其他模块的直接交互。 |
VoiceCall流程
主要代码介绍
在学习VoiceCall的流程之前,先总结一下通话流程中的主要代码分布和作用
| 路径 | 主要代码文件 | 代码功能介绍 |
|---|---|---|
| packages/apps/Dialer | DialpadFragment.java | 拨号盘界面 |
| packages/apps/Dialer | InCallScreen.java | 通话界面(通话信息、状态显示,通话控制按钮) |
| packages/services/Telecomm | NewOutgoingCallIntentBroadcaster.java | 接收CALL、CALL_PRIVILEGED、CALL_EMERGENCY类型的ACTION,发送ACTION_NEW_OUTGOING_CALL广播 |
| packages/services/Telephony | PhoneApp.java | 创建Phone对象,控制耳机、蓝牙、感应器、背景灯和Call状态等 |
| packages/services/Telephony | PhoneUtils.java | 通话控制辅助类 |
| packages/services/Telephony | CallNotifier.java | 电话应用程序模块,用于侦听电话状态更改以及来自电话层的各种其他事件,并触发任何生成的UI行为(例如启动Incoming Call UI,播放通话音,更新通知,编写通话记录条目等) |
| frameworks/opt/telephony | Phone.java | Phone对象的抽象接口 |
| frameworks/opt/telephony | CallManager.java | 为PhoneApp提供了一个访问和控制调用的抽象层,负责Framework和APP层的交互 1.呼叫控制和操作,例如dial()和hangup()2.通道功能,例如CanConference()3.注册通知 |
| frameworks/opt/telephony | CallTracker.java | 和RIL.java交互,发起Call相关请求、跟踪Call状态 |
| frameworks/opt/telephony | ServiceStateTracker.java | 和RIL.java交互,跟踪服务状态变化,并发起相关消息通知,SIM卡注册服务,SIM卡状态,手机信号等功能 |
| frameworks/opt/telephony | DcTracker.java | 和RIL.java交互,跟踪数据链接相关状态 |
| frameworks/opt/telephony | RIL.java | 和RIL(native)交互,完成AT命令执行,Call状态更新 |
| frameworks/base/telephony | TelephonyManager.java | 提供对设备上telephony services信息的访问 |
| hardware/ril | ril.cpp | native层的RIL环境 |
| hardware/ril | rild.c | RILD守护进程 |
主动呼叫(MO)
对于熟悉Android O之前RIL的开发者来说,Android O上RIL最大的改变就是将socket通信换成了binder通信,只不过是/dev/hwbinder,而不是/dev/binder。Binder IPC的开发模式是服务端注册service, 客户端获取service,然后调用相关API。Server端RILD不再是socket监听,而是注册service; RILJ也不再是连接socket,而是获取service,持有引用。通信方式的改变导致RILD和RILJ都发生了改变,但是这个变化并不算大,以前的轮廓还在。
被动接听(MT)
2.2 Voice Call中的基本概念:
要了解Voice Call,需要熟悉其中的基本概念。Voice Call的几个基本概念包括:
Phone:Phone是一个最基本的概念,用来控制Telephony相关模块的处理
Call:此处是TeleService中的Call,是用来管理Connection的,有且仅有三种Call存在:foregroundcall, backgroundcall, ringingcall
CallList:App侧会维护Call的CallList,如果CallList变更,界面会做出对应的响应操作
Connection: 一个通路。
Call和Connection并不是一一对应的,一个Connection必须要依附于一个Call, 一个Call可以有多个Connection。在多方通话中,一个Call会对应多个Connection。最多可以同时有7个Connection存在,对于一个Call中最多有5个Connection。
Example 2-2 最多允许的connection数
1 2 |
static final int MAX_CONNECTIONS = 7; // only 7 connections allowed in GSM static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call |
Call的基本状态如下:
DIALING,CONNECTING,ACTIVE,ON_HOLD,DISCONNECTING,DISCONNECTED,RINGING
2.3 各模块之间的调用关系
Voice Call中有很多模块,这里我们会介绍各模块之间的调用关系:
在上图中,TeleCom Service接受到应用发来的Intent之外,通过TeleCom Framework进行通信。
其中TeleCom Service 以及 TeleCom Framewokr,我们统称为Telecom,其主要负责所有Call的业务逻辑。上层APP(InCallUI)接触到的Phone、Call以及Connection对象,实际上是Telecom Framework的Phone、Call和Connection对象,并不是Telephony Framework中的GSMPhone、GsmCall和GsmConnection。
其中,Telecom Framework,负责通话数据的传递以及控制指令的下发。而Telecom Service中的CallsManager则负责所有通话数据以及指令的处理,并将结果传递给TelecomFramework。
对于CallSetting,需要发消息到网络。TeleCom模块仅用于处理Call相关的操作,所以把CallSetting放在TeleService中,和MODEM通信比较方便。
2.4 Android侧Call中的关键机制介绍:
消息***制:
在TeleService和TeleService Framework中采用的是消息***制。
消息***制更加丰富了MessageHandle的流程,它把过程严格阶段化了,分成消息注册和通知消息处理两个部分,让人一目了然。
消息***制的总体思想是:一个对象中开辟一个空间用于存放Message,当调用regist方法时将Message存放进去,当其调用notify方法时将所有Message取出并发送到MessageQueue中等待处理。
这里用到了观察者模式,下面是TeleService里面的消息***制的对比。
注:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
模式中的角色
抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
3 Voice Call主要流程
这里会介绍Voice Call的主要流程,包括:MO,MT
3.1 MO Call时序图:
3.2 MT Call时序图: