Telephony基础之VoiceCall业务(MT流程)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cornerOfHeart/article/details/79896548

                                                                                              MT流程之启动InCallUI时序图

MT流程是从底层状态变化开始。

首先进入RIL.processUnsolicited()
private void processUnsolicited (Parcel p) {
    ...
    try {switch(response) {
    ...
    case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
    ret =  responseVoid(p); break;
    ...
    }
    switch(response) {
    ...
    case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
         if (RILJ_LOGD)
         unsljLog(response);//打印log日志
         //发出通知(RegistrantList消息处理机制)
         mCallStateRegistrants.notifyRegistrants(new
         AsyncResult(null, null, null));
    ...
    }
}


进入GsmCdmaCallTracker.handleMessage():
 public void
     handleMessage (Message msg) {
     ...
     case EVENT_CALL_STATE_CHANGE:
          //调用父类CallTracker查询Call List方法
          pollCallsWhenSafe();
     break;
     ...
}


进入CallTracker.pollCallsWhenSafe():
protected void pollCallsWhenSafe() {
        ...
        if (checkNoOperationsPending()) {
        //注意mLastRelevantPoll对象的消息类型,后面会用到
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
            mCi.getCurrentCalls(mLastRelevantPoll);
        }
}


进入RIL.getCurrentCalls():
    public void getCurrentCalls (Message result) {
        //注意rr对象的消息类型,后面会用到
        RILRequest rr = RILRequest.obtain(
        RIL_REQUEST_GET_CURRENT_CALLS, result);
        //打印log日志
        if (RILJ_LOGD)
        riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
        send(rr);
    }

返回RIL.processSolicited ():
private RILRequest processSolicited (Parcel p) {
        ...
        case RIL_REQUEST_GET_CURRENT_CALLS:
        ret =  responseCallList(p); break;
        ...
        //打印log日志
        if (RILJ_LOGD) riljLog(rr.serialString() + "< " +
        requestToString(rr.mRequest)
                    + " " + retToString(rr.mRequest, ret));
        if (rr.mResult != null) {
            AsyncResult.forMessage(rr.mResult, null, tr);
            rr.mResult.sendToTarget();//发出handler消息通知
}


进入GsmCdmaCallTracker.handleMessage ():
public void handleMessage (Message msg) {
        ...
        switch (msg.what) {
            case EVENT_POLL_CALLS_RESULT:{
                //打印log日志
                Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
                ar = (AsyncResult)msg.obj;

                if(msg == mLastRelevantPoll) {
                    if(DBG_POLL) log(
                            "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
                    mNeedsPoll = false;
                    mLastRelevantPoll = null;
                    handlePollCalls((AsyncResult)msg.obj);
                }
            }
       break;
       ...
}

进入GsmCdmaCallTracker.handlePollCalls():
protected void
    handlePollCalls(AsyncResult ar){
    ...
    if (newRinging != null) {
    mPhone.notifyNewRingingConnection(newRinging);
    ...
}



进入GsmCdmaPhone.notifyNewRingingConnection():
void notifyNewRingingConnection(Connection c) {
        /* we'd love it if this was package-scoped*/
        super.notifyNewRingingConnectionP(c);
    }

进入Phone.notifyNewRingingConnectionP():
    public void notifyNewRingingConnectionP(Connection cn) {
        if (!mIsVoiceCapable)
            return;
        AsyncResult ar = new AsyncResult(null, cn, null);
        mNewRingingConnectionRegistrants.notifyRegistrants(ar);
    }


进入PstnIncomingCallNotifier.Handler.handleMessage():
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case EVENT_NEW_RINGING_CONNECTION:
                    handleNewRingingConnection((AsyncResult) msg.obj);
    ...    
      }

进入PstnIncomingCallNotifier.handleNewRingingConnection():
    private void handleNewRingingConnection(AsyncResult asyncResult) {
        Log.d(this, "handleNewRingingConnection");
        Connection connection = (Connection) asyncResult.result;
        if (connection != null) {
            Call call = connection.getCall();

            // Final verification of the ringing state before sending the intent to Telecom.
            if (call != null && call.getState().isRinging()) {
                sendIncomingCallIntent(connection);
            }
        }
    }

进入PstnIncomingCallNotifier.sendIncomingCallIntent():
   private void sendIncomingCallIntent(Connection connection) {
      ...
      TelecomManager.from(mPhoneProxy.getContext()).addNewIncomingCall(
    }


进入TelecomManager.addNewIncomingCall():
    public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
        try {
            if (isServiceConnected()) {
                getTelecomService().addNewIncomingCall(
                        phoneAccount, extras == null ? new Bundle() : extras);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException adding a new incoming call: " + phoneAccount, e);
        }
    }


进入TelecomServiceImpl.addNewIncomingCall():
        @Override
        public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
            try {
                Log.startSession("TSI.aNIC");
                synchronized (mLock) {
                       ...
                        try {
                            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);
                        } finally {
                            Binder.restoreCallingIdentity(token);
                        }
                    } else {
                        Log.w(this, "Null phoneAccountHandle. Ignoring request to add new" +
                                " incoming call");
                    }
                 ...
        }


进入CallIntentProcessor.AdapterImpl.processIncomingCallIntent():
        @Override
        public void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
            CallIntentProcessor.processIncomingCallIntent(callsManager, intent);
        }


进入CallIntentProcessor.processIncomingCallIntent():
    static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
    ...
        Log.d(CallIntentProcessor.class,
                "Processing incoming call from connection service [%s]",
                phoneAccountHandle.getComponentName());
        callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
    }



进入CallsManager.processIncomingCallIntent():

    /**
     * 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) {
        Log.d(this, "processIncomingCallIntent");
        Uri handle = extras.getParcelable(TelephonyManager.EXTRA_INCOMING_NUMBER);
        Call call = new Call(
                mContext,
                mConnectionServiceRepository,
                handle,
                null /* gatewayInfo */,
                null /* connectionManagerPhoneAccount */,
                phoneAccountHandle,
                true /* isIncoming */,
                false /* isConference */);

        call.setExtras(extras);
        // TODO: Move this to be a part of addCall()
        call.addListener(this);
        call.startCreateConnection(mPhoneAccountRegistrar);
    }

