赞
踩
来电过程, 是由com.android.phone进程发起的,因为 com.android.phone 进程中 Telephony 直接与Moderm层交互, com.android.phone 进程收到来来电消息后,发送消息给 system 进程, system 进程(Telecom作为中介)开始和com.android.phone 进程建立链接, 并通知 UI 进程 (com.android.dialer) 更新。大体上和拨号过程类似。
来电流程时序图:
对于MO Call来说,一般是由用户自己操作来发起的主动动作,可以根据UI上的button来跟踪流程。但是对于MTcall来说,一般是被动的接收modem的消息,不太好从UI的层面来跟踪流程,所以大概的总结下MT流程。
首先,查来电消息的处理。在来电时,首先是由modem向上上报来电的消息,上层来处理。第一条消息是:RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,消息报上来后,到RadioIndication.java来处理(在Android O后,UNSOL消息在RadioIndication处理,SOL消息在RadioResponse里处理。替代了之前的processUnsolicited & processSolicited方法)。这条消息就是modem 告知上层:当前Call的状态发送变化了。但是上层并不知道真正的变化是什么,所以Tele回去询问当前Call到底是属于什么状态,发出请求:RIL_REQUEST_GET_CURRENT_CALLS。当Modem得到这些请求后,会将这些信息返回给Tele.
从RIL层开始往上追溯,RIL接收底层来电消息。来电的消息属于主动上报的UnSolicited消息,其对应的事件ID是CALL_STATE_CHANGE,我们进入RIL.java开始查找。
UNSOL_RESPONSE_CALL STATE CHANGED状态改变
- @UnsupportedAppUsage
- 5692 void unsljLog(int response) {
- 5693 riljLog("[UNSL]< " + responseToString(response));
- 5694 }
-
- @UnsupportedAppUsage
- 5561 static String responseToString(int request) {
- 5562 switch(request) {
- 5563 case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
- 5564 return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
- 5565 case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
- 5566 return "UNSOL_RESPONSE_CALL_STATE_CHANGED";
- 5567 case RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED:
RadioIndication 类有17 个方法调用RIL 对象的unsljLog 方法打印消息,处理此
RIL 消息的代码逻辑详情如下:
- public void callStateChanged(int indicationType) {
- mRil.processIndication(indicationType);
-
- if (RIL.RILJ_LOGD) mRil.unsljLog(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED);
-
- mRil.mCallStateRegistrants.notifyRegistrants();
- }
RIL层在接收到底层的消息后,发起了notify通知。----------- 观测者模式
其中:
public class RadioIndication extends IRadioIndication.Stub {
而 mCallStateRegistrants 在:
RIL继承于父类 BaseCommands ,实现了 mCallStateRegistrants
public class RIL extends BaseCommands implements CommandsInterface
protected RegistrantList mCallStateRegistrants = new RegistrantList();
此处是: registerForCallStateChanged
搜索到有:
其中BascCommands,CommandsInterface都是接口
mCalIStateReg istrants. notifyRegistrant 发出通知后,仅一个 地方可响应此消息通知,即GsmCdmaCallTracker 类的handleMessage 方法,本质上是个Handler处理类
跟进GsmCdmaCallTracker的handleMessage方法,可以看到其在初始化的地方注册了CallStateChanged消息的监听,注册的时候传入了自身的handler,notify的时候使用该handler发送消息,所以我们可以在handleMessage中响应并处理EVENT_CALL_STATE_CHANGE消息。
- @Override
- public void handleMessage(Message msg) {
- AsyncResult ar;
-
- switch (msg.what) {
- ...
- case EVENT_CALL_STATE_CHANGE:
- pollCallsWhenSafe();
-
- ...
pollCallsWhenSafe 调用父类CallTracker 方法
- protected void pollCallsWhenSafe() {
- mNeedsPoll = true;
-
- mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
- mCi.getCurrentCalls(mLastRelevantPoll);
- }
- }
发现其又调用了mCi.getCurrentCalls去查询当前的Call情况,此方法会调用到RIL中对应的方法去(Phone创建的时候对mCi进行初始化使得具有RIL通信能力,其mCi即调用RIL.java)
又回到了 RIL 中
- @Override
- public void getCurrentCalls(Message result) {
- IRadio radioProxy = getRadioProxy(result);
- if (radioProxy != null) {
- RILRequest rr = obtainRequest(RIL_REQUEST_GET_CURRENT_CALLS, result,
- mRILDefaultWorkSource);
-
- if (RILJ_LOGD) {
- riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- }
-
- try {
-
- //向底层发起请求
- radioProxy.getCurrentCalls(rr.mSerial);
- } catch (RemoteException | RuntimeException e) {
- handleRadioProxyExceptionForRR(rr, "getCurrentCalls", e);
- }
- }
- }

在发送请求后,等待modem返回结果给RIL层,继续跟踪返回消息的接收(省去 与 RIL 层的交互)
在RIL.java中查找底层消息反馈的处理方法,发现有两个方法processRespose和processResponseDone,向上追溯发现其是在RadioResponse.java中的
responseCurrentCalls方法 调用了 processResponseDone 方法,如下:
其继承自一个底层的服务
public class RadioResponse extends IRadioResponse.Stub
CurrentCall的消息继续在responseCurrentCalls方法追踪。
- public void getCurrentCallsResponse(RadioResponseInfo responseInfo,
- ArrayList<android.hardware.radio.V1_0.Call> calls) {
- responseCurrentCalls(responseInfo, calls);
- }
继续追踪调用的responseCurrentCalls方法
- private void responseCurrentCalls(RadioResponseInfo responseInfo,
- ArrayList<android.hardware.radio.V1_0.Call> calls) {
- RILRequest rr = mRil.processResponse(responseInfo);
-
- if (rr != null) {
- int num = calls.size();
- ArrayList<DriverCall> dcCalls = new ArrayList<DriverCall>(num);
- DriverCall dc;
-
- for (int i = 0; i < num; i++) {
- dc = new DriverCall();
- // TODO: change name of function stateFromCLCC() in DriverCall.java to name
- // clarifying what is CLCC
- dc.state = DriverCall.stateFromCLCC((int) (calls.get(i).state));
- dc.index = calls.get(i).index;
- dc.TOA = calls.get(i).toa;
- dc.isMpty = calls.get(i).isMpty;
- dc.isMT = calls.get(i).isMT;
- dc.als = calls.get(i).als;
- dc.isVoice = calls.get(i).isVoice;
- dc.isVoicePrivacy = calls.get(i).isVoicePrivacy;
- dc.number = calls.get(i).number;
- dc.numberPresentation =
- DriverCall.presentationFromCLIP(
- (int) (calls.get(i).numberPresentation));
- dc.name = calls.get(i).name;
- dc.namePresentation =
- DriverCall.presentationFromCLIP((int) (calls.get(i).namePresentation));
- if (calls.get(i).uusInfo.size() == 1) {
- dc.uusInfo = new UUSInfo();
- dc.uusInfo.setType(calls.get(i).uusInfo.get(0).uusType);
- dc.uusInfo.setDcs(calls.get(i).uusInfo.get(0).uusDcs);
- if (!TextUtils.isEmpty(calls.get(i).uusInfo.get(0).uusData)) {
- byte[] userData = calls.get(i).uusInfo.get(0).uusData.getBytes();
- dc.uusInfo.setUserData(userData);
- } else {
- mRil.riljLog("responseCurrentCalls: uusInfo data is null or empty");
- }
-
- mRil.riljLogv(String.format("Incoming UUS : type=%d, dcs=%d, length=%d",
- dc.uusInfo.getType(), dc.uusInfo.getDcs(),
- dc.uusInfo.getUserData().length));
- mRil.riljLogv("Incoming UUS : data (hex): "
- + IccUtils.bytesToHexString(dc.uusInfo.getUserData()));
- } else {
- mRil.riljLogv("Incoming UUS : NOT present!");
- }
-
- // Make sure there's a leading + on addresses with a TOA of 145
- dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA);
- dcCalls.add(dc);
- if (dc.isVoicePrivacy) {
- mRil.mVoicePrivacyOnRegistrants.notifyRegistrants();
- mRil.riljLog("InCall VoicePrivacy is enabled");
- } else {
- mRil.mVoicePrivacyOffRegistrants.notifyRegistrants();
- mRil.riljLog("InCall VoicePrivacy is disabled");
- }
- }
- Collections.sort(dcCalls);
- if ((num == 0) && mRil.mTestingEmergencyCall.getAndSet(false)) {
- if (mRil.mEmergencyCallbackModeRegistrant != null) {
- mRil.riljLog("responseCurrentCalls: call ended, testing emergency call,"
- + " notify ECM Registrants");
- mRil.mEmergencyCallbackModeRegistrant.notifyRegistrant();
- }
- }
- //发送返回消息
- if (responseInfo.error == RadioError.NONE) {
- sendMessageResponse(rr.mResult, dcCalls);
- }
- mRil.processResponseDone(rr, responseInfo, dcCalls);
- }
- }
- 发现其通过底层返回的消息创建了dcCalls对象,也就是当前的Call状态信息,对dc状态进行判断后如果有需要就notify通知,如果没有异常则通过sendMessageResponse方法发送消息
- public static void sendMessageResponse(Message msg, Object ret) {
- if (msg != null) {
- AsyncResult.forMessage(msg, ret, null);
- msg.sendToTarget();
- }
- }

继续回到GsmCdmaCallTracker的handleMessage中,之前发送请求的时候有发送EVENT_POLL_CALLS_RESULT,这里我们继续回到该事件处理的地方来分析
- @Override
- public void handleMessage(Message msg) {
- AsyncResult ar;
-
- switch (msg.what) {
- case EVENT_POLL_CALLS_RESULT:
- Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
-
- if (msg == mLastRelevantPoll) {
- if (DBG_POLL) log(
- "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
- mNeedsPoll = false;
- mLastRelevantPoll = null;
- handlePollCalls((AsyncResult)msg.obj);
- }
- break;

继续追踪handlePollCalls
- @Override
- protected synchronized void handlePollCalls(AsyncResult ar) {
- //解析返回的结果
- for (int i = 0, curDC = 0, dcSize = polledCalls.size()
- ; i < mConnections.length; i++) {
- GsmCdmaConnection conn = mConnections[i];
- DriverCall dc = null;
-
- // polledCall list is sparse
- if (curDC < dcSize) {
- dc = (DriverCall) polledCalls.get(curDC);
-
- if (dc.index == i+1) {
- curDC++;
- } else {
- dc = null;
- }
- }
- ...
- if (conn == null && dc != null) {
- ...状态的处理及识别
-
- //响铃消息通知
- if (newRinging != null) {
- mPhone.notifyNewRingingConnection(newRinging);
- }
-
- // clear the "local hangup" and "missed/rejected call"
- // cases from the "dropped during poll" list
- // These cases need no "last call fail" reason
- ArrayList<GsmCdmaConnection> locallyDisconnectedConnections = new ArrayList<>();
- for (int i = mDroppedDuringPoll.size() - 1; i >= 0 ; i--) {
- GsmCdmaConnection conn = mDroppedDuringPoll.get(i);
- //CDMA
- boolean wasDisconnected = false;
- //来电处理,本地挂断或者未接,本地挂断的话直接设置挂断的原因为LOCAL或INVALID_NUMBER
- if (conn.isIncoming() && conn.getConnectTime() == 0) {
- // Missed or rejected call
- int cause;
- if (conn.mCause == DisconnectCause.LOCAL) {
- cause = DisconnectCause.INCOMING_REJECTED;
- } else {
- cause = DisconnectCause.INCOMING_MISSED;
- }
-
- if (Phone.DEBUG_PHONE) {
- log("missed/rejected call, conn.cause=" + conn.mCause);
- log("setting cause to " + cause);
- }
- mDroppedDuringPoll.remove(i);
- hasAnyCallDisconnected |= conn.onDisconnect(cause);
- wasDisconnected = true;
- locallyDisconnectedConnections.add(conn);
- } else if (conn.mCause == DisconnectCause.LOCAL
- || conn.mCause == DisconnectCause.INVALID_NUMBER) {
- mDroppedDuringPoll.remove(i);
- hasAnyCallDisconnected |= conn.onDisconnect(conn.mCause);
- wasDisconnected = true;
- locallyDisconnectedConnections.add(conn);
- }
-
- if (!isPhoneTypeGsm() && wasDisconnected && unknownConnectionAppeared
- && conn == newUnknownConnectionCdma) {
- unknownConnectionAppeared = false;
- newUnknownConnectionCdma = null;
- }
- }
- if (locallyDisconnectedConnections.size() > 0) {
- mMetrics.writeRilCallList(mPhone.getPhoneId(), locallyDisconnectedConnections);
- }
-
- /* Disconnect any pending Handover connections */
- //通话断开的一些处理操作
- ...
- if (newRinging != null || hasNonHangupStateChanged || hasAnyCallDisconnected) {
- internalClearDisconnected();
- }
- //更新phone状态
- if (VDBG) log("handlePollCalls calling updatePhoneState()");
- updatePhoneState();
-
- ...
-
- }

其先对底层反馈的消息进行解析,获取其通话状态,判断如果是来电则发出notifyNewRingingConnection响铃消息通知,然后进行一些通话断开连接的操作及更新phone状态。继续跟进notifyNewRingingConnection响铃消息,该消息调用的是phone的方法,往上追溯。
继续查看响铃消息通知到何处,全局搜索(registerForNewRingingConnection),找到
PstnIncommingCallNotifier.java
- /**
- * Listens to incoming-call events from the associated phone object and notifies Telecom upon each
- * occurence. One instance of these exists for each of the telephony-based call services.
- */
用来 监听来电消息
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch(msg.what) {
- case EVENT_NEW_RINGING_CONNECTION:
- handleNewRingingConnection((AsyncResult) msg.obj);
- break;
- case EVENT_CDMA_CALL_WAITING:
- handleCdmaCallWaiting((AsyncResult) msg.obj);
- break;
- case EVENT_UNKNOWN_CONNECTION:
- handleNewUnknownConnection((AsyncResult) msg.obj);
- break;
- default:
- break;
- }
- }
- };

继续调用handleNewRingingConnection方法处理调用sendIncommingCallIntent发送Intent,这里其实就已经从RIL传递消息到了应用层了
- private void handleNewRingingConnection(AsyncResult asyncResult) {
- Log.d(this, "handleNewRingingConnection");
- Connection connection = (Connection) asyncResult.result;
- if (connection != null) {
- Call call = connection.getCall();
- // Check if we have a pending number verification request.
- if (connection.getAddress() != null) {
- if (NumberVerificationManager.getInstance()
- .checkIncomingCall(connection.getAddress())) {
- // Disconnect the call if it matches
- try {
- connection.hangup();
- } catch (CallStateException e) {
- Log.e(this, e, "Error hanging up potential number verification call");
- }
- return;
- }
- }
-
- // Final verification of the ringing state before sending the intent to Telecom.
- if (call != null && call.getState().isRinging()) {
- sendIncomingCallIntent(connection);
- }
- }
- }

- private void sendIncomingCallIntent(Connection connection) {
- ------
-
- PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
- if (handle == null) {
- try {
- connection.hangup();
- } catch (CallStateException e) {
- // connection already disconnected. Do nothing
- }
- } else {
- TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
- }
- }
//获取telecomm服务,通过aidl接口调用 telecomService 的addNewIncomingCall方法
- //获取telecomm服务
- public static TelecomManager from(Context context) {
- return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
- }
- 108 private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
- 109 @Override
-
- 1083 public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
- 1084 try {
- 1085 Log.startSession("TSI.aNIC");
- 1086 synchronized (mLock) {
- 1087 Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
- 1088 phoneAccountHandle);
- 1089 。。。。。。。。。
- 。。。。。。。。。
- 1116 long token = Binder.clearCallingIdentity();
- 1117 try {
- 1118 Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
- 1119 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
- 1120 phoneAccountHandle);
- 1121 intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
- 1122 if (extras != null) {
- 1123 extras.setDefusable(true);
- 1124 intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
- 1125 }
- 1126 mCallIntentProcessorAdapter.processIncomingCallIntent(
- 1127 mCallsManager, intent);
- 1128 } finally {
- 1129 Binder.restoreCallingIdentity(token);
- 1130 }
- 1131 } else {
- 1132 Log.w(this, "Null phoneAccountHandle. Ignoring request to add new" +
- 1133 " incoming call");
- 1134 }
- 1135 }
- 1136 } finally {
- 1137 Log.endSession();
- 1138 }
- 1139 }

继续跟进mCallIntentProcessorAdapter.processIncomingCallIntent,
- 287 static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
- 288 PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
- 289 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
- 290
- 291 if (phoneAccountHandle == null) {
- 292 Log.w(CallIntentProcessor.class,
- 293 "Rejecting incoming call due to null phone account");
- 294 return;
- 295 }
- 296 if (phoneAccountHandle.getComponentName() == null) {
- 297 Log.w(CallIntentProcessor.class,
- 298 "Rejecting incoming call due to null component name");
- 299 return;
- 300 }
- 301
- 302 Bundle clientExtras = null;
- 303 if (intent.hasExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS)) {
- 304 clientExtras = intent.getBundleExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS);
- 305 }
- 306 if (clientExtras == null) {
- 307 clientExtras = new Bundle();
- 308 }
- 309
- 310 Log.d(CallIntentProcessor.class,
- 311 "Processing incoming call from connection service [%s]",
- 312 phoneAccountHandle.getComponentName());
- 313 callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
- 314 }

