安卓10 来电流程梳理

来电过程, 是由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:
  1. frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioIndication.java

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();
    }
  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消息。

     @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);
    }

进入到TelecomService层

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

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

    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);
        }
    }

Telecomm Framework

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  中分析

Dialer  层

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

 

 

 

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值