Telephony-Service
1.上篇分析到PstnIncommingCallNotifier 中handleMessage处理来电消息,继续跟进分析
switch (msg.what) {
case EVENT_NEW_RINGING_CONNECTION:
handleNewRingingConnection((AsyncResult) msg.obj);
2.继续跟进handleNewRingingConnection
/**
* Verifies the incoming call and triggers sending the incoming-call intent to Telecom.
*
* @param asyncResult The result object from the new ringing event.
*/
private void handleNewRingingConnection(AsyncResult asyncResult) {
Log.d(this, "handleNewRingingConnection");
Connection connection = (Connection) asyncResult.result;
if (connection != null) {
Call call = connection.getCall();
// Final verification of the ringing state before sending the intent to Telecom.
if (call != null && call.getState().isRinging()) {
if (ExtensionManager.getDigitsUtilExt().isConnectionMatched(connection,
mPhoneAccountHandle, mPhone.getContext()) == false) {
return;
}
sendIncomingCallIntent(connection);
}
}
}
3.继续跟进sendIncomingCallIntent
/**
* Sends the incoming call intent to telecom.
*/
private void sendIncomingCallIntent(Connection connection) {
Bundle extras = new Bundle();
//extras填充一些数据
...
PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
if (handle == null) {
//挂断
} else {
TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
}
}
//获取telecomm服务
public static TelecomManager from(Context context) {
return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
}
通过aidl接口调用 telecomService 的addNewIncomingCall方法
TelecomService层
4.跟进到TelecomServiceImpl成员变量mBinderImpl的具体实现类
/**
* Implementation of the ITelecom interface.
*/
public class TelecomServiceImpl
private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
/**
* @see android.telecom.TelecomManager#addNewIncomingCall
*/
@Override
public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
...
Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
phoneAccountHandle);
intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
if (extras != null) {
extras.setDefusable(true);
intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
}
mCallIntentProcessorAdapter.processIncomingCallIntent(
mCallsManager, intent);
...
5.继续跟进mCallIntentProcessorAdapter.processIncomingCallIntent,
static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
...
Log.d(CallIntentProcessor.class,
"Processing incoming call from connection service [%s]",
phoneAccountHandle.getComponentName());
callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
}
...
6.进入到CallsManager中继续跟进
void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Log.d(this, "processIncomingCallIntent");
...
Call call = new Call(
getNextCallId(),
mContext,
this,
mLock,
mConnectionServiceRepository,
mContactsAsyncHelper,
mCallerInfoAsyncQueryFactory,
mPhoneNumberUtilsAdapter,
handle,
null /* gatewayInfo */,
null /* connectionManagerPhoneAccount */,
phoneAccountHandle,
Call.CALL_DIRECTION_INCOMING /* callDirection */,
false /* forceAttachToExistingConnection */,
false, /* isConference */
mClockProxy);
...
call的一些状态设置
...
call.initAnalytics();
if (getForegroundCall() != null) {
getForegroundCall().getAnalytics().setCallIsInterrupted(true);
call.getAnalytics().setCallIsAdditional(true);
}
setIntentExtrasAndStartTime(call, extras);
//添加监听
// TODO: Move this to be a part of addCall()
call.addListener(this);
if (!isHandoverAllowed || (call.isSelfManaged() && !isIncomingCallPermitted(call,
call.getTargetPhoneAccount()))) {
notifyCreateConnectionFailed(phoneAccountHandle, call);
} else {
//成功上报上去建立连接
call.startCreateConnection(mPhoneAccountRegistrar);
}
}
这里和之前MO的流程是一样的,创建了一个Call然后调用startCreateConnection去创建connection,有需要的可以看下去电流程二的后半部分
TelecomFramework
7.跟进到IConnectionService中Binder的实现中去
/** @hide */
protected IBinder mBinder = new IConnectionService.Stub() {
@Override
public void createConnection(
...
mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();
...
8.找到handler事件处理的地方
case MSG_CREATE_CONNECTION: {
...
if (!mAreAccountsInitialized) {
Log.d(this, "Enqueueing pre-init request %s", id);
mPreInitializationConnectionRequests.add(
new android.telecom.Logging.Runnable(
SESSION_HANDLER + SESSION_CREATE_CONN + ".pICR",
null /*lock*/) {
@Override
public void loggedRun() {
createConnection(
connectionManagerPhoneAccount,
id,
request,
isIncoming,
isUnknown);
}
}.prepare());
} else {
createConnection(
connectionManagerPhoneAccount,
id,
request,
isIncoming,
isUnknown);
}
}
...
9.可以看到无论如何都会调用createConnection,点击跟进到ConnectionService中的此方法
/**
* This can be used by telecom to either create a new outgoing call or attach to an existing
* incoming call. In either case, telecom will cycle through a set of services and call
* createConnection util a connection service cancels the process or completes it successfully.
*/
/** {@hide} */
protected void createConnection(
final PhoneAccountHandle callManagerAccount,
final String callId,
final ConnectionRequest request,
boolean isIncoming,
boolean isUnknown) {
Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
"isIncoming: %b, isUnknown: %b", callManagerAccount, callId, request,
isIncoming,
isUnknown);
//判断是来电还是去电创造不同的connection
Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
: isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
...
Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
//创建成功后调用
mAdapter.handleCreateConnectionComplete(
callId,
request,
new ParcelableConnection(
...
if (isIncoming && request.shouldShowIncomingCallUi() &&
(connection.getConnectionProperties() & Connection.PROPERTY_SELF_MANAGED) ==
Connection.PROPERTY_SELF_MANAGED) {
// Tell ConnectionService to show its incoming call UX.
connection.onShowIncomingCallUi();
}
if (isUnknown) {
triggerConferenceRecalculate();
}
}
9.1当判断是来电时会通过 onCreateIncomingConnection 创建连接,直接跟进去发现是空实现,那么该方法的实现应该在该类的子类中,跟进到其子类TelephonyConnectionService中
/**
* Service for making GSM and CDMA connections.
*/
public class TelephonyConnectionService extends ConnectionService
@Override
public Connection onCreateIncomingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
ConnectionRequest request) {
...
Phone phone = getPhoneForAccount(accountHandle, isEmergency);
...
Call call = phone.getRingingCall();
com.android.internal.telephony.Connection originalConnection =
call.getState() == Call.State.WAITING ?
call.getLatestConnection() : call.getEarliestConnection();
...
Connection connection =
createConnectionFor(phone, originalConnection, false /* isOutgoing */,
request.getAccountHandle(), request.getTelecomCallId(),
request.getAddress(), videoState);
...
}
9.2 可以看到其是通过createConnectionFor创建
//返回需要的connection
protected TelephonyConnection createConnectionFor(
Phone phone,
com.android.internal.telephony.Connection originalConnection,
boolean isOutgoing,
PhoneAccountHandle phoneAccountHandle,
String telecomCallId,
Uri address,
int videoState) {
TelephonyConnection returnConnection = null;
int phoneType = phone.getPhoneType();
boolean allowsMute = allowsMute(phone);
returnConnection = new MtkGsmCdmaConnection(phoneType, originalConnection, telecomCallId,
mEmergencyTonePlayer, allowsMute, isOutgoing);
if (returnConnection != null) {
// Listen to Telephony specific callbacks from the connection
returnConnection.addTelephonyConnectionListener(mTelephonyConnectionListener);
returnConnection.setVideoPauseSupported(
TelecomAccountRegistry.getInstance(this).isVideoPauseSupported(
phoneAccountHandle));
}
return returnConnection;
}
10.继续回到之前的 handleCreateConnectionComplet中跟进
public void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection connection) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.handleCreateConnectionComplete(id, request, connection,
Log.getExternalSession());
} catch (RemoteException e) {
}
}
}
11.这里通过AIDL进行通信,搜索 IConnectionServiceAdapter.Stub,
跟进到 ConnectionServiceWrapper
@Override
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection, Session.Info sessionInfo) {
...
logIncoming("handleCreateConnectionComplete %s", callId);
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection);
...
}
之前在拨号创建完connection并呼叫之后也会走到这个地方
12.继续跟进handleCreateConnectionComplete
private void handleCreateConnectionComplete(
String callId,
ConnectionRequest request,
ParcelableConnection connection) {
...
if (connection.getState() == Connection.STATE_DISCONNECTED) {
removeCall(callId, connection.getDisconnectCause());
} else {
// Successful connection
if (mPendingResponses.containsKey(callId)) {
String num = connection.getHandle().getSchemeSpecificPart();
/// M: add for CMCC L + C ecc retry
if (PhoneNumberUtils.isEmergencyNumber(num)) {
mPendingResponses.get(callId).
handleCreateConnectionSuccess(mCallIdMapper, connection);
} else {
mPendingResponses.remove(callId)
.handleCreateConnectionSuccess(mCallIdMapper, connection);
}
}
}
}
mPendingResponses是hashMap容器,每次在 createConnection 的时候会将对象加入该容器,如果此时connection还未断开的,会移除此connection,调用hanleCreateConnectionSuccess方法。
往上追溯createConnection跟踪到mService.createConnection(mCall, this);
CreateConnectionProcessor.java会把自身传入,发现该类也实现了 CreateConnectionResponse ,所以这里的 handleCreateConnectionSuccess
调用的是这个类里面的方法
13.继续跟进 CreateConnectionProcessor 中的此方法
@Override
public void handleCreateConnectionSuccess(
CallIdMapper idMapper,
ParcelableConnection connection) {
if (mCallResponse == null) {
mService.abort(mCall);
} else {
mCallResponse.handleCreateConnectionSuccess(idMapper, connection);
String number = connection == null || connection.getHandle() == null ?
null : connection.getHandle().getSchemeSpecificPart();
if (!PhoneNumberUtils.isEmergencyNumber(number)) {
mCallResponse = null;
}
}
}
14.发现这里的 mCallResponse (mCallResponse为何是 telecomm Call 对象?),继续跟进telecomm Call中的
@Override
public void handleCreateConnectionSuccess(
CallIdMapper idMapper,
ParcelableConnection connection) {
...
switch (mCallDirection) {
case CALL_DIRECTION_INCOMING:
// Listeners (just CallsManager for now) will be responsible for checking whether
// the call should be blocked.
for (Listener l : mListeners) {
//触发回调
l.onSuccessfulIncomingCall(this);
}
break;
case CALL_DIRECTION_OUTGOING:
for (Listener l : mListeners) {
l.onSuccessfulOutgoingCall(this,
getStateFromConnectionState(connection.getState()));
}
break;
case CALL_DIRECTION_UNKNOWN:
for (Listener l : mListeners) {
l.onSuccessfulUnknownCall(this, getStateFromConnectionState(connection
.getState()));
}
break;
}
}
这里根据来电类型,触发回调,监听者会收到通知,之前在CallManager中执行 processIncomingCallIntent 方法创建Call的时候就添加了监听,所以最后会回调到
CallsManager中