当前位置:   article > 正文

安卓10 来电流程梳理_android 来电流程分析

android 来电流程分析

来电过程, 是由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状态改变

  1. @UnsupportedAppUsage
  2. 5692 void unsljLog(int response) {
  3. 5693 riljLog("[UNSL]< " + responseToString(response));
  4. 5694 }
  5. @UnsupportedAppUsage
  6. 5561 static String responseToString(int request) {
  7. 5562 switch(request) {
  8. 5563 case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
  9. 5564 return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
  10. 5565 case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
  11. 5566 return "UNSOL_RESPONSE_CALL_STATE_CHANGED";
  12. 5567 case RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED:
  1. frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioIndication.java

RadioIndication 类有17 个方法调用RIL 对象的unsljLog 方法打印消息,处理此
RIL 消息的代码逻辑详情如下:

  1. public void callStateChanged(int indicationType) {
  2. mRil.processIndication(indicationType);
  3. if (RIL.RILJ_LOGD) mRil.unsljLog(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED);
  4. mRil.mCallStateRegistrants.notifyRegistrants();
  5. }
  1. 调用processIndication向底层发送确认收到消息
  2. notifyRegistrant发出通知

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

搜索到有:

  1. BaseCommands
  2. GsmCdmaCallTracker
  3. CommandsInterface

其中BascCommands,CommandsInterface都是接口

mCalIStateReg istrants. notifyRegistrant 发出通知后,仅一个 地方可响应此消息通知,即GsmCdmaCallTracker 类的handleMessage 方法,本质上是个Handler处理类

跟进GsmCdmaCallTracker的handleMessage方法,可以看到其在初始化的地方注册了CallStateChanged消息的监听,注册的时候传入了自身的handler,notify的时候使用该handler发送消息,所以我们可以在handleMessage中响应并处理EVENT_CALL_STATE_CHANGE消息。

  1. @Override
  2. public void handleMessage(Message msg) {
  3. AsyncResult ar;
  4. switch (msg.what) {
  5. ...
  6. case EVENT_CALL_STATE_CHANGE:
  7. pollCallsWhenSafe();
  8. ...

pollCallsWhenSafe 调用父类CallTracker 方法

  1. protected void pollCallsWhenSafe() {
  2. mNeedsPoll = true;
  3. mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
  4. mCi.getCurrentCalls(mLastRelevantPoll);
  5. }
  6. }

发现其又调用了mCi.getCurrentCalls去查询当前的Call情况,此方法会调用到RIL中对应的方法去(Phone创建的时候对mCi进行初始化使得具有RIL通信能力,其mCi即调用RIL.java)

又回到了 RIL 中

  1. @Override
  2. public void getCurrentCalls(Message result) {
  3. IRadio radioProxy = getRadioProxy(result);
  4. if (radioProxy != null) {
  5. RILRequest rr = obtainRequest(RIL_REQUEST_GET_CURRENT_CALLS, result,
  6. mRILDefaultWorkSource);
  7. if (RILJ_LOGD) {
  8. riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
  9. }
  10. try {
  11. //向底层发起请求
  12. radioProxy.getCurrentCalls(rr.mSerial);
  13. } catch (RemoteException | RuntimeException e) {
  14. handleRadioProxyExceptionForRR(rr, "getCurrentCalls", e);
  15. }
  16. }
  17. }

在发送请求后,等待modem返回结果给RIL层,继续跟踪返回消息的接收(省去  与 RIL 层的交互)

 

在RIL.java中查找底层消息反馈的处理方法,发现有两个方法processRespose和processResponseDone,向上追溯发现其是在RadioResponse.java中的

responseCurrentCalls方法 调用了 processResponseDone 方法,如下:

其继承自一个底层的服务 

public class RadioResponse extends IRadioResponse.Stub

CurrentCall的消息继续在responseCurrentCalls方法追踪。

  1. public void getCurrentCallsResponse(RadioResponseInfo responseInfo,
  2. ArrayList<android.hardware.radio.V1_0.Call> calls) {
  3. responseCurrentCalls(responseInfo, calls);
  4. }

继续追踪调用的responseCurrentCalls方法

  1. private void responseCurrentCalls(RadioResponseInfo responseInfo,
  2. ArrayList<android.hardware.radio.V1_0.Call> calls) {
  3. RILRequest rr = mRil.processResponse(responseInfo);
  4. if (rr != null) {
  5. int num = calls.size();
  6. ArrayList<DriverCall> dcCalls = new ArrayList<DriverCall>(num);
  7. DriverCall dc;
  8. for (int i = 0; i < num; i++) {
  9. dc = new DriverCall();
  10. // TODO: change name of function stateFromCLCC() in DriverCall.java to name
  11. // clarifying what is CLCC
  12. dc.state = DriverCall.stateFromCLCC((int) (calls.get(i).state));
  13. dc.index = calls.get(i).index;
  14. dc.TOA = calls.get(i).toa;
  15. dc.isMpty = calls.get(i).isMpty;
  16. dc.isMT = calls.get(i).isMT;
  17. dc.als = calls.get(i).als;
  18. dc.isVoice = calls.get(i).isVoice;
  19. dc.isVoicePrivacy = calls.get(i).isVoicePrivacy;
  20. dc.number = calls.get(i).number;
  21. dc.numberPresentation =
  22. DriverCall.presentationFromCLIP(
  23. (int) (calls.get(i).numberPresentation));
  24. dc.name = calls.get(i).name;
  25. dc.namePresentation =
  26. DriverCall.presentationFromCLIP((int) (calls.get(i).namePresentation));
  27. if (calls.get(i).uusInfo.size() == 1) {
  28. dc.uusInfo = new UUSInfo();
  29. dc.uusInfo.setType(calls.get(i).uusInfo.get(0).uusType);
  30. dc.uusInfo.setDcs(calls.get(i).uusInfo.get(0).uusDcs);
  31. if (!TextUtils.isEmpty(calls.get(i).uusInfo.get(0).uusData)) {
  32. byte[] userData = calls.get(i).uusInfo.get(0).uusData.getBytes();
  33. dc.uusInfo.setUserData(userData);
  34. } else {
  35. mRil.riljLog("responseCurrentCalls: uusInfo data is null or empty");
  36. }
  37. mRil.riljLogv(String.format("Incoming UUS : type=%d, dcs=%d, length=%d",
  38. dc.uusInfo.getType(), dc.uusInfo.getDcs(),
  39. dc.uusInfo.getUserData().length));
  40. mRil.riljLogv("Incoming UUS : data (hex): "
  41. + IccUtils.bytesToHexString(dc.uusInfo.getUserData()));
  42. } else {
  43. mRil.riljLogv("Incoming UUS : NOT present!");
  44. }
  45. // Make sure there's a leading + on addresses with a TOA of 145
  46. dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA);
  47. dcCalls.add(dc);
  48. if (dc.isVoicePrivacy) {
  49. mRil.mVoicePrivacyOnRegistrants.notifyRegistrants();
  50. mRil.riljLog("InCall VoicePrivacy is enabled");
  51. } else {
  52. mRil.mVoicePrivacyOffRegistrants.notifyRegistrants();
  53. mRil.riljLog("InCall VoicePrivacy is disabled");
  54. }
  55. }
  56. Collections.sort(dcCalls);
  57. if ((num == 0) && mRil.mTestingEmergencyCall.getAndSet(false)) {
  58. if (mRil.mEmergencyCallbackModeRegistrant != null) {
  59. mRil.riljLog("responseCurrentCalls: call ended, testing emergency call,"
  60. + " notify ECM Registrants");
  61. mRil.mEmergencyCallbackModeRegistrant.notifyRegistrant();
  62. }
  63. }
  64. //发送返回消息
  65. if (responseInfo.error == RadioError.NONE) {
  66. sendMessageResponse(rr.mResult, dcCalls);
  67. }
  68. mRil.processResponseDone(rr, responseInfo, dcCalls);
  69. }
  70. }
  71. 发现其通过底层返回的消息创建了dcCalls对象,也就是当前的Call状态信息,对dc状态进行判断后如果有需要就notify通知,如果没有异常则通过sendMessageResponse方法发送消息
  72. public static void sendMessageResponse(Message msg, Object ret) {
  73. if (msg != null) {
  74. AsyncResult.forMessage(msg, ret, null);
  75. msg.sendToTarget();
  76. }
  77. }

继续回到GsmCdmaCallTracker的handleMessage中,之前发送请求的时候有发送EVENT_POLL_CALLS_RESULT,这里我们继续回到该事件处理的地方来分析

  1. @Override
  2. public void handleMessage(Message msg) {
  3. AsyncResult ar;
  4. switch (msg.what) {
  5. case EVENT_POLL_CALLS_RESULT:
  6. Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
  7. if (msg == mLastRelevantPoll) {
  8. if (DBG_POLL) log(
  9. "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
  10. mNeedsPoll = false;
  11. mLastRelevantPoll = null;
  12. handlePollCalls((AsyncResult)msg.obj);
  13. }
  14. break;

继续追踪handlePollCalls

  1. @Override
  2. protected synchronized void handlePollCalls(AsyncResult ar) {
  3. //解析返回的结果
  4. for (int i = 0, curDC = 0, dcSize = polledCalls.size()
  5. ; i < mConnections.length; i++) {
  6. GsmCdmaConnection conn = mConnections[i];
  7. DriverCall dc = null;
  8. // polledCall list is sparse
  9. if (curDC < dcSize) {
  10. dc = (DriverCall) polledCalls.get(curDC);
  11. if (dc.index == i+1) {
  12. curDC++;
  13. } else {
  14. dc = null;
  15. }
  16. }
  17. ...
  18. if (conn == null && dc != null) {
  19. ...状态的处理及识别
  20. //响铃消息通知
  21. if (newRinging != null) {
  22. mPhone.notifyNewRingingConnection(newRinging);
  23. }
  24. // clear the "local hangup" and "missed/rejected call"
  25. // cases from the "dropped during poll" list
  26. // These cases need no "last call fail" reason
  27. ArrayList<GsmCdmaConnection> locallyDisconnectedConnections = new ArrayList<>();
  28. for (int i = mDroppedDuringPoll.size() - 1; i >= 0 ; i--) {
  29. GsmCdmaConnection conn = mDroppedDuringPoll.get(i);
  30. //CDMA
  31. boolean wasDisconnected = false;
  32. //来电处理,本地挂断或者未接,本地挂断的话直接设置挂断的原因为LOCAL或INVALID_NUMBER
  33. if (conn.isIncoming() && conn.getConnectTime() == 0) {
  34. // Missed or rejected call
  35. int cause;
  36. if (conn.mCause == DisconnectCause.LOCAL) {
  37. cause = DisconnectCause.INCOMING_REJECTED;
  38. } else {
  39. cause = DisconnectCause.INCOMING_MISSED;
  40. }
  41. if (Phone.DEBUG_PHONE) {
  42. log("missed/rejected call, conn.cause=" + conn.mCause);
  43. log("setting cause to " + cause);
  44. }
  45. mDroppedDuringPoll.remove(i);
  46. hasAnyCallDisconnected |= conn.onDisconnect(cause);
  47. wasDisconnected = true;
  48. locallyDisconnectedConnections.add(conn);
  49. } else if (conn.mCause == DisconnectCause.LOCAL
  50. || conn.mCause == DisconnectCause.INVALID_NUMBER) {
  51. mDroppedDuringPoll.remove(i);
  52. hasAnyCallDisconnected |= conn.onDisconnect(conn.mCause);
  53. wasDisconnected = true;
  54. locallyDisconnectedConnections.add(conn);
  55. }
  56. if (!isPhoneTypeGsm() && wasDisconnected && unknownConnectionAppeared
  57. && conn == newUnknownConnectionCdma) {
  58. unknownConnectionAppeared = false;
  59. newUnknownConnectionCdma = null;
  60. }
  61. }
  62. if (locallyDisconnectedConnections.size() > 0) {
  63. mMetrics.writeRilCallList(mPhone.getPhoneId(), locallyDisconnectedConnections);
  64. }
  65. /* Disconnect any pending Handover connections */
  66. //通话断开的一些处理操作
  67. ...
  68. if (newRinging != null || hasNonHangupStateChanged || hasAnyCallDisconnected) {
  69. internalClearDisconnected();
  70. }
  71. //更新phone状态
  72. if (VDBG) log("handlePollCalls calling updatePhoneState()");
  73. updatePhoneState();
  74. ...
  75. }

其先对底层反馈的消息进行解析,获取其通话状态,判断如果是来电则发出notifyNewRingingConnection响铃消息通知,然后进行一些通话断开连接的操作及更新phone状态。继续跟进notifyNewRingingConnection响铃消息,该消息调用的是phone的方法,往上追溯。

继续查看响铃消息通知到何处,全局搜索(registerForNewRingingConnection),找到

PstnIncommingCallNotifier.java

  1. /**
  2. * Listens to incoming-call events from the associated phone object and notifies Telecom upon each
  3. * occurence. One instance of these exists for each of the telephony-based call services.
  4. */

用来 监听来电消息 

  1. private final Handler mHandler = new Handler() {
  2. @Override
  3. public void handleMessage(Message msg) {
  4. switch(msg.what) {
  5. case EVENT_NEW_RINGING_CONNECTION:
  6. handleNewRingingConnection((AsyncResult) msg.obj);
  7. break;
  8. case EVENT_CDMA_CALL_WAITING:
  9. handleCdmaCallWaiting((AsyncResult) msg.obj);
  10. break;
  11. case EVENT_UNKNOWN_CONNECTION:
  12. handleNewUnknownConnection((AsyncResult) msg.obj);
  13. break;
  14. default:
  15. break;
  16. }
  17. }
  18. };

继续调用handleNewRingingConnection方法处理调用sendIncommingCallIntent发送Intent,这里其实就已经从RIL传递消息到了应用层了

  1. private void handleNewRingingConnection(AsyncResult asyncResult) {
  2. Log.d(this, "handleNewRingingConnection");
  3. Connection connection = (Connection) asyncResult.result;
  4. if (connection != null) {
  5. Call call = connection.getCall();
  6. // Check if we have a pending number verification request.
  7. if (connection.getAddress() != null) {
  8. if (NumberVerificationManager.getInstance()
  9. .checkIncomingCall(connection.getAddress())) {
  10. // Disconnect the call if it matches
  11. try {
  12. connection.hangup();
  13. } catch (CallStateException e) {
  14. Log.e(this, e, "Error hanging up potential number verification call");
  15. }
  16. return;
  17. }
  18. }
  19. // Final verification of the ringing state before sending the intent to Telecom.
  20. if (call != null && call.getState().isRinging()) {
  21. sendIncomingCallIntent(connection);
  22. }
  23. }
  24. }
  1. private void sendIncomingCallIntent(Connection connection) {
  2. ------
  3. PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
  4. if (handle == null) {
  5. try {
  6. connection.hangup();
  7. } catch (CallStateException e) {
  8. // connection already disconnected. Do nothing
  9. }
  10. } else {
  11. TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
  12. }
  13. }

//获取telecomm服务,通过aidl接口调用 telecomService 的addNewIncomingCall方法

  1. //获取telecomm服务
  2. public static TelecomManager from(Context context) {
  3. return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
  4. }

进入到TelecomService层

  1. 108 private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
  2. 109 @Override
  3. 1083 public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
  4. 1084 try {
  5. 1085 Log.startSession("TSI.aNIC");
  6. 1086 synchronized (mLock) {
  7. 1087 Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
  8. 1088 phoneAccountHandle);
  9. 1089 。。。。。。。。。
  10. 。。。。。。。。。
  11. 1116 long token = Binder.clearCallingIdentity();
  12. 1117 try {
  13. 1118 Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
  14. 1119 intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
  15. 1120 phoneAccountHandle);
  16. 1121 intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
  17. 1122 if (extras != null) {
  18. 1123 extras.setDefusable(true);
  19. 1124 intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
  20. 1125 }
  21. 1126 mCallIntentProcessorAdapter.processIncomingCallIntent(
  22. 1127 mCallsManager, intent);
  23. 1128 } finally {
  24. 1129 Binder.restoreCallingIdentity(token);
  25. 1130 }
  26. 1131 } else {
  27. 1132 Log.w(this, "Null phoneAccountHandle. Ignoring request to add new" +
  28. 1133 " incoming call");
  29. 1134 }
  30. 1135 }
  31. 1136 } finally {
  32. 1137 Log.endSession();
  33. 1138 }
  34. 1139 }

继续跟进mCallIntentProcessorAdapter.processIncomingCallIntent,

  1. 287 static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
  2. 288 PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
  3. 289 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
  4. 290
  5. 291 if (phoneAccountHandle == null) {
  6. 292 Log.w(CallIntentProcessor.class,
  7. 293 "Rejecting incoming call due to null phone account");
  8. 294 return;
  9. 295 }
  10. 296 if (phoneAccountHandle.getComponentName() == null) {
  11. 297 Log.w(CallIntentProcessor.class,
  12. 298 "Rejecting incoming call due to null component name");
  13. 299 return;
  14. 300 }
  15. 301
  16. 302 Bundle clientExtras = null;
  17. 303 if (intent.hasExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS)) {
  18. 304 clientExtras = intent.getBundleExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS);
  19. 305 }
  20. 306 if (clientExtras == null) {
  21. 307 clientExtras = new Bundle();
  22. 308 }
  23. 309
  24. 310 Log.d(CallIntentProcessor.class,
  25. 311 "Processing incoming call from connection service [%s]",
  26. 312 phoneAccountHandle.getComponentName());
  27. 313 callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
  28. 314 }