--------------------------------------------------------------------------
下方与拨号相同
进入到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);
- }
- }

- void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
- if (mCreateConnectionProcessor != null) {
- Log.w(this, "mCreateConnectionProcessor in startCreateConnection is not null. This is" +
- " due to a race between NewOutgoingCallIntentBroadcaster and " +
- "phoneAccountSelected, but is harmlessly resolved by ignoring the second " +
- "invocation.");
- return;
- }
- mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
- phoneAccountRegistrar, mContext);
- mCreateConnectionProcessor.process();
- }
继续跟踪process 方法
- public void process() {
- Log.v(this, "process");
- clearTimeout();
- mAttemptRecords = new ArrayList<>();
- if (mCall.getTargetPhoneAccount() != null) {
- mAttemptRecords.add(new CallAttemptRecord(
- mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
- }
- if (!mCall.isSelfManaged()) {
- adjustAttemptsForConnectionManager();
- adjustAttemptsForEmergency(mCall.getTargetPhoneAccount());
- }
- mAttemptRecordIterator = mAttemptRecords.iterator();
- attemptNextPhoneAccount();
- }
-
-

其中 attemptNextPhoneAccount 方法
- private void attemptNextPhoneAccount() {
- Log.v(this, "attemptNextPhoneAccount");
- CallAttemptRecord attempt = null;
-
-
- if (mCallResponse != null && attempt != null) {
- Log.i(this, "Trying attempt %s", attempt);
- PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
- mService = mRepository.getService(phoneAccount.getComponentName(),
- phoneAccount.getUserHandle());
- if (mService == null) {
- Log.i(this, "Found no connection service for attempt %s", attempt);
- attemptNextPhoneAccount();
- } else {
- mConnectionAttempt++;
- mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
- mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
- mCall.setConnectionService(mService);
- setTimeoutIfNeeded(mService, attempt);
- if (mCall.isIncoming()) {
- mService.createConnection(mCall, CreateConnectionProcessor.this);
- } else {
- // Start to create the connection for outgoing call after the ConnectionService
- // of the call has gained the focus.
- mCall.getConnectionServiceFocusManager().requestFocus(
- mCall,
- new CallsManager.RequestCallback(new CallsManager.PendingAction() {
- @Override
- public void performAction() {
- Log.d(this, "perform create connection");
- mService.createConnection(
- mCall,
- CreateConnectionProcessor.this);
- }
- }));
-
- }
- }
- } else {
- Log.v(this, "attemptNextPhoneAccount, no more accounts, failing");
- DisconnectCause disconnectCause = mLastErrorDisconnectCause != null ?
- mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR);
- notifyCallConnectionFailure(disconnectCause);
- }
- }

核心代码:
- private ConnectionServiceWrapper mService;
-
- if (mCall.isIncoming()) {
- mService.createConnection(mCall, CreateConnectionProcessor.this);
- }
- void createConnection(final Call call, final CreateConnectionResponse response) {
-
- // 链接创建成功后 onSuccess 会被调用
- BindCallback callback = new BindCallback() {
- @Override
- public void onSuccess() {
-
- try {
- /// M: For VoLTE @{
- boolean isConferenceDial = call.isConferenceDial();
-
- // 会议通话
- if (isConferenceDial) {
- logOutgoing("createConference(%s) via %s.", call, getComponentName());
- mServiceInterface.createConference(
- call.getConnectionManagerPhoneAccount(),
- callId,
- new ConnectionRequest(
- call.getTargetPhoneAccount(),
- call.getHandle(),
- extras,
- call.getVideoState()),
- call.getConferenceParticipants(),
- call.isIncoming());
-
- // 非会议(拨打电话会走这里)
- } else {
-
- // 通过远程接口创建链接
- mServiceInterface.createConnection(
- call.getConnectionManagerPhoneAccount(),
- callId,
- new ConnectionRequest(
- call.getTargetPhoneAccount(),
- call.getHandle(),
- extras,
- call.getVideoState()),
- call.isIncoming(),
- call.isUnknown());
- }
- /// @}
- } catch (RemoteException e) {
-
- }
- }
-
- @Override
- public void onFailure() {
- }
- };
-
- mBinder.bind(callback, call);
- }

mBinder是Binder2对象,Binder2是ConnectionServiceWrapper的父类ServiceBinder内部类,所以此处调用的是的ServiceBinder的内部类的Binder2类的bind()方法,先new一个ServiceConnection对象,然后绑定一个远程服务端服务。如果绑定成功的话,在ServiceBinder的内部类ServiceBinderConnection的onServiceConnected()方法就被调用。
在这里做了两件事:
1).通过setBinder()方法,回调ConnectionServiceWrapper的setServiceInterface()方法,通过mServiceInterface = IConnectionService.Stub.asInterface(binder);
这行代码获取一个远程服务端的对象mServiceInterface 。
2)、再通过调用handleSuccessfulConnection()方法回调callback 的onSuccess()方法,也就又回到ConnectionServiceWrapper的createConnection()方法里。调用ConnectionService.java里mBinder的createConnection()方法然后通过message传递调用createConnection()方法。
mBider 的bind 方法
- void bind(BindCallback callback, Call call) {
-
- if (mServiceConnection == null) {
- Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
- ServiceConnection connection = new ServiceBinderConnection(call);
-
- // 进行绑定
- if (mUserHandle != null) {
- isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
- mUserHandle);
- } else {
- isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
- }
- if (!isBound) {
- handleFailedConnection();
- return;
- }
- } else {
- }
- }

