这里以MTK4.0(6575/6577 6589)代码为基础进行分析。
源码下载http://download.csdn.net/detail/wds1181977/6387551
首先是Contacts.apk
拨号盘是依附于DialpadFragment上的。查看源码可以发现。无论是普通拨号还是视频拨号都会调用如下方法
protected void dialButtonPressedInner(String number, int type) {
if (TextUtils.isEmpty(number)) { / .....}
......
final Intent intent = newDialNumberIntent(number, type);
if (getActivity() instanceof DialtactsActivity) {
intent.putExtra(DialtactsActivity.EXTRA_CALL_ORIGIN,
DialtactsActivity.CALL_ORIGIN_DIALTACTS);
}
mCallOptionHandler.startActivity(intent);
}
其中
private Intent newDialNumberIntent(String number, int type) {
final Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
Uri.fromParts("tel", number, null));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if((type & DIAL_NUMBER_INTENT_IP) != 0)
intent.putExtra(Constants.EXTRA_IS_IP_DIAL, true);
if((type & DIAL_NUMBER_INTENT_VIDEO) != 0)
intent.putExtra(Constants.EXTRA_IS_VIDEO_CALL, true);
return intent;
}
会加入Intent.ACTION_CALL_ PRIVILEGED, Uri.fromParts("tel", number, null)和是否是VIDEO_CALL / IP_CALL的Extra.调用CallOptionHandler的StartActivity方法
public void startActivity(Intent intent) {
.......
if(PhoneNumberUtils.isEmergencyNumber(mNumber) || intent.getIntExtra(Constants.EXTRA_SLOT_ID, -1) != -1) {
final Intent broadcastIntent = newCallBroadcastIntent(mNumber, CallOptionHelper.DIAL_TYPE_VOICE, 0);
mContext.sendBroadcast(broadcastIntent);
return;
}
mCallOptionHelper.makeCall(intent);
} else {
intent.setClassName(Constants.PHONE_PACKAGE, Constants.OUTGOING_CALL_BROADCASTER);
mContext.startActivity(intent);
}
Profiler.trace(Profiler.CallOptionHandlerLeaveStartActivity);
}
这里会判断是否是紧急拨号。如果是紧急拨号则调用
newCallBroadcastIntent返回的Intent发送广播。不是则CallOptionHandler.makeCall
public void makeCall(Intent intent) {
int type = DIAL_TYPE_VOICE;
if(intent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false))
type = DIAL_TYPE_VIDEO;
final Uri uri = intent.getData();
final String scheme = uri.getScheme();
if(scheme.equals("sip") && !followSimSetting)
type = DIAL_TYPE_SIP;
if(Constants.VOICEMAIL_URI.equals(intent.getData().toString()))
type = DIAL_TYPE_VOICE;
......
makeCall(number, type, originalSim);
}
这里又将Type类型分为3种 DIAL_TYPE_VOICE,DIAL_TYPE_VIDEO,DIAL_TYPE_SIP
protected void makeCall(String number, int type, long originalSim) {
....
switch(type) {
case DIAL_TYPE_SIP:
.....
break;
case DIAL_TYPE_VIDEO:{
.....
break;
case DIAL_TYPE_VOICE:
makeVoiceCall(number, type, originalSim, callbackArgs);
break;
}
mCallback.onMakeCall(callbackArgs);
}
这里会根据type的类型去实现CallbackArgs callbackArgs对象的不同属性。其中这3种type会存放在callbackArgs.type属性中。然后调用mCallback.onMakeCall方法。查找可以知道onMakeCall是在CallOptionHandler里面实现的。
public void onMakeCall(final CallbackArgs args) {
int slot = -1;
switch (args.reason) {
case CallOptionHelper.MAKE_CALL_REASON_OK: {
if(args.type == CallOptionHelper.DIAL_TYPE_VOICE){
//获取slot
}
if(args.type == ...){
//获取slot
}
mIntent.putExtra(Constants.EXTRA_SLOT_ID, slot);
....
afterCheckSIMStatus(com.mediatek.CellConnService.CellConnMgr.RESULT_STATE_NORMAL, slot);
....
break;
case MAKE_CALL_REASON_3G_SERVICE_OFF:
.....
.... }
}
}
这里的mIntent为CallOptionHAndler.startActivity中的intent,在onMakeCall方法中加入了slot字段。然后调用afterCheckSIMStatus方法。
【笔者这里理解的slot字段是一个标志电话类型的标志位。如果slot =1 则是一般电话,slot = 0则是紧急拨号,slot<0则是没有插入SIM卡,不知道正确与否。】
private boolean afterCheckSIMStatus(int result, int slot) {
...
// ip dial only support voice call
boolean noSim = SIMInfoWrapper.getDefault().getInsertedSimCount() == 0;
if(!mIntent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false) && mIntent.getBooleanExtra(Constants.EXTRA_IS_IP_DIAL, false) && !noSim) {
..
}
}
// a little tricky here, check the voice mail number
if(Constants.VOICEMAIL_URI.equals(mIntent.getData().toString())) {
//VoiceMailNumber
..
}
}
String number = getInitialNumber(mIntent);
final int type = mIntent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false) ? CallOptionHelper.DIAL_TYPE_VIDEO : CallOptionHelper.DIAL_TYPE_VOICE;
final Intent broadcastIntent = newCallBroadcastIntent(number, type, slot);
mContext.sendBroadcast(broadcastIntent);
return true;
}
这里最后将调用 newCallBroadcastIntent。我们发现紧急拨号或者其他的拨号,如果拨号成功,都是使用newCallBroadcastIntent 返回的Intent来发送广播。
private Intent newCallBroadcastIntent(String number, int type, int slot) {
Intent intent = new Intent(OUTGOING_CALL_RECEIVER);
intent.setClassName(PACKAGE, OUTGOING_CALL_RECEIVER);
if(type == CallOptionHelper.DIAL_TYPE_VIDEO)
intent.putExtra(Constants.EXTRA_IS_VIDEO_CALL, true);
if(type == CallOptionHelper.DIAL_TYPE_SIP)
intent.setData(Uri.fromParts("sip", number, null));
else
intent.setData(Uri.fromParts("tel", number, null));
intent.putExtra(Constants.EXTRA_SLOT_ID, slot);
return intent;
}
到这里会发现,最后发送出去的intent只会包含2个有用的信息。就是Uri和Constants.EXTRA_SLOT_ID。最后该广播将在Phone.apk中的OutgoingCallReceiver中截获。