Android TelecomService的来电处理过程
Posted Jason_Wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android TelecomService的来电处理过程相关的知识,希望对你有一定的参考价值。
在上一篇文章里,讲到了TelecomService的启动与初始化,这里我们着重以来电(Mobile Terminal)过程来分析一下TelecomService是如何传递通话信息并最终与上层UI交互的。主要分以下几个部分:
- 来电后,Telephony中间层如何将通话通知到TelecomService;
- TelecomService如何建立通话连接;
- TelecomService如何告知UI来电信息
TelecomService的初始化过程:http://blog.csdn.net/jason_wzn/article/details/58164251
下图是来电在Telecom服务中的处理流程,可以让我们对整个流程有个感性的认识。
Telephony将来电通知TelcomService
Phone进程初始化时,会创建两个CALL相关的通知类PstnIncomingCallNotifier
(接受来电相关的信息)以及PstnCallNotifier
(主要用于处理CDMA相关的来电信息)用于向TelecomService
发送来电信息:
public class TelephonyGlobals
private static TelephonyGlobals sInstance;
....
public void onCreate()
// Make this work with Multi-SIM devices
Phone[] phones = PhoneFactory.getPhones();
for (Phone phone : phones)
mTtyManagers.add(new TtyManager(mContext, phone));
//添加Telecom账户(通话相关的数据管理)
TelecomAccountRegistry.getInstance(mContext).setupOnBoot();
AdvancedEmergencyManager.getInstance(mContext).setupOnBoot();
初始化Telecom通话相关的账号,每个账号都包含了一个PstnIncomingCallNotifier
成员对象:
final class TelecomAccountRegistry
private List<AccountEntry> mAccounts = new LinkedList<AccountEntry>();
AccountEntry(Context context, Phone phone, boolean isEmergency, boolean isDummy)
mPhone = phone;
mIsEmergency = isEmergency;
mIsDummy = isDummy;
// 创建用于通话的PhoneAccount
mAccount = registerPstnPhoneAccount(isEmergency, isDummy);
// 来电通知类,有来电时CallManager会通知它
mIncomingCallNotifier = new PstnIncomingCallNotifier((Phone) mPhone);
mPhoneCapabilitiesNotifier = new PstnPhoneCapabilitiesNotifier((Phone) mPhone,
this);
mPstnCallNotifier = new PstnCallNotifier(context, (Phone) mPhone);
/**
* Sets up all the phone accounts for SIMs on first boot.
*/
void setupOnBoot()
// setup accounts immediately on boot if it's encryption mode or airplane mode.
setupOnBootImmediately();
....
private void setupOnBootImmediately()
if ((TeleServiceFeature.hasFeature(TeleServiceFeature.MultiSIM.FEATURE_MULTISIM)
|| TeleServiceFeature.hasFeature(TeleServiceFeature.Function.SUPPORT_WFC))
&& (PhoneUtils.isEncryptionMode() || PhoneUtils.isAirplaneModeOn()))
Log.i(this, "setupOnBootImmediately");
//创建PhoneAccount
setupAccounts();
//创建通话相关的PhoneAccount
private void setupAccounts()
Phone[] phones = PhoneFactory.getPhones();
Log.d(this, "Found %d phones. Attempting to register.", phones.length);
final boolean phoneAccountsEnabled = mContext.getResources().getBoolean(
R.bool.config_pstn_phone_accounts_enabled);
synchronized (mAccountsLock)
if (phoneAccountsEnabled)
for (Phone phone : phones)
int subscriptionId = phone.getSubId();
//创建新的PhoneAccount
if ((subscriptionId >= 0 && PhoneUtils.getFullIccSerialNumber(phone) != null)
|| TeleServiceFeature.hasFeature(TeleServiceFeature.MultiSIM.FEATURE_MULTISIM))
mAccounts.add(new AccountEntry(mContext, phone, false /* emergency */,
false /* isDummy */));
// 注册PhoneAccount用于紧急拨号
if (mAccounts.isEmpty())
Log.w(this, "adding account for emergency ");
mAccounts.add(new AccountEntry(mContext, PhoneFactory.getDefaultPhone(), true /* emergency */,
false /* isDummy */));
....
这里创建的PhoneAccount对象的ComponetName是:
ComponentName PSTN_CONNECTION_SERVICE_COMPONENT = new ComponentName("com.android.phone","com.android.services.telephony.TelephonyConnectionService")
;
在绑定Telephony层的通话连接服务时需要用到该组件名
创建PstnIncomingCallNotifier
来电通知对象:
final class PstnIncomingCallNotifier
/** The phone object to listen to. */
private final Phone mPhone;
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;
....
default:
break;
;
PstnIncomingCallNotifier(Phone phone)
Preconditions.checkNotNull(phone);
mPhone = phone;
registerForNotifications();
// 监听Phone(由PhoneFactory创建)中的事件
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);
mPhone.registerForSuppServiceNotification(mHandler, EVENT_SUPP_SERVICE_NOTIFY, null);
上述初始化过程准备完后,Telecom就可以收到来自Phone进程的来电信息了:只要telephony中有来电,Phone
就会发送消息到PstnIncomingCallNotifier
中的线程消息队列,由Handler
对消息进行处理:
final class PstnIncomingCallNotifier
private void handleNewRingingConnection(AsyncResult asyncResult)
//通话连接,里边包含了所有来电的信息
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())
PhoneUtils.hideMmiDialog();
// 告知Telecom来电信息
sendIncomingCallIntent(connection);
// 将来电信息发送给Telecom
private void sendIncomingCallIntent(Connection connection)
Bundle extras = TelephonyConnectionUtils.makeIncomingSecCallExtra(mPhone.getContext(), connection);
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);
//查找mPhone对应的PhoneAccountHandle对象
PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
if (handle == null)
try
connection.hangup();
catch (CallStateException e)
// connection already disconnected. Do nothing
else
// 向TelecomService发送来电信息
TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
TelecomService建立通话连接
调用TelecomManager的接口addNewIncomingCall
,发送IPC请求到TelecomService
,告知其由来电信息:
public class TelecomManager
private ITelecomService getTelecomService()
if (mTelecomServiceOverride != null)
return mTelecomServiceOverride;
return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));
public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras)
try
if (isServiceConnected())
// 调用TelecomServiceImpl的IBinder接口添加来电信息
getTelecomService().addNewIncomingCall(
phoneAccount, extras == null ? new Bundle() : extras);
catch (RemoteException e)
Log.e(TAG, "RemoteException adding a new incoming call: " + phoneAccount, e);
在TelecomService
绑定时,我们了解到,实际注册到系统的IBinder
接口是getTelecomServiceImpl().getBinder()
,即TelecomServiceImpl
中的一个服务端实现:
public class TelecomServiceImpl
private final CallIntentProcessor.Adapter mCallIntentProcessorAdapter;
private CallsManager mCallsManager;
public ITelecomService.Stub getBinder()
return mBinderImpl;
// ITelecomService.aidl接口的实现
private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub()
public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras)
try
synchronized (mLock)
if (phoneAccountHandle != null &&
phoneAccountHandle.getComponentName() != null)
....
TelecomUtils.boostCPU();
long token = Binder.clearCallingIdentity();
try
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);
//调用CallIntentProcessor的Adapter接口处理来电intent
mCallIntentProcessorAdapter.processIncomingCallIntent(
mCallsManager, intent);
finally
Binder.restoreCallingIdentity(token);
finally
Log.endSession();
调用CallIntentProcessor的Adapter接口处理来电intent:
public class CallIntentProcessor
public interface Adapter
void processOutgoingCallIntent(Context context, CallsManager callsManager,
Intent intent);
void processIncomingCallIntent(CallsManager callsManager, Intent intent);
void processUnknownCallIntent(CallsManager callsManager, Intent intent);
public static class AdapterImpl implements Adapter
@Override
public void processIncomingCallIntent(CallsManager callsManager, Intent intent)
CallIntentProcessor.processIncomingCallIntent(callsManager, intent);
....
static void processIncomingCallIntent(CallsManager callsManager, Intent intent)
PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
....
Bundle clientExtras = null;
if (intent.hasExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS))
clientExtras = intent.getBundleExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS);
//调用CallsManager处理来电信息
callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
调用CallsManager
的接口,创建一个Call
对象,并着手建立与ConnectionService
之间的连接:
public class CallsManager extends Call.ListenerBase
implements VideoProviderProxy.Listener, CallFilterResultCallback
void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras)
mIsIncomingPreProcessing = true;
// 获取来电号码
Uri handle = extras.getParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS);
// 新建一个Call对象表示来电信息
Call call = TelecomUtils.makeCall(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 */), extras
);
call.addListener(this);
call.startCreateConnection(mPhoneAccountRegistrar);
// Set current calling subscription as default subscription
changeDefaultVoiceSubId(call, false, false, null);
创建Call
对象后,将其发送给CreateConnectionProcessor
进一步处理,
public class Call implements CreateConnectionResponse
....
void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar)
if (mCreateConnectionProcessor != null)
Log.w(this, "mCreateConnectionProcessor in startCreateConnection is not null. This is" +
" due to a race between NewOutgoingCallIntentBroadcaster and " +
"phoneAccountSelected, but is harmlessly resolved by ignoring the second " +
"invocation.");
return;
mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
phoneAccountRegistrar, mContext);
mCreateConnectionProcessor.process();
得到一个Call
对象后,CreateConnectionProcessor
负责检查所有PhoneAccount中是否有需要处理的通话,CallAttemptRecord
中保存了维持一路通话的所有信息:
public class CreateConnectionProcessor implements CreateConnectionResponse
private final ConnectionServiceRepository mRepository;
private ConnectionServiceWrapper mService;
....
public void process()
Log.v(this, "process");
clearTimeout();
mAttemptRecords = new ArrayList<>();
if (mCall.getTargetPhoneAccount() != null)
mAttemptRecords.add(new CallAttemptRecord(
mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
adjustAttemptsForConnectionManager();
adjustAttemptsForEmergency(mCall.getTargetPhoneAccount());
mAttemptRecordIterator = mAttemptRecords.iterator();
// 处理下一个PhoneAccount
attemptNextPhoneAccount();
// 检查下一个PhoneAccount是否有一路通话请求
private void attemptNextPhoneAccount()
CallAttemptRecord attempt = null;
if ((mAttemptRecordIterator != null) && mAttemptRecordIterator.hasNext())
attempt = mAttemptRecordIterator.next();
if (mCallResponse != null && attempt != null)
PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
// 从通话连接服务池中搜索相应的连接服务(该连接服务池在CallsManager中创建)
mService = mRepository.getService(phoneAccount.getComponentName(),
phoneAccount.getUserHandle());
if (mService == null)
Log.i(this, "Found no connection service for attempt %s", attempt);
attemptNextPhoneAccount();
else
mConnectionAttempt++;
mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
mCall.setConnectionService(mService);
setTimeoutIfNeeded(mService, attempt);
// 创建一路通话链接
mService.createConnection(mCall, this);
else
Log.v(this, "attemptNextPhoneAccount, no more accounts, failing");
DisconnectCause disconnectCause = mLastErrorDisconnectCause != null ?
mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR);
notifyCallConnectionFailure(disconnectCause);
准备绑定CALL APP中的ConnectionService
服务,并且设置回调函数,这里Binder2
是ServiceBinder
中的私有类,
public class ConnectionServiceWrapper extends ServiceBinder
private final class Adapter extends IConnectionServiceAdapter.Stub
// 通话连接成功后的回调接口
@Override
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection)
try
synchronized (mLock)
logIncoming("handleCreateConnectionComplete %s", callId);
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection);
finally
Binder.restoreCallingIdentity(token);
Log.endSession();
....
ConnectionServiceWrapper(
ComponentName componentName,
ConnectionServiceRepository connectionServiceRepository,
PhoneAccountRegistrar phoneAccountRegistrar,
CallsManager callsManager,
Context context,
TelecomSystem.SyncRoot lock,
UserHandle userHandle)
super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle);
....
private final Adapter mAdapter = new Adapter();
private Binder2 mBinder = new Binder2();
private IConnectionService mServiceInterface;
// 设置IConnectionService接口
@Override
protected void setServiceInterface(IBinder binder)
mServiceInterface = IConnectionService.Stub.asInterface(binder);
Log.v(this, "Adding Connection Service Adapter.");
// 添加连接后的回调Adapter接口
addConnectionServiceAdapter(mAdapter);
public void createConnection(final Call call, final CreateConnectionResponse response)
//新建 绑定通话连接服务的回调接口
BindCallback callback = new BindCallback()
@Override
public void onSuccess()
if (call == null) return;
String callId = mCallIdMapper.getCallId(call);
mPendingResponses.put(callId, response);
Bundle extras = call.getIntentExtras();
extras = updateIntentExtras(call, extras);
// 发送IPC请求到通话链接服务,告知其来电信息
try
mServiceInterface.createConnection(
call.getConnectionManagerPhoneAccount(),
callId,
new ConnectionRequest(
call.getTargetPhoneAccount(),
call.getHandle(),
extras,
call.getVideoState(),
callId),
call.shouldAttachToExistingConnection(),
call.isUnknown());
catch (RemoteException e)
.....
@Override
public void onFailure()
....
;
// 绑定通话连接服务,并设置绑定回调函数
mBinder.bind(callback, call);
向通话账户中指定的组件mComponentName
(在创建PhoneAccount时指定,实际是TelephonyConnectionService
对象)发送绑定服务的请求,请求其处理动作名为:"android.telecom.ConnectionService";
的消息:
// 用于绑定通话链接服务的抽象类
abstract class ServiceBinder
// 绑定回调
interface BindCallback
void onSuccess();
void onFailure();
// 执行绑定操作的Helper类
final class Binder2
void bind(BindCallback callback, Call call)
mCallbacks.add(callback);
if (mServiceConnection == null)
Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
ServiceConnection connection = new ServiceBinderConnection(call);
final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
final boolean isBound;
if (mUserHandle != null)
// 发送绑定服务的请求
isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
mUserHandle);
else
isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
if (!isBound)
handleFailedConnection();
return;
// 已经存在绑定的服务
else
Log.d(ServiceBinder.this, "Service is already bound.");
Preconditions.checkNotNull(mBinder);
handleSuccessfulConnection();
// 绑定成功后的回调对象
private final class ServiceBinderConnection implements ServiceConnection
private Call mCall;
ServiceBinderConnection(Call call)
mCall = call;
@Override
public void onServiceConnected(ComponentName componentName, IBinder binder)
try
synchronized (mLock)
mCall = null;
// 设置IBinder接口
mServiceConnection = this;
setBinder(binder);
handleSuccessfulConnection();
finally
Log.endSession();
@Override
public void onServiceDisconnected(ComponentName componentName)
try
synchronized (mLock)
mServiceConnection = null;
handleServiceDisconnected();
finally
Log.endSession();
private void setBinder(IBinder binder)
if (mBinder != binder)
if (binder == null)
removeServiceInterface();
mBinder = null;
else
mBinder = binder;
// 设置IBinder接口,即ConnectionServiceWrapper中的mService
setServiceInterface(binder);
为什么这里需要绑定一个
TelephonyConnectionService
了?TelephonyConnectionService
的作用是Telephony模块用来记录以及维护当前通话信息,当没有通话时(既不存在来电,也没有去电),telecom就会解绑TelephonyConnectionService
。
到现在,通过调用ConnectionService
的接口createConnection
,一个通话对象Call
就跟ConnectionService
建立了一个具体的连接,同时创建一个通话连接对象connnection
返回给ConnectionServiceWrapper
:
public abstract class ConnectionService extends Service
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);
connection.setTelecomCallId(callId);
if (connection.getState() != Connection.STATE_DISCONNECTED)
addConnection(callId, connection);
// 注意,mAdapter就是设置IConnectionService接口时设置的回调
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()));
调用Adapter
中的接口调用handleCreateConnectionComplete
,接着继续调用ConnectionServiceWrapper
中的函数handleCreateConnectionComplete
继续回调过程。调用CreateConnectionProcessor
的接口handleCreateConnectionSuccess
,以此继调用Call
中的回调接口handleCreateConnectionSuccess
:
public class ConnectionServiceWrapper extends ServiceBinder
// 保存了上层调用CreateConnectionProcessor的接口
private final Map<String, CreateConnectionResponse> mPendingResponses = new HashMap<>();
private final class Adapter extends IConnectionServiceAdapter.Stub
@Override
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection)
long token = Binder.clearCallingIdentity();
try
synchronized (mLock)
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection);
finally
Binder.restoreCallingIdentity(token);
Log.endSession();
private void handleCreateConnectionComplete(
String callId,
ConnectionRequest request,
ParcelableConnection connection)
if (connection.getState() == Connection.STATE_DISCONNECTED)
// fail
removeCall(callId, connection.getDisconnectCause());
else
// Successful connection
if (mPendingResponses.containsKey(callId))
mPendingResponses.remove(callId)
.handleCreateConnectionSuccess(mCallIdMapper, connection);
通话连接成功回调到了Call
之后,会继续通过回调的方式将消息传给CallsManager
:
public class Call implements CreateConnectionResponse
private final Set<Listener> mListeners = Collections.newSetFromMap(
new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
@Override
public void handleCreateConnectionSuccess(CallIdMapper idMapper,ParcelableConnection connection)
setTargetPhoneAccount(connection.getPhoneAccount());
setHandle(connection.getHandle(), connection.getHandlePresentation());
setCallerDisplayName(
connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
....
switch (mCallDirection)
case CALL_DIRECTION_INCOMING:
for (Listener l : mListeners)
// 告诉CallsManager通话连接建立成功
l.onSuccessfulIncomingCall(this);
break;
....
Telecom与Call APP之间的交互
Telecom将来电与ConnectionService
绑定后,就要讲来电信息告知上层UI了。作为Telecom服务的通话的管家,CallsManager
收到连接建立成功的消息后,首先会对来电进行过滤操作(检查通话是否需要转接到语音信箱或者阻断通话),如果来电是正常的,则准备将该通话与CALL APP的UI界面进行连接:
public class CallsManager extends Call.ListenerBase
implements VideoProviderProxy.Listener, CallFilterResultCallback
private final List<CallsManagerListener> mListeners = new CopyOnWriteArrayList<>();
@Override
public void onSuccessfulIncomingCall(Call incomingCall)
List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
// 添加通话过滤类
filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
// 确保可以连上UI界面
filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
mDefaultDialerManagerAdapter,
new ParcelableCallUtils.Converter(), mLock));
// 对来电进行过滤操作,完成后调用回调函数
new IncomingCallFilter(mContext, this, incomingCall, mLock,
mTimeoutsAdapter, filters).performFiltering();
@Override
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");
if (result.shouldAllowCall)
// 通话路数超限,直接挂断
if (hasMaximumRingingCalls())
rejectCallAndLog(incomingCall);
else if (hasMaximumDialingCalls())
rejectCallAndLog(incomingCall);
else
// 添加通话
if (addSuccessfulIncomingCall(incomingCall))
if (incomingCall != null) addCall(incomingCall);
else
....
函数addSuccessfulIncomingCall()
针对不同的用户模式对通话进行处理,并打开话筒,处理返回成功后,接着addCall()
会将此路通话跟CALL APP的UI服务ICallScreeningService
进行绑定,
private void addCall(Call call)
if (call == null)
return;
call.addListener(this);
mCalls.add(call);
// 更新call,状态有变化时,通知监听对象
updateCanAddCall();
// 调用监听接口onCallAdded(),通知上层来电信息
for (CallsManagerListener listener : mListeners)
listener.onCallAdded(call);
....
在CallsManager
初始化时,会添加一个叫InCallController
的监听类,其实现了CallsManagerListenerBase
的接口;该监听接口就是用于绑定上层通话界面的服务IncallService
:
public final class InCallController extends CallsManagerListenerBase
....
@Override
public void onCallAdded(Call call)
// 服务没有绑定,则重新绑定,绑定成功后,将通话添加到Incall
if (!isBoundToServices())
bindToServices(call);
else
// 记录通话状态,并打开audio
addCall(call);
List<ComponentName> componentsUpdated = new ArrayList<>();
for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet())
InCallServiceInfo info = entry.getKey();
componentsUpdated.add(info.getComponentName());
IInCallService inCallService = entry.getValue();
ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
info.isExternalCallsSupported());
try
//将此路通话添加IncallService
inCallService.addCall(parcelableCall);
catch (RemoteException ignored)
至此CallsManager
就将来电告知InCallUI了,这时用户就可以再手机上看到一个来电提醒的对话框了。
以上是关于Android TelecomService的来电处理过程的主要内容,如果未能解决你的问题,请参考以下文章
Android 系统服务TelecomService启动过程分析
Android 系统服务TelecomService启动过程分析