Version:1.0 StartHTML:0000000194 EndHTML:0000209014 StartFragment:0000024273 EndFragment:0000208974 SourceURL:file:///Y:\Desktop\学习\新建文件夹\%5bAndroid%20O来电call流程.docx
Android O来电call流程
frameworktelephony
- 来电的消息属于主动上报的UnSolicited消息,其对应的事件ID是CALL_STATE_CHANGE,首先会调用RadioIndication.java中的callStateChanged方法来通知上层,这个时候会调用RIL.java中的processIndication方法,来向底层发送确认消息。
public void callStateChanged(int indicationType) {
mRil.processIndication(indicationType);
if (RIL.RILJ_LOGD) mRil.unsljLog(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED);
mRil.mCallStateRegistrants.notifyRegistrants();
}
public void processIndication(int indicationType) {
if (indicationType == RadioIndicationType.UNSOLICITED_ACK_EXP) {
sendAck();
if (RILJ_LOGD) riljLog("Unsol response received; Sending ack to ril.cpp");
} else {
// ack is not expected to be sent back. Nothing is required to be done here.
}
}
- 这里通知完毕会调用notifyRegistrants方法来通知已注册的观察者(观察者模式)。在GsmCdmaCallTracker初始化的时候,就已经注册了,并传入了自身的handler,用来处理EVENT_CALL_STATE_CHANGE消息。
public GsmCdmaCallTracker (GsmCdmaPhone phone) {
…………………………
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
…………………….
}
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
。。。。。。。。。。。。。。。。。
case EVENT_CALL_STATE_CHANGE:
pollCallsWhenSafe();
break;
。。。。。。。。。。。。。。。。。
}
}
- 接下来就会调用pollCallsWhenSafe方法,这里的mCi,实质上可以看成是RIL.java对象,这里调用了它的getCurrentCalls方法来重新去获取了当前call的状态。
protected void pollCallsWhenSafe() {
mNeedsPoll = true;
if (checkNoOperationsPending()) {
mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
mCi.getCurrentCalls(mLastRelevantPoll);
}
}
- 来到了RIL.java中的getCurrentCalls方法,这里会创建一个请求消息,然后通过Radio代理来向底层发起请求。
public void getCurrentCalls(Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
//创建一个请求消息
RILRequest rr = obtainRequest(RIL_REQUEST_GET_CURRENT_CALLS, result,
mRILDefaultWorkSource);
…….
//向底层发起请求
try {
radioProxy.getCurrentCalls(rr.mSerial);
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "getCurrentCalls", e);
}
}
}
- 等待modem层返回结果给RIL层,调用RadioResponse中的responseCurrentCalls方法。(N上的processSolicited的消息回复被抽取到这个类来了),通过底层返回的消息创建了dcCalls对象,也就是当前的Call状态信息,对dc状态进行判断后如果有需要就notify通知,如果没有异常则通过sendMessageResponse方法发送消息
private void responseCurrentCalls(RadioResponseInfo responseInfo,
ArrayList<android.hardware.radio.V1_0.Call> calls) {
判断电话状态,进行notify通知
…………
//发送返回消息
if (responseInfo.error == RadioError.NONE) {
sendMessageResponse(rr.mResult, dcCalls);
}
mRil.processResponseDone(rr, responseInfo, dcCalls);
}
}
- 之前说过,GsmCdmaCallTracker注册了观察者,这里返回的消息就会发送给他之前注册时候传入的handler来进行处理,这里我们回到GsmCdmaCallTracker中的handleMessage方法中。因为之前我们发送的是EVENT_POLL_CALLS_RESULT消息,所以我们这里只看EVENT_POLL_CALLS_RESULT消息。
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;
……..
}
}
- 继续追踪handlePollCalls方法,在这方法中先对底层反馈的消息进行解析,获取其通话状态,判断如果是来电则发出notifyNewRingingConnection响铃消息通知,然后进行一些通话断开连接的操作及更新phone状态。继续跟进notifyNewRingingConnection响铃消息,该消息调用的是phone的方法。
protected synchronized void handlePollCalls(AsyncResult ar) {
//解析返回的结果
for (int i = 0, curDC = 0, dcSize = polledCalls.size()
; i < mConnections.length; i++) {
GsmCdmaConnection conn = mConnections[i];
DriverCall dc = null;
// polledCall list is sparse
if (curDC < dcSize) {
dc = (DriverCall) polledCalls.get(curDC);
if (dc.index == i+1) {
curDC++;
} else {
dc = null;
}
}
...
if (conn == null && dc != null) {
...状态的处理及识别
//响铃消息通知
if (newRinging != null) {
mPhone.notifyNewRingingConnection(newRinging);
}
// clear the "local hangup" and "missed/rejected call"
// cases from the "dropped during poll" list
// These cases need no "last call fail" reason
ArrayList<GsmCdmaConnection> locallyDisconnectedConnections = new ArrayList<>();
for (int i = mDroppedDuringPoll.size() - 1; i >= 0 ; i--) {
GsmCdmaConnection conn = mDroppedDuringPoll.get(i);
//CDMA
boolean wasDisconnected = false;
//来电处理,本地挂断或者未接,本地挂断的话直接设置挂断的原因为LOCAL或INVALID_NUMBER
if (conn.isIncoming() && conn.getConnectTime() == 0) {
// Missed or rejected call
int cause;
if (conn.mCause == DisconnectCause.LOCAL) {
cause = DisconnectCause.INCOMING_REJECTED;
} else {
cause = DisconnectCause.INCOMING_MISSED;
}
if (Phone.DEBUG_PHONE) {
log("missed/rejected call, conn.cause=" + conn.mCause);
log("setting cause to " + cause);
}
mDroppedDuringPoll.remove(i);
hasAnyCallDisconnected |= conn.onDisconnect(cause);
wasDisconnected = true;
locallyDisconnectedConnections.add(conn);
} else if (conn.mCause == DisconnectCause.LOCAL
|| conn.mCause == DisconnectCause.INVALID_NUMBER) {
mDroppedDuringPoll.remove(i);
hasAnyCallDisconnected |= conn.onDisconnect(conn.mCause);
wasDisconnected = true;
locallyDisconnectedConnections.add(conn);
}
if (!isPhoneTypeGsm() && wasDisconnected && unknownConnectionAppeared
&& conn == newUnknownConnectionCdma) {
unknownConnectionAppeared = false;
newUnknownConnectionCdma = null;
}
}
if (locallyDisconnectedConnections.size() > 0) {
mMetrics.writeRilCallList(mPhone.getPhoneId(), locallyDisconnectedConnections);
}
/* Disconnect any pending Handover connections */
//通话断开的一些处理操作
...
if (newRinging != null || hasNonHangupStateChanged || hasAnyCallDisconnected) {
internalClearDisconnected();
}
//更新phone状态
if (VDBG) log("handlePollCalls calling updatePhoneState()");
updatePhoneState();
...
}
- 查看一下是如何往上通知响铃消息的,同样的观察者模式,通知到注册的人
public void notifyNewRingingConnectionP(Connection cn) {
if (!mIsVoiceCapable)
return;
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
}
查看发现,CallsManager注册了,所以这个时候会同时到CallsManager,
protected void registerForPhoneStates(Phone phone) {
…………..
phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION,
mRegistrantidentifier);
}
同样的,来到CallsManager中的handleMessage方法查看EVENT_NEW_RINGING_CONNECTION消息处理。再判断完是否需要挂断之后,会通知到PstnIncommingCallNotifier来处理此消息。这里会调用handleNewRingingConnection方法,来
sendIncomingCallIntent。
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()) {
if (ExtensionManager.getDigitsUtilExt().isConnectionMatched(connection,
mPhoneAccountHandle, mPhone.getContext()) == false) {
return;
}
sendIncomingCallIntent(connection);
}
}
}
Telephony-Service
- 在sendIncomingCallIntent方法中,获取了teltecom的服务,调用到了telecomService 的addNewIncomingCall方法。
private void sendIncomingCallIntent(Connection connection) {
Bundle extras = new Bundle();
//extras填充一些数据
...
PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
if (handle == null) {
//挂断
} else {
TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
}
}
//获取telecomm服务
public static TelecomManager from(Context context) {
return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
}
- 接下来来到了TelecomServiceImpl类中,在addNewIncomingCall方法中调用了CallIntentProcessor的processIncomingCallIntent方法,再往后就调用了package中telecom中的callsManager的processIncomingCallIntent方法
void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
Log.d(this, "processIncomingCallIntent");
...
Call call = new Call(
getNextCallId(),
mContext,
this,
mLock,
mConnectionServiceRepository,
mContactsAsyncHelper,
mCallerInfoAsyncQueryFactory,
mPhoneNumberUtilsAdapter,
handle,
null /* gatewayInfo */,
null /* connectionManagerPhoneAccount */,
phoneAccountHandle,
Call.CALL_DIRECTION_INCOMING /* callDirection */,
false /* forceAttachToExistingConnection */,
false, /* isConference */
mClockProxy);
...
call的一些状态设置
...
call.initAnalytics();
if (getForegroundCall() != null) {
getForegroundCall().getAnalytics().setCallIsInterrupted(true);
call.getAnalytics().setCallIsAdditional(true);
}
setIntentExtrasAndStartTime(call, extras);
//添加监听
// TODO: Move this to be a part of addCall()
call.addListener(this);
if (!isHandoverAllowed || (call.isSelfManaged() && !isIncomingCallPermitted(call,
call.getTargetPhoneAccount()))) {
notifyCreateConnectionFailed(phoneAccountHandle, call);
} else {
//成功上报上去建立连接
call.startCreateConnection(mPhoneAccountRegistrar);
}
}
- 来到CallsManager的processIncomingCallIntent方法中,在这个方法中,会创建一个call对象,创建完毕之后会调用startCreateConnection去创建connection,这里会调用到ConnectionService中的createConnection方法。(注意,无论是什么都会在这里建立连接)
- 这里只管incomingcall的情况,会调用onCreateIncomingConnection方法。
Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
: isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
public Connection onCreateIncomingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
ConnectionRequest request) {
return null;
}
- 在这里并没有实现,该方法的实现应该在该类的子类中,跟进到其子类TelephonyConnectionService中,在onCreateIncomingConnection方法中,调用了createConnectionFor来创建连接。
- 创建完毕之后,会通知到ConnectionServiceWrapper中,调用handleCreateConnectionComplete方法、
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection, Session.Info sessionInfo) {
...
logIncoming("handleCreateConnectionComplete %s", callId);
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection);
...
}
跟进handleCreateConnectionComplete,mPendingResponses是hashMap容器,每次在 createConnection 的时候会将对象加入该容器,如果此时connection还未断开的,会移除此connection,调用hanleCreateConnectionSuccess方法。 往上追溯createConnection跟踪到mService.createConnection(mCall, this); CreateConnectionProcessor.java会把自身传入,发现该类也实现了 CreateConnectionResponse ,所以这里的 handleCreateConnectionSuccess
调用的是CreateConnectionProcessor类里面的方法
private void handleCreateConnectionComplete(
String callId,
ConnectionRequest request,
ParcelableConnection connection) {
...
if (connection.getState() == Connection.STATE_DISCONNECTED) {
removeCall(callId, connection.getDisconnectCause());
} else {
// Successful connection
if (mPendingResponses.containsKey(callId)) {
String num = connection.getHandle().getSchemeSpecificPart();
/// M: add for CMCC L + C ecc retry
if (PhoneNumberUtils.isEmergencyNumber(num)) {
mPendingResponses.get(callId).
handleCreateConnectionSuccess(mCallIdMapper, connection);
} else {
mPendingResponses.remove(callId)
.handleCreateConnectionSuccess(mCallIdMapper, connection);
}
}
}
}
- 继续跟进 CreateConnectionProcessor 中的此方法,这里根据来电类型,触发回调,监听者会收到通知,之前在CallManager中执行 processIncomingCallIntent 方法创建Call的时候就添加了监听,所以最后会回调到 CallsManager中
public void handleCreateConnectionSuccess(
CallIdMapper idMapper,
ParcelableConnection connection) {
if (mCallResponse == null) {
mService.abort(mCall);
} else {
mCallResponse.handleCreateConnectionSuccess(idMapper, connection);
String number = connection == null || connection.getHandle() == null ?
null : connection.getHandle().getSchemeSpecificPart();
if (!PhoneNumberUtils.isEmergencyNumber(number)) {
mCallResponse = null;
}
}
}
- 创建成功,调用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;
}
//迭代器模式
List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock));
//IncomingCallFilter创建并执行 performFiltering
new IncomingCallFilter(mContext, this, incomingCall, mLock,
mTimeoutsAdapter, filters).performFiltering();
}
- 这里用到了迭代器模式,一个来电触发三个对象的处理, 最后创建一个IncomingCallFilter并调用performFiltering
public void performFiltering() {
Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED);
for (CallFilter filter : mFilters) {
//遍历调用,依次执行异步查询方法
filter.startFilterLookup(mCall, this);
}
// synchronized to prevent a race on mResult and to enter into Telecom.
mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) { // performFiltering time-out
@Override
public void loggedRun() {
if (mIsPending) {
//超时处理的方法
Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
//回CallsManager中的监听事件
mListener.onCallFilteringComplete(mCall, mResult);
mIsPending = false;
}
}
}.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
}
- 如果没有超时则在异步查询结束后,会通过回调方法将CallFilterResult传回onCallFilteringComplete.,接下来回到CallsManager中进行onCallFilteringComplete处理,正常的话会将Call状态置为ring,并且添加Call,继续跟进addCall
private void addCall(Call call) {
call.addListener(this);
mCalls.add(call);
// Specifies the time telecom finished routing the call. This is used by the dialer for
// analytics.
Bundle extras = call.getIntentExtras();
extras.putLong(TelecomManager.EXTRA_CALL_TELECOM_ROUTING_END_TIME_MILLIS,
SystemClock.elapsedRealtime());
updateCanAddCall();
// onCallAdded for calls which immediately take the foreground (like the first call).
for (CallsManagerListener listener : mListeners) {
//通知监听Call添加的观察者,这里的mListeners在CallsManager初始化的时候就已经添加
listener.onCallAdded(call);
}
/// M: single video call mode
if (MtkUtil.isInSingleVideoCallMode(call)) {
for (Call c : mCalls) {
c.refreshConnectionCapabilities();
}
}
}
- 查看onCallAdded方法,在InCallController中进行了实现。在InCallController的onCallAdded方法中,会调用到IInCallService中的addCall方法,发送出MSG_ADD_CALL消息,然后调用Phone的internalAddCall方法。
final void internalAddCall(ParcelableCall parcelableCall) {
//创建Call
Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);
mCallByTelecomCallId.put(parcelableCall.getId(), call);
//添加到列表中
mCalls.add(call);
checkCallTree(parcelableCall);
call.internalUpdate(parcelableCall, mCallByTelecomCallId);
//调用phone的监听者的onCallAdded
fireCallAdded(call);
}
private void fireCallAdded(Call call) {
for (Listener listener : mListeners) {
listener.onCallAdded(this, call);
}
}
- 在 InCallService 中handleMessage处理MSG_SET_IN_CALL_ADAPTER消息的时候就注册了监听,这里继续跟进到InCallService中的实现去
Private Phone.Listener mPhoneListener = new Phone.Listener()
...
@Override
public void onCallAdded(Phone phone, Call call) {
//调用InCallService对象的onCallAdded方法
InCallService.this.onCallAdded(call);
}
- 这里调用的InCallService中的onCallAdded方法并未实现,而是在子类中进行了实现。
public class InCallServiceImpl extends InCallService
@Override
public void onCallAdded(Call call) {
if ((CallList.getInstance().getVideoUpgradeRequestCall() != null ||
CallList.getInstance().getSendingVideoUpgradeRequestCall() != null ||
/// M: When is cancel upgrade progress,we can't add another call in calllist. @{
CallList.getInstance().getSendingCancelUpgradeRequestCall() != null)
///@}
&& !isEmergency(call)) {
...
} else {
InCallPresenter.getInstance().onCallAdded(call);
}
}
- 从这里开始,就完全属于我们dialer上层来进行处理了,InCallPresenter是InCallUI用于处理通话逻辑的核心类,继续跟进查看onCallAdded方法
public void onCallAdded(final android.telecom.Call call) {
LatencyReport latencyReport = new LatencyReport(call);
if (shouldAttemptBlocking(call)) {
maybeBlockCall(call, latencyReport);
} else {
if (call.getDetails().hasProperty(CallCompat.Details.PROPERTY_IS_EXTERNAL_CALL)) {
mExternalCallList.onCallAdded(call);
} else {
latencyReport.onCallBlockingDone();
//CallList(Call的维护列表)调用onCallAdded
mCallList.onCallAdded(mContext, call, latencyReport);
}
}
// Since a call has been added we are no longer waiting for Telecom to send us a call.
setBoundAndWaitingForOutgoingCall(false, null);
call.registerCallback(mCallCallback);
}
- 调用calllist中的onCallAdded方法
public void onCallAdded(
final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) {
Trace.beginSection("onCallAdded");
...
if (call.getState() == DialerCall.State.INCOMING
|| call.getState() == DialerCall.State.CALL_WAITING) {
//来电调用
onIncoming(call);
} else {
dialerCallListener.onDialerCallUpdate();
}
...
}
- 接着调用onIncoming方法,调用listener的onIncomingCall方法,实质上就是InCallPreSenter的onIncomingCall方法。在这里,会调用startOrFinishUi方法来启动InCallActivity。
private void onIncoming(DialerCall call) {
if (updateCallInMap(call)) {
LogUtil.i("CallList.onIncoming", String.valueOf(call));
}
///M:add for Dual ringing of DSDA. @{
updateIncomingCallList(call);
/// @}
for (Listener listener : mListeners) {
listener.onIncomingCall(call);
}
}