Android call 流程以及其他case整理(3)--MT

    对于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.

具体的代码如下:

    Step1.接收Modem上报的call状态变化的消息。

http://androidxref.com/8.1.0_r33/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioIndication.java

    // 得到消息后,就去通知监听这个消息的对象
    public void callStateChanged(int indicationType) {
        mRil.processIndication(indicationType);

        if (RIL.RILJ_LOGD) mRil.unsljLog(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED);

        mRil.mCallStateRegistrants.notifyRegistrants();
    }

  Step2.处理从Modem上报的call状态变化的消息。代码里可以看出GsmCdmaCallTracker.java有注册该监听:

http://androidxref.com/8.1.0_r33/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java

    // 初始化时,监听EVENT_CALL_STATE_CHANGE消息
    public GsmCdmaCallTracker (GsmCdmaPhone phone) {
        ......
        mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
        ......
    }

    // handle 处理
    @Override
    public void handleMessage(Message msg) {
        AsyncResult ar;
        switch (msg.what) {
            ......
            case EVENT_CALL_STATE_CHANGE:
                // 该方法并没有在GsmCdmaCallTracker重写,所以要在父类中查看该方法
                pollCallsWhenSafe();
            break;
            ......
        }
    }


Step3. 处理完后,向Modem请求Call的信息。

http://androidxref.com/8.1.0_r33/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/CallTracker.java

    protected void pollCallsWhenSafe() {
        mNeedsPoll = true;

        if (checkNoOperationsPending()) {
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
            // 通过RIL向Modem发起请求
            mCi.getCurrentCalls(mLastRelevantPoll);
        }
    }

Step4. 当Modem处理完毕后,就返回这个response.

http://androidxref.com/8.1.0_r33/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioResponse.java

    /**
     * @param responseInfo Response info struct containing response type, serial no. 
     *        and error
     * @param calls Current call list
     */
    public void getCurrentCallsResponse(RadioResponseInfo responseInfo,
                                        ArrayList<android.hardware.radio.V1_0.Call> calls) {
        responseCurrentCalls(responseInfo, calls);
    }


    /**
     * 处理这个消息,然后返回给请求者   
     */
    private void responseCurrentCalls(RadioResponseInfo responseInfo,
                                      ArrayList<android.hardware.radio.V1_0.Call> calls) {
        RILRequest rr = mRil.processResponse(responseInfo);

        if (rr != null) {
            ......

            /**
             * 处理消息体,发现其通过底层返回的消息创建了dcCalls对象,也就是当前的Call状态信
             * 息,对dc状态进行判断后如果有需要就notify通知,如果没有异常则通过
             * sendMessageResponse方法发送消息。这部分就和N的一样了,将返回值返回给当初的请求
             *者,由请求者去决定如何处理。
            */
            if (responseInfo.error == RadioError.NONE) {
                sendMessageResponse(rr.mResult, dcCalls);
            }
            mRil.processResponseDone(rr, responseInfo, dcCalls);
        }
    }

Step5: 处理response。在Step3时候可以看到,CallTracker发起了请求,所以RIL返回的reponse就返回到CallTracker.查看了CallTracker里并没有处理EVENT_POLL_CALLS_RESULT的消息,查看了子类GsmCdmaCallTracker.java中有处理该消息:

http://androidxref.com/8.1.0_r33/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java#EVENT_POLL_CALLS_RESULT

    //****** Overridden from Handler

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

    // ***** Overwritten from CallTracker

    @Override
    protected synchronized void handlePollCalls(AsyncResult ar) {
        List polledCalls;
        ...
        if (newRinging != null) {
            //通知newRinging
            mPhone.notifyNewRingingConnection(newRinging);
        }
        ...
    }

Step6: 查看响铃的通知。查找这个通知,最终是PstnIncomingCallNotifier来处理这个通知。

http://androidxref.com/8.1.0_r33/xref/packages/services/Telephony/src/com/android/services/telephony/PstnIncomingCallNotifier.java

    /**
     * Used to listen to events from {@link #mPhone}.
     */
    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;
                 ...
            }
        }
    };

    /**
     * Verifies the incoming call and triggers sending the incoming-call intent to 
     * Telecom.
     * @param asyncResult The result object from the new ringing event.
     */
    private void handleNewRingingConnection(AsyncResult asyncResult) {
            ...    
            if (call != null && call.getState().isRinging()) {
                sendIncomingCallIntent(connection);
            }
    }


    /**
     * Sends the incoming call intent to telecom.
     */
    private void sendIncomingCallIntent(Connection connection) {
        ...
        TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
    }