--------------------------------------------------------------------------

下方与拨号相同

进入到CallsManager中继续跟进

  1. void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
  2. Log.d(this, "processIncomingCallIntent");
  3. ...
  4. Call call = new Call(
  5. getNextCallId(),
  6. mContext,
  7. this,
  8. mLock,
  9. mConnectionServiceRepository,
  10. mContactsAsyncHelper,
  11. mCallerInfoAsyncQueryFactory,
  12. mPhoneNumberUtilsAdapter,
  13. handle,
  14. null /* gatewayInfo */,
  15. null /* connectionManagerPhoneAccount */,
  16. phoneAccountHandle,
  17. Call.CALL_DIRECTION_INCOMING /* callDirection */,
  18. false /* forceAttachToExistingConnection */,
  19. false, /* isConference */
  20. mClockProxy);
  21. ...
  22. call的一些状态设置
  23. ...
  24. call.initAnalytics();
  25. if (getForegroundCall() != null) {
  26. getForegroundCall().getAnalytics().setCallIsInterrupted(true);
  27. call.getAnalytics().setCallIsAdditional(true);
  28. }
  29. setIntentExtrasAndStartTime(call, extras);
  30. //添加监听
  31. // TODO: Move this to be a part of addCall()
  32. call.addListener(this);
  33. if (!isHandoverAllowed || (call.isSelfManaged() && !isIncomingCallPermitted(call,
  34. call.getTargetPhoneAccount()))) {
  35. notifyCreateConnectionFailed(phoneAccountHandle, call);
  36. } else {
  37. //成功上报上去建立连接
  38. call.startCreateConnection(mPhoneAccountRegistrar);
  39. }
  40. }

 

  1. void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
  2. if (mCreateConnectionProcessor != null) {
  3. Log.w(this, "mCreateConnectionProcessor in startCreateConnection is not null. This is" +
  4. " due to a race between NewOutgoingCallIntentBroadcaster and " +
  5. "phoneAccountSelected, but is harmlessly resolved by ignoring the second " +
  6. "invocation.");
  7. return;
  8. }
  9. mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
  10. phoneAccountRegistrar, mContext);
  11. mCreateConnectionProcessor.process();
  12. }

