Telecomm Service
这里我们可以看出CallsManager的管理作用,创建Calls并添加监听,在完成Call的相关初始化后进行进一步处理,其实就是传递消息到别的的地方去。
1.那么继续到CallsManager中跟进
@Override
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();
}
2.这里用到了迭代器模式,一个来电触发三个对象的处理,
最后创建一个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()));
}
3.如果没有超时则在异步查询结束后,会通过回调方法将CallFilterResult传回onCallFilteringComplete.
public void onCallFilteringComplete(Call call, CallFilteringResult result) {
synchronized (mTelecomLock) { // synchronizing to prevent race on mResult
mNumPendingFilters--;
//对之前三种过滤查询结果进行运算,满足条件才可以通话
//这里不对三种过滤器具体分析,有兴趣的可以进一步分析
mResult = result.combine(mResult);
if (mNumPendingFilters == 0) {
// synchronized on mTelecomLock to enter into Telecom.
mHandler.post(new Runnable("ICF.oCFC", mTelecomLock) {
@Override
public void loggedRun() {
if (mIsPending) {
Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, mResult);
//继续回调
mListener.onCallFilteringComplete(mCall, mResult);
mIsPending = false;
}
}
}.prepare());
}
}
}
4.回到CallsManager中进行onCallFilteringComplete处理
@Override
public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
...
if (incomingCall.getState() != CallState.DISCONNECTED &&
incomingCall.getState() != CallState.DISCONNECTING &&
incomingCall.getState() != CallState.ACTIVE) {
//设置Call状态为Ring
setCallState(incomingCall, CallState.RINGING,
result.shouldAllowCall ? "successful incoming call" : "blocking call");
} else {
Log.i(this, "onCallFilteringCompleted: call already disconnected.");
return;
}
if (result.shouldAllowCall) {
if (MtkUtil.isInSingleVideoCallMode(incomingCall)) {
...
}
if (hasMaximumManagedRingingCalls(incomingCall)) {
if (shouldSilenceInsteadOfReject(incomingCall)) {
incomingCall.silence();
} else {
Log.i(this, "onCallFilteringCompleted: Call rejected! " +
"Exceeds maximum number of ringing calls.");
rejectCallAndLog(incomingCall);
}
} else {
//添加Call
addCall(incomingCall);
}
} else {
if (result.shouldReject) {
Log.i(this, "onCallFilteringCompleted: blocked call, rejecting.");
incomingCall.reject(false, null);
}
if (result.shouldAddToCallLog) {
Log.i(this, "onCallScreeningCompleted: blocked call, adding to call log.");
if (result.shouldShowNotification) {
Log.w(this, "onCallScreeningCompleted: blocked call, showing notification.");
}
//添加通话记录
mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
result.shouldShowNotification);
} else if (result.shouldShowNotification) {
Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
mMissedCallNotifier.showMissedCallNotification(
new MissedCallNotifier.CallInfo(incomingCall));
}
}
}
5.正常的话会将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添加的观察者
listener.onCallAdded(call);
}
/// M: single video call mode
if (MtkUtil.isInSingleVideoCallMode(call)) {
for (Call c : mCalls) {
c.refreshConnectionCapabilities();
}
}
}
6.查看监听Call添加的观察者
在CallsManager构造函数初始化的时候添加了一些列观察者,还有就是通过addListener去添加的。
mListeners.add(mInCallWakeLockController);
mListeners.add(statusBarNotifier);
mListeners.add(mCallLogManager);
mListeners.add(mPhoneStateBroadcaster);
mListeners.add(mInCallController);
mListeners.add(mCallAudioManager);
mListeners.add(missedCallNotifier);
mListeners.add(mHeadsetMediaButton);
mListeners.add(mProximitySensorManager);
...
mListeners.add(new CallConnectedVibrator(mContext));
这里我们继续跟进mInCallController,
@Override
public void onCallAdded(Call call) {
if (!isBoundAndConnectedToServices()) {
bindToServices(call);
} else {
// We are bound, and we are connected.
adjustServiceBindingsForEmergency();
// This is in case an emergency call is added while there is an existing call.
mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(call,
mCallsManager.getCurrentUserHandle());
//添加Call
addCall(call);
List<ComponentName> componentsUpdated = new ArrayList<>();
for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
InCallServiceInfo info = entry.getKey();
if (call.isExternalCall() && !info.isExternalCallsSupported()) {
continue;
}
if (call.isSelfManaged() && !info.isSelfManagedCallsSupported()) {
continue;
}
// Only send the RTT call if it's a UI in-call service
boolean includeRttCall = info.equals(mInCallServiceConnection.getInfo());
componentsUpdated.add(info.getComponentName());
IInCallService inCallService = entry.getValue();
ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
info.isExternalCallsSupported(), includeRttCall);
try {
//AIDL调用远程的addCall方法
inCallService.addCall(parcelableCall);
} catch (RemoteException ignored) {
}
}
Log.i(this, "Call added to components: %s", componentsUpdated);
}
}
Telecomm Framework
7.继续查找IInCallService的实现,跟进addCall方法
/** Manages the binder calls so that the implementor does not need to deal with it. */
private final class InCallServiceBinder extends IInCallService.Stub {
@Override
public void setInCallAdapter(IInCallAdapter inCallAdapter) {
mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
}
@Override
public void addCall(ParcelableCall call) {
mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
}
8.继续跟进MSG_SET_IN_CALL_ADAPTER消息的处理
public void handleMessage(Message msg) {
switch (msg.what) {
...
case MSG_ADD_CALL:
mPhone.internalAddCall((ParcelableCall) msg.obj);
...
9.继续跟进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);
}
}
10.在 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);
}
...
可以看到这其实是个空实现,具体实现是在子类中,继续跟进到子类中分析
Dialer
11.查找InCallService的子类
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下的inCallUI了,这就到dialer层了,如果查看Diler的清单文件可以发现其有android.telecom.InCallService声明
12.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);
}
13.继续跟进mCallList
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();
}
...
}
最终调用其InCall的来电界面,这里就不再继续详细分析了。
本系列的来电显示流程参考了以下博客,
https://www.cnblogs.com/lance2016/p/6035351.html,
结合自己的理解做了一些分析,有错误和缺漏的欢迎指出,可以看到android O对于RIL层往上的Telephony架构的修改不大。
来电流程时序图