绑定成功后,ServiceBinderConnection 的 onServiceConnected 会触发
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder binder) {
- try {
-
- if (binder != null) {
- mServiceDeathRecipient = new ServiceDeathRecipient(componentName);
- try {
- binder.linkToDeath(mServiceDeathRecipient, 0);
- mServiceConnection = this;
- // 会触发 ConnectionServiceWrapper.setServiceInterface ==>
- ConnectionServiceWrapper.addConnectionServiceAdapter
- 通过mServiceInterface,给绑定的服务,提供一个访问自己的接口
-
-
- setBinder(binder);
-
- // 触发bind(BindCallback callback, Call call) 中 callback 的 onSuccess
-
- handleSuccessfulConnection();
- } catch (RemoteException e) {
- Log.w(this, "onServiceConnected: %s died.");
- if (mServiceDeathRecipient != null) {
- mServiceDeathRecipient.binderDied();
- }
- }
- }
- }
- } finally {
- Log.endSession();
- }
- }

整个绑定过程,只做2件事,
一是给远程服务提供访问自己的接口,
二是利用远程接口创建一个通话链接。
这2件事都是跨进程进行的。远程服务访问自己的接口是 ConnectionServiceWrapper.Adapter
, 是一个Binder。
由内部类 Adapter 继承于 IConnectionServiceAdapter.Stub,可以看出会进行跨进程访问
- public class ConnectionServiceWrapper extends ServiceBinder implements
- ConnectionServiceFocusManager.ConnectionServiceFocus {
-
- private final class Adapter extends IConnectionServiceAdapter.Stub {
调用ConnectionService.java里mBinder的createConnection()方法然后通过message传递调用createConnection()方法。
- private void handleSuccessfulConnection() {
- // Make a copy so that we don't have a deadlock inside one of the callbacks.
- Set<BindCallback> callbacksCopy = new ArraySet<>();
- synchronized (mCallbacks) {
- callbacksCopy.addAll(mCallbacks);
- mCallbacks.clear();
- }
-
- for (BindCallback callback : callbacksCopy) {
- callback.onSuccess();
- }
- }
通过调用handleSuccessfulConnection()方法回调callback 的onSuccess()方法,也就又回到ConnectionServiceWrapper的createConnection()方法里。
- 1094 public void createConnection(final Call call, final CreateConnectionResponse response) {
- 1095 Log.d(this, "createConnection(%s) via %s.", call, getComponentName());
- 1096 BindCallback callback = new BindCallback() {
- 1097 @Override
- 1098 public void onSuccess() {
- 1099 String callId = mCallIdMapper.getCallId(call);
- 1100 mPendingResponses.put(callId, response);
- 1101
- ///---------//
-
- 1146
- 1150 // 核心代码
- 1151 try {
- 1152 mServiceInterface.createConnection(
- 1153 call.getConnectionManagerPhoneAccount(),
- 1154 callId,
- 1155 connectionRequest,
- 1156 call.shouldAttachToExistingConnection(),
- 1157 call.isUnknown(),
- 1158 Log.getExternalSession());
- 1159
- 1160 } catch (RemoteException e) {
- 1161 Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
- 1162 mPendingResponses.remove(callId).handleCreateConnectionFailure(
- 1163 new DisconnectCause(DisconnectCause.ERROR, e.toString()));
- 1164 }
- 1165 }
- 1166
- 1167 @Override
- 1168 public void onFailure() {
- 1169 Log.e(this, new Exception(), "Failure to call %s", getComponentName());
- 1170 response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.ERROR));
- 1171 }
- 1172 };
- 1173
- 1174 mBinder.bind(callback, call);
- 1175 }