继续跟踪process 方法

packages/services/Telecomm/src/com/android/server/telecom/CreateConnectionProcessor.java

  1. public void process() {
  2. Log.v(this, "process");
  3. clearTimeout();
  4. mAttemptRecords = new ArrayList<>();
  5. if (mCall.getTargetPhoneAccount() != null) {
  6. mAttemptRecords.add(new CallAttemptRecord(
  7. mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
  8. }
  9. if (!mCall.isSelfManaged()) {
  10. adjustAttemptsForConnectionManager();
  11. adjustAttemptsForEmergency(mCall.getTargetPhoneAccount());
  12. }
  13. mAttemptRecordIterator = mAttemptRecords.iterator();
  14. attemptNextPhoneAccount();
  15. }

其中 attemptNextPhoneAccount 方法

  1. private void attemptNextPhoneAccount() {
  2. Log.v(this, "attemptNextPhoneAccount");
  3. CallAttemptRecord attempt = null;
  4. if (mCallResponse != null && attempt != null) {
  5. Log.i(this, "Trying attempt %s", attempt);
  6. PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
  7. mService = mRepository.getService(phoneAccount.getComponentName(),
  8. phoneAccount.getUserHandle());
  9. if (mService == null) {
  10. Log.i(this, "Found no connection service for attempt %s", attempt);
  11. attemptNextPhoneAccount();
  12. } else {
  13. mConnectionAttempt++;
  14. mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
  15. mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
  16. mCall.setConnectionService(mService);
  17. setTimeoutIfNeeded(mService, attempt);
  18. if (mCall.isIncoming()) {
  19. mService.createConnection(mCall, CreateConnectionProcessor.this);
  20. } else {
  21. // Start to create the connection for outgoing call after the ConnectionService
  22. // of the call has gained the focus.
  23. mCall.getConnectionServiceFocusManager().requestFocus(
  24. mCall,
  25. new CallsManager.RequestCallback(new CallsManager.PendingAction() {
  26. @Override
  27. public void performAction() {
  28. Log.d(this, "perform create connection");
  29. mService.createConnection(
  30. mCall,
  31. CreateConnectionProcessor.this);
  32. }
  33. }));
  34. }
  35. }
  36. } else {
  37. Log.v(this, "attemptNextPhoneAccount, no more accounts, failing");
  38. DisconnectCause disconnectCause = mLastErrorDisconnectCause != null ?
  39. mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR);
  40. notifyCallConnectionFailure(disconnectCause);
  41. }
  42. }

核心代码:

  1. private ConnectionServiceWrapper mService;
  2. if (mCall.isIncoming()) {
  3. mService.createConnection(mCall, CreateConnectionProcessor.this);
  4. }

 

  1. void createConnection(final Call call, final CreateConnectionResponse response) {
  2. // 链接创建成功后 onSuccess 会被调用
  3. BindCallback callback = new BindCallback() {
  4. @Override
  5. public void onSuccess() {
  6. try {
  7. /// M: For VoLTE @{
  8. boolean isConferenceDial = call.isConferenceDial();
  9. // 会议通话
  10. if (isConferenceDial) {
  11. logOutgoing("createConference(%s) via %s.", call, getComponentName());
  12. mServiceInterface.createConference(
  13. call.getConnectionManagerPhoneAccount(),
  14. callId,
  15. new ConnectionRequest(
  16. call.getTargetPhoneAccount(),
  17. call.getHandle(),
  18. extras,
  19. call.getVideoState()),
  20. call.getConferenceParticipants(),
  21. call.isIncoming());
  22. // 非会议(拨打电话会走这里)
  23. } else {
  24. // 通过远程接口创建链接
  25. mServiceInterface.createConnection(
  26. call.getConnectionManagerPhoneAccount(),
  27. callId,
  28. new ConnectionRequest(
  29. call.getTargetPhoneAccount(),
  30. call.getHandle(),
  31. extras,
  32. call.getVideoState()),
  33. call.isIncoming(),
  34. call.isUnknown());
  35. }
  36. /// @}
  37. } catch (RemoteException e) {
  38. }
  39. }
  40. @Override
  41. public void onFailure() {
  42. }
  43. };
  44. mBinder.bind(callback, call);
  45. }

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 方法 

  1. void bind(BindCallback callback, Call call) {
  2. if (mServiceConnection == null) {
  3. Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
  4. ServiceConnection connection = new ServiceBinderConnection(call);
  5. // 进行绑定
  6. if (mUserHandle != null) {
  7. isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
  8. mUserHandle);
  9. } else {
  10. isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
  11. }
  12. if (!isBound) {
  13. handleFailedConnection();
  14. return;
  15. }
  16. } else {
  17. }
  18. }

