Android7.0 Phone应用源码分析(二) phone来电流程分析

接上篇博文:Android7.0 Phone应用源码分析(一) phone拨号流程分析

今天我们再来分析下Android7.0 的phone的来电流程

Android7.0 Phone应用源码分析(二) phone来电流程分析

1.1TelephonyFramework

当有来电通知时,首先接收到消息的是Modem层,然后Medoem再上传给RIL层,RIL进程通过sokcet将消息发送给RILJ(framework层的RIL),同样进入RILJ的processResponse方法,根据上一章节去电流程的分析得知,来电属于UnSolicited消息,事件ID是

RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,看看RILJ里的处理

com.android.internal.telephony.RIL
processUnsolicited (Parcel p, int type) {
………………………………
switch(response) {
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p);
        break;
………………………………
}
………………………………
switch(response) {
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
if (RILJ_LOGD) unsljLog(response);
mCallStateRegistrants .notifyRegistrants(new AsyncResult(null, null, null));
break;
………………………………
}
………………………………
}

mCallStateRegistrants是RegistrantList实例,这里用到了观察者模式,mCallStateRegistrants将call状态的变化通知给了所有感兴趣的注册者,BaseCommands提供了相关注册接口

com.android.internal.telephony. registerForCallStateChanged
@Override
public void registerForCallStateChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj); mCallStateRegistrants.add(r);
}
}

最后找到GsmCdmaCallTracker在创建的时候注册了该事件

com.android.internal.telephony. GsmCdmaCallTracker
public GsmCdmaCallTracker (GsmCdmaPhone phone) {
this.mPhone = phone;
mCi = phone.mCi;
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
mCi.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
mCi.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
...... ...... }

收到EVENT_CALL_STATE_CHANGE消息后进入pollCallsWhenSafe方法

protected void pollCallsWhenSafe() {
mNeedsPoll = true; if (checkNoOperationsPending()) {
mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
mCi.getCurrentCalls(mLastRelevantPoll);
}}
}

这里的处理流程跟之前拨号类似,同样是通过RILJ获取当前call状态,收到回应后进入handlePollCalls方法

protected synchronized void handlePollCalls(AsyncResult ar) {
………………………………
if (newRinging != null) { // 新来电通知
mPhone.notifyNewRingingConnection(newRinging);
}
………………………………
updatePhoneState(); // 更新phone状态
………………………………
if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) {
mPhone.notifyPreciseCallStateChanged(); // 发出call状态变化通知 }
}

新来电进入phone的notifyNewRingingConnection的方法

com.android.internal.telephony.Phone
public void notifyNewRingingConnectionP(Connection cn) {
if (!mIsVoiceCapable)
return;
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);}
}

又是一个观察者模式,最后找到是注册了该事件的监听对象PstnIncomingCallNotifier

1.2TelephonyService

com.android.services.telephony. PstnIncomingCallNotifier
private void registerForNotifications() {
if (mPhone != null) {
Log.i(this, "Registering: %s", mPhone);
mPhone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null);
mPhone.registerForCallWaiting(mHandler, EVENT_CDMA_CALL_WAITING, null);
mPhone.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null);
}
}

Handler处理消息进入handleNewRingingConnection方法

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()) {
sendIncomingCallIntent(connection);
}
}
}

获取到call对象以后,最后进入sendIncomingCallIntent

private void sendIncomingCallIntent(Connection connection) {
………………………………
PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
if (handle == null) {
try {
connection.hangup();
} catch (CallStateException e) {
// connection already disconnected. Do nothing
}
} else {
TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
}
}

通过aidl接口调用telecomservice的的addNewIncomingCall方法

1.3 TelecomService

TelecomServiceImpl的成员变量mBinderImpl是具体实现类

com.android.server.telecom.TelecomServiceImpl
private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub(){
public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
………………………………
Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
if (extras != null) {
extras.setDefusable(true);
intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
}
mCallIntentProcessorAdapter.processIncomingCallIntent(mCallsManager, intent); }
……………………………… }

这里调用到的是CallIntentProcessor 的processIncomingCallIntent方法

