1,去电流程分析
1.1 app dialer
拨号盘界面有关拨号的部分由DialpadFragment.java实现,无论是单卡还是双卡,当点击拨号按键时,最后都会调用
handleDialButtonPressed方法进行处理,调用流程图如下,
在handleDialButtonPressed方法中,首先进行号码的有效性检查,然后调用DialerUtils的startActivityWithErrorToast的方法进行处理,
final Intent intent = CallUtil.getCallIntent(number);
if (!isDigitsShown && !PhoneNumberUtils.isEmergencyNumber(number)) {
// must be dial conference add extra
intent.putExtra(EXTRA_DIAL_CONFERENCE_URI, true);
}
intent.putExtra(ADD_PARTICIPANT_KEY, mAddParticipant && isPhoneInUse());
if (subcription != INVALID_SUBSCRIPTION) {
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subcription);
}
DialerUtils.startActivityWithErrorToast(getActivity(), intent);
hideAndClearDialpad(false);//隐藏拨号盘
CallUtil的getCallIntent获取的intent,
final Intent intent = new Intent(Intent.ACTION_CALL, uri);
DialerUtils的startActivityWithErrorToast方法在此就是启动一个Activity,
context.startActivity(intent);
这样,在dialer进程中就处理完成了。
1.2 services telecom
telecom 中的AndroidManifest有关定义如下,
package="com.android.server.telecom"
coreApp="true"
android:sharedUserId="android.uid.system"
并且,在UserCallActivity下面,定义了intent-filter等信息,
因此, Intent.ACTION_CALL 会启动UserCallActivity,调用流程图如下,
UserCallActivity的onCreate方法如下,
new UserCallIntentProcessor(this, userHandle).processIntent(getIntent(),
getCallingPackage(), true /* hasCallAppOp*/);
创建并调用UserCallIntentProcessor对象的processIntent方法,主要是一些检查,
if (!canCallNonEmergency && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
showErrorDialogForRestrictedOutgoingCall(mContext,
R.string.outgoing_call_not_allowed_no_permission);
Log.w(this, "Rejecting non-emergency phone call because "
+ android.Manifest.permission.CALL_PHONE + " permission is not granted.");
return;
}
检查完成之后,调用sendBroadcastToReceiver方法发送广播。
private boolean sendBroadcastToReceiver(Intent intent) {
intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.setClass(mContext, PrimaryCallReceiver.class);
Log.d(this, "Sending broadcast as user to CallReceiver");
mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
return true;
}
直接发送给PrimaryCallReceiver, 调用流程图如下,
onReceive方法如下,
public void onReceive(Context context, Intent intent) {
synchronized (getTelecomSystem().getLock()) {
getTelecomSystem().getCallIntentProcessor().processIntent(intent);
}
}
getTelecomSystem方法如下,
public TelecomSystem getTelecomSystem() {
return TelecomSystem.getInstance();
}
返回的是TelecomSystem对象, TelecomSystem也是一个单例,整个android系统中只有一个, TelecomSystem的
getCallIntentProcessor方法如下,
public CallIntentProcessor getCallIntentProcessor() {
return mCallIntentProcessor;
}
返回的是CallIntentProcessor对象, CallIntentProcessor是在TelecomSystem的构造方法中构造的。
因此,最后调用的是CallIntentProcessor的processIntent方法,该方法如下,
if (isUnknownCall) {
processUnknownCallIntent(mCallsManager, intent);
} else {
processOutgoingCallIntent(mContext, mCallsManager, intent);
}
如果是未知号码如空号由processUnknownCallIntent方法处理
否则调用processOutgoingCallIntent方法,该方法主要逻辑如下,
1,从intent中获取各种参数,
Uri handle = intent.getData();
String scheme = handle.getScheme();
String uriString = handle.getSchemeSpecificPart();
•••
2,调用CallsManager的startOutgoingCall启动拨号界面,
Call call = callsManager.startOutgoingCall(handle, phoneAccountHandle, clientExtras);
3,调用NewOutgoingCallIntentBroadcaster的processIntent方法继续拨号,
NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
context, callsManager, call, intent, isPrivilegedDialer);
final int result = broadcaster.processIntent();
拨号界面的启动后面再详细的论述。processIntent方法的调用流程图如下,
processIntent方法主要对三种类型call的一些检查,
普通call Intent.ACTION_CALL
系统call Intent.ACTION_CALL_PRIVILEGED
紧急呼叫call Intent.ACTION_CALL_EMERGENCY
普通call任何应用都可以发起,第三方应用拨号都是使用该intent
系统call只有系统应用才能使用
紧急呼叫call 同样只有系统应用才能使用,并且可以在无卡状态下拨号.
if (Intent.ACTION_CALL.equals(action)) {
if (isPotentialEmergencyNumber) {
if (!mIsDefaultOrSystemPhoneApp) {
Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
+ "unless caller is system or default dialer.", number, intent);
launchSystemDialer(intent.getData());
return DisconnectCause.OUTGOING_CANCELED;
} else {
callImmediately = true;
}
}
•••
最后调用broadcastIntent方法发送广播,
broadcastIntent(intent, number, !callImmediately);
broadcastIntent方法如下,
private void broadcastIntent(Intent originalCallIntent, String number, boolean receiverRequired) {
Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
if (number != null) {
broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
}
// Force receivers of this broadcast intent to run at foreground priority because we
// want to finish processing the broadcast intent as soon as possible.
broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Log.v(this, "Broadcasting intent: %s.", broadcastIntent);
checkAndCopyProviderExtras(originalCallIntent, broadcastIntent);
mContext.sendOrderedBroadcastAsUser(broadcastIntent, UserHandle.CURRENT,
android.Manifest.permission.PROCESS_OUTGOING_CALLS,
AppOpsManager.OP_PROCESS_OUTGOING_CALLS,
receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null,
null, // scheduler
Activity.RESULT_OK, // initialCode
number, // initialData: initial value for the result data (number to be modified)
null); // initialExtras
}
直接发送给内部类NewOutgoingCallBroadcastIntentReceiver进行处理, onReceive方法又进行一系列检查,
最后调用CallsManager的placeOutgoingCall方法进行拨号,
mCallsManager.placeOutgoingCall(mCall, resultHandleUri, gatewayInfo,
mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,false),
mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,VideoProfile.STATE_AUDIO_ONLY));
真觉得这个内部类是多余的。
CallsManager的placeOutgoingCall方法会调用Call的startCreateConnection建立拨号连接,
startCreateConnection方法首先创建CreateConnectionProcessor对象,然后调用其process方法,
CreateConnectionProcessor的process方法调用流程图如下,
process方法会调用attemptNextPhoneAccount方法,在该方法中,首先获取ConnectionServiceWrapper对象,
然后调用createConnection方法建立连接,
PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
ConnectionServiceWrapper service = mRepository.getService(
phoneAccount.getComponentName(),phoneAccount.getUserHandle());
if (service == null) {
Log.i(this, "Found no connection service for attempt %s", attempt);
attemptNextPhoneAccount();
} else {
mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
mCall.setConnectionService(service);
setTimeoutIfNeeded(service, attempt);
service.createConnection(mCall, new Response(service));
}
mRepository是ConnectionServiceRepository对象,其getService方法如下,
ConnectionServiceWrapper getService(ComponentName componentName, UserHandle userHandle) {
Pair cacheKey = Pair.create(componentName, userHandle);
ConnectionServiceWrapper service = mServiceCache.get(cacheKey);
if (service == null) {
service = new ConnectionServiceWrapper(componentName, this,
mPhoneAccountRegistrar, mCallsManager, mContext, mLock, userHandle);
service.addListener(mUnbindListener);
mServiceCache.put(cacheKey, service);
}
return service;
}
在mServiceCache变量中找不到就创建ConnectionServiceWrapper对象,相当于一个本地的service管理。
ConnectionServiceWrapper继承于ServiceBinder,
ConnectionServiceWrapper的createConnection方法中,定义了BindCallback匿名类并且实现了onSuccess
和onFailure回调方法,并且调用了Binder2的bind方法,该方法如下,
mCallbacks.add(callback);//添加回调
if (mServiceConnection == null) {//连接未建立
Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
ServiceConnection connection = new ServiceBinderConnection(call);
Log.event(call, Log.Events.BIND_CS, mComponentName);
final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
final boolean isBound;
if (mUserHandle != null) {
isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
mUserHandle);
} else {
isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
}
if (!isBound) {
handleFailedConnection();
return;
}
} else {//连接已建立
Log.d(ServiceBinder.this, "Service is already bound.");
Preconditions.checkNotNull(mBinder);
handleSuccessfulConnection();
}
如果未建立连接,会调用bindService绑定远程服务, mServiceAction和mComponentName变量都是在ServiceBinder的构造方法中赋值的,
ConnectionServiceWrapper的构造方法中会调用ServiceBinder的构造方法,
super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle);
ConnectionService的SERVICE_INTERFACE变量如下,
public static final String SERVICE_INTERFACE = "android.telecom.ConnectionService";
ConnectionService只是一个抽象类,具体的实现在services Telephony的TelephonyConnectionService中,并且
services Telephony的AndroidManifest关于TelephonyConnectionService有关定义如下,
因此,绑定的就是TelephonyConnectionService服务。
当然,绑定失败的代码在此就不分析了,仅分析绑定成功的代码。
绑定成功之后, 就会回调ServiceBinder的内部类ServiceBinderConnection的onServiceConnected方法,
setBinder(binder); //获取远程服务的binder
handleSuccessfulConnection();//回调方法
setBinder方法会调用ConnectionServiceWrapper的setServiceInterface方法,如下,
mServiceInterface = IConnectionService.Stub.asInterface(binder);
addConnectionServiceAdapter(mAdapter);
为mServiceInterface变量赋值,这样mServiceInterface就指向远程的TelephonyConnectionService对象。
ServiceBinder的handleSuccessfulConnection方法如下,
private void handleSuccessfulConnection() {
for (BindCallback callback : mCallbacks) {
callback.onSuccess();
}
mCallbacks.clear();
}
回调createConnection方法中的callback的onSuccess方法,
mServiceInterface.createConnection(call.getConnectionManagerPhoneAccount(),
callId, new ConnectionRequest(call.getTargetPhoneAccount(),call.getHandle(),extras,
call.getVideoState()),call.isIncoming(),call.isUnknown());
这样,就会调用TelephonyConnectionService的createConnection方法。
创建连接实际上就是创建services telecom 到 services Telephony的一个连接。
这样, services telecom中的流程也处理完成了。