绑定成功后,ServiceBinderConnection 的 onServiceConnected 会触发

  1. @Override
  2. public void onServiceConnected(ComponentName componentName, IBinder binder) {
  3. try {
  4. if (binder != null) {
  5. mServiceDeathRecipient = new ServiceDeathRecipient(componentName);
  6. try {
  7. binder.linkToDeath(mServiceDeathRecipient, 0);
  8. mServiceConnection = this;
  9. // 会触发 ConnectionServiceWrapper.setServiceInterface ==>
  10. ConnectionServiceWrapper.addConnectionServiceAdapter
  11. 通过mServiceInterface,给绑定的服务,提供一个访问自己的接口
  12. setBinder(binder);
  13. // 触发bind(BindCallback callback, Call call) 中 callback 的 onSuccess
  14. handleSuccessfulConnection();
  15. } catch (RemoteException e) {
  16. Log.w(this, "onServiceConnected: %s died.");
  17. if (mServiceDeathRecipient != null) {
  18. mServiceDeathRecipient.binderDied();
  19. }
  20. }
  21. }
  22. }
  23. } finally {
  24. Log.endSession();
  25. }
  26. }

整个绑定过程,只做2件事,

一是给远程服务提供访问自己的接口,

二是利用远程接口创建一个通话链接。

这2件事都是跨进程进行的。远程服务访问自己的接口是 ConnectionServiceWrapper.Adapter , 是一个Binder。

由内部类 Adapter 继承于 IConnectionServiceAdapter.Stub,可以看出会进行跨进程访问

  1. public class ConnectionServiceWrapper extends ServiceBinder implements
  2. ConnectionServiceFocusManager.ConnectionServiceFocus {
  3. private final class Adapter extends IConnectionServiceAdapter.Stub {

调用ConnectionService.java里mBinder的createConnection()方法然后通过message传递调用createConnection()方法。

  1. private void handleSuccessfulConnection() {
  2. // Make a copy so that we don't have a deadlock inside one of the callbacks.
  3. Set<BindCallback> callbacksCopy = new ArraySet<>();
  4. synchronized (mCallbacks) {
  5. callbacksCopy.addAll(mCallbacks);
  6. mCallbacks.clear();
  7. }
  8. for (BindCallback callback : callbacksCopy) {
  9. callback.onSuccess();
  10. }
  11. }

通过调用handleSuccessfulConnection()方法回调callback 的onSuccess()方法,也就又回到ConnectionServiceWrapper的createConnection()方法里。

  1. 1094 public void createConnection(final Call call, final CreateConnectionResponse response) {
  2. 1095 Log.d(this, "createConnection(%s) via %s.", call, getComponentName());
  3. 1096 BindCallback callback = new BindCallback() {
  4. 1097 @Override
  5. 1098 public void onSuccess() {
  6. 1099 String callId = mCallIdMapper.getCallId(call);
  7. 1100 mPendingResponses.put(callId, response);
  8. 1101
  9. ///---------//
  10. 1146
  11. 1150 // 核心代码
  12. 1151 try {
  13. 1152 mServiceInterface.createConnection(
  14. 1153 call.getConnectionManagerPhoneAccount(),
  15. 1154 callId,
  16. 1155 connectionRequest,
  17. 1156 call.shouldAttachToExistingConnection(),
  18. 1157 call.isUnknown(),
  19. 1158 Log.getExternalSession());
  20. 1159
  21. 1160 } catch (RemoteException e) {
  22. 1161 Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
  23. 1162 mPendingResponses.remove(callId).handleCreateConnectionFailure(
  24. 1163 new DisconnectCause(DisconnectCause.ERROR, e.toString()));
  25. 1164 }
  26. 1165 }
  27. 1166
  28. 1167 @Override
  29. 1168 public void onFailure() {
  30. 1169 Log.e(this, new Exception(), "Failure to call %s", getComponentName());
  31. 1170 response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.ERROR));
  32. 1171 }
  33. 1172 };
  34. 1173
  35. 1174 mBinder.bind(callback, call);
  36. 1175 }
private IConnectionService mServiceInterface;

线中间的处理过程 和 拨号 流程一样 

----------------------------------------------------------------- 

