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服务,并且设置回调函数,这里Binder2ServiceBinder中的私有类,


    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启动过程分析

在 Android 原生来电屏幕上弹出窗口,如真正的来电者 Android 应用程序

Android来电监听

Android来电监听

Android来电监听