背景
以下内容基于Android P code。
应用框架设计
Android电话模块是一个典型的分层结构设计,如下:
IMS在CS通话的基础上增加了telephony/ims net/ims vendor/ims 和ims相关的media模块。
其中:
telephony/ims:主要包括了对外接口ImsPhone,通话管理中心ImsPhoneCallTracker,某一路通话ImsPhoneCall,某一路通话连接ImsPhoneConnection。需要实现的提供IMS相关服务的ImsService。
net/ims:主要包括提供了IMS services API的ImsManager,以及ImsManager创建的负责处理 IMS语音和视频通话连接的ImsCall。
vendor/ims:主要包括了ImsService的实现类,提供ims相关的服务。负责和modem和media打交道,这一模块由各个芯片厂商定制,所以各个芯片厂商的实现方式都不同。但都有一个实现 ImsService的类。
IMS service
IMS的服务类,telephony通过ImsResolver来和绑定它。它的实现类必需在AndroidManifest中对它进行注册以便fw检测到它。
其主要结构如下:
主要包括 ImsService、ImsManager、MmTelFeatureConnection、ImsCallSession。其中:
ImsService:ims的Service,实现了所有的ImsFeature(MmTelFeature和RcsFeature)和ims协议行为。通过ImsResolver绑定。由ImsServiceController来负责管理其生命周期及这个service所支持的ImsFeatures。其主要操作可以通过IImsServiceController来调用。
ImsManager:单例类。提供了与IMS services交互的API,如创建ims call。这个类是所有ims相关操作的起点。
MmTelFeatureConnection:IImsServiceController binder的容器类。
ImsCallSession:负责ImsCall的发起和终止,以及两个ims端点间的媒体交换。它和ImsService直接交互。
其service的绑定过程如下:
可以看到,phone进程在创建后由ImsResolver通过ImsServiceController来绑定service,service返回IImsServiceController给ImsServiceController,然后通过这个binder来创建IImsMmTelFeature的binder。之后可以通过TelephonyManager来获取IImsMmTelFeature的binder,用它可以获取IImsCallSession的binder。
具体的绑定流程如下:
应用间进程交互
交互方式如下:
在android o之前phone和ril的交互是通过socket,android o之后改成了HIDL。其余进程间的交互都是通过AIDL,具体交互方式如图:
其中,phone到modem的过程,CS Call是由RILRequest通过HIDL调用IRadio.hal再到modem,IMS Call是由ImsCallSession通过AIDL调用ImsCallSessionImpl再通过HIDL调用IImsRadio.hal再到modem。而modem到phone的过程,CS Call是由IRadioResponse.hal通过HIDL非主动上报结果给RadioResponse,而IRadioIndication.hal通过HIDL主动上报通知给RadioIndication,IMS Call则是从hal上报到Ims service,再通过ImsCallSessionListener通知到ImsCallSession。
总的来说就是IMS Call比CS Call在phone进程和ril hal中多了一层ims service。
通话流程
IMS Call结构
先看CS Call和IMS Call的结构对比:
从图中可以看出,其实整体的设计模式差不多。其对比如下:
1. 对外接口GsmCdmaPhone对应ImsPhone。
2. 一路通话的封装类GsmCdmaCall对应ImsPhoneCall。
3. 通话中的某路连接GsmCdmaConnection对应ImsPhoneConnection。
4. modem返回回来的某一路通话连接DriverCall对应ImsCall。
5. CS Call phone 通过IRadio、IRadioResponse、IRadioIndication和RIL交互。
6. IMS Call phone 通过IImsCallSession、IImsCallSessionListener、IImsMmTelListener和ims service交互。
IMS Call MO流程
先看IMS和CS的对比:
可以看到CallTracker拨号之前的过程两者一样,CallTracker拨号时CS Call直接通过RIL用HIDL来调用IRadio.hal拨号;而IMS Call需要由ImsManager通过ImsCallSession用AIDL调用ImsCallSessionImpl,再通过HIDL调用IImsRadio.hal来拨号,比CS Call多了ims service进程中的处理。
CallTracker拨号之前的过程可以参考我之前的文章 Android通话应用设计,其大致流程没有变。这里补充一下telecom进程拨号的具体细节如下:
其大至流程就是:
1. 拨号应用如Dialer调用TelecomManager#placeCall()。
2. CallsManager#startOutgoingCall()创建Call,并设置Call状态为Connecting。判断是否mmi code,如果不是通知InCallUI更新界面。
3. 发送order broadcast给接收该广播的应用更改号码相关信息。
4. CallsManager#placeOutgoingCall()根据intent中所带参数判断该通电话是否为视频电话.
5. 建立同ConnectionService的连接,通知TelephonyConnectionService拨号。
6. TelephonyConnectionService通知拨号成功,更新Call状态为Dialing。
其中IMS Call增加的流程就是在拨号时的intent中带参数配置该通电话是否为视频电话,然后把这个videoState一直传递下去。
IMS Call 状态变更流程
先看IMS和CS的对比:
和MO一样,IMS Call多了ims service这一部分,而CS Call 多了GET_CURRENT_CALLS的过程。
其中的重点部分是IMS Call 中的ImsPhoneCallTracker#processCallStateChange()及CS Call 中的GsmCdmaCallTracker#handlePollCalls()。
和app相关的流程请参考 Android通话应用设计。
IMS Call MT流程
先看IMS和CS的对比:
其对比如下:
1. CS Call 在收到RadioIndication上报的callStateChanged()后会通过GET_CURRENT_CALL来更新DriverCall, 然后在GsmCdmaCallTracker#handlePollCalls()中通过DriverCall来更新Connection并通知app来电。
2. IMS Call 中会在ImsPhoneCallTracker#onIncomingCall()中通过ImsCallSession来创建ImsCall连接,并创建Connection,创建Connection时会通过IImsCallSession里带的参数判断通话是否为视频通话。
app来电后的流程可参考 Android通话应用设计,这里补充telecom app 来电的流程,如下:
1. telephony收到来电通知时根据来电的phone找到PhoneAccountHandle,通话TelecomManager#processIncomingCallIntent()通知telecom来电。
2. CallsManager#processIncomingCallIntent()创建Call,并建立和ConnectionService的连接。
3. ConnectionService返回连接成功,通过phone进程中的Connection更新telecom/Call,包括是否视频电话。
4. CallsManager#onSuccessfulIncomingCall()开始号码过滤查询(包括黑名单查询),如果是过滤号码来电直接拒接。
5. 如果是非过滤号码来电更新Call状态为RINGING。
6. 通过InCallController建立与通话界面的连接,更新通话界面。
MMI Code 流程
MMI:Man-Machine-Interface,人机界面,所有带*或#的号码都是MMI Code。通常以*、#、*#、**、##等开头,以#号结束,各个部分以*隔开。它们有些仅在设备上使用,有些发送给sim卡处理,有些则发给运营商网络处理。它主要分为:
1. USSD:Unstructured Supplementary Service Data,非结构化补充服务数据码,发送给网络处理。所有以#号结尾且没有被识别为MMI Code的号码都会被发送到网络来确认该号码是否为运营商支持的USSD。
2. SS:Supplementary Service,补充服务码,发送给网络处理。如*21*xxx xxxx xxxx#为GSM/UMTS/LTE网络的来电转接码,这个号码会由手机转换成网络可识别的来电转接码。
3. Manufacturer defined MMI codes:手机厂商自定义的mmi码,在设备上执行。如通用的*#06#会显示手机IMEI号。各家手机厂商也可以定义自己的mmi码来做为暗码,它的处理一般在Dialer/SpeciaCharSequenceMgr中。
4. SIM control codes:sim卡控制码,发送给sim卡处理。如**04*1234*6789*6789#会把sim卡的pin码从1234改成6789。
MMI code 分主动上报和非主动上报两种,下图为非主动手报流程:
1. 手机自己处理的mmi码一般直接通过Dialer处理。
2. 发送给sim卡处理的码通过Dialer直接传到GsmMmiCode给UiccCardApplication再由IRadio.hal处理,其处理结果会在PhoneUtils#displayMMIComplete()显示给用户。
3. 发送给网络处理的码则和正常拨号一样,只不过telecom在判断其为mmi code后不会通知InCallUI,CallTracker#dial()后返回空的Connection给phone app通知其弹出对话框提示用户正在进行MMI码的处理。
4. 会先判断该mmi code是不是ims网络的码,如果是直接由ims网络处理,如果不是则由gsm/umts/lte网络处理。
5. SS code手机能直接判断出,然后转换为网络能识别的命令发送给网络,CS Call和通话一样由IRadio.hal处理,而IMS Call则不是由IImsCallSession处理而是通过IImsUt处理。USSD code直接透传给网络处理。网络处理结果CS Call和通话状态一样直接由IRadioResponse.hal通知,IMS Call则由IImsUtListener通知。
原创内容欢迎转载,但请注明出处,谢谢!