com.android.server.telecom. CallIntentProcessor
static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
………………………………
Log.d(CallIntentProcessor.class,
"Processing incoming call from connection service [%s]",
phoneAccountHandle.getComponentName());
callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
}

进入callsmanager的processIncomingCallIntent方法

void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
………………………………
Call call = new Call(
getNextCallId(),
mContext,
this,
mLock,
mConnectionServiceRepository,
mContactsAsyncHelper,
mCallerInfoAsyncQueryFactory,
handle,
null /* gatewayInfo */,
null /* connectionManagerPhoneAccount */,
phoneAccountHandle,
Call.CALL_DIRECTION_INCOMING /* callDirection */,
false /* forceAttachToExistingConnection */,
false /* isConference */
);
………………………………
call.addListener(this);
call.startCreateConnection(mPhoneAccountRegistrar);
}

走到这一步,跟之前分析的拨号流程一样,创建了一个call对象,然后调用

startCreateConnection创建连接,根据之前拨号的流程分析最后会进入 ConnectionService的createConnection方法

1.4 TelecommFramework

再把实现代码贴一遍:

private void createConnection(final PhoneAccountHandle callManagerAccount, final String callId, 
             final ConnectionRequest request,  boolean isIncoming,  boolean isUnknown) {
………………………………
Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
: isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
              ………………………………
mAdapter.handleCreateConnectionComplete(
callId,
request,
new ParcelableConnection(
request.getAccountHandle(),
connection.getState(),
connection.getConnectionCapabilities(),
connection.getConnectionProperties(),
connection.getAddress(),
connection.getAddressPresentation(),
connection.getCallerDisplayName(),
connection.getCallerDisplayNamePresentation(),
connection.getVideoProvider() == null ?
null : connection.getVideoProvider().getInterface(),
connection.getVideoState(),
connection.isRingbackRequested(),
connection.getAudioModeIsVoip(),
connection.getConnectTimeMillis(),
connection.getStatusHints(),
connection.getDisconnectCause(),
createIdList(connection.getConferenceables()),
connection.getExtras(),
connection.getUserData()));//MOTO Calling Code - IKPIM-1774 (ftr 33860)
if (isUnknown) {
triggerConferenceRecalculate();
}
}

这里由于是来电,所以调用onCreateIncomingConnection方法,该方法同样返回null,所以具体是由其子类实现的,也就是TelephonyConnectionService

public Connection onCreateIncomingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
ConnectionRequest request) { Connection connection = createConnectionFor(phone, originalConnection, false /* isOutgoing */,
request.getAccountHandle(), request.getTelecomCallId(),
request.getAddress());
if (connection == null) {
return Connection.createCanceledConnection();
} else {
return connection;
}
}

最后根据GMS或是CDMA返回对应Connection对象,最后进入ConnectionServiceAdapter处理

android.telecom. ConnectionServiceAdapter
void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection connection) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.handleCreateConnectionComplete(id, request, connection);
} catch (RemoteException e) {
}
}
}

这里的adapter实际上就是ConnectionServiceWrapper的内部类Adapter,需要注意的是之前拨号的时候创建完connection并呼出之后,后续也会走到这个流程里

public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection) {
Log.startSession("CSW.hCCC");
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("handleCreateConnectionComplete %s", callId);
ConnectionServiceWrapper.this
handleCreateConnectionComplete(callId, request, connection);
}
} finally {
Binder.restoreCallingIdentity(token);
Log.endSession();
}
}

最后进入handleCreateConnectionComplete方法

private void handleCreateConnectionComplete(
String callId,
ConnectionRequest request,
ParcelableConnection connection) {
// TODO: Note we are not using parameter "request", which is a side effect of our tacit
// assumption that we have at most one outgoing connection attempt per ConnectionService.
// This may not continue to be the case.
if (connection.getState() == Connection.STATE_DISCONNECTED) {
// A connection that begins in the DISCONNECTED state is an indication of
// failure to connect; we handle all failures uniformly
removeCall(callId, connection.getDisconnectCause());
} else {
// Successful connection
if (mPendingResponses.containsKey(callId)) {
mPendingResponses.remove(callId).handleCreateConnectionSuccess(mCallIdMapper, connection);
}
}
}

