拨号时序图:
总体分为四个部分:Dialer,PhoneCommon,TeleService,Telephony Framework。分别对应packages/apps/Dialer、packages/apps/PhoneCommon、packages/services/TeleService、framework/opt/telephony。实际上拨号操作会调用到RIL并使用AT指令发送给Modem,最终Modem与硬件交互后向基站发起通话请求。
拨号入口Dialer:
拨号预处理PhoneCommon
通过Dialer拨号我们可以知道,在Dialer的ContactsCallOptionHandler类中,调用doCallOptionHandle方法开启Phone的入口。
整个拨号预处理过程分为10个阶段,分别为:
1. FirstCallOptionHandler
开始拨号预处理,判断呼叫号码是否属于voicemail,如果是则对intent进行一些处理,添加simId字段;
2. EmergencyCallOptionHandler
判断呼叫号码是否为紧急号码,如果是紧急号码则不再进行后续判断而直接开始拨号操作(跳转到OutgoingCallReceiver);
3. InternetCallOptionHandler
判断当前呼叫号码是否为网络拨号,即SIP Phone;
4. VideoCallOptionHandler
判断当前是否是进行的视屏拨号,即Video Call;
5. SimSelectionCallOptionHandler
判断当前使用哪一张SIM卡进行拨号。这一步会根据用户设置的默认SIM卡进行拨号,默认是弹出对话框,用户选择其中一张SIM卡进行拨号;
6. SimStatusCallOptionHandler
判断当前SIM卡状态是否允许拨号操作;
7. VoiceMailCallOptionHandler
判断当前呼叫号码是否属于voicemail,如果是则进行相关处理;
8. InternationalCallOptionHandler
判断呼叫号码是否符合当前国家ISO码;
9. IpCallOptionHandler
判断当前呼叫号码是否是IP呼叫(加拨17951);
10. FinalCallOptionHandler
会到Dialer中的ContactsCallOptionHandler中;
以上就是拨号的号码预处理流程,这个预处理流程时序图如下:
TeleService服务处理
在TeleService中还是会进行各种判断,这些判断有的是在PhoneCommon中做过的,但这是Android原生流程,MTK并没有去修改。比如期间还是有SIP Call和Emergency Call的判断。经过前面的PhoneCommon之后,会使用以下方式发出广播:
public void onContinueCallProcess(Intent intent) {
//清楚PhoneCommon过程中产生的dialog
dismissDialogs();
/** @} */
intent.setAction(Constants.OUTGOING_CALL_RECEIVER);
intent.setClassName(Constants.PHONE_PACKAGE, Constants.OUTGOING_CALL_RECEIVER);
DialerApplication.getInstance().sendBroadcast(intent);
}
TeleService中Call处理部分,实际上主要是后台逻辑处理,Android 4.4 Phone最重要的特点就是将显示和逻辑分离。这块与Android 4.2改动并不大,只是从原来的Phone中分离了出来。
TeleService执行时序图如下:
Framework Telephony处理拨号请求
这里的调用和参数传递也比较多,有几个关键点需要提一下。当我们跳转到CallManager的dial方法后,会执行到以下代码获取Connection:
result = basePhone.dial(dialString);
basePhone是Phone对象,而Phone是一个接口类,而且这里是通过参数传递过来的。我们在CallController的placeCallInternal()方法中可以看到以下代码:
phone = PhoneUtils.pickPhoneBasedOnNumber(mCM, scheme, number, sipPhoneUri);
继续查看pickPhoneBasedOnNumber方法:
public static Phone pickPhoneBasedOnNumber(CallManager cm,
String scheme, String number, String primarySipUri) {
if (primarySipUri != null) {
Phone phone = getSipPhoneFromUri(cm, primarySipUri);
if (phone != null) return phone;
}
return CallManagerWrapper.getDefaultPhone();//不是SIP Call
}
继续查看CallManagerWrapper中的getDefaultPhone方法:
public static Phone getDefaultPhone() {
Phone phone = null;
if (GeminiUtils.isGeminiSupport()) {//是否支持双卡
phone = ((GeminiPhone) MTKCallManager.getInstance().getDefaultPhoneGemini());
} else {
phone = CallManager.getInstance().getDefaultPhone();
}
return phone;
}
因为这里是MTK GSM/WCDMA制式的手机,因此是支持双SIM卡的。双SIM卡支持是Android原生没有的,MTK自己做了这一块,但却把相关方法实现封装到了jar包中。
回过头来,我们终于找到了
result = basePhone.dial(dialString);
中的basePhone,实际应为GSMPhone自然继续跳转拨号。后续流程就是通过framework通知到RIL层,RIL层再使用AT指令发送到modem端最终完成拨号动作。
整个时序图如下:
总结
整个MO流程看起来很复杂,但我们可以简单的归结为四个步骤:
1. 拨号处理;
2. 号码预处理;
3. TeleService后台处理;
4. framework telephony处理;