对于Call模块最先接触的应该就是MO call,这也是比较常见的case.对于MO call, 在没有正式分析流程前,其实也可以考虑下,这个流程到底干了些什么事:首先通过Dialer 开始拨号,然后Telephony & Telecomm去处理逻辑,InCallUI 显示通话界面,然后通过RIL命令把Dial发给Modem.Modem 返回Dial 成功,电话拨打成功,然后InCallUI 根据Call的状态去更新UI。那接下来就从代码级别依次来查看下流程。
1.开始拨号,构建Intent
从操作来看,我们会先输入将要拨打号码,然后点击拨号键。其实这个过程就是Dialer build Intent的过程。构建的这个intent 会包含dial的action,且包含将要拨打的号码。这个Intent会传递给Telecomm处理,只有带了这两个extra,telecom才知道收到广播后去干什么。
http://androidxref.com/8.0.0_r4/xref/packages/apps/Dialer/java/com/android/dialer/app/dialpad/DialpadFragment.java#handleDialButtonPressed
/**
* In most cases, when the dial button is pressed, there is a number in digits area. Pack it in
* the intent, start the outgoing call broadcast as a separate task and finish this activity.
*
* <p>When there is no digit and the phone is CDMA and off hook, we're sending a blank flash for
* CDMA. CDMA networks use Flash messages when special processing needs to be done, mainly for
* 3-way or call waiting scenarios. Presumably, here we're in a special 3-way scenario where the
* network needs a blank flash before being able to add the new participant. (This is not the case
* with all 3-way calls, just certain CDMA infrastructures.)
*
* <p>Otherwise, there is no digit, display the last dialed number. Don't finish since the user
* may want to edit it. The user needs to press the dial button again, to dial it (general case
* described above).
*/
private void handleDialButtonPressed() {
if (isDigitsEmpty()) { // No number entered.
handleDialButtonClickWithEmptyDigits();
} else {
final String number = mDigits.getText().toString();
// "persist.radio.otaspdial" is a temporary hack needed for one carrier's automated
// test equipment.
// TODO: clean it up.
if (number != null
&& !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp)
&& number.matches(mProhibitedPhoneNumberRegexp)) {
LogUtil.i(
"DialpadFragment.handleDialButtonPressed",
"The phone number is prohibited explicitly by a rule.");
if (getActivity() != null) {
DialogFragment dialogFragment =
ErrorDialogFragment.newInstance(R.string.dialog_phone_call_prohibited_message);
dialogFragment.show(getFragmentManager(), "phone_prohibited_dialog");
}
// Clear the digits just in case.
clearDialpad();
} else {
final Intent intent =
new CallIntentBuilder(number, CallInitiationType.Type.DIALPAD).build();
DialerUtils.startActivityWithErrorToast(getActivity(), intent);
hideAndClearDialpad(false);
}