这里的mPendingResponses是map容器

private final Map<String, CreateConnectionResponse> mPendingResponses = new HashMap<>();

ConnectionServiceWrapper在调用createConnection的时候会往该容器里添加对象,也就是CreateConnectionProcessor对象

public void handleCreateConnectionSuccess(
CallIdMapper idMapper,
ParcelableConnection connection) {
if (mCallResponse == null) {
// Nobody is listening for this connection attempt any longer; ask the responsible
// ConnectionService to tear down any resources associated with the call
mService.abort(mCall);
} else {
// Success -- share the good news and remember that we are no longer interested
// in hearing about any more attempts
mCallResponse.handleCreateConnectionSuccess(idMapper, connection);
mCallResponse = null;
// If there's a timeout running then don't clear it. The timeout can be triggered
// after the call has successfully been created but before it has become active.
}
}

这个mCallResponse是CreateConnectionProcessor创建的时候引入的,也就是call对象

com.android.server.telecom.Call
public void handleCreateConnectionSuccess(
CallIdMapper idMapper,
ParcelableConnection connection) { switch (mCallDirection) {
case CALL_DIRECTION_INCOMING: for (Listener l : mListeners) {
l.onSuccessfulIncomingCall(this);
}
break;
case CALL_DIRECTION_OUTGOING:
for (Listener l : mListeners) {
l.onSuccessfulOutgoingCall(this,
getStateFromConnectionState(connection.getState()));
}
break;
case CALL_DIRECTION_UNKNOWN:
for (Listener l : mListeners) {
l.onSuccessfulUnknownCall(this, getStateFromConnectionState(connection .getState()));
}
break;
}
}

这里根据是来电还是去电类型,执行相应回调,监听者会收到通知,来电事件则触发onSuccessfulIncomingCall的回调

1.5 TelecommService

前面提到CallsManager在执行processIncomingCallIntent方法时候会创建call,之后就会给call添加监听,所以最后会回调到CallsManager类

public void onSuccessfulIncomingCall(Call incomingCall) {
Log.d(this, "onSuccessfulIncomingCall");
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,
mDefaultDialerManagerAdapter,
new ParcelableCallUtils.Converter(), mLock));
new

IncomingCallFilter

(mContext, this, incomingCall, mLock,
mTimeoutsAdapter, filters).performFiltering();
}

这里用到了一个迭代器模式,一个来电操作触发这三个对象的处理:

DirectToVoicemailCallFilter,AsyncBlockCheckFilter,CallScreeningServiceFilter

生成一个IncomingCallFilter对象,调用performFiltering方法