private IConnectionService mServiceInterface;
线中间的处理过程 和 拨号 流程一样
-----------------------------------------------------------------
createConnection()方法通过判断是来电还是去电分别创建不同的connection,
- /**
- * 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();
- }
- }

此处先分析: onCreateIncomingConnection
运行完成后分析:mAdapter.handleCreateConnectionComplete
其中:
- public Connection onCreateIncomingConnection(
- PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- return null;
- }
当判断是来电时会通过 onCreateIncomingConnection 创建连接,直接跟进去发现是空实现,那么该方法的实现应该在该类的子类中,跟进到其子类TelephonyConnectionService中
public class TelephonyConnectionService extends ConnectionService {
- /**
- * 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);
-
- ...
- }

跳转到 createConnectionFor 方法中
- private 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();
- if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
- returnConnection = new GsmConnection(originalConnection, telecomCallId, isOutgoing);
- } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
- boolean allowsMute = allowsMute(phone);
- returnConnection = new CdmaConnection(originalConnection, mEmergencyTonePlayer,
- allowsMute, isOutgoing, telecomCallId);
- }
- if (returnConnection != null) {
- // Listen to Telephony specific callbacks from the connection
- returnConnection.addTelephonyConnectionListener(mTelephonyConnectionListener);
- returnConnection.setVideoPauseSupported(
- TelecomAccountRegistry.getInstance(this).isVideoPauseSupported(
- phoneAccountHandle));
- returnConnection.setManageImsConferenceCallSupported(
- TelecomAccountRegistry.getInstance(this).isManageImsConferenceCallSupported(
- phoneAccountHandle));
- returnConnection.setShowPreciseFailedCause(
- TelecomAccountRegistry.getInstance(this).isShowPreciseFailedCause(
- phoneAccountHandle));
- }
- return returnConnection;
- }

继续 分析 mAdapter.handleCreateConnectionComplete
这里通过AIDL进行通信,搜索 IConnectionServiceAdapter.Stub,跟进到 ConnectionServiceWrapper
- private final class Adapter extends IConnectionServiceAdapter.Stub {
-
- @Override
- public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
- ParcelableConnection connection, Session.Info sessionInfo) {
- Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
- long token = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- logIncoming("handleCreateConnectionComplete %s", callId);
- ConnectionServiceWrapper.this
- .handleCreateConnectionComplete(callId, request, connection);
-
-
继续跟进handleCreateConnectionComplete
-
- private void handleCreateConnectionComplete(
- String callId,
- ConnectionRequest request,
- ParcelableConnection connection) {
- // TODO: Note we are not using parameter "request", which is a side effect of our tacit
- // assumption that we have at most one outgoing connection attempt per ConnectionService.
- // This may not continue to be the case.
- if (connection.getState() == Connection.STATE_DISCONNECTED) {
- // A connection that begins in the DISCONNECTED state is an indication of
- // failure to connect; we handle all failures uniformly
- Call foundCall = mCallIdMapper.getCall(callId);
- if (foundCall != null) {
- // The post-dial digits are created when the call is first created. Normally
- // the ConnectionService is responsible for stripping them from the address, but
- // since a failed connection will not have done this, we could end up with duplicate
- // post-dial digits.
- foundCall.clearPostDialDigits();
- }
- removeCall(callId, connection.getDisconnectCause());
- } else {
- // Successful connection
- if (mPendingResponses.containsKey(callId)) {
- mPendingResponses.remove(callId)
- .handleCreateConnectionSuccess(mCallIdMapper, connection);
- }
- }
- }

mPendingResponses是hashMap容器,每次在 createConnection 的时候会将对象加入该容器,如果此时connection还未断开的,会移除此connection,调用hanleCreateConnectionSuccess方法。
往上追溯CreateConnectionResponse,是一个接口,跟踪到mService.createConnection(mCall, this);
public class CreateConnectionProcessor implements CreateConnectionResponse {
CreateConnectionProcessor.java会把自身传入,发现该类也实现了 CreateConnectionResponse ,所以这里的 handleCreateConnectionSuccess
调用的是这个类里面的方法
- private CreateConnectionResponse mCallResponse;
-
- @Override
- public void handleCreateConnectionSuccess(
- CallIdMapper idMapper,
- ParcelableConnection connection) {
- if (mCallResponse == null) {
- // Nobody is listening for this connection attempt any longer; ask the responsible
- // ConnectionService to tear down any resources associated with the call
- mService.abort(mCall);
- } else {
- // Success -- share the good news and remember that we are no longer interested
- // in hearing about any more attempts
- // 核心代码
- mCallResponse.handleCreateConnectionSuccess(idMapper, connection);
- mCallResponse = null;
- // If there's a timeout running then don't clear it. The timeout can be triggered
- // after the call has successfully been created but before it has become active.
- }
- }

还是 CreateConnectionResponse 接口
实现的是 Call 对象 ,Call 也实现了该接口
- public class Call implements CreateConnectionResponse, EventManager.Loggable,
- 84 ConnectionServiceFocusManager.CallFocus {
- public void handleCreateConnectionSuccess(
- CallIdMapper idMapper,
- ParcelableConnection connection) {
- Log.v(this, "handleCreateConnectionSuccessful %s", connection);
- setTargetPhoneAccount(connection.getPhoneAccount());
- setHandle(connection.getHandle(), connection.getHandlePresentation());
- setCallerDisplayName(
- connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
-
- setConnectionCapabilities(connection.getConnectionCapabilities());
- setConnectionProperties(connection.getConnectionProperties());
- setIsVoipAudioMode(connection.getIsVoipAudioMode());
- setSupportedAudioRoutes(connection.getSupportedAudioRoutes());
- setVideoProvider(connection.getVideoProvider());
- setVideoState(connection.getVideoState());
- setRingbackRequested(connection.isRingbackRequested());
- setStatusHints(connection.getStatusHints());
- putExtras(SOURCE_CONNECTION_SERVICE, connection.getExtras());
-
- mConferenceableCalls.clear();
- for (String id : connection.getConferenceableConnectionIds()) {
- mConferenceableCalls.add(idMapper.getCall(id));
- }
-
- switch (mCallDirection) {
- case CALL_DIRECTION_INCOMING:
-
- for (Listener l : mListeners) {
- // 此处触发了回调
- l.onSuccessfulIncomingCall(this);
- }
- break;
- 。。。。。

这里根据来电类型,触发回调,监听者会收到通知
,之前在CallManager中执行 processIncomingCallIntent 方法创建Call的时候就添加了监听,所以最后会回调到CallsManager中
可以看出CallsManager的管理作用,创建Calls并添加监听,在完成Call的相关初始化后进行进一步处理,其实就是传递消息到别的的地方去。
- public void onSuccessfulIncomingCall(Call incomingCall) {
- Log.d(this, "onSuccessfulIncomingCall");
- PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
- incomingCall.getTargetPhoneAccount());
- Bundle extras =
- phoneAccount == null || phoneAccount.getExtras() == null
- ? new Bundle()
- : phoneAccount.getExtras();
- if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE) ||
- incomingCall.isSelfManaged() ||
- extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING)) {
- Log.i(this, "Skipping call filtering for %s (ecm=%b, selfMgd=%b, skipExtra=%b)",
- incomingCall.getId(),
- incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE),
- incomingCall.isSelfManaged(),
- extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING));
- onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
- incomingCall.setIsUsingCallFiltering(false);
- return;
- }
-
- incomingCall.setIsUsingCallFiltering(true);
- //迭代器模式
- List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
- filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
- filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
- mCallerInfoLookupHelper, null));
- filters.add(new CallScreeningServiceController(mContext, this, mPhoneAccountRegistrar,
- new ParcelableCallUtils.Converter(), mLock,
- new TelecomServiceImpl.SettingsSecureAdapterImpl(), mCallerInfoLookupHelper,
- new CallScreeningServiceHelper.AppLabelProxy() {
- @Override
- public CharSequence getAppLabel(String packageName) {
- PackageManager pm = mContext.getPackageManager();
- try {
- ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
- return pm.getApplicationLabel(info);
- } catch (PackageManager.NameNotFoundException nnfe) {
- Log.w(this, "Could not determine package name.");
- }
-
- return null;
- }
- }));
- //IncomingCallFilter创建并执行 performFiltering
- new IncomingCallFilter(mContext, this, incomingCall, mLock,
- mTimeoutsAdapter, filters).performFiltering();
- }

IncomingCallFilter创建并执行 performFiltering
- public void performFiltering() {
- Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED);
- for (CallFilter filter : mFilters) {
- //遍历调用,依次执行异步查询方法
- filter.startFilterLookup(mCall, this);
- }
- // synchronized to prevent a race on mResult and to enter into Telecom.
- mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) { // performFiltering time-out
- @Override
- public void loggedRun() {
- if (mIsPending) {
- //超时处理的方法
- Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
- Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
- //回CallsManager中的监听事件
- mListener.onCallFilteringComplete(mCall, mResult);
- mIsPending = false;
- }
- }
- }.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
- }

如果没有超时则在异步查询结束后,会通过回调方法将CallFilterResult传回onCallFilteringComplete.
- public void onCallFilteringComplete(Call call, CallFilteringResult result) {
- synchronized (mTelecomLock) { // synchronizing to prevent race on mResult
- mNumPendingFilters--;
- mResult = result.combine(mResult);
- if (mNumPendingFilters == 0) {
- // synchronized on mTelecomLock to enter into Telecom.
- mHandler.post(new Runnable("ICF.oCFC", mTelecomLock) {
- @Override
- public void loggedRun() {
- if (mIsPending) {
- Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, mResult);
- mListener.onCallFilteringComplete(mCall, mResult);
- mIsPending = false;
- }
- }
- }.prepare());
- }
- }
- }

然后, 回到CallsManager中进行onCallFilteringComplete处理
- @Override
- public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
- ...
- if (incomingCall.getState() != CallState.DISCONNECTED &&
- incomingCall.getState() != CallState.DISCONNECTING &&
- incomingCall.getState() != CallState.ACTIVE) {
- //设置Call状态为Ring
- setCallState(incomingCall, CallState.RINGING,
- result.shouldAllowCall ? "successful incoming call" : "blocking call");
- } else {
- Log.i(this, "onCallFilteringCompleted: call already disconnected.");
- return;
- }
-
- if (result.shouldAllowCall) {
- if (MtkUtil.isInSingleVideoCallMode(incomingCall)) {
- ...
- }
-
- if (hasMaximumManagedRingingCalls(incomingCall)) {
- if (shouldSilenceInsteadOfReject(incomingCall)) {
- incomingCall.silence();
- } else {
- Log.i(this, "onCallFilteringCompleted: Call rejected! " +
- "Exceeds maximum number of ringing calls.");
- rejectCallAndLog(incomingCall);
- }
-
- } else {
- //添加Call
- addCall(incomingCall);
- }
- } else {
- if (result.shouldReject) {
- Log.i(this, "onCallFilteringCompleted: blocked call, rejecting.");
- incomingCall.reject(false, null);
- }
- if (result.shouldAddToCallLog) {
- Log.i(this, "onCallScreeningCompleted: blocked call, adding to call log.");
- if (result.shouldShowNotification) {
- Log.w(this, "onCallScreeningCompleted: blocked call, showing notification.");
- }
- //添加通话记录
- mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
- result.shouldShowNotification);
- } else if (result.shouldShowNotification) {
- Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
- mMissedCallNotifier.showMissedCallNotification(
- new MissedCallNotifier.CallInfo(incomingCall));
- }
- }
- }

跟踪到 addCall 方法
- 3207 @VisibleForTesting
- 3208 public void addCall(Call call) {
- 3209 Trace.beginSection("addCall");
- 3210 Log.v(this, "addCall(%s)", call);
- 3211 call.addListener(this);
- 3212 mCalls.add(call);
- 3213
- 3214 // Specifies the time telecom finished routing the call. This is used by the dialer for
- 3215 // analytics.
- 3216 Bundle extras = call.getIntentExtras();
- 3217 extras.putLong(TelecomManager.EXTRA_CALL_TELECOM_ROUTING_END_TIME_MILLIS,
- 3218 SystemClock.elapsedRealtime());
- 3219
- 3220 updateCanAddCall();
- 3221 // onCallAdded for calls which immediately take the foreground (like the first call).
- 3222 for (CallsManagerListener listener : mListeners) {
- 3223 if (LogUtils.SYSTRACE_DEBUG) {
- 3224 Trace.beginSection(listener.getClass().toString() + " addCall");
- 3225 }
- 3226 listener.onCallAdded(call);
- 3227 if (LogUtils.SYSTRACE_DEBUG) {
- 3228 Trace.endSection();
- 3229 }
- 3230 }
- 3231 Trace.endSection();
- 3232 }

//通知监听Call添加的观察者
listener.onCallAdded(call);
添加的观察者,和拨号一样,主要是 CllAudilManager (负责响铃)和 InCallController
- mListeners.add(mInCallWakeLockController);
- mListeners.add(statusBarNotifier);
- mListeners.add(mCallLogManager);
- mListeners.add(mPhoneStateBroadcaster);
- mListeners.add(mInCallController);
- mListeners.add(mCallAudioManager);
- mListeners.add(mCallRecordingTonePlayer);
- mListeners.add(missedCallNotifier);
- mListeners.add(mHeadsetMediaButton);
- mListeners.add(mProximitySensorManager);
其中:
- private void onCallEnteringRinging() {
- 641 if (mRingingCalls.size() == 1) {
- 642 mCallAudioModeStateMachine.sendMessageWithArgs(
- 643 CallAudioModeStateMachine.NEW_RINGING_CALL,
- 644 makeArgsForModeStateMachine());
- 645 }
- 646 }
查看 InCallController 的 onCallAdded 方法
- @Override
- public void onCallAdded(Call call) {
- if (!isBoundAndConnectedToServices()) {
- bindToServices(call);
- } else {
- // We are bound, and we are connected.
- adjustServiceBindingsForEmergency();
-
- // This is in case an emergency call is added while there is an existing call.
- mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(call,
- mCallsManager.getCurrentUserHandle());
-
- //添加Call
- addCall(call);
-
- List<ComponentName> componentsUpdated = new ArrayList<>();
- for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
- InCallServiceInfo info = entry.getKey();
-
- if (call.isExternalCall() && !info.isExternalCallsSupported()) {
- continue;
- }
-
- if (call.isSelfManaged() && !info.isSelfManagedCallsSupported()) {
- continue;
- }
-
- // Only send the RTT call if it's a UI in-call service
- boolean includeRttCall = info.equals(mInCallServiceConnection.getInfo());
- componentsUpdated.add(info.getComponentName());
- IInCallService inCallService = entry.getValue();
- ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
- true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
- info.isExternalCallsSupported(), includeRttCall);
- try {
- //AIDL调用远程的addCall方法
- inCallService.addCall(parcelableCall);
- } catch (RemoteException ignored) {
- }
- }
- Log.i(this, "Call added to components: %s", componentsUpdated);
- }
- }

- 291 /** Manages the binder calls so that the implementor does not need to deal with it. */
- 292 private final class InCallServiceBinder extends IInCallService.Stub {
- 293 @Override
- 294 public void setInCallAdapter(IInCallAdapter inCallAdapter) {
- 295 mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
- 296 }
- 297
- 298 @Override
- 299 public void addCall(ParcelableCall call) {
- 300 mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
- 301 }
继续跟进MSG_ADD_CALL消息的处理
- 205 /** Default Handler used to consolidate binder method calls onto a single thread. */
- 206 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
- 207 @Override
- 208 public void handleMessage(Message msg) {
- 209 if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
- 210 return;
- 211 }
- 212
- 213 switch (msg.what) {
- 214 case MSG_SET_IN_CALL_ADAPTER:
- 215 String callingPackage = getApplicationContext().getOpPackageName();
- 216 mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage,
- 217 getApplicationContext().getApplicationInfo().targetSdkVersion);
- 218 mPhone.addListener(mPhoneListener);
- 219 onPhoneCreated(mPhone);
- 220 break;
- 221 case MSG_ADD_CALL:
- 222 mPhone.internalAddCall((ParcelableCall) msg.obj);
- 223 break;

继续跟进internalAddCall
- final void internalAddCall(ParcelableCall parcelableCall) {
- //创建Call
- Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
- parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);
-
- mCallByTelecomCallId.put(parcelableCall.getId(), call);
- //添加到列表中
- mCalls.add(call);
- checkCallTree(parcelableCall);
- call.internalUpdate(parcelableCall, mCallByTelecomCallId);
- //调用phone的监听者的onCallAdded
- fireCallAdded(call);
- }
-
- private void fireCallAdded(Call call) {
- for (Listener listener : mListeners) {
- listener.onCallAdded(this, call);
- }
- }

