转自: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 telecomInCallAdapter的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 TelephonyTelephonyConnectionService的父类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。
当然,这里面还包括一部分界面的更新,既然接听电话了,肯定要跳到通话界面。
以上是接听电话流程分析的内容,更多 接听 流程 电话 分析 的内容,请您使用右上方搜索功能获取相关信息。