com.android.server.telecom.callfiltering. IncomingCallFilter
public void performFiltering() {
Log.event(mCall, Log.Events.FILTERING_INITIATED);
for (CallFilter filter : mFilters) {
filter.startFilterLookup(mCall, this);
}
mHandler.postDelayed(new Runnable("ICF.pFTO") { // performFiltering time-out
@Override
public void loggedRun() {
// synchronized to prevent a race on mResult and to enter into Telecom.
synchronized (mTelecomLock) {
if (mIsPending) {
Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
Log.event(mCall, Log.Events.FILTERING_TIMED_OUT);
mListener.onCallFilteringComplete(mCall, mResult);
mIsPending = false;
}
}
}
}.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
}

他们依次执行startFilterLookup异步查询方法,通过回调方法并将结果CallFilteringResult传回onCallFilteringComplete将CallFilteringResult对象传递回来

public class CallFilteringResult {

    public boolean shouldAllowCall;          // 是否允许通话
public boolean shouldReject; // 是否拒接
public boolean shouldAddToCallLog; // 是否添加至通话记
public boolean shouldShowNotification; // 是否显示通知栏消息
………………………………
………………………………
} public void onCallFilteringComplete(Call call, CallFilteringResult result) {
synchronized (mTelecomLock) { // synchronizing to prevent race on mResult
mNumPendingFilters--;
mResult = result.combine(mResult);
if (mNumPendingFilters == 0) {
mHandler.post(new Runnable("ICF.oCFC") {
@Override
public void loggedRun() {
// synchronized to enter into Telecom.
synchronized (mTelecomLock) {
if (mIsPending) {
mListener.onCallFilteringComplete(mCall, mResult);
mIsPending = false;
}
}
}
}.prepare());
}
}
}

先看看DirectToVoicemailCallFilter对象,它处理的是voicemail相关信息,

实际上是由CallerInfoLookupHelper完成查询的,内部调用CallerInfoAsyncQueryFactory的startQuery方法,而CallerInfoAsyncQueryFactory是个接口类,在CallsManager创建的时候由外部传参进来,最后找到是TelecomService的initializeTelecomSystem里创建的

com.android.server.telecom.components. TelecomService
static void initializeTelecomSystem(Context context) {
new CallerInfoAsyncQueryFactory() {
@Override
public CallerInfoAsyncQuery startQuery(
int token, Context context, String number,
CallerInfoAsyncQuery.OnQueryCompleteListener listener,
Object cookie) {
Log.i(TelecomSystem.getInstance(),
"CallerInfoAsyncQuery.startQuery number=%s cookie=%s",
Log.pii(number), cookie);
return CallerInfoAsyncQuery.startQuery(
token, context, number, listener, cookie);
}
}

进入CallerInfoAsyncQuery的startQuery方法

com.android.internal.telephony.CallerInfoAsyncQuery
public static CallerInfoAsyncQuery startQuery(int token, Context context, String number,
OnQueryCompleteListener listener, Object cookie, int subId) { final Uri contactRef = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
.appendPath(number)
.appendQueryParameter(PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS,
String.valueOf(PhoneNumberUtils.isUriNumber(number)))
.build();
}

查询的uri是PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI

返回cursor结果集后转化成CallerInfo,其中shouldSendToVoicemail变量查询的

是PhoneLookup.SEND_TO_VOICEMAIL字段

public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) {
...... ......
...... ......
columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL);
info.shouldSendToVoicemail = (columnIndex != -1) &&
((cursor.getInt(columnIndex)) == 1);
info.contactExists = true;
...... ......
}

最后回到DirectToVoicemailCallFilter的查询回调,shouldSendToVoicemail为true时表示允许通话,否则是拒接

if (info.shouldSendToVoicemail) {
result = new CallFilteringResult(
false, // shouldAllowCall
true, // shouldReject
true, // shouldAddToCallLog
true // shouldShowNotification
);
} else {
result = new CallFilteringResult(
true, // shouldAllowCall
false, // shouldReject
true, // shouldAddToCallLog
true // shouldShowNotification
);
}
}

再看看AsyncBlockCheckFilter,它处理的是黑名单事件

判断一个电话号码是否在黑名单里调用到了BlockChecker的isBlocked方法

com.android.internal.telephony. BlockChecker
public static boolean isBlocked(Context context, String phoneNumber) {
boolean isBlocked = false;
long startTimeNano = System.nanoTime(); try {
if (BlockedNumberContract.SystemContract.shouldSystemBlockNumber(
context, phoneNumber)) {
Rlog.d(TAG, phoneNumber + " is blocked.");
isBlocked = true;
}
} catch (Exception e) {
Rlog.e(TAG, "Exception checking for blocked number: " + e);
} int durationMillis = (int) ((System.nanoTime() - startTimeNano) / 1000000);
if (durationMillis > 500 || VDBG) {
Rlog.d(TAG, "Blocked number lookup took: " + durationMillis + " ms.");
}
return isBlocked;
}

BlockedNumberContract.SystemContract是framework里的一个黑名单协议类

public static final String AUTHORITY = "com.android.blockednumber";
public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER =
"should_system_block_number"; public static boolean shouldSystemBlockNumber(Context context, String phoneNumber) {
final Bundle res = context.getContentResolver().call(
AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, null);
return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
}

黑名单是BlockedNumberProvider数据库, 调用call方法

