博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CS] 来电处理流程
阅读量:6829 次
发布时间:2019-06-26

本文共 16602 字,大约阅读时间需要 55 分钟。

hot3.png

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() {
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 {
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) {
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()) {
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

你可能感兴趣的文章
Origami
查看>>
初试ASP.NET Web API/MVC API(附Demo)
查看>>
人脸识别算法初次了解
查看>>
设计模式(十)组合(结构型)
查看>>
JAVA复制文件最快的算法
查看>>
UICamera(NGUI Event system)原理
查看>>
sudo nopasswd
查看>>
用自己的话描述wcf中的传输安全与消息安全的区别(二)
查看>>
99 Lisp Problems 列表处理(P1~P28)
查看>>
实用图片滑块,传送带,幻灯片效果【附源码】
查看>>
Bluez SPP实现代码分析(转)
查看>>
android中给TextView或者Button的文字添加阴影效果
查看>>
读《被投资人“送”入看守所》一文有感(转)
查看>>
生产环境线上測试的慘淡人生
查看>>
代码阅读分析工具Understand 2.0试用
查看>>
Linux Load average负载详细解释
查看>>
Android多媒体框架图
查看>>
jps命令使用
查看>>
ADC In An FPGA
查看>>
在 Windows上配置NativeScript CLI
查看>>