createConnection()方法通过判断是来电还是去电分别创建不同的connection,

  1. /**
  2. * This can be used by telecom to either create a new outgoing call or attach to an existing
  3. * incoming call. In either case, telecom will cycle through a set of services and call
  4. * createConnection util a connection service cancels the process or completes it successfully.
  5. */
  6. /** {@hide} */
  7. protected void createConnection(
  8. final PhoneAccountHandle callManagerAccount,
  9. final String callId,
  10. final ConnectionRequest request,
  11. boolean isIncoming,
  12. boolean isUnknown) {
  13. Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
  14. "isIncoming: %b, isUnknown: %b", callManagerAccount, callId, request,
  15. isIncoming,
  16. isUnknown);
  17. //判断是来电还是去电创造不同的connection
  18. Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
  19. : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
  20. : onCreateOutgoingConnection(callManagerAccount, request);
  21. ...
  22. Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
  23. //创建成功后调用
  24. mAdapter.handleCreateConnectionComplete(
  25. callId,
  26. request,
  27. new ParcelableConnection(
  28. ...
  29. if (isIncoming && request.shouldShowIncomingCallUi() &&
  30. (connection.getConnectionProperties() & Connection.PROPERTY_SELF_MANAGED) ==
  31. Connection.PROPERTY_SELF_MANAGED) {
  32. // Tell ConnectionService to show its incoming call UX.
  33. connection.onShowIncomingCallUi();
  34. }
  35. if (isUnknown) {
  36. triggerConferenceRecalculate();
  37. }
  38. }

此处先分析: onCreateIncomingConnection

运行完成后分析:mAdapter.handleCreateConnectionComplete

其中:

  1. public Connection onCreateIncomingConnection(
  2. PhoneAccountHandle connectionManagerPhoneAccount,
  3. ConnectionRequest request) {
  4. return null;
  5. }

当判断是来电时会通过 onCreateIncomingConnection 创建连接,直接跟进去发现是空实现,那么该方法的实现应该在该类的子类中,跟进到其子类TelephonyConnectionService中 

public class TelephonyConnectionService extends ConnectionService {
  1. /**
  2. * Service for making GSM and CDMA connections.
  3. */
  4. public class TelephonyConnectionService extends ConnectionService
  5. @Override
  6. public Connection onCreateIncomingConnection(
  7. PhoneAccountHandle connectionManagerPhoneAccount,
  8. ConnectionRequest request) {
  9. ...
  10. Phone phone = getPhoneForAccount(accountHandle, isEmergency);
  11. ...
  12. Call call = phone.getRingingCall();
  13. com.android.internal.telephony.Connection originalConnection =
  14. call.getState() == Call.State.WAITING ?
  15. call.getLatestConnection() : call.getEarliestConnection();
  16. ...
  17. Connection connection =
  18. createConnectionFor(phone, originalConnection, false /* isOutgoing */,
  19. request.getAccountHandle(), request.getTelecomCallId(),
  20. request.getAddress(), videoState);
  21. ...
  22. }

跳转到 createConnectionFor 方法中

  1. private TelephonyConnection createConnectionFor(
  2. Phone phone,
  3. com.android.internal.telephony.Connection originalConnection,
  4. boolean isOutgoing,
  5. PhoneAccountHandle phoneAccountHandle,
  6. String telecomCallId,
  7. Uri address,
  8. int videoState) {
  9. TelephonyConnection returnConnection = null;
  10. int phoneType = phone.getPhoneType();
  11. if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
  12. returnConnection = new GsmConnection(originalConnection, telecomCallId, isOutgoing);
  13. } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
  14. boolean allowsMute = allowsMute(phone);
  15. returnConnection = new CdmaConnection(originalConnection, mEmergencyTonePlayer,
  16. allowsMute, isOutgoing, telecomCallId);
  17. }
  18. if (returnConnection != null) {
  19. // Listen to Telephony specific callbacks from the connection
  20. returnConnection.addTelephonyConnectionListener(mTelephonyConnectionListener);
  21. returnConnection.setVideoPauseSupported(
  22. TelecomAccountRegistry.getInstance(this).isVideoPauseSupported(
  23. phoneAccountHandle));
  24. returnConnection.setManageImsConferenceCallSupported(
  25. TelecomAccountRegistry.getInstance(this).isManageImsConferenceCallSupported(
  26. phoneAccountHandle));
  27. returnConnection.setShowPreciseFailedCause(
  28. TelecomAccountRegistry.getInstance(this).isShowPreciseFailedCause(
  29. phoneAccountHandle));
  30. }
  31. return returnConnection;
  32. }

继续 分析  mAdapter.handleCreateConnectionComplete

这里通过AIDL进行通信,搜索 IConnectionServiceAdapter.Stub,跟进到 ConnectionServiceWrapper

  1. private final class Adapter extends IConnectionServiceAdapter.Stub {
  2. @Override
  3. public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
  4. ParcelableConnection connection, Session.Info sessionInfo) {
  5. Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
  6. long token = Binder.clearCallingIdentity();
  7. try {
  8. synchronized (mLock) {
  9. logIncoming("handleCreateConnectionComplete %s", callId);
  10. ConnectionServiceWrapper.this
  11. .handleCreateConnectionComplete(callId, request, connection);

继续跟进handleCreateConnectionComplete

  1. private void handleCreateConnectionComplete(
  2. String callId,
  3. ConnectionRequest request,
  4. ParcelableConnection connection) {
  5. // TODO: Note we are not using parameter "request", which is a side effect of our tacit
  6. // assumption that we have at most one outgoing connection attempt per ConnectionService.
  7. // This may not continue to be the case.
  8. if (connection.getState() == Connection.STATE_DISCONNECTED) {
  9. // A connection that begins in the DISCONNECTED state is an indication of
  10. // failure to connect; we handle all failures uniformly
  11. Call foundCall = mCallIdMapper.getCall(callId);
  12. if (foundCall != null) {
  13. // The post-dial digits are created when the call is first created. Normally
  14. // the ConnectionService is responsible for stripping them from the address, but
  15. // since a failed connection will not have done this, we could end up with duplicate
  16. // post-dial digits.
  17. foundCall.clearPostDialDigits();
  18. }
  19. removeCall(callId, connection.getDisconnectCause());
  20. } else {
  21. // Successful connection
  22. if (mPendingResponses.containsKey(callId)) {
  23. mPendingResponses.remove(callId)
  24. .handleCreateConnectionSuccess(mCallIdMapper, connection);
  25. }
  26. }
  27. }

mPendingResponses是hashMap容器,每次在 createConnection 的时候会将对象加入该容器,如果此时connection还未断开的,会移除此connection,调用hanleCreateConnectionSuccess方法。
往上追溯CreateConnectionResponse,是一个接口,跟踪到mService.createConnection(mCall, this);

public class CreateConnectionProcessor implements CreateConnectionResponse {

CreateConnectionProcessor.java会把自身传入,发现该类也实现了 CreateConnectionResponse ,所以这里的 handleCreateConnectionSuccess
调用的是这个类里面的方法

  1. private CreateConnectionResponse mCallResponse;
  2. @Override
  3. public void handleCreateConnectionSuccess(
  4. CallIdMapper idMapper,
  5. ParcelableConnection connection) {
  6. if (mCallResponse == null) {
  7. // Nobody is listening for this connection attempt any longer; ask the responsible
  8. // ConnectionService to tear down any resources associated with the call
  9. mService.abort(mCall);
  10. } else {
  11. // Success -- share the good news and remember that we are no longer interested
  12. // in hearing about any more attempts
  13. // 核心代码
  14. mCallResponse.handleCreateConnectionSuccess(idMapper, connection);
  15. mCallResponse = null;
  16. // If there's a timeout running then don't clear it. The timeout can be triggered
  17. // after the call has successfully been created but before it has become active.
  18. }
  19. }

还是 CreateConnectionResponse 接口

实现的是 Call 对象 ,Call 也实现了该接口

  1. public class Call implements CreateConnectionResponse, EventManager.Loggable,
  2. 84 ConnectionServiceFocusManager.CallFocus {
  1. public void handleCreateConnectionSuccess(
  2. CallIdMapper idMapper,
  3. ParcelableConnection connection) {
  4. Log.v(this, "handleCreateConnectionSuccessful %s", connection);
  5. setTargetPhoneAccount(connection.getPhoneAccount());
  6. setHandle(connection.getHandle(), connection.getHandlePresentation());
  7. setCallerDisplayName(
  8. connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
  9. setConnectionCapabilities(connection.getConnectionCapabilities());
  10. setConnectionProperties(connection.getConnectionProperties());
  11. setIsVoipAudioMode(connection.getIsVoipAudioMode());
  12. setSupportedAudioRoutes(connection.getSupportedAudioRoutes());
  13. setVideoProvider(connection.getVideoProvider());
  14. setVideoState(connection.getVideoState());
  15. setRingbackRequested(connection.isRingbackRequested());
  16. setStatusHints(connection.getStatusHints());
  17. putExtras(SOURCE_CONNECTION_SERVICE, connection.getExtras());
  18. mConferenceableCalls.clear();
  19. for (String id : connection.getConferenceableConnectionIds()) {
  20. mConferenceableCalls.add(idMapper.getCall(id));
  21. }
  22. switch (mCallDirection) {
  23. case CALL_DIRECTION_INCOMING:
  24. for (Listener l : mListeners) {
  25. // 此处触发了回调
  26. l.onSuccessfulIncomingCall(this);
  27. }
  28. break;
  29. 。。。。。

这里根据来电类型,触发回调,监听者会收到通知

,之前在CallManager中执行 processIncomingCallIntent 方法创建Call的时候就添加了监听,所以最后会回调到CallsManager中

可以看出CallsManager的管理作用,创建Calls并添加监听,在完成Call的相关初始化后进行进一步处理,其实就是传递消息到别的的地方去。

  1. public void onSuccessfulIncomingCall(Call incomingCall) {
  2. Log.d(this, "onSuccessfulIncomingCall");
  3. PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
  4. incomingCall.getTargetPhoneAccount());
  5. Bundle extras =
  6. phoneAccount == null || phoneAccount.getExtras() == null
  7. ? new Bundle()
  8. : phoneAccount.getExtras();
  9. if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE) ||
  10. incomingCall.isSelfManaged() ||
  11. extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING)) {
  12. Log.i(this, "Skipping call filtering for %s (ecm=%b, selfMgd=%b, skipExtra=%b)",
  13. incomingCall.getId(),
  14. incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE),
  15. incomingCall.isSelfManaged(),
  16. extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING));
  17. onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
  18. incomingCall.setIsUsingCallFiltering(false);
  19. return;
  20. }
  21. incomingCall.setIsUsingCallFiltering(true);
  22. //迭代器模式
  23. List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
  24. filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
  25. filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
  26. mCallerInfoLookupHelper, null));
  27. filters.add(new CallScreeningServiceController(mContext, this, mPhoneAccountRegistrar,
  28. new ParcelableCallUtils.Converter(), mLock,
  29. new TelecomServiceImpl.SettingsSecureAdapterImpl(), mCallerInfoLookupHelper,
  30. new CallScreeningServiceHelper.AppLabelProxy() {
  31. @Override
  32. public CharSequence getAppLabel(String packageName) {
  33. PackageManager pm = mContext.getPackageManager();
  34. try {
  35. ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
  36. return pm.getApplicationLabel(info);
  37. } catch (PackageManager.NameNotFoundException nnfe) {
  38. Log.w(this, "Could not determine package name.");
  39. }
  40. return null;
  41. }
  42. }));
  43. //IncomingCallFilter创建并执行 performFiltering
  44. new IncomingCallFilter(mContext, this, incomingCall, mLock,
  45. mTimeoutsAdapter, filters).performFiltering();
  46. }

