一个电话打出去流程分析
1. 配置文件AndroidManifest.xml
文件路径:packages/apps/Contacts/AndroidManifest.xml
其中属性android:enabled="@*android:bool/config_voice_capable"是用来控制应用是否在菜单中显示的,在禁用通话时会用到
<activityandroid:name=".activities.BestoneDialtactsActivity"
android:label="@string/launcherDialer"
android:theme="@style/BestoneDialtactsTheme"
android:uiOptions="splitActionBarWhenNarrow"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:icon="@drawable/ic_launcher_phone"
android:screenOrientation="portrait"
android:enabled="@*android:bool/config_voice_capable"
android:taskAffinity="android.task.contacts.phone"
android:windowSoftInputMode="stateAlwaysHidden|adjustPan"
android:hardwareAccelerated="true">
….
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.DEFAULT" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
<categoryandroid:name="android.intent.category.BROWSABLE" />
</intent-filter>
……
</activity>
2. 在联系人目录中,从拨号盘界面,输入拨打号码,按下拨打按钮
(a). 拨号盘界面的构建
文件路径:packages/apps/Contacts/src/com/android/contacts/activities/BestoneDialtactsActivity.java
public void onCreate(Bundle icicle) {
......
//此布局是框架布局,嵌入搜索(SearchFragment),拨号盘(DialpadFragment)
setContentView(R.layout.bestone_dialtacts_activity);
......
}
(b).按数字按钮和拨打按钮
文件路径:packages/apps/Contacts/src/com/android/contacts/activities/BestoneDialtactsActivity.java
public boolean onKeyDown(int keyCode,KeyEvent event) {
……
handled = mDialpadFragment.onKeyDown(keyCode,event);
……
}
文件路径:packages/apps/Contacts/src/com/android/contacts/activities/DialpadFragment.javas
public booleanonKeyDown(int keyCode, KeyEvent event) {
……
if (event.getKeyCode() ==KeyEvent.KEYCODE_CALL) {
//如果点击的是拨打按钮,则拨出电话
dialButtonPressed();
return true;
}
//如果点击的是数字按钮,则作播放提示音等处理
……
}
public voiddialButtonPressed() {
dialButtonPressedInner(mDigits.getText().toString(),
Constants.DIAL_NUMBER_INTENT_NORMAL);
}
protected void dialButtonPressedInner(String number, int type) {
……
//这里返回的intent指向com.android.phone.PrivilegedOutgoingCallBroadcaster(备注,在package/app/Phone目录下)
final Intent intent = ContactsUtils.getCallIntent(number,
(getActivity() instanceofBestoneDialtactsActivity ? ((BestoneDialtactsActivity) getActivity())
.getCallOrigin(): null), type);
mCallOptionHandler.doCallOptionHandle(intent);
……
}
文件路径:packages/apps/Contacts/src/com/android/contacts/calloption/ContactsCallOptionHandler.java
public void doCallOptionHandle(Intent intent) {
……
//获取Telephony服务的接口
final ITelephonytelephony =
ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
……
SimAssociateHandler.getInstance(ContactsApplication.getInstance()).load();
//启动到package/app/Phone/src/com/android/phone/PrevilegedOutgoingCallBroadcaster
super.doCallOptionHandle(mActivityContext,ContactsApplication.getInstance(), intent,
this, ContactsApplication.getInstance().cellConnMgr,
telephony, SlotUtils.isGeminiEnabled(),
FeatureOption.MTK_GEMINI_3G_SWITCH);
……
}
3. 在电话目录下,接到Intent,继续将电话打出去
(a). 配置文件AndroidManifest.xml
文件路径:package/app/Phone/AndroidManifest.xml
<activity-aliasandroid:name="PrivilegedOutgoingCallBroadcaster"
android:targetActivity="OutgoingCallBroadcaster"
android:screenOrientation="nosensor"
android:excludeFromRecents="true"
android:permission="android.permission.CALL_PRIVILEGED">
……
</activity-alias>
(b).文件路径:package/app/Phone/src/com/android/phone/OutgoingCallBroadcaster.java
protected voidonCreate(Bundle icicle) {
……
Intent intent =getIntent();
//处理意图
processIntent(intent);
}
private voidprocessIntent(Intent intent) {
final Configurationconfiguration = getResources().getConfiguration();
if(!PhoneGlobals.sVoiceCapable) {
//如果禁用语言业务,则做相应处理
handleNonVoiceCapable(intent);
return;
}
//省略号码合法性检查,以及紧急号码的处理,点亮屏幕
……
if (callNow) {
……
// InCallScreen todisplay the in-call UI:
PhoneGlobals.getInstance().callController.placeCall(intent);
……
}
}
(c). 文件路径:package/app/Phone/src/com/android/phone/CallController.java
public voidplaceCall(Intent intent) {
......
//获取拨号界面的状态,以便正确显示相应状态下UI
final InCallUiStateinCallUiState = mApp.inCallUiState;
......
//检查当前是否有前端通话或者后台通话,如果有先挂断这些通话
PhoneConstants.Statestate = mCM.getState();
if (isEccCall && state !=PhoneConstants.State.IDLE) {
......
try {
mCM.hangupAllEx();
log("Waiting for disconnect exist calls.");
return;
} catch (CallStateExceptione) {
log("catch exception = " + e);
}
}
......
}
......
//拨打电话
CallStatusCode status= placeCallInternal(intent);
switch (status) {
//拨打结果的处理
case SUCCESS:
case EXITED_ECM:
....
}
......
}
private CallStatusCodeplaceCallInternal(Intent intent) {
……
callStatus =PhoneUtils.placeCall(mApp,
phone,
number,
contactUri,
(isEmergencyNumber || isEmergencyIntent),inCallUiState.providerGatewayUri);
……
}
(d). 文件路径:package/app/Phone/src/com/android/phone/PhoneUtils.java
public static intplaceCall(Context context, Phone phone,
String number, Uri contactRef, boolean isEmergencyCall,
Uri gatewayUri) {
returnplaceCallGemini(context, phone, number, contactRef, isEmergencyCall,gatewayUri, -1);
}
public static intplaceCallGemini(Context context, Phone phone,
String number, UricontactRef, boolean isEmergencyCall,
Uri gatewayUri,int simId) {
……
try {
// Google code: connection = app.mCM.dial(phone,numberToDial);
connection =GeminiRegister.dial(callManager, phone, numberToDial, simId);
} catch(CallStateException ex) {
……
}
}
文件路径:package/app/Phone/src/com/mediatek/phone/gemini/GeminiRegister.java
public staticConnection dial(Object callManager, Phone phone, String numberToDial, intslotId)
throwsCallStateException {
……
Connectionconnection = null;
try {
if(GeminiUtils.isGeminiSupport() && !isSipPhone) {
……
connection = ((MTKCallManager) callManager).dialGemini(phone,numberToDial, dialSlot);
} else{
//到这里才算真正调用到Framework中接口方法
connection = ((CallManager) callManager).dial(phone, numberToDial);
}
} catch(CallStateException ex) {
……
}
……
}
4. Framework下调用Telephony相关接口,将电话拨出
文件路径:framework/opt/telephony/src/java/com/android/internal/telephony/CallManager.java
publicConnection dial(Phone phone, String dialString) throws CallStateException {
//根据Phone类型,获得GSMPhone或者CDMAPhone实例
Phone basePhone = getPhoneBase(phone);
......
result = basePhone.dial(dialString);
......
}
文件路径:framework/opt/telephony/src/java/com/android/internal/telephony/gsm/GSMPhone.java
publicConnection dial(String dialString) throws CallStateException {
return dial(dialString, null);
}
publicConnection dial (String dialString, UUSInfo uusInfo) throws CallStateException{
//对MMI码作处理
……
if (mmi == null) {
return mCT.dial(newDialString,uusInfo);
}
}
文件路径:framework/opt/telephony/src/java/com/android/internal/telephony/gsm/
未完待续。。。。