目前没有时间和精力来分析总结细节,本篇主要内容是讲一些理解性的东西,先写一些,以后慢慢更新维护。
回顾自己的学习过程,我发现这些理解性的东西,对学习掌握这部分知识还是非常重要的,因为很多初学者很容易淹没在略显复杂的流程和无尽的细节中。
我个人认为,搞清楚代码的包、关键类的继承关系以及运行时的进程是重中之重,可以加快学习过程,对掌握细节也很有帮助,下面的图也是按照这个思路基于Android O源生代码画的,只展示了SIM-based Call(Carrier call)的流程,没有涉及VoIP call。
代码运行时的进程包括:
1.“com.android.dialer”,in-cal UI运行在这个进程中。
2.“system”, Telecom.apk运行在这个进程中。
3.“com.adnroid.phone”,TeleService.apk运行的进程。
涉及到的主要代码包括:
1."packages/apps/Dialer"中的in-call UI
2.“packages/service/Telecom”
3.“packages/servoce/Telephony”
4.“framework/base/telecom”
5.“framework/opt/telephony”
代码量看上去不是很大,但是内部的逻辑联系非常紧密,而且把其中任何一部分单独拿出来,都有很多东西需要细心的理解。
Telecom service是整个设计的核心,可以管理call,audio等; 另外,Telecom会去连接InCallService 实现和ConnectionService实现(如图中的InCallServiceImpl和TelephonyConnectionService), 并为两者的通信起到了调度和中转的作用。
InCallService实现 用于为用户提供图像界面以及和Telecom 中的call交互的方法; ConnectionService实现 除了我们比较熟悉的TelephonyConnectionService外,还可能是SipConnectionService或者third-party的ConnectionService实现。
现在MO的方式有两种:
- 通过发送广播:android.intent.action.CALL,android.intent.action.CALL_PRIVILEGED和android.intent.action.CALL_EMERGENCY。
这些广播会启动UserCallActivity,然后转到UserCallIntentProcessor处理。
2.通过TelecomManger.placeCall方法。用户设置的dialer应用或者系统预置的dialer应用可以使用该方法,否则需要android.Manifest.permission#CALL_PHONE权限。
使用这种方式也会调用到UserCallIntentProcessor中处理。
UserCallIntentProcessor只是一个跳点,做了一些user权限相关的判断(能否拨打电话,能否拨打非紧急电话)。
第三方Dialer(phone)应用比较多,如果用户在手机上安装了多个,那么incall-ui该怎么启动呢?
在需要bind InCallService的时候会Telecom调用到getDefaultDialerApplication@DefaultDialerManager,这个方法会去判断在Settings.Secure.DIALER_DEFAULT_APPLICATION中是否有默认Phone应用的信息(用户可以通过菜单settings->apps设置),如果没有会返回系统Phone应用的信息。系统Phone应用我们(OEM)可以在packages/service/Telecom/config.xml的ui_default_package中配置。
当然bind InCallService除了需要Phone应用相关的信息外,还需要check 相应AndroidMenifest.xml对InCallService的配置,permission、meta-data, 下面是一个配置的例子:
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
</service>
在packages/service/Telecom/config.xml中与Phone相关的配置除了ui_default_package,还有incall_default_class和dialer_default_class。