[CS] 来电处理流程

Platform:Android-7.1.1_r22

CS Call来电上报流程

当有来电时,modem会上报CALL_STATE_CHANGED,RIL收到此消息后,会通知GsmCdmaCallTracker进行处理。
由于GsmCdmaCallTracker的构造函数中注册监听call状态改变的事件为EVENT_CALL_STATE_CHANGE,因此RIL上报的call状态改变将会触发EVENT_CALL_STATE_CHANGE事件的处理流程。
GsmCdmaCallTracker.java

public void handleMessage(Message msg) {
......
case EVENT_CALL_STATE_CHANGE:
pollCallsWhenSafe();
......
}

调用父类的方法处理。
通过RIL发起获取当前call的请求。
CallTracker.java
protected void pollCallsWhenSafe() {
mNeedsPoll = true;

if (checkNoOperationsPending()) {
mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
mCi.getCurrentCalls(mLastRelevantPoll);
}
}

取得当前call后,继续在GsmCdmaCallTracker中处理。

public void handleMessage(Message msg) {
......
case EVENT_POLL_CALLS_RESULT:
......
handlePollCalls((AsyncResult)msg.obj);
......
}


protected synchronized void handlePollCalls(AsyncResult ar) {
......


for (int i = 0, curDC = 0, dcSize = polledCalls.size()
; i < mConnections.length; i++) {
// 将取得的当前call转换为DriverCall对象
if (curDC < dcSize) {
dc = (DriverCall) polledCalls.get(curDC);
......
}
......
if (conn == null && dc != null) { // 获取到了新的链接
// Connection appeared in CLCC response that we don't know about
if (mPendingMO != null && mPendingMO.compareTo(dc)) {
......
} else {
......
// 新建Connection
mConnections[i] = new GsmCdmaConnection(mPhone, dc, this, i);
......
if (hoConnection != null) {
......
} else {
// find if the MT call is a new ring or unknown connection
newRinging = checkMtFindNewRinging(dc,i); // 判断是来电还是未知链接
if (newRinging == null) {
......
}
}
}
hasNonHangupStateChanged = true;
} else if (conn != null && dc == null) {
......
}
......
if (newRinging != null) { // 通知有新的来电
mPhone.notifyNewRingingConnection(newRinging);
}
......
// 清空所有断开的call
if (newRinging != null || hasNonHangupStateChanged || hasAnyCallDisconnected) {
internalClearDisconnected();
}
......
updatePhoneState(); // 更新Phone状态
......
if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) {
mPhone.notifyPreciseCallStateChanged(); // 通知Phone状态变化
}
......
}



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

先看mPhone.notifyNewRingingConnection(newRinging)的流程
其会通过GsmCdmaPhone → Phone最终通知PstnIncomingCallNotifier处理EVENT_NEW_RINGING_CONNECTION事件。

PstnIncomingCallNotifier.java

private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case EVENT_NEW_RINGING_CONNECTION:
handleNewRingingConnection((AsyncResult) msg.obj);
break;
......
}
};

对来电进行一些判断,然后就要准备交给telecom处理。

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);
}
}
}

private void sendIncomingCallIntent(Connection connection) {
// 处理来电显示
Bundle extras = new Bundle();
if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED &&
!TextUtils.isEmpty(connection.getAddress())) {
Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri);
}
......
PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
if (handle == null) {
......
} else {
TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
}
}

接下来就通过TelecomManager进入了telecom中,注册新的来电。

TelecomServiceImpl.java

private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
......
mCallIntentProcessorAdapter.processIncomingCallIntent(
mCallsManager, intent);
......
}
}


CallIntentProcessor.java

public static class AdapterImpl implements Adapter {
public void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
CallIntentProcessor.processIncomingCallIntent(callsManager, intent);
}
}

将intent解包,然后再转到CallsManager处理。
static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
......
callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
}




CallsManager.java

void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
......
// 新建Call对象
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 */
);

// 初始化CallInfoImpl对象
call.initAnalytics();
......
// 准备建立Connection
call.startCreateConnection(mPhoneAccountRegistrar);
}


开始建立Connection的流程。
com.android.server.telecom.Call.java

void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
......
mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
phoneAccountRegistrar, mContext);
mCreateConnectionProcessor.process();
}

从这里开始,建立Connection的准备阶段跟拨号的流程基本相同,因此不再赘述。
从下面开始建立来电Connection的流程就跟去电不一样了。
ConnectionService.java

private void createConnection(
......
boolean isUnknown) {
......
Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
: isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
......
mAdapter.handleCreateConnectionComplete(
callId,
request,
new ParcelableConnection(
......
connection.getExtras()));
......
}

建立来电Connection。

TelephonyConnectionService.java

