Android7.0 Phone应用源码分析(三) phone拒接流程分析,android7.0拒接
接上篇博文:Android7.0 Phone应用源码分析(二) phone来电流程分析
今天我们再来分析下Android7.0 的phone的拒接流程
下面先来看一下拒接电话流程时序图
步骤1:滑动按钮到拒接图标,会调用到AnswerFragment的onDecline方法
com.android.incallui.AnswerFragment
public void onDecline(Context context) { getPresenter().onDecline(context); }
最后是调用到AnswerPresenteronDecline方法
com.android.incallui.AnswerPresenter public void onDecline(Context context) { Log.d(this, "onDecline " + mCallId); if (mCall.getSessionModificationState() == Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) { InCallPresenter.getInstance().declineUpgradeRequest(context); } else { TelecomAdapter.getInstance().rejectCall(mCall.getId(), false, null); } }
步骤2:进入TelecomAdapter的rejectCall方法
com.android.incallui.TelecomAdapter void rejectCall(String callId, boolean rejectWithMessage, String message) { android.telecom.Call call = getTelecomCallById(callId); if (call != null) { call.reject(rejectWithMessage, message); } else { Log.e(this, "error rejectCall, call not in call list: " + callId); } }
TelecomAdapter是incallui与telecom通信的代理类,这里通过callid取出对应的Call对象(android.telecom.Call)
步骤3:调用到framework里Call的reject方法
android.telecom.Call public void reject(boolean rejectWithMessage, String textMessage) { mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage); }
这里mInCallAdapter是android.telecom.InCallAdapter类,是在Call对象创建的时候由外部传入的参数
在telecom绑定InCallService服务的时候,会传递一个AIDL接口对象,InCallService会生成InCallAdapter对象来保存这个接口对象
步骤4:InCallAdapter的rejectCall方法
android.telecom.InCallAdapter
public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) { try { mAdapter.rejectCall(callId, rejectWithMessage, textMessage); } catch (RemoteException e) { } }
mAdapter就是incallui与telecom通信的AIDL接口
步骤5:跨进程调用进入telecom进程,该AIDL接口具体实现类是InCallAdapter,虽然类名一样但是不同的包名,这里需要注意一下
com.android.server.telecom.InCallAdapter public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) { try { Log.startSession("ICA.rC", mOwnerComponentName); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Log.d(this, "rejectCall(%s,%b,%s)", callId, rejectWithMessage, textMessage); Call call = mCallIdMapper.getCall(callId); if (call != null) { mCallsManager.rejectCall(call, rejectWithMessage, textMessage); } else { Log.w(this, "setRingback, unknown call id: %s", callId); } } } finally { Binder.restoreCallingIdentity(token); } } finally { Log.endSession(); } }
这里同样是根据callid取出对应Call(com.android.server.telecom.Call),最后调用CallsManager的rejectCall方法传入call
步骤6:CallsManager的rejectCall方法
com.android.server.telecom.CallsManager public void rejectCall(Call call, boolean rejectWithMessage, String textMessage) { if (!mCalls.contains(call)) { Log.i(this, "Request to reject a non-existent call %s", call); } else { for (CallsManagerListener listener : mListeners) { listener.onIncomingCallRejected(call, rejectWithMessage, textMessage); } call.reject(rejectWithMessage, textMessage); } }
这里先通知观察者来电拒接事件,比如CallAudioManager对该事件感兴趣,它的处理是停止播放来电铃声和来电等待声
com.android.server.telecom.CallAudioManager public void onIncomingCallRejected(Call call, boolean rejectWithMessage, String message) { maybeStopRingingAndCallWaitingForAnsweredOrRejectedCall(call); } private void maybeStopRingingAndCallWaitingForAnsweredOrRejectedCall(Call call) { // Check to see if the call being answered/rejected is the only ringing call, since this // will be called before the connection service acknowledges the state change. if (mRingingCalls.size() == 0 || (mRingingCalls.size() == 1 && call == mRingingCalls.iterator().next())) { mRinger.stopRinging(); mRinger.stopCallWaiting(); } }
最后再调用前面传进来的call对象的reject方法
步骤7:Call的reject方法
com.android.server.telecom.Call public void reject(boolean rejectWithMessage, String textMessage) { Preconditions.checkNotNull(mConnectionService); // Check to verify that the call is still in the ringing state. A call can change states // between the time the user hits 'reject' and Telecomm receives the command. if (isRinging("reject")) { // Ensure video state history tracks video state at time of rejection. mVideoStateHistory |= mVideoState; mConnectionService.reject(this, rejectWithMessage, textMessage); Log.event(this, Log.Events.REQUEST_REJECT); } }
这里的mConnectionService是ConnectionServiceWrapper类,是telecom与telephony通信的代理类
步骤8:ConnectionServiceWrapper的reject方法
com.android.server.telecom.ConnectionServiceWrapper void reject(Call call, boolean rejectWithMessage, String message) { final String callId = mCallIdMapper.getCallId(call); if (callId !=