IncomingCallFilter创建并执行 performFiltering

  1. public void performFiltering() {
  2. Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED);
  3. for (CallFilter filter : mFilters) {
  4. //遍历调用,依次执行异步查询方法
  5. filter.startFilterLookup(mCall, this);
  6. }
  7. // synchronized to prevent a race on mResult and to enter into Telecom.
  8. mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) { // performFiltering time-out
  9. @Override
  10. public void loggedRun() {
  11. if (mIsPending) {
  12. //超时处理的方法
  13. Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
  14. Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
  15. //回CallsManager中的监听事件
  16. mListener.onCallFilteringComplete(mCall, mResult);
  17. mIsPending = false;
  18. }
  19. }
  20. }.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
  21. }

如果没有超时则在异步查询结束后,会通过回调方法将CallFilterResult传回onCallFilteringComplete.

  1. public void onCallFilteringComplete(Call call, CallFilteringResult result) {
  2. synchronized (mTelecomLock) { // synchronizing to prevent race on mResult
  3. mNumPendingFilters--;
  4. mResult = result.combine(mResult);
  5. if (mNumPendingFilters == 0) {
  6. // synchronized on mTelecomLock to enter into Telecom.
  7. mHandler.post(new Runnable("ICF.oCFC", mTelecomLock) {
  8. @Override
  9. public void loggedRun() {
  10. if (mIsPending) {
  11. Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, mResult);
  12. mListener.onCallFilteringComplete(mCall, mResult);
  13. mIsPending = false;
  14. }
  15. }
  16. }.prepare());
  17. }
  18. }
  19. }

然后, 回到CallsManager中进行onCallFilteringComplete处理

  1. @Override
  2. public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
  3. ...
  4. if (incomingCall.getState() != CallState.DISCONNECTED &&
  5. incomingCall.getState() != CallState.DISCONNECTING &&
  6. incomingCall.getState() != CallState.ACTIVE) {
  7. //设置Call状态为Ring
  8. setCallState(incomingCall, CallState.RINGING,
  9. result.shouldAllowCall ? "successful incoming call" : "blocking call");
  10. } else {
  11. Log.i(this, "onCallFilteringCompleted: call already disconnected.");
  12. return;
  13. }
  14. if (result.shouldAllowCall) {
  15. if (MtkUtil.isInSingleVideoCallMode(incomingCall)) {
  16. ...
  17. }
  18. if (hasMaximumManagedRingingCalls(incomingCall)) {
  19. if (shouldSilenceInsteadOfReject(incomingCall)) {
  20. incomingCall.silence();
  21. } else {
  22. Log.i(this, "onCallFilteringCompleted: Call rejected! " +
  23. "Exceeds maximum number of ringing calls.");
  24. rejectCallAndLog(incomingCall);
  25. }
  26. } else {
  27. //添加Call
  28. addCall(incomingCall);
  29. }
  30. } else {
  31. if (result.shouldReject) {
  32. Log.i(this, "onCallFilteringCompleted: blocked call, rejecting.");
  33. incomingCall.reject(false, null);
  34. }
  35. if (result.shouldAddToCallLog) {
  36. Log.i(this, "onCallScreeningCompleted: blocked call, adding to call log.");
  37. if (result.shouldShowNotification) {
  38. Log.w(this, "onCallScreeningCompleted: blocked call, showing notification.");
  39. }
  40. //添加通话记录
  41. mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
  42. result.shouldShowNotification);
  43. } else if (result.shouldShowNotification) {
  44. Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
  45. mMissedCallNotifier.showMissedCallNotification(
  46. new MissedCallNotifier.CallInfo(incomingCall));
  47. }
  48. }
  49. }

跟踪到 addCall 方法

  1. 3207 @VisibleForTesting
  2. 3208 public void addCall(Call call) {
  3. 3209 Trace.beginSection("addCall");
  4. 3210 Log.v(this, "addCall(%s)", call);
  5. 3211 call.addListener(this);
  6. 3212 mCalls.add(call);
  7. 3213
  8. 3214 // Specifies the time telecom finished routing the call. This is used by the dialer for
  9. 3215 // analytics.
  10. 3216 Bundle extras = call.getIntentExtras();
  11. 3217 extras.putLong(TelecomManager.EXTRA_CALL_TELECOM_ROUTING_END_TIME_MILLIS,
  12. 3218 SystemClock.elapsedRealtime());
  13. 3219
  14. 3220 updateCanAddCall();
  15. 3221 // onCallAdded for calls which immediately take the foreground (like the first call).
  16. 3222 for (CallsManagerListener listener : mListeners) {
  17. 3223 if (LogUtils.SYSTRACE_DEBUG) {
  18. 3224 Trace.beginSection(listener.getClass().toString() + " addCall");
  19. 3225 }
  20. 3226 listener.onCallAdded(call);
  21. 3227 if (LogUtils.SYSTRACE_DEBUG) {
  22. 3228 Trace.endSection();
  23. 3229 }
  24. 3230 }
  25. 3231 Trace.endSection();
  26. 3232 }