com.android.providers.blockednumber. BlockedNumberProvider
@Override
public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) {
final Bundle res = new Bundle();
switch (method) {
case SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER:
enforceSystemReadPermissionAndPrimaryUser();
res.putBoolean(
BlockedNumberContract.RES_NUMBER_IS_BLOCKED, shouldSystemBlockNumber(arg));
break;
............
............
} } private boolean shouldSystemBlockNumber(String phoneNumber) {
if (getBlockSuppressionStatus().isSuppressed) {
return false;
}
if (isEmergencyNumber(phoneNumber)) {
return false;
} return isBlocked(phoneNumber);
}

最后调用isBlocked方法查询blocked表中是否存在该number

查询得到结果后返回

CallFilteringResult result;
if (isBlocked) {
result = new CallFilteringResult(
false, // shouldAllowCall
true, //shouldReject
false, //shouldAddToCallLog
false // shouldShowNotification
);
} else {
result = new CallFilteringResult(
true, // shouldAllowCall
false, // shouldReject
true, // shouldAddToCallLog
true // shouldShowNotification
);
}

如果号码在黑名单里则拦截

最后是CallScreeningServiceFilter不知道是处理什么,内部绑定一个抽象服务

CallScreeningService但是却找不到哪个子类继承了它,这里先忽略它

回到前面IncomingCallFilter的onCallFilteringCompletev方法,结果集会做个逻辑运算

mResult = result.combine(mResult);看看它的实现

com.android.server.telecom.callfilteringCallFilteringResult
public CallFilteringResult combine(CallFilteringResult other) {
if (other == null) {
return this;
} return new CallFilteringResult(
shouldAllowCall && other.shouldAllowCall,
shouldReject || other.shouldReject,
shouldAddToCallLog && other.shouldAddToCallLog,
shouldShowNotification && other.shouldShowNotification);
}

只有三个过滤结果都是允许通话才允许通话,添加至通话记录以及是否显示到通知栏同理

当然这里的查询操作也有超时限制,时间是5秒,超过5秒后忽略还未查询到的过滤器则被忽略mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));

最后过滤结果被回调到CallsManager的onCallFilteringComplete

public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
………………………………
if (incomingCall.getState() != CallState.DISCONNECTED &&
incomingCall.getState() != CallState.DISCONNECTING) {
setCallState(incomingCall, CallState.RINGING,
result.shouldAllowCall

? "successful incoming call" : "blocking call"

);
} else {
Log.i(this, "onCallFilteringCompleted: call already disconnected.");
} if (result.shouldAllowCall) {
if (hasMaximumRingingCalls()) {
rejectCallAndLog(incomingCall);
} else if (hasMaximumDialingCalls()) {
rejectCallAndLog(incomingCall);
} else {
addCall(incomingCall);
}
} else {
if (result.shouldReject) {
incomingCall.reject(false, null);
}
if (result.shouldAddToCallLog) { mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
result.shouldShowNotification);
} else if (result.shouldShowNotification) { mMissedCallNotifier.showMissedCallNotification(incomingCall);
}
}
}

调用setCallState设置通话状态为CallState.RINGING,接着判断是否拒接,是否写入通话记录等, 正常情况下调用addCall方法

private void addCall(Call call) {
………………………………
updateCallsManagerState();
// onCallAdded for calls which immediately take the foreground (like the first call).
for (CallsManagerListener listener : mListeners) {
if (Log.SYSTRACE_DEBUG) {
Trace.beginSection(listener.getClass().toString() + " addCall");
}
listener.onCallAdded(call);
if (Log.SYSTRACE_DEBUG) {
Trace.endSection();
}
}
Trace.endSection();
}

遍历回调监听者的onCallAdded方法,InCallController是其中一个观察者,看看它的实现

com.android.server.telecom. InCallController
@Override
public void onCallAdded(Call call) {
if (!isBoundToServices()) {
bindToServices(call);
} else {
adjustServiceBindingsForEmergency();
Log.i(this, "onCallAdded: %s", call);
// Track the call if we don't already know about it.
addCall(call);
for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
ComponentName componentName = entry.getKey();
IInCallService inCallService = entry.getValue();
ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
true,mCallsManager.getPhoneAccountRegistrar());
try {
inCallService.addCall(parcelableCall);
} catch (RemoteException ignored) {
}
}
}
}