在 InCallService 中handleMessage处理MSG_SET_IN_CALL_ADAPTER消息的时候就注册了监听,这里继续跟进到InCallService中的实现去
- private Phone.Listener mPhoneListener = new Phone.Listener() {
- /** ${inheritDoc} */
- @Override
- public void onAudioStateChanged(Phone phone, AudioState audioState) {
- InCallService.this.onAudioStateChanged(audioState);
- }
- 。。。。。//
-
-
- /** ${inheritDoc} */
- @Override
- public void onCallAdded(Phone phone, Call call) {
- InCallService.this.onCallAdded(call);
- }
这其实是个空实现,具体实现是在子类中,继续跟进到子类 InCallServiceImpl 中分析
- public class InCallServiceImpl extends InCallService {
-
- private ReturnToCallController returnToCallController;
- private CallList.Listener feedbackListener;
- // We only expect there to be one speakEasyCallManager to be instantiated at a time.
- // We did not use a singleton SpeakEasyCallManager to avoid holding on to state beyond the
- // lifecycle of this service, because the singleton is associated with the state of the
- // Application, not this service.
- private SpeakEasyCallManager speakEasyCallManager;
-
- @Override
- public void onCallAudioStateChanged(CallAudioState audioState) {
- Trace.beginSection("InCallServiceImpl.onCallAudioStateChanged");
- AudioModeProvider.getInstance().onAudioStateChanged(audioState);
- Trace.endSection();
- }
-
- ///-----------
-
- @Override
- public void onCallAdded(Call call) {
- Trace.beginSection("InCallServiceImpl.onCallAdded");
- InCallPresenter.getInstance().onCallAdded(call);
- Trace.endSection();
- }

跟踪到这里可以看到其所在目录是Dialer下的inCallUI了,这就到dialer层了,如果查看Diler的清单文件可以发现其有android.telecom.InCallService声明
- public void onCallAdded(final android.telecom.Call call) {
- LatencyReport latencyReport = new LatencyReport(call);
- if (shouldAttemptBlocking(call)) {
- maybeBlockCall(call, latencyReport);
- } else {
- if (call.getDetails().hasProperty(CallCompat.Details.PROPERTY_IS_EXTERNAL_CALL)) {
- mExternalCallList.onCallAdded(call);
- } else {
- latencyReport.onCallBlockingDone();
- //CallList(Call的维护列表)调用onCallAdded
- mCallList.onCallAdded(mContext, call, latencyReport);
- }
- }
-
- // Since a call has been added we are no longer waiting for Telecom to send us a call.
- setBoundAndWaitingForOutgoingCall(false, null);
- call.registerCallback(mCallCallback);
- }

- public void onCallAdded(
- final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) {
- Trace.beginSection("onCallAdded");
- ...
- if (call.getState() == DialerCall.State.INCOMING
- || call.getState() == DialerCall.State.CALL_WAITING) {
- //来电调用
- onIncoming(call);
- } else {
- dialerCallListener.onDialerCallUpdate();
- }
- ...
- }
跟踪 onIncoming 方法
- /** Called when a single call has changed. */
- private void onIncoming(DialerCall call) {
- Trace.beginSection("CallList.onIncoming");
- if (updateCallInMap(call)) {
- LogUtil.i("CallList.onIncoming", String.valueOf(call));
- }
-
- for (Listener listener : listeners) {
- listener.onIncomingCall(call);
- }
- Trace.endSection();
- }
InCallPresenter 监听来电状态
可以看出 InCallPresenter 实现了 CallList.Listener 的接口,所以可以监听来电的状态
public class InCallPresenter implements CallList.Listener, AudioModeProvider.AudioModeListener {
跟踪到 onCallListChange 方法
- @Override
- public void onCallListChange(CallList callList) {
- Trace.beginSection("InCallPresenter.onCallListChange");
- if (inCallActivity != null && inCallActivity.isInCallScreenAnimating()) {
- awaitingCallListUpdate = true;
- Trace.endSection();
- return;
- }
- if (callList == null) {
- Trace.endSection();
- return;
- }
-
- awaitingCallListUpdate = false;
-
- InCallState newState = getPotentialStateFromCallList(callList);
- InCallState oldState = inCallState;
- LogUtil.d(
- "InCallPresenter.onCallListChange",
- "onCallListChange oldState= " + oldState + " newState=" + newState);
-
- // If the user placed a call and was asked to choose the account, but then pressed "Home", the
- // incall activity for that call will still exist (even if it's not visible). In the case of
- // an incoming call in that situation, just disconnect that "waiting for account" call and
- // dismiss the dialog. The same activity will be reused to handle the new incoming call. See
- // a bug for more details.
- DialerCall waitingForAccountCall;
- if (newState == InCallState.INCOMING
- && (waitingForAccountCall = callList.getWaitingForAccountCall()) != null) {
- waitingForAccountCall.disconnect();
- // The InCallActivity might be destroyed or not started yet at this point.
- if (isActivityStarted()) {
- inCallActivity.dismissPendingDialogs();
- }
- }
-
- // 核心代码
- newState = startOrFinishUi(newState);
- LogUtil.d(
- "InCallPresenter.onCallListChange", "onCallListChange newState changed to " + newState);
-
- // Set the new state before announcing it to the world
- LogUtil.i(
- "InCallPresenter.onCallListChange",
- "Phone switching state: " + oldState + " -> " + newState);
- inCallState = newState;
-
- // Foreground call changed
- DialerCall primary = null;
- if (newState == InCallState.INCOMING) {
- primary = callList.getIncomingCall();
- } else if (newState == InCallState.PENDING_OUTGOING || newState == InCallState.OUTGOING) {
- primary = callList.getOutgoingCall();
- if (primary == null) {
- primary = callList.getPendingOutgoingCall();
- }
- } else if (newState == InCallState.INCALL) {
- primary = getCallToDisplay(callList, null, false);
- }
- if (primary != null) {
- onForegroundCallChanged(primary);
-
- }
-
- // notify listeners of new state
- for (InCallStateListener listener : listeners) {
- LogUtil.d(
- "InCallPresenter.onCallListChange",
- "Notify " + listener + " of state " + inCallState.toString());
- listener.onStateChange(oldState, inCallState, callList);
- }
-
-
- if (isActivityStarted()) {
- final boolean hasCall =
- callList.getActiveOrBackgroundCall() != null || callList.getOutgoingCall() != null;
- inCallActivity.dismissKeyguard(hasCall);
- }
-
-
- Trace.endSection();
- }

继续跟踪 startOrFinishUi 方法
- private InCallState startOrFinishUi(InCallState newState) {
-
- if ((showCallUi || showAccountPicker) && !shouldStartInBubbleMode()) {
- LogUtil.i("InCallPresenter.startOrFinishUi", "Start in call UI");
- // 展示来电界面
- showInCall(false /* showDialpad */, !showAccountPicker /* newOutgoingCall */);
- } else if (newState == InCallState.INCOMING) {
- LogUtil.i("InCallPresenter.startOrFinishUi", "Start Full Screen in call UI");
-
- try {
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- PowerHALManager powerHALManager = new PowerHALManager(context, new Handler());
- PowerHALManager.PowerHintScene sceneIncall = powerHALManager.createPowerHintScene(
- "InCall: InCallPresenter", PowerHintVendorSprd.POWER_HINT_VENDOR_RADIO_CALL, null);
- if (sceneIncall != null && !pm.isScreenOn()) {
- Log.i(this, "power Hint POWER_HINT_VENDOR_RADIO_CALL");
- sceneIncall.acquire(1000);
- }
- } catch (java.lang.NoClassDefFoundError e) {
- LogUtil.e("InCallPresenter.startOrFinishUi", "Exception:" + e.getMessage());
- } catch (java.util.NoSuchElementException e) {
- LogUtil.e("InCallPresenter.startOrFinishUi", "Exception:" + e.getMessage());
- } catch (Exception e) {
- LogUtil.e("InCallPresenter.startOrFinishUi", "Exception:" + e.getMessage());
- }
-
- } else if (newState == InCallState.NO_CALLS) {
- // The new state is the no calls state. Tear everything down.
- inCallState = newState;
- attemptFinishActivity();
- attemptCleanup();
- }

跟踪 showInCall 方法
- public void showInCall(boolean showDialpad, boolean newOutgoingCall) {
- LogUtil.i("InCallPresenter.showInCall", "Showing InCallActivity");
- context.startActivity(
- InCallActivity.getIntent(context, showDialpad, newOutgoingCall, false /* forFullScreen */));
- }
至此,显示来电界面。
MO 是从Dialer 发起,MT是从Modem发起。所以两个流程最大的差别也就是如何开始创建Call & connection。当准备开始创建和创建完成后,MO & MT在流程上几乎是没有差异的,都是一些Call & connection的控制,然后通过UI显示出来。
总的来电各层之间的流程:
RIL→TelephonyFramework →TeleponyService→ TeleComService→
TeleComFramework→ TeleComService→TeleComFramework-->InCallUI
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。