//通知监听Call添加的观察者

listener.onCallAdded(call);

添加的观察者,和拨号一样,主要是 CllAudilManager (负责响铃)和  InCallController

  1. mListeners.add(mInCallWakeLockController);
  2. mListeners.add(statusBarNotifier);
  3. mListeners.add(mCallLogManager);
  4. mListeners.add(mPhoneStateBroadcaster);
  5. mListeners.add(mInCallController);
  6. mListeners.add(mCallAudioManager);
  7. mListeners.add(mCallRecordingTonePlayer);
  8. mListeners.add(missedCallNotifier);
  9. mListeners.add(mHeadsetMediaButton);
  10. mListeners.add(mProximitySensorManager);

其中:

  1. private void onCallEnteringRinging() {
  2. 641 if (mRingingCalls.size() == 1) {
  3. 642 mCallAudioModeStateMachine.sendMessageWithArgs(
  4. 643 CallAudioModeStateMachine.NEW_RINGING_CALL,
  5. 644 makeArgsForModeStateMachine());
  6. 645 }
  7. 646 }

查看 InCallController 的 onCallAdded 方法

  1. @Override
  2. public void onCallAdded(Call call) {
  3. if (!isBoundAndConnectedToServices()) {
  4. bindToServices(call);
  5. } else {
  6. // We are bound, and we are connected.
  7. adjustServiceBindingsForEmergency();
  8. // This is in case an emergency call is added while there is an existing call.
  9. mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(call,
  10. mCallsManager.getCurrentUserHandle());
  11. //添加Call
  12. addCall(call);
  13. List<ComponentName> componentsUpdated = new ArrayList<>();
  14. for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
  15. InCallServiceInfo info = entry.getKey();
  16. if (call.isExternalCall() && !info.isExternalCallsSupported()) {
  17. continue;
  18. }
  19. if (call.isSelfManaged() && !info.isSelfManagedCallsSupported()) {
  20. continue;
  21. }
  22. // Only send the RTT call if it's a UI in-call service
  23. boolean includeRttCall = info.equals(mInCallServiceConnection.getInfo());
  24. componentsUpdated.add(info.getComponentName());
  25. IInCallService inCallService = entry.getValue();
  26. ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
  27. true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
  28. info.isExternalCallsSupported(), includeRttCall);
  29. try {
  30. //AIDL调用远程的addCall方法
  31. inCallService.addCall(parcelableCall);
  32. } catch (RemoteException ignored) {
  33. }
  34. }
  35. Log.i(this, "Call added to components: %s", componentsUpdated);
  36. }
  37. }

Telecomm Framework

  1. 291 /** Manages the binder calls so that the implementor does not need to deal with it. */
  2. 292 private final class InCallServiceBinder extends IInCallService.Stub {
  3. 293 @Override
  4. 294 public void setInCallAdapter(IInCallAdapter inCallAdapter) {
  5. 295 mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
  6. 296 }
  7. 297
  8. 298 @Override
  9. 299 public void addCall(ParcelableCall call) {
  10. 300 mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
  11. 301 }

继续跟进MSG_ADD_CALL消息的处理

  1. 205 /** Default Handler used to consolidate binder method calls onto a single thread. */
  2. 206 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
  3. 207 @Override
  4. 208 public void handleMessage(Message msg) {
  5. 209 if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
  6. 210 return;
  7. 211 }
  8. 212
  9. 213 switch (msg.what) {
  10. 214 case MSG_SET_IN_CALL_ADAPTER:
  11. 215 String callingPackage = getApplicationContext().getOpPackageName();
  12. 216 mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage,
  13. 217 getApplicationContext().getApplicationInfo().targetSdkVersion);
  14. 218 mPhone.addListener(mPhoneListener);
  15. 219 onPhoneCreated(mPhone);
  16. 220 break;
  17. 221 case MSG_ADD_CALL:
  18. 222 mPhone.internalAddCall((ParcelableCall) msg.obj);
  19. 223 break;

继续跟进internalAddCall

  1. final void internalAddCall(ParcelableCall parcelableCall) {
  2. //创建Call
  3. Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
  4. parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);
  5. mCallByTelecomCallId.put(parcelableCall.getId(), call);
  6. //添加到列表中
  7. mCalls.add(call);
  8. checkCallTree(parcelableCall);
  9. call.internalUpdate(parcelableCall, mCallByTelecomCallId);
  10. //调用phone的监听者的onCallAdded
  11. fireCallAdded(call);
  12. }
  13. private void fireCallAdded(Call call) {
  14. for (Listener listener : mListeners) {
  15. listener.onCallAdded(this, call);
  16. }
  17. }

