接听电话流程分析

转自:https://www.aliyun.com/jiaocheng/7560.html

  • 阿里云  >  教程中心   >  android教程  >  接听电话流程分析  
  • 接听电话流程分析
  • 发布时间:2018-01-18 来源:网络 上传者:用户

    关键字: 接听 流程 电话 分析

    发表文章
  • 摘要:2,接听电话流程分析2.1InCallUI当有来电时,在来电界面,一般向左滑动是拒接电话,向右滑动是接听电话.在AnswerFragment.java中,接听电话会调用到onAnswer方法,调用流程图如下,onAnswer方法如下,publicvoidonAnswer(intvideoState,Contextcontext){Log.d(this,"onAnswervideoState="+videoState+"context="
  • 2,接听电话流程分析 2.1 InCallUI

    当有来电时,在来电界面,一般向左滑动是拒接电话,向右滑动是接听电话.

    在AnswerFragment.java中,接听电话会调用到onAnswer方法,调用流程图如下,

    接听电话流程分析

     

    onAnswer方法如下,

    public void onAnswer(int videoState, Context context) { Log.d(this, "onAnswer videoState=" + videoState + " context=" + context); getPresenter().onAnswer(videoState, context);}

    拒接电话会调用到onDecline方法,

    public void onDecline(Context context) { getPresenter().onDecline(context);}

    父类BaseFragment 的getPresenter的方法如下,

    public T getPresenter() { return mPresenter;}

    返回的是mPresenter变量,该变量是在BaseFragment的构造方法中初始化的,

    protected BaseFragment() { mPresenter = createPresenter();}

    createPresenter是一个抽象方法,具体的AnswerFragment实现如下,

    public AnswerPresenter createPresenter() { return InCallPresenter.getInstance().getAnswerPresenter();}

    InCallPresenter的getAnswerPresenter方法如下,

    AnswerPresenter getAnswerPresenter() { return mAnswerPresenter;}

    mAnswerPresenter变量定义如下,

    private AnswerPresenter mAnswerPresenter = new AnswerPresenter();

    因此, AnswerFragment的getPresenter方法最后返回的是AnswerPresenter对象。

    AnswerFragment的AnswerPresenter方法如下,

    int phoneId = getActivePhoneId();//获取idif (mCallId == null || phoneId == -1) { return;}•••QtiCallUtils.answerCall(mCall[phoneId], videoState);

    QtiCallUtils的answerCall方法如下,

    TelecomAdapter.getInstance().answerCall(call.getId(), videoState);

    TelecomAdapter的answerCall方法如下,

    void answerCall(String callId, int videoState) { android.telecom.Call call = getTelecommCallById(callId); if (call != null) { call.answer(videoState); •••

    frameworks/base/telecomm路径下的Call是services telecom对外提供的接口,

    Call的answer方法如下,

    public void answer(int videoState) { mInCallAdapter.answerCall(mTelecomCallId, videoState);}

    InCallAdapter的answerCall方法如下,

    public void answerCall(String callId, int videoState) { try { mAdapter.answerCall(callId, videoState); } catch (RemoteException e) { }}

    这里的mAdapter对象是在InCallAdapter的构造方法中赋值的,

    public InCallAdapter(IInCallAdapter adapter) { mAdapter = adapter;}

    并且mInCallAdapter变量的定义如下,

    private final IInCallAdapter mAdapter;

    看名称就知道这里的mInCallAdapter是一个binder, mAdapter是incallui与services telecom通信的AIDL接口。

    在services telecom中的InCallController的onCallAdded方法中会绑定InCallService服务并调用setInCallAdapter设置,

    构造InCallAdapter对象。详细的过程后面的章节论述。

    在此,只需要知道InCallUI的InCallAdapter只是services telecom InCallAdapter中的一个代理。

    mAdapter就是具体的代理对象。

    这样,调用mAdapter的answerCall实际上就跨进程调用到services telecom中的InCallAdapter的answerCall方法。

    虽然名称都是InCallAdapter,但是运行于不同的进程中。

    2.2 services telecom

    InCallAdapter的answerCall方法调用流程图如下,

    接听电话流程分析

     

    answerCall方法如下,

    Call call = mCallIdMapper.getCall(callId);//获取当前的callif (call != null) {mCallsManager.answerCall(call, videoState);•••

    CallsManager的answerCall方法主要逻辑如下,

    for (CallsManagerListener listener : mListeners) { listener.onIncomingCallAnswered(call); //通知该call已接听}call.answer(videoState);

    调用监听器的onIncomingCallAnswered方法通知已接听,更新一下界面。

    调用Call的answer方法继续处理。

    Call的answer方法如下,

    mConnectionService.answer(this, videoState);

    ConnectionServiceWrapper的answer方法如下,

    void answer(Call call, int videoState) { final String callId = mCallIdMapper.getCallId(call); if (callId != null &;&; isServiceValid("answer")) { try { logOutgoing("answer %s %d", callId, videoState); if (VideoProfile.isAudioOnly(videoState)) { mServiceInterface.answer(callId); } else { mServiceInterface.answerVideo(callId, videoState); } } catch (RemoteException e) { } }}

    前面多次论述过,mServiceInterface 实际上指向的是services Telephony 的TelephonyConnectionService的父类

    ConnectionService的内部类IConnectionService.Stub对象,也是一个跨进程的调用。

    2.3 services Telephony

    TelephonyConnectionService的父类ConnectionService的内部类IConnectionService.Stub的answer方法如下,

     

    public void answer(String callId) { mHandler.obtainMessage(MSG_ANSWER, callId).sendToTarget();}

     

    发送消息,切换到主线程中调用,变量mHandler的handleMessage方法对MSG_ANSWER消息处理如下,

    case MSG_ANSWER: answer((String) msg.obj); break;

    直接调用ConnectionService的answer方法,调用流程图如下,

    接听电话流程分析

    answer方法如下,

    private void answer(String callId) { Log.d(this, "answer %s", callId); findConnectionForAction(callId, "answer").onAnswer();}

    首先根据callId调用findConnectionForAction方法获取对应的Connection对象,一般根据GSM制式不同分为2种, 

    GsmConnection和CdmaConnection。都继承于TelephonyConnection,然后继承于Connection。在此以

    GsmConnection为例论述。一般的都方法都是在父类TelephonyConnection中实现, TelephonyConnection

    的onAnswer方法如下,

    public void onAnswer(int videoState) { Log.v(this, "onAnswer"); if (isValidRingingCall() &;&; getPhone() != null) { try { getPhone().acceptCall(videoState); } catch (CallStateException e) { Log.e(this, e, "Failed to accept call."); } }}

    当然,如果是GSM call,调用getPhone方法获取的就是GSMPhone对象, acceptCall方法如下,

    public void acceptCall(int videoState) throws CallStateException { ImsPhone imsPhone = mImsPhone; if ( imsPhone != null &;&; imsPhone.getRingingCall().isRinging() ) { imsPhone.acceptCall(videoState); } else { mCT.acceptCall(); } }

    调用GsmCallTracker的acceptCall方法,如下,

    mCi.acceptCall(obtainCompleteMessage());

    首先调用obtainCompleteMessage封装消息,然后调用RIL的acceptCall方法,这样当RIL收到ril库对应的消息时,

    会在GsmCallTracker中进行处理, obtainCompleteMessage方法如下,

    private Message obtainCompleteMessage() { return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);}

    RIL的acceptCall方法如下,

    public void acceptCall (Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_ANSWER, result); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr);}

    向ril库发送RIL_REQUEST_ANSWER消息,ril库处理完该消息之后, GsmCallTracker的handleMessage方法会

    处理EVENT_OPERATION_COMPLETE消息,如下,

     

    case EVENT_OPERATION_COMPLETE: ar = (AsyncResult)msg.obj; operationComplete(); break;

     

    后面的处理在此就不论述了。

    小结:

    接听电话的流程还是很简单,通过2次binder跨进程通信。

    1,首先从InCallUI到services telecom的binder.

    2,然后从services telecom到services Telephony的binder。

    当然,这里面还包括一部分界面的更新,既然接听电话了,肯定要跳到通话界面。

    以上是接听电话流程分析的内容,更多 接听 流程 电话 分析 的内容,请您使用右上方搜索功能获取相关信息。
阅读更多
换一批

没有更多推荐了,返回首页