这里的inCallService是个aidl接口,抽象服务InCallService的嵌套类InCallServiceBinder 实现了该接口

1.6 TelecommFramework

android.telecom. InCallService
private final class InCallServiceBinder extends IInCallService.Stub {
@Override
public void addCall(ParcelableCall call) {
mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
}
...... ......
...... ......
}

handle对象处理消息MSG_ADD_CALL

private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
case MSG_ADD_CALL:
mPhone.internalAddCall((ParcelableCall) msg.obj);
break;
}
} candroid.telecom.Phone
final void internalAddCall(ParcelableCall parcelableCall) {
Call call

= new Call(this

, parcelableCall.getId(), mInCallAdapter,
parcelableCall.getState());
mCallByTelecomCallId.put(parcelableCall.getId(), call);
mCalls.add(call);
checkCallTree(parcelableCall);
call.internalUpdate(parcelableCall, mCallByTelecomCallId);
fireCallAdded(call);
} private void fireCallAdded(Call call) {
for (Listener listener : mListeners) {
listener.onCallAdded(this, call);
}
}

mPhone对象内部新建了一个call对象,获取并转化ParcelableCall的相关信息,并将call对象加入列表,最后回调Phone的监听者的onCallAdded方法,这里就是InCallService的

mPhoneListener成员变量

private Phone.Listener mPhoneListener = new Phone.Listener() {
/** ${inheritDoc} */
...... ...... /** ${inheritDoc} */
@Override
public void onCallAdded(Phone phone, Call call) {
InCallService.this.onCallAdded(call);
}
...... ......
};

这里InCallService的onCallAdded方法是一个抽象方法,具体实现在它的子类

1.7 Dialer

InCallServiceImpl继承了InCallService,该服务在Dialer工程的manifest文件里有声明

<service android:name="com.android.incallui.InCallServiceImpl"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:directBootAware="true" >
<meta-data android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true" />
<meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
android:value="false"/>
<intent-filter>
<action android:name="

android.telecom.InCallService

"/>
</intent-filter>
</service>

看看InCallServiceImpl的onCallAdded方法

com.android.incallui. InCallServiceImpl
@Override
public void onCallAdded(Call call) {
InCallPresenter.getInstance().onCallAdded(call);
}

InCallPresenter是incallui用于处理通话逻辑的核心类,内部就是各种业务逻辑操作,看看onCallAdded方法

com.android.incallui. InCallPresenter
public void onCallAdded(final android.telecom.Call call) {
if (shouldAttemptBlocking(call)) {
maybeBlockCall(call);
} else {
mCallList.onCallAdded(call);
} // Since a call has been added we are no longer waiting for Telecom to send us a call.
setBoundAndWaitingForOutgoingCall(false, null);
call.registerCallback(mCallCallback);
}

mCallList维护了call列表

com.android.incallui.CallList
public void onCallAdded(final android.telecom.Call telecomCall) {
Trace.beginSection("onCallAdded");
final Call call = new Call(telecomCall);
Log.d(this, "onCallAdded: callState=" + call.getState()); if (call.getState() == Call.State.INCOMING ||
call.getState() == Call.State.CALL_WAITING) {
onIncoming(call, call.getCannedSmsResponses());
} else {
onUpdate(call);
} call.logCallInitiationType();
Trace.endSection();
}

来电则调用onIncoming方法,其它call状态则调用onUpdate方法,具体过程这里就不详述了,最终incallui拉起来电界面显示,至此,一个来电的整体流程都分析完了,大致流程如下:

RIL→TelephonyFramework →TeleponyService→ TeleComService→

TeleComFramework→ TeleComService→TeleComFramework-->InCallUI

Android7.0 Phone应用源码分析(二) phone来电流程分析

下一章节:Android7.0 Phone应用源码分析(三) phone拒接流程分析

上一篇:创建第一个Android 5.0应用程序


下一篇:ExecutorService中submit和execute的区别