注意:
这里通过Call.startCreateConnection创建connection与MO基本相同.
先在ConnectionServiceWrapper bind to TelephonyConnectionservice,成功返回后通过Binder接口创建connection(GSMCDMAConnection).
这里和MO不同的是创建完connection后就调用mAdapter.handleCreateConnectionComplete()返回,而没有phone.dial()流程,因为是MT.

进入Call.startCreateConnection():
    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();
    }


进入CreateConnectionProcessor.process():
    public void process() {
        Log.v(this, "process");
        clearTimeout();
        mAttemptRecords = new ArrayList<>();
        if (mCall.getTargetPhoneAccount() != null) {
            mAttemptRecords.add(new CallAttemptRecord(
                    mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
        }
        adjustAttemptsForConnectionManager();
        adjustAttemptsForEmergency(mCall.getTargetPhoneAccount());
        mAttemptRecordIterator = mAttemptRecords.iterator();
        attemptNextPhoneAccount();
    }

进入CreateConnectionProcessor.attemptNextPhoneAccount():
    private void attemptNextPhoneAccount() {
        Log.v(this, "attemptNextPhoneAccount");
        ...
            } else {
                mConnectionAttempt++;
                mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
                mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
                mCall.setConnectionService(mService);
                setTimeoutIfNeeded(mService, attempt);

                mService.createConnection(mCall, this);
            }

    }

进入ConnectionServiceWrapper.BindCallback.onSuccess():
 public void onSuccess() {
        ...try {
                    mServiceInterface.createConnection(
                            call.getConnectionManagerPhoneAccount(),
                            callId,
                            new ConnectionRequest(
                                    call.getTargetPhoneAccount(),
                                    call.getHandle(),
                                    extras,
                                    call.getVideoState(),
                                    callId),
                            call.shouldAttachToExistingConnection(),
                            call.isUnknown());
                }
        ...
    }


回到ConnectionServiceWrapper.Adapter.handleCreateConnectionComplete():
    private final class Adapter extends IConnectionServiceAdapter.Stub {

        @Override
        public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
                ParcelableConnection connection) {
            Log.startSession(Log.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
            long token = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    logIncoming("handleCreateConnectionComplete %s", callId);
                    ConnectionServiceWrapper.this
                            .handleCreateConnectionComplete(callId, request, connection);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
                Log.endSession();
            }
        }

进入ConnectionServiceWrapper.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
            removeCall(callId, connection.getDisconnectCause());
        } else {
            // Successful connection
            if (mPendingResponses.containsKey(callId)) {
                mPendingResponses.remove(callId)
                        .handleCreateConnectionSuccess(mCallIdMapper, connection);
            }
        }
    }