public Connection onCreateIncomingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
ConnectionRequest request) {
......
// 是否为video
int videoState = originalConnection != null ? originalConnection.getVideoState() :
VideoProfile.STATE_AUDIO_ONLY;

Connection connection =
createConnectionFor(phone, originalConnection, false /* isOutgoing */,
request.getAccountHandle(), request.getTelecomCallId(),
request.getAddress(), videoState);
......
}


private TelephonyConnection createConnectionFor(
......
int videoState) {
......
if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
// 建立Connection
returnConnection = new GsmConnection(originalConnection, telecomCallId);
} else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
......
}
if (returnConnection != null) {
// 监听Connection配置完成的事件,在GsmConnection初始化完成后就会被触发
returnConnection.addTelephonyConnectionListener(mTelephonyConnectionListener);
......
}
......
}

Connection现在就已经建立好了,然后接着看ConnectionService.createConnection()中mAdapter.handleCreateConnectionComplete()的流程。
ConnectionServiceAdapter.java

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

IConnectionServiceAdapter在ConnectionServiceWrapper中进行了实现。
ConnectionServiceWrapper.java

private final class Adapter extends IConnectionServiceAdapter.Stub {

@Override
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection) {
......
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection);
......
}
}
然后又调用ConnectionServiceWrapper的handleCreateConnectionComplete()函数。

private void handleCreateConnectionComplete(
String callId,
ConnectionRequest request,
ParcelableConnection connection) {
......
if (connection.getState() == Connection.STATE_DISCONNECTED) {
......
} else {
if (mPendingResponses.containsKey(callId)) {
mPendingResponses.remove(callId)
.handleCreateConnectionSuccess(mCallIdMapper, connection);
}
}
}

mPendingResponses中的对象为com.android.server.telecom.Call,是在CreateConnectionProcessor.attemptNextPhoneAccount()中通过mService.createConnection(mCall, this)添加到mPendingResponses中的。

com.android.server.telecom.Call.java

public void handleCreateConnectionSuccess(
CallIdMapper idMapper,
ParcelableConnection connection) {
......
switch (mCallDirection) {
case CALL_DIRECTION_INCOMING:
......
for (Listener l : mListeners) {
l.onSuccessfulIncomingCall(this);
}
break;
......
}
}

回调到CallsManager,这里会判断是否阻止来电
CallsManager.java

public void onSuccessfulIncomingCall(Call incomingCall) {
......
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();
}

这里用到了3个filter,DirectToVoicemailCallFilter/AsyncBlockCheckFilter/CallScreeningServiceFilter,其中AsyncBlockCheckFilter就是用于黑名单处理的,而DirectToVoicemailCallFilter应该是Voice相关的,CallScreeningServiceFilter不大清楚是干啥的。

IncomingCallFilter.java

public void performFiltering() {
Log.event(mCall, Log.Events.FILTERING_INITIATED);
for (CallFilter filter : mFilters) {
filter.startFilterLookup(mCall, this);
}
......
}

我们这里仅仅看下AsyncBlockCheckFilter的处理流程。
AsyncBlockCheckFilter.java

public void startFilterLookup(Call call, CallFilterResultCallback callback) {
......
this.execute(number);
}

AsyncBlockCheckFilter是一个AsyncTask对象,在doInBackground()中执行给定的任务,其返回的结果将由onPostExecute()处理。

protected Boolean doInBackground(String... params) {
......
return mBlockCheckerAdapter.isBlocked(mContext, params[0]);
......
}

mBlockCheckerAdapter是在CallsManager.onSuccessfulIncomingCall()中新建的BlockCheckerAdapter对象。
BlockCheckerAdapter.java

public boolean isBlocked(Context context, String number) {
return BlockChecker.isBlocked(context, number);
}

最终会通过BlockedNumberProvider来判断来电号码是否在黑名单内,如果在,则返回true。
BlockChecker.java

public static boolean isBlocked(Context context, String phoneNumber) {
......
if (BlockedNumberContract.SystemContract.shouldSystemBlockNumber(
context, phoneNumber)) {
......
isBlocked = true;
}
......
return isBlocked;
}

判断完黑名单后,再转到AsyncBlockCheckFilter.onPostExecute()中处理结果。
根据block的状态创建返回结果,再回调。
AsyncBlockCheckFilter.java

protected void onPostExecute(Boolean isBlocked) {
......
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
);
}
......
mCallback.onCallFilteringComplete(mIncomingCall, result);
......
}

回调到IncomingCallFilter。

IncomingCallFilter.java

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.event(mCall, Log.Events.FILTERING_COMPLETED, mResult);
mListener.onCallFilteringComplete(mCall, mResult);
mIsPending = false;
}
}
}.prepare());
}
}
}

处理结果时,会把DirectToVoicemailCallFilter/AsyncBlockCheckFilter/CallScreeningServiceFilter的结果进行综合。

CallFilteringResult.java
public CallFilteringResult combine(CallFilteringResult other) {
......
return new CallFilteringResult(
shouldAllowCall && other.shouldAllowCall,
shouldReject || other.shouldReject,
shouldAddToCallLog && other.shouldAddToCallLog,
shouldShowNotification && other.shouldShowNotification);
}