至此,已经将RIL消息处理完毕,然后发出这个intent.将Modem上报的response向上层传递。大概的方法传递如下:

  1. RadioIndication.java#callStateChanged
  2. -->GsmCdmaCallTracker.java#mCi.registerForCallStateChanged# EVENT_CALL_STATE_CHANGE
  3. -->GsmCdmaCallTracker.java#pollCallsWhenSafe()
  4. --> Ril.java # getCurrentCalls # RIL_REQUEST_GET_CURRENT_CALLS
  5.  --> RadioResponse.java # getCurrentCallsResponse # responseCurrentCalls # sendMessageResponse
  6.  --> GsmCdmaCallTracker.java # EVENT_POLL_CALLS_RESULT #  handlePollCall
  7.  --> GsmCdmaPhone.java # notifyNewRingingConnection
  8. --> Phone.java#notifyNewRingingConnectionP
  9. -->PstnIncomingCallNotifier.java#handleNewRingingConnection#sendIncomingCallIntent

Step7: Packages/service里的处理,intent的传递。 在Step6中,通过获取Telecomm的service.然后去调用addNewIncomingCall,通过aidl接口调用 telecomService 的addNewIncomingCall方法。查看具体实现的地方:

http://androidxref.com/8.1.0_r33/xref/packages/services/Telecomm/src/com/android/server/telecom/TelecomServiceImpl.java#addNewIncomingCall

        /**
         * @see android.telecom.TelecomManager#addNewIncomingCall
         */
        @Override
        public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
          ......
                            Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
                            intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
                                    phoneAccountHandle);
                            intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
                            if (extras != null) {
                                extras.setDefusable(true);
                                intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
                            }
                            mCallIntentProcessorAdapter.processIncomingCallIntent(
                                    mCallsManager, intent);
          ......              
        }

  继续跟进代码:

http://androidxref.com/8.1.0_r33/xref/packages/services/Telecomm/src/com/android/server/telecom/CallIntentProcessor.java


    static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
        PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
                TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
        ...
        callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
    }

    /**
     * Starts the process to attach the call to a connection service.
     *
     * @param phoneAccountHandle The phone account which contains the component name of the
     *        connection service to use for this call.
     * @param extras The optional extras Bundle passed with the intent used for the incoming call.
     */
    void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
         
        ...
        if (!isHandoverAllowed || (call.isSelfManaged() && !isIncomingCallPermitted(call,
                call.getTargetPhoneAccount()))) {
            notifyCreateConnectionFailed(phoneAccountHandle, call);
        } else {
            //通过这个call 来开始创建Connection
            call.startCreateConnection(mPhoneAccountRegistrar);
        }
    }

   这块的代码走向大概如下:

  1. TelecomManager.java # addNewIncomingCall 
  2. --> TelecomServiceImpl.java # addNewIncomingCall
  3. --> CallIntentProcessor.java # processIncomingCallIntent
  4. --> CallsManager.java #  processIncomingCallIntent 

Step8:开始创建connection。这里和之前MO的流程是一样的,创建了一个Call然后调用startCreateConnection去创建connection。没有太多的逻辑调用,大概的代码走向如下:

  1. Call.java # startCreateConnection 
  2. --> CreateConnectionProcessor.java # process() # attemptNextPhoneAccount()
  3. --> ConnectionServiceWrapper.java # createConnection
  4. --> ConnectionService.java # createConnection #MSG_CREATE_CONNECTION
  5. --> ConnectionServiceAdapter.java # handleCreateConnectionComplete
  6. --> ConnectionServiceWrapper.java # handleCreateConnectionComplete
  7. --> Call.java #  handleCreateConnectionSuccess

Setp9: 对Call进行处理。这里的流程也没有太大的逻辑,且与MO相似:

  1. CallsManager.java # onSuccessfulIncomingCall
  2. --> IncomingCallFilter.java # performFiltering # onCallFilteringComplete
  3. --> CallsManager.java #  onCallFilteringComplete # addCall
  4. --> InCallController.java # onCallAdded

Setp10:显示UI界面,与MO一致

  1. InCallService.java # MSG_ADD_CALL # 
  2. --> Phone.java # internalAddCall # fireCallAdded
  3. --> InCallService.java # onCallAdded
  4. --> InCallServiceImpl.java # onCallAdded
  5. --> InCallPresenter.java # onCallAdded
  6. --> CallList.java # onCallAdded
  7. --> CallList.java # onDialerCallUpdate 
  8. --> CallList.java # notifyGenericListeners 
  9. --> InCallPresenter.java # onCallListChange  
  10. --> InCallPresenter.java # startOrFinishUi 
  11. --> InCallPresenter.java # showInCall

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

猜你喜欢

转载自blog.csdn.net/Clear_ws/article/details/81666741