回调CreateConnectionProcessor.handleCreateConnectionSuccess():
    @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.
        }
    }


回调Call.handleCreateConnectionSuccess():

    public void handleCreateConnectionSuccess(
            CallIdMapper idMapper,
            ParcelableConnection connection) {
        Log.v(this, "handleCreateConnectionSuccessful %s", connection);
     switch (mCallDirection) {
            case CALL_DIRECTION_INCOMING:
                // Listeners (just CallsManager for now) will be responsible for checking whether
                // the call should be blocked.
                for (Listener l : mListeners) {
                    l.onSuccessfulIncomingCall(this);
                }
                break;
    ...
    }


回调CallsManager.onSuccessfulIncomingCall():
  public void onSuccessfulIncomingCall(Call incomingCall) {
        Log.d(this, "onSuccessfulIncomingCall");
        if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE)) {
            Log.i(this, "Skipping call filtering due to ECBM");
            onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
            return;
        }

    ...
    }

进入CallsManager.onCallFilteringComplete():
    public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
        // Only set the incoming call as ringing if it isn't already disconnected. It is possible
        // that the connection service disconnected the call before it was even added to Telecom, in
        // which case it makes no sense to set it back to a ringing state.
        if (incomingCall.getState() != CallState.DISCONNECTED &&
                incomingCall.getState() != CallState.DISCONNECTING) {
            setCallState(incomingCall, CallState.RINGING,
                    result.shouldAllowCall ? "successful incoming call" : "blocking call");
        } else {
            Log.i(this, "onCallFilteringCompleted: call already disconnected.");
            return;
        }
        ...
        if (result.shouldAllowCall) {
            ...
            } else {
                addCall(incomingCall);
                setActiveSubscription(incomingCall.getTargetPhoneAccount().getId());
            }
        } else {
            if (result.shouldReject) {
            ...
            }
        }
    }

进入CallsManager.addCall():
private void addCall(Call call) {
    ...
        updateCanAddCall();
        // onCallAdded for calls which immediately take the foreground (like the first call).
        for (CallsManagerListener listener : mListeners) {
            if (Log.SYSTRACE_DEBUG) {
                Trace.beginSection(listener.getClass().toString() + " addCall");
            }
            listener.onCallAdded(call);
            if (Log.SYSTRACE_DEBUG) {
                Trace.endSection();
            }
        }
        RcsCallHandler.getInstance().updateCallComposerDataToCall(call);
        Trace.endSection();
    }


进入InCallController.onCallAdded()
    public void onCallAdded(Call call) {
        if (!isBoundToServices()) {
            bindToServices(call);
        } else {
            adjustServiceBindingsForEmergency();

            Log.i(this, "onCallAdded: %s", call);
            // Track the call if we don't already know about it.
            addCall(call);
        ...
        }
    }

从这里开始就跟MO的启动UI的流程一样了。
首先,如果没有bind service就先去bind service.成功返回依次调用:
InCallController.addCall()-->InCallService.allCall()-->Phone.internalAddCall()-->InCallServiceImpl.onCallAdded()-->InCallPresenter.onCallAdded()-->InCallPresenter.startOrFinishUi()
至此InComingCall UI启动完毕, MT流程完毕。














 

猜你喜欢

转载自blog.csdn.net/cornerOfHeart/article/details/79896548