Android 8.0来电流程分析(二)

2019-04-14 12:01发布

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中