MTK IMS框架简析(1)——代码架构及模块初始化
2017-12-07 10:38
435 查看
1.前言
随着4G技术的诞生和国内运营商网络的全面升级,以往流量贵上网慢的问题不再有,而类似微信这类即时通讯软件也得到快速的普及,互联网行业的发展还延伸到金融/零售等线上线下的各行各业,短短几年内国内IT产业迎来全面的机遇。而得益于移动网络技术的突破,政策的开放和乔帮主的1%的智慧,成就了今天高效的互联网+社会。4G协议中定义了包含volte和RCS等基于运营商核心网实现的功能,将发挥网速优势消灭CS域,同时提供高清语音通话和多媒体IM通讯功能,当年还在卖短信挣钱的运营商们想到这些肯定心理暗爽。但实际成本高昂,除了要进一步升级核心网,还要联合芯片商和终端厂商合作开发或集成volte和RCS方案才能产生威力,而且体验也是一个大问题,因此对此支持少之又少,目前深圳只有中移动支持volte,但了解和使用的人其实不多。
中国移动早年开始捣鼓Ophone的时候(欲通过4G升级占领终端继延续统治),第三方软件厂们已经发力开始在IM上厮杀,一向财大气粗运营商们眼看着江山四分五裂,又只能靠卖流量卖手机甚至卖宽带来抢客户了。。。
言归正传,目前高通和MTK等芯片大厂都已完美支持volte,就以MTK为例分析下功能实现。
2. 代码结构
MTKIMS相关代码由4部分构成,有Google添加的框架,和MTK实现的Service部分://原有框架中拓展出ims相关类,如ImsPhone/ImsPhoneCallTracker/ImsCallConnection/ImsPhoneCall等 /frameworks/opt/telephony/src/java/com/android/internal/telephony/imsphone //实现了Parcelable的公共类,和一些aidl接口 /frameworks/base/telephony/java/com/android/ims //为Ims服务提供接口,ImsManager提供通话/开关volte/更新和获取ims状态等接口。 /frameworks/opt/net/ims/ //mtk实现部分,实现了与rild-ims的对接方式ims CommandsInterface实现 /vendor/mediatek/proprietary/packages/services/Ims/1
2
3
4
5
6
7
8
9
10
11
接下来依次分析以上4个目录的架构和职责。
telephony框架
/frameworks/opt/telephony/src/java/com/android/internal/telephony/imsphone 此部分代码主要为volte通话功能添加。
ImsPhone为在PhoneBase的子类,而PhoneBase直接持有ImsPhone的实例,在原有的GsmPhone和CdmaPhone类中增加对ims的判断,例如拨号方法dial中,会先判断当前是否支持volte,再决定使用imsPhone的dial还是的当前phoneBase中的dial方法。
为什么不把ImsPhone像GsmPhone和CdmaPhone那样独立出来?
这样设计可能更精简。对于telephony框架添加的部分只涉及到通话功能,且Volte只作为一个可选业务,基于当前网络的数据业务承载,这样设计只需要在原来GsmPhone和CdmaPhone通话相关的接口加入volte的判断即可。
上图看到架构基本与GsmPhone/CdmaPhone一致,都有CallTracker / Connection / Call / Phone,ImsPhoneCallTracker拥有ImsManager实例,总管电话业务,负责执行操作和更新电话状态。而ImsPhone是这一层的管家,掌握通话的控制入口ImsPhoneCallTracker,实时关注Service state,上报状态到应用层等。
opt/net/ims
/frameworks/opt/net/ims/更像中间层的处理,只向上提供接口。 ImsManager就是提供IMS操作接口的类,接口功能包括开关volte功能 / 打电话 / 设置补充业务(呼叫转移等) / 设置IMS服务属性 (但不包括短彩信操作) 等等。
ImsManager.java中的一段说明:
/** * Provides APIs for IMS services, such as initiating IMS calls, and provides access to * the operator's IMS network. This class is the starting point for any IMS actions. **/ ImsManager是IMS服务的起始点,并为IMS服务提供接口,如建立通话和接入ims网络等。1
2
3
4
5
ImsManager成员及作用:
1. IImsService —— aidl实例,负责ims服务状态相关的操作。
2. ImsCall和ImsCallSession —— 负责通话的建立和状态跟踪,通过listener来同步消息,对接com.mediatek.ims中的ImsCallSessionProxy。
3. ImsUt —— 负责补充业务,对接ImsUtStub。
4. ImsConfig —— 负责IMS功能设置,对接ImsConfigImpl。
明显看到,opt/net/ims这一层只提供接口,对接packages/services/Ims/并由它来实现具体的业务。
ims app
/vendor/mediatek/proprietary/packages/services/Ims/ 以app形式存在,主要负责具体业务的执行,与rild和库对接。ImsRILAdapter——CommandsInterface接口的实现者,与RIL.java设计类似,有ImsRILSender和ImsRILReceiver在各自线程中执行收发,和rild-ims交互;
ImsService —— 管理ims服务状态,提供状态的get接口,执行ims注册 / 创建通话 等操作。
ImsCallSessionProxy —— 负责执行通话相关操作,直接与ImsRILAdapter交互,并通过Listener上报状态。
ImsConfigImpl —— 负责执行设置的操作,直接与ImsRILAdapter交互。
ImsUtStub —— 负责补充业务的设置,特殊的是并不通过ImsRILAdapter执行,而是单独实现的路径。
ImsAdapter —— MTK封装了一些处理到volte_imsm.so,ImsAdapter负责对接这个库,这个类的用途就是单独处理MTK不开源的部分;ImsEventDispatcher将volte_imsm上报的消息分发给实现了VaEventDispatcher的类:DataDispatcher——负责ims连接管理(如发起data call);CallControlDispatcher负责volte call相关。
(工程中查找volte_imsm.so,发现MTK并没有开源:vendor/letv/libs/mt6797_64/volte_imsm/)
framework中相关公共类和aidl定义
/frameworks/base/telephony/java/com/android/ims frameworks/base…/ims下定义了一些可以公用的类,都属于特定数据的封装,基本上都继承了aidl stub跨进程无压力。
internal包下还定义了一系列aidl文件,具体实现都在/vendor/mediatek/proprietary/packages/services/Ims/中,为其提供访问入口。
3. 模块的初始化
以上模块在开机后即开始初始化过程,下面来看下它们如何开始初始化。
mtk ims应用初始化
/vendor/mediatek/…/services/Ims/ 在AndroidManifest中定义了application的persistent为true,因此ims app开机即自动加载:<application android:name="ImsApp" android:persistent="true"> ... </application>1
2
3
4
ImsApp在onCreate方法中创建ImsService实例,并将其添加为系统服务:
public class ImsApp extends Application { public ImsApp() { } @Override public void onCreate() { if (UserHandle.myUserId() == 0) { ImsService imsService = new ImsService(this); ServiceManager.addService(ImsManager.IMS_SERVICE, imsService.asBinder(), true); } } }1
2
3
4
5
6
7
8
9
10
11
12
13
而ImsAdapter / ImsRILAdapter及ImsConfigImpl等实例在ImsService构造方法中创建。
public ImsService(Context context) { //初始化ImsAdapter和ImsRILAdapter实例 mImsAdapter = new ImsAdapter(context); mImsRILAdapter = new ImsRILAdapter(context); mContext = context; mHandler = new MyHandler(); ... //创建ImsConfigImpl实例 if (SubscriptionManager.isValidPhoneId(mainPhoneId)) { synchronized (this) { ImsConfigImpl instance = new ImsConfigImpl(mContext, mImsRILAdapter, mainPhoneId); mImsConfigInstanceMap.put(mainPhoneId, instance); } } //注册ims及radio状态监听 mImsRILAdapter.registerForImsRegistrationInfo(mHandler, EVENT_IMS_REGISTRATION_INFO, null); mImsRILAdapter.registerForImsEnableStart(mHandler, EVENT_IMS_ENABLING_URC, null); mImsRILAdapter.registerForImsEnableComplete(mHandler, EVENT_IMS_ENABLED_URC, null); mImsRILAdapter.registerForImsDisableStart(mHandler, EVENT_IMS_DISABLING_URC, null); mImsRILAdapter.registerForImsDisableComplete(mHandler, EVENT_IMS_DISABLED_URC, null); mImsRILAdapter.setOnIncomingCallIndication(mHandler, EVENT_INCOMING_CALL_INDICATION, null); mImsRILAdapter.setOnCallRing(mHandler, EVENT_CALL_RING, null); mImsRILAdapter.registerForCallProgressIndicator(mHandler, EVENT_SIP_CODE_INDICATION, null); /// register for radio state changed mImsRILAdapter.registerForNotAvailable(mHandler, EVENT_RADIO_NOT_AVAILABLE, null); //mImsRILAdapter.registerForOff(mHandler, EVENT_RADIO_OFF, null); mImsRILAdapter.registerForOn(mHandler, EVENT_RADIO_ON, null); ... }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
框架层初始化
ImsPhone的存活由ImsService的2个广播消息决定。 一切从PhoneBase::makeDefaultPhone方法开始,在创建GSMPhone和CDMAPhone后,调用startMonitoringImsService方法监控IMS状态。
for (int i = 0; i < numPhones; i++) { PhoneBase phone = null; int phoneType = TelephonyManager.getPhoneType(networkModes[i]); if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { phone = new GSMPhone(context, sCommandsInterfaces[i], sPhoneNotifier, i); phone.startMonitoringImsService(); } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { phone = new CDMALTEPhone(context, sCommandsInterfaces[i], sPhoneNotifier, i); phone.startMonitoringImsService(); } sProxyPhones[i] = new PhoneProxy(phone); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
startMonitoringImsService中做了3件事:
1. 注册receiver监听IMS_SERVICE_UP和IMS_SERVICE_DOWN消息
2. 初始化了ImsManager
3. 如果检查到ImsService已经启动,即调用updateImsPhone
public void startMonitoringImsService() { ... synchronized(PhoneProxy.lockForRadioTechnologyChange) { IntentFilter filter = new IntentFilter(); filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP); filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN); mContext.registerReceiver(mImsIntentReceiver, filter); mImsIntentReceiverRegistered = true; ImsManager imsManager = ImsManager.getInstance(mContext, getPhoneId()); if (imsManager != null && imsManager.isServiceAvailable()) { mImsServiceReady = true; updateImsPhone(); } } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
updateImsPhone方法需要判断mImsServiceReady标志决定创建或销毁ImsPhone。mImsServiceReady标志取值由谁决定?这里先回头看在mImsIntentReceiver能否找到答案。
PhoneBase.java protected void updateImsPhone() { if (mImsServiceReady && (mImsPhone == null)) { mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this); CallManager.getInstance().registerPhone(mImsPhone); } else if (!mImsServiceReady && (mImsPhone != null)) { mImsPhone.unregisterForSilentRedial(this); mImsPhone.dispose(); mImsPhone = null; } }1
2
3
4
5
6
7
8
9
10
11
答案果然就在mImsIntentReceiver这个receiver处理中,IMS_SERVICE_UP和IMS_SERVICE_DOWN消息决定着mImsServiceReady的值。
IMS_SERVICE_UP和IMS_SERVICE_DOWN消息直接对应着ImsRilAdapter的RIL_UNSOL_IMS_ENABLE_DONE和RIL_UNSOL_IMS_DISABLE_DONE消息,在打开/关闭IMS服务后上报。
private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { ... synchronized (PhoneProxy.lockForRadioTechnologyChange) { if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) { mImsServiceReady = true; updateImsPhone(); ImsManager.updateImsServiceConfig(mContext, mPhoneId, false); } else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) { mImsServiceReady = false; updateImsPhone(); } } } };1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
因此,ImsPhone初始化需要2个条件:1. ImsService已启动,2. ims ril上报RIL_UNSOL_IMS_ENABLE_DONE。
rild-ims
MTK单独提供socket来专门处理ims消息。 init.rc中的描述:
service ril-daemon-mtk /system/bin/mtkrild class core socket rild stream 660 root radio socket rild2 stream 660 root radio socket rild3 stream 660 root radio socket rild4 stream 660 root radio #rild-ims 相关socket socket rild-ims stream 660 root radio socket rild-debug stream 660 radio system socket rild-oem stream 660 radio system socket rild-mtk-ut stream 660 radio net_bt socket rild-mtk-ut-2 stream 660 radio net_bt socket rild-mtk-modem stream 660 radio system socket rild-atci stream 660 root radio socket rild-mal stream 660 radio system socket rild-mal-at stream 660 radio system socket rild-vsim stream 660 root radio socket rild-mbim stream 660 root radio socket sap_uim_socket1 stream 660 bluetooth bluetooth socket sap_uim_socket2 stream 660 bluetooth bluetooth user root group radio cache inet misc audio sdcard_r sdcard_rw log system disabled oneshot1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
小结
google为IMS扩展了framework处理并向上提供了接口,而MTK实现了ims app(vendor目录),对接so库和rild的核心逻辑。后续有空再分析ims业务的注册流程,还有volte的通话流程。
相关文章推荐
- MTK IMS框架简析(1)——代码架构及模块初始化
- MTK IMS框架简析(2)——IMS注册过程
- MTK IMS框架简析(2)——IMS注册过程
- Android原生”SlidingMenu”框架的代码简析
- Ajax底层代码简析(可直接用的框架)
- Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用
- uboot 2013.01 代码简析(3)第二阶段初始化
- 毕业生的商业软件开发之路 --- C#基本语法-C#代码模块逻辑框架
- Linux USB Host-Controller的初始化代码框架分析
- 系统架构师——搭建SpringMVC,Spring,Mybatis框架——从模块开发到系统架构搭建
- 架构、框架、模式、模块、组件、插件、控件、中间件的含义和区别
- ACE_Proactor框架代码简析
- mtk git取代码new和编译kernal 和单个模块脚本
- 开源框架之Bonita BPM的使用(八):bonita bpm数据库初始化命令在代码中的地址
- 框架采用s2sm架构 ,处理apk上传下载, 处理图片上传下载,核心代码.
- nginx代码分析--进程和模块初始化
- 架构探险--框架初始化
- Linux音频设备驱动_OSS驱动框架(二)————OSS驱动架构代码vmsnd.c
- MTK android代码架构
- 架构、框架、模式、模块、组件、插件、控件、中间件的含义和区别