在 InCallService 中handleMessage处理MSG_SET_IN_CALL_ADAPTER消息的时候就注册了监听,这里继续跟进到InCallService中的实现去

  1. private Phone.Listener mPhoneListener = new Phone.Listener() {
  2. /** ${inheritDoc} */
  3. @Override
  4. public void onAudioStateChanged(Phone phone, AudioState audioState) {
  5. InCallService.this.onAudioStateChanged(audioState);
  6. }
  7. 。。。。。//
  8. /** ${inheritDoc} */
  9. @Override
  10. public void onCallAdded(Phone phone, Call call) {
  11. InCallService.this.onCallAdded(call);
  12. }

这其实是个空实现,具体实现是在子类中,继续跟进到子类 InCallServiceImpl  中分析

Dialer  层

  1. public class InCallServiceImpl extends InCallService {
  2. private ReturnToCallController returnToCallController;
  3. private CallList.Listener feedbackListener;
  4. // We only expect there to be one speakEasyCallManager to be instantiated at a time.
  5. // We did not use a singleton SpeakEasyCallManager to avoid holding on to state beyond the
  6. // lifecycle of this service, because the singleton is associated with the state of the
  7. // Application, not this service.
  8. private SpeakEasyCallManager speakEasyCallManager;
  9. @Override
  10. public void onCallAudioStateChanged(CallAudioState audioState) {
  11. Trace.beginSection("InCallServiceImpl.onCallAudioStateChanged");
  12. AudioModeProvider.getInstance().onAudioStateChanged(audioState);
  13. Trace.endSection();
  14. }
  15. ///-----------
  16. @Override
  17. public void onCallAdded(Call call) {
  18. Trace.beginSection("InCallServiceImpl.onCallAdded");
  19. InCallPresenter.getInstance().onCallAdded(call);
  20. Trace.endSection();
  21. }

跟踪到这里可以看到其所在目录是Dialer下的inCallUI了,这就到dialer层了,如果查看Diler的清单文件可以发现其有android.telecom.InCallService声明

  1. public void onCallAdded(final android.telecom.Call call) {
  2. LatencyReport latencyReport = new LatencyReport(call);
  3. if (shouldAttemptBlocking(call)) {
  4. maybeBlockCall(call, latencyReport);
  5. } else {
  6. if (call.getDetails().hasProperty(CallCompat.Details.PROPERTY_IS_EXTERNAL_CALL)) {
  7. mExternalCallList.onCallAdded(call);
  8. } else {
  9. latencyReport.onCallBlockingDone();
  10. //CallList(Call的维护列表)调用onCallAdded
  11. mCallList.onCallAdded(mContext, call, latencyReport);
  12. }
  13. }
  14. // Since a call has been added we are no longer waiting for Telecom to send us a call.
  15. setBoundAndWaitingForOutgoingCall(false, null);
  16. call.registerCallback(mCallCallback);
  17. }
  1. public void onCallAdded(
  2. final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) {
  3. Trace.beginSection("onCallAdded");
  4. ...
  5. if (call.getState() == DialerCall.State.INCOMING
  6. || call.getState() == DialerCall.State.CALL_WAITING) {
  7. //来电调用
  8. onIncoming(call);
  9. } else {
  10. dialerCallListener.onDialerCallUpdate();
  11. }
  12. ...
  13. }

跟踪 onIncoming 方法

  1. /** Called when a single call has changed. */
  2. private void onIncoming(DialerCall call) {
  3. Trace.beginSection("CallList.onIncoming");
  4. if (updateCallInMap(call)) {
  5. LogUtil.i("CallList.onIncoming", String.valueOf(call));
  6. }
  7. for (Listener listener : listeners) {
  8. listener.onIncomingCall(call);
  9. }
  10. Trace.endSection();
  11. }

InCallPresenter 监听来电状态

可以看出 InCallPresenter 实现了 CallList.Listener 的接口,所以可以监听来电的状态

public class InCallPresenter implements CallList.Listener, AudioModeProvider.AudioModeListener {

跟踪到 onCallListChange 方法

  1. @Override
  2. public void onCallListChange(CallList callList) {
  3. Trace.beginSection("InCallPresenter.onCallListChange");
  4. if (inCallActivity != null && inCallActivity.isInCallScreenAnimating()) {
  5. awaitingCallListUpdate = true;
  6. Trace.endSection();
  7. return;
  8. }
  9. if (callList == null) {
  10. Trace.endSection();
  11. return;
  12. }
  13. awaitingCallListUpdate = false;
  14. InCallState newState = getPotentialStateFromCallList(callList);
  15. InCallState oldState = inCallState;
  16. LogUtil.d(
  17. "InCallPresenter.onCallListChange",
  18. "onCallListChange oldState= " + oldState + " newState=" + newState);
  19. // If the user placed a call and was asked to choose the account, but then pressed "Home", the
  20. // incall activity for that call will still exist (even if it's not visible). In the case of
  21. // an incoming call in that situation, just disconnect that "waiting for account" call and
  22. // dismiss the dialog. The same activity will be reused to handle the new incoming call. See
  23. // a bug for more details.
  24. DialerCall waitingForAccountCall;
  25. if (newState == InCallState.INCOMING
  26. && (waitingForAccountCall = callList.getWaitingForAccountCall()) != null) {
  27. waitingForAccountCall.disconnect();
  28. // The InCallActivity might be destroyed or not started yet at this point.
  29. if (isActivityStarted()) {
  30. inCallActivity.dismissPendingDialogs();
  31. }
  32. }
  33. // 核心代码
  34. newState = startOrFinishUi(newState);
  35. LogUtil.d(
  36. "InCallPresenter.onCallListChange", "onCallListChange newState changed to " + newState);
  37. // Set the new state before announcing it to the world
  38. LogUtil.i(
  39. "InCallPresenter.onCallListChange",
  40. "Phone switching state: " + oldState + " -> " + newState);
  41. inCallState = newState;
  42. // Foreground call changed
  43. DialerCall primary = null;
  44. if (newState == InCallState.INCOMING) {
  45. primary = callList.getIncomingCall();
  46. } else if (newState == InCallState.PENDING_OUTGOING || newState == InCallState.OUTGOING) {
  47. primary = callList.getOutgoingCall();
  48. if (primary == null) {
  49. primary = callList.getPendingOutgoingCall();
  50. }
  51. } else if (newState == InCallState.INCALL) {
  52. primary = getCallToDisplay(callList, null, false);
  53. }
  54. if (primary != null) {
  55. onForegroundCallChanged(primary);
  56. }
  57. // notify listeners of new state
  58. for (InCallStateListener listener : listeners) {
  59. LogUtil.d(
  60. "InCallPresenter.onCallListChange",
  61. "Notify " + listener + " of state " + inCallState.toString());
  62. listener.onStateChange(oldState, inCallState, callList);
  63. }
  64. if (isActivityStarted()) {
  65. final boolean hasCall =
  66. callList.getActiveOrBackgroundCall() != null || callList.getOutgoingCall() != null;
  67. inCallActivity.dismissKeyguard(hasCall);
  68. }
  69. Trace.endSection();
  70. }

继续跟踪 startOrFinishUi 方法

  1. private InCallState startOrFinishUi(InCallState newState) {
  2. if ((showCallUi || showAccountPicker) && !shouldStartInBubbleMode()) {
  3. LogUtil.i("InCallPresenter.startOrFinishUi", "Start in call UI");
  4. // 展示来电界面
  5. showInCall(false /* showDialpad */, !showAccountPicker /* newOutgoingCall */);
  6. } else if (newState == InCallState.INCOMING) {
  7. LogUtil.i("InCallPresenter.startOrFinishUi", "Start Full Screen in call UI");
  8. try {
  9. PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
  10. PowerHALManager powerHALManager = new PowerHALManager(context, new Handler());
  11. PowerHALManager.PowerHintScene sceneIncall = powerHALManager.createPowerHintScene(
  12. "InCall: InCallPresenter", PowerHintVendorSprd.POWER_HINT_VENDOR_RADIO_CALL, null);
  13. if (sceneIncall != null && !pm.isScreenOn()) {
  14. Log.i(this, "power Hint POWER_HINT_VENDOR_RADIO_CALL");
  15. sceneIncall.acquire(1000);
  16. }
  17. } catch (java.lang.NoClassDefFoundError e) {
  18. LogUtil.e("InCallPresenter.startOrFinishUi", "Exception:" + e.getMessage());
  19. } catch (java.util.NoSuchElementException e) {
  20. LogUtil.e("InCallPresenter.startOrFinishUi", "Exception:" + e.getMessage());
  21. } catch (Exception e) {
  22. LogUtil.e("InCallPresenter.startOrFinishUi", "Exception:" + e.getMessage());
  23. }
  24. } else if (newState == InCallState.NO_CALLS) {
  25. // The new state is the no calls state. Tear everything down.
  26. inCallState = newState;
  27. attemptFinishActivity();
  28. attemptCleanup();
  29. }

跟踪 showInCall 方法

  1. public void showInCall(boolean showDialpad, boolean newOutgoingCall) {
  2. LogUtil.i("InCallPresenter.showInCall", "Showing InCallActivity");
  3. context.startActivity(
  4. InCallActivity.getIntent(context, showDialpad, newOutgoingCall, false /* forFullScreen */));
  5. }

至此,显示来电界面。

MO 是从Dialer 发起,MT是从Modem发起。所以两个流程最大的差别也就是如何开始创建Call & connection。当准备开始创建和创建完成后,MO & MT在流程上几乎是没有差异的,都是一些Call & connection的控制,然后通过UI显示出来。

 

总的来电各层之间的流程:

RIL→TelephonyFramework →TeleponyService→ TeleComService→

TeleComFramework→ TeleComService→TeleComFramework-->InCallUI

 

 

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/894897
推荐阅读
相关标签
  

闽ICP备14008679号