当3个filter都处理完成后,最终又回调到CallsManager。
这里会将Call的状态设置为RINGING,并把Call添加到活动的Call列表中。

CallsManager.java

public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
......
if (incomingCall.getState() != CallState.DISCONNECTED &&
incomingCall.getState() != CallState.DISCONNECTING) {
// 设置Call的状态为RINGING
setCallState(incomingCall, CallState.RINGING,
result.shouldAllowCall ? "successful incoming call" : "blocking call");
} else {
......
}

if (result.shouldAllowCall) {
if (hasMaximumRingingCalls()) {
......
} else if (hasMaximumDialingCalls()) {
......
} else {
addCall(incomingCall);
}
} else {
......
}
}

private void addCall(Call call) {
......
// 为Call设置listener,并添加到Call的集合中
call.addListener(this);
mCalls.add(call);
......
for (CallsManagerListener listener : mListeners) {
......
listener.onCallAdded(call);
......
}
......
}

未完待续......

添加call后,会回调InCallController.onCallAdded(),InCallController是在CallsManager的构造函数中初始化并添加到listener中的。

InCallController.java
public void onCallAdded(Call call) {
......
addCall(call); // InCallController中也会跟踪call
......
for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
......
inCallService.addCall(parcelableCall); // AIDL调用InCallServiceBinder
......
}
......
}

InCallServiceBinder.addCall()中未做任何处理,直接发送MSG_ADD_CALL消息给InCallService的Handler处理。

InCallService.java

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


private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
......
switch (msg.what) {
......
case MSG_ADD_CALL:
mPhone.internalAddCall((ParcelableCall) msg.obj); // 到android.telecom.Phone中进行处理
break;
......
}

注意,此Phone并非frameworks/opt/telephony中的Phone对象。
Phone中会把传入的ParcelableCall转换为android.telecom.Call对象进行保存,然后又通过InCallService中的mPhoneListener回调到onCallAdded()。
android.telecom.Phone.java

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);
}
}

InCallService.onCallAdded()的具体实现在其子类InCallServiceImpl中。
InCallServiceImpl.java

public void onCallAdded(Call call) {
InCallPresenter.getInstance().onCallAdded(call);
}


将Call添加到CallList。
InCallPresenter.java

public void onCallAdded(final android.telecom.Call call) {
......
mCallList.onCallAdded(call);
......
}

对于来电,call状态当然是INCOMING,因此调用onIncoming()。
CallList.java

public void onCallAdded(final android.telecom.Call telecomCall) {
......
if (call.getState() == Call.State.INCOMING ||
call.getState() == Call.State.CALL_WAITING) {
onIncoming(call, call.getCannedSmsResponses());
} else {
onUpdate(call);
}
......
}

onIncoming()又回调到InCallPresenter。
public void onIncoming(Call call, List<String> textMessages) {
......
for (Listener listener : mListeners) {
listener.onIncomingCall(call);
}
}


调用startOrFinishUi(),最终启动来电界面。具体过程就略过了。
InCallPresenter.java

public void onIncomingCall(Call call) {
InCallState newState = startOrFinishUi(InCallState.INCOMING);
InCallState oldState = mInCallState;

Log.i(this, "Phone switching state: " + oldState + " -> " + newState);
mInCallState = newState;

for (IncomingCallListener listener : mIncomingCallListeners) {
listener.onIncomingCall(oldState, mInCallState, call);
}
}



















~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


GsmCdmaCallTracker.handlePollCalls()中调用updatePhoneState()

private void updatePhoneState() {
PhoneConstants.State oldState = mState;
if (mRingingCall.isRinging()) {
mState = PhoneConstants.State.RINGING;
} else if (mPendingMO != null ||
......

if (mState == PhoneConstants.State.IDLE && oldState != mState) {
mVoiceCallEndedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
} else if (oldState == PhoneConstants.State.IDLE && oldState != mState) {
// 通知相关监听者Call已经建立起来了
mVoiceCallStartedRegistrants.notifyRegistrants (
new AsyncResult(null, null, null));
}
......
if (mState != oldState) {
// 通知Phone状态变化
mPhone.notifyPhoneStateChanged();
TelephonyMetrics.getInstance().writePhoneState(mPhone.getPhoneId(), mState);
}
}


notifyPhoneStateChanged()会通过GsmCdmaPhone → DefaultPhoneNotifier最终通知到TelephonyRegistry。

TelephonyRegistry.java
public void notifyCallStateForPhoneId(int phoneId, int subId, int state,
String incomingNumber) {
......
// 回调监听了LISTEN_CALL_STATE事件的listener
r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
......
broadcastCallStateChanged(state, incomingNumber, phoneId, subId);
}















 

转载于:https://my.oschina.net/igiantpanda/blog/2222412

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值