三.创建去电通话连接
1.在调用到CallsManager.java中startOutgoingCall去做每路通话管理和通话界面显示的过程中,同时发出了 NewOutgoingCallIntentBroadcaster,我们看在这里做了什么,进入NewOutgoingCallIntentBroadcaster.java,主要方法是processIntent():
if (Intent.ACTION_CALL.equals(action)|| Intent.ACTION_CALL_PRIVILEGED.equals(action)) {
// Voicemail calls will be handled directly by the telephony connection manager
Log.i(this, "Placing call immediately instead of waiting for + " OutgoingCallBroadcastReceiver: %s", intent);
boolean speakerphoneOn = mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
mCallsManager.placeOutgoingCall(mCall, handle, null, speakerphoneOn,VideoProfile.VideoState.AUDIO_ONLY);
return DisconnectCause.NOT_DISCONNECTED;
} else {
Log.i(this, "Unhandled intent %s. Ignoring and not placing call.", intent);
return DisconnectCause.OUTGOING_CANCELED;
}
看关键的一行:
mCallsManager.placeOutgoingCall(mCall, handle, null, speakerphoneOn,VideoProfile.VideoState.AUDIO_ONLY);
2.这里做了什么呢?其实跟进去既可以看到,在CallsManager中的 placeOutgoingCall()方法中:
call.setHandle(uriHandle);
call.setGatewayInfo(gatewayInfo);
call.setStartWithSpeakerphoneOn(speakerphoneOn);
call.setVideoState(videoState);
boolean isEmergencyCall = TelephonyUtil.shouldProcessAsEmergency(mContext,call.getHandle());
if (isEmergencyCall) {
// Emergency -- CreateConnectionProcessor will choose accounts automatically
call.setTargetPhoneAccount(null);
}
if (call.getTargetPhoneAccount() != null || isEmergencyCall) {
// If the account has been set, proceed to place the outgoing call.
// Otherwise the connection will be initiated when the account is set by the user.
call.startCreateConnection(mPhoneAccountRegistrar);
}
这里先拿到call的实例,然后对这个实例做一些配置工作,比如设置状态,对方号码,即将进入拨号,不过,这里出现了非常重要的一行代码:
call.startCreateConnection(mPhoneAccountRegistrar);
我们知道拨打电话,这一路通话必须要建立一个连接Connection,这个连接就好比一个通道,只有将连接建立好我们的电话才有可能到达对方端,才能够拨打电话成功,我们继续跟踪,看看这个连接是如何建立起来的,进入Call.java(packages/services/Telecomm)中查看方法startCreateConnection():
Preconditions.checkState(mCreateConnectionProcessor == null);
mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,phoneAccountRegistrar, mContext);
mCreateConnectionProcessor.process();
直接查看CreateConnectionProcessor.java(packages/services/Telecomm)中的方法process():
clearTimeout();
mAttemptRecords = new ArrayList<>();
if (mCall.getTargetPhoneAccount() != null) {
mAttemptRecords.add(new CallAttemptRecord(
mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
}
adjustAttemptsForConnectionManager();
adjustAttemptsForEmergency();
mAttemptRecordIterator = mAttemptRecords.iterator();
attemptNextPhoneAccount();
这个CreateConnectionProcessor就是建立通话连接的类,看它的 attemptNextPhoneAccount()方法:
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);
Log.i(this, "Attempting to call from %s", service.getComponentName());
service.createConnection(mCall, new Response(service));
}
}
看代码看关键地方,我们看到这里先拿到了ConnectionServiceWrapper的一个实例service,然后:
mCall.setConnectionService(service);
service.createConnection(mCall, new Response(service));
这里调用了Call.java(packages/services/Telecomm)中的 setConnectionService方法保存service实例,然后调用service实例也就是ConnectionServiceWrapper类的createConnection方法,在这个方法中才最终创建了connection,创建成功后会调用当前类的handleCreateConnectionSuccess方法:
for (Listener l : mListeners) {
l.onSuccessfulOutgoingCall(this,getStateFromConnectionState(connection.getState()));
}
在这里,最终是调用了CallsManager.java中的onSuccessfulOutgoingCall方法去做显示通话界面的动作了,至于为什么是调用了CallsManager.java类中的方法,我们在后面的具体如何创建通话连接中会有详细的剖析。那么到这里,我们介绍了通话的两路进程的大概流程,那么,这两路进程又有什么联系呢,创建通话连接成功后是怎么具体通知前台显示通话界面呢,我们接下来继续分析。