安卓电话交互桥梁 Telecom【System进程】

本文详细介绍了Android系统的Telecom服务,包括其在通话管理中的角色、服务启动与初始化过程、核心组件如CallsManager的工作机制,以及Listener回调消息的处理。Telecom作为电话功能的桥梁,连接了底层Telephony模块与上层UI,处理来电显示、接听、挂断等操作,并通过Listener回调机制实现状态更新。此外,还探讨了耳机事件的处理。
摘要由CSDN通过智能技术生成

1. Telecom所处位置

由下图,Telecom的作用是起到交互桥梁,与IncallUI 和 Telephony【Phone进程、TeleService】交互

路径统称进程
packages/app/DialerDialercom.android.dialer
packages/service/telecommtelecomsystem_service
packages/service/telephonyTeleServicecom.android.phone
framework/base/telecommframework无进程只是提供调用framwork
framework/opt/Telephonytelephonysystem_service或com.android.phone

2. 什么是Telecom 服务

telecom所处的代码路径:

代码路径:

  • /packages/services/Telecomm
  • /frameworks/base/telecomm/java/android/telecom/

Telecom是Android的一个系统服务,其主要作用是管理Android系统当前的通话,如来电显示,接听电话,挂断电话等功能,在Telephony模块与上层UI之间起到了一个桥梁的作用。比如,Telephony有接收到新的来电时,首先会告知Telecom,然后由Telecom服务通知上层应用来电信息,并显示来电界面。

Telecom服务对外提供了一个接口类TelecomManager,通过其提供的接口,客户端可以查询通话状态,发送通话请求以及添加通话链接等。

Telecom进程对应的AndroidManifest.xml文件来看,Telecom进程的用户ID跟系统进程用户ID相同,是系统的核心服务。那么,其中android:process="system"这个属性值表示什么意思了?查看官方文档,这个表示Telecom将启动在进程system中,这样可以跟其他进程进行资源共享了(对于Android这个全局进程,就是SystemServer所在的进程)。

AndroidManifest.xml 在/packages/services/Telecomm,包含了 ITelecomService

/packages/services/Telecomm/AndroidManifest.xml

17 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
18         xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
19         package="com.android.server.telecom"
20         coreApp="true"
21         android:sharedUserId="android.uid.system">
22 
23     <protected-broadcast android:name="android.intent.action.SHOW_MISSED_CALLS_NOTIFICATION" />
24     <protected-broadcast android:name="com.android.server.telecom.MESSAGE_SENT" />

330         <service android:name=".components.BluetoothPhoneService"
331                 android:singleUser="true"
332                 android:process="system">
333             <intent-filter>
334                 <action android:name="android.bluetooth.IBluetoothHeadsetPhone" />
335             </intent-filter>
336         </service>
337 
338         <service android:name=".components.TelecomService"
339                 android:singleUser="true"
340                 android:process="system">
341             <intent-filter>
342                 <action android:name="android.telecom.ITelecomService" />
343             </intent-filter>
344         </service>
345 
346     </application>
347 </manifest>

3. Telecom代码路径

1) /packages/services/Telecomm 代码路径

action: android.intent.action.CALL

141         <!-- Activity that starts the outgoing call process by listening to CALL intent which
142              contain contact information in the intent's data. CallActivity handles any data
143              URL with the schemes "tel", "sip", and "voicemail". It also handles URLs linked to
144              contacts provider entries. Any data not fitting the schema described is ignored. -->
145         <activity android:name=".components.UserCallActivity"
146                 android:label="@string/userCallActivityLabel"
147                 android:theme="@style/Theme.Telecomm.Transparent"
148                 android:permission="android.permission.CALL_PHONE"
149                 android:excludeFromRecents="true"
150                 android:process=":ui">
151             <!-- CALL action intent filters for the various ways of initiating an outgoing call. -->
152             <intent-filter>
153                 <action android:name="android.intent.action.CALL" />
154                 <category android:name="android.intent.category.DEFAULT" />
155                 <data android:scheme="tel" />

-------------
184         <activity-alias android:name="PrivilegedCallActivity"
185                 android:targetActivity=".components.UserCallActivity"
186                 android:permission="android.permission.CALL_PRIVILEGED"
187                 android:process=":ui">
188             <intent-filter android:priority="1000">
189                 <action android:name="android.intent.action.CALL_PRIVILEGED" />
190                 <category android:name="android.intent.category.DEFAULT" />
191                 <data android:scheme="tel" />
192             </intent-filter>

action:android.intent.action.CALL_EMERGENCY

212         <!-- Works like CallActivity with CALL_EMERGENCY instead of CALL intent.
213              CALL_EMERGENCY allows calls *only* to emergency numbers. Intent-sender must have the
214              CALL_PRIVILEGED permission or the broadcast will not be processed. High priority of
215              1000 is used in all intent filters to prevent anything but the system from processing
216              this intent (b/8871505). -->
217         <!-- TODO: Is there really a notion of an emergency SIP number? If not, can
218              that scheme be removed from this activity? -->
219         <activity-alias android:name="EmergencyCallActivity"
220                 android:targetActivity=".components.UserCallActivity"
221                 android:permission="android.permission.CALL_PRIVILEGED"
222                 android:process=":ui">
223             <intent-filter android:priority="1000">
224                 <action android:name="android.intent.action.CALL_EMERGENCY" />
225                 <category android:name="android.intent.category.DEFAULT" />
226                 <data android:scheme="tel" />
227             </intent-filter>

2) /frameworks/base/telecomm/java/android/telecom/ 框架层路径

4. Telecom进程的启动和初始化

首先会走到 main 方法中,然后在调用 run 方法:在SystemServer进程初始化完成启动完系统的核心服务如ActivityManagerService后,就会加载系统其它服务,这其中就包含了一个与Telecom服务启动相关的系统服务专门用于加载Telecom: 

917      private void startOtherServices() {
1004                  traceBeginAndSlog("StartTelecomLoaderService");
1005                  mSystemServiceManager.startService(TelecomLoaderService.class);
1006                  traceEnd();
1007  
1008                  traceBeginAndSlog("StartTelephonyRegistry");
1009                  telephonyRegistry = new TelephonyRegistry(context);
1010                  ServiceManager.addService("telephony.registry", telephonyRegistry);
1011                  traceEnd();

调用系统服务管家SystemServiceManager的接口startService创建新的服务,并注册到系统中,最后调用onStart()启动服务。


    public class SystemServiceManager {

        @SuppressWarnings("unchecked")
        public SystemService startService(String className) {
            final Class<SystemService> serviceClass;
            try {
                serviceClass = (Class<SystemService>)Class.forName(className);
            } catch (ClassNotFoundException ex) {
                ....
            }
            return startService(serviceClass);
        }

        // 服务的class文件来创建新的服务对象(服务必须继承SystemService)
        @SuppressWarnings("unchecked")
        public <T extends SystemService> T startService(Class<T> serviceClass) {
            try {
                final String name = serviceClass.getName();
                Slog.i(TAG, "Starting " + name);
                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);

                // Create the service.
                if (!SystemService.class.isAssignableFrom(serviceClass)) {
                    throw new RuntimeException("Failed to create " + name
                            + ": service must extend " + SystemService.class.getName());
                }
                final T service;
                try {
                    Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                    service = constructor.newInstance(mContext);
                } catch (InstantiationException ex) {
                    throw new RuntimeException("Failed to create service " + name
                            + ": service could not be instantiated", ex);
                } 
                ....
                // Register it.
                mServices.add(service);

                // Start it.
                try {
                    service.onStart();
                } catch (RuntimeException ex) {
                    throw new RuntimeException("Failed to start service " + name
                            + ": onStart threw an exception", ex);
                }
                return service;
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }
        }
    }

创建TelecomLoaderService系统服务,将系统默认的SMS应用,拨号应用以及SIM通话管理应用告知PackageManagerService(PMS),以便在适当的时候可以找到应用。


    public class TelecomLoaderService extends SystemService {
        ...
        public TelecomLoaderService(Context context) {
            super(context);
            mContext = context;
            registerDefaultAppProviders();
        }

        @Override
        public void onStart() {
        }

        private void registerDefaultAppProviders() {
            final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                    PackageManagerInternal.class);

            // Set a callback for the package manager to query the default sms app.
            packageManagerInternal.setSmsAppPackagesProvider(
                    new PackageManagerInternal.PackagesProvider() {
                @Override
                public String[] getPackages(int userId) {
                    synchronized (mLock) {
                    ....
                    ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
                            mContext, true);
                    if (smsComponent != null) {
                        return new String[]{smsComponent.getPackageName()};
                    }
                    return null;
                }
            });

            // Set a callback for the package manager to query the default dialer app.
            packageManagerInternal.setDialerAppPackagesProvider(
                    new PackageManagerInternal.PackagesProvider() {
                @Override
                public String[] getPackages(int userId) {
                    synchronized (mLock) {
                    ....
                    String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
                    if (packageName != null) {
                        return new String[]{packageName};
                    }
                    return null;
                }
            });

            // Set a callback for the package manager to query the default sim call manager.
            packageManagerInternal.setSimCallManagerPackagesProvider(
                    new PackageManagerInternal.PackagesProvider() {
                @Override
                public String[] getPackages(int userId) {
                    synchronized (mLock) {
                    ....
                    TelecomManager telecomManager =
                        (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
                    PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
                    if (phoneAccount != null) {
                        return new String[]{phoneAccount.getComponentName().getPackageName()};
                    }
                    return null;
                }
            });
        }
    }

telecom 服务的启动:

有一个onBootPhase的函数,用于SystemServer告知系统服务目前系统启动所处的阶段。这里可以看到,等(ActivityManagerService)AMS启动完成以后,就可以开始连接Telecom服务了:

  • 首先,注册默认应用(SMS/Dialer etc)通知对象,以便这些应用发送变更(如下载了一个第三方的SMS应用时,可以通知系统这一变化);
  • 接着,注册运营商配置变化的广播接收器,如果配置有变化时,系统会收到通知;
  • 绑定TelecomService,并将其注册到系统中。

    public class TelecomLoaderService extends SystemService {

        private static final ComponentName SERVICE_COMPONENT = new ComponentName(
                "com.android.server.telecom",
                "com.android.server.telecom.components.TelecomService");

        private static final String SERVICE_ACTION = "com.android.ITelecomService";

        // 当前系统启动的阶段
        @Override
        public void onBootPhase(int phase) {
            if (phase == PHASE_ACTIVITY_MANAGER_READY) {
                registerDefaultAppNotifier();
                registerCarrierConfigChangedReceiver();
                connectToTelecom();
            }
        }

        //绑定Telecom服务
        private void connectToTelecom() {
            synchronized (mLock) {
                if (mServiceConnection != null) {
                    // TODO: Is unbinding worth doing or wait for system to rebind?
                    mContext.unbindService(mServiceConnection);
                    mServiceConnection = null;
                }

                TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
                Intent intent = new Intent(SERVICE_ACTION);
                intent.setComponent(SERVICE_COMPONENT);
                int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_AUTO_CREATE;

                // Bind to Telecom and register the service
                if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
                    mServiceConnection = serviceConnection;
                }
            }
        }
    }

绑定服务时,调用TelecomServiceonBind接口,对整个Telecom系统进行初始化,并返回一个IBinder接口:


    /**
     * Implementation of the ITelecom interface.
     */
    public class TelecomService extends Service implements TelecomSystem.Component {

        @Override
        public IBinder onBind(Intent intent) {
            // 初始化整个Telecom系统
            initializeTelecomSystem(this);
            //返回IBinder接口
            synchronized (getTelecomSystem().getLock()) {
                return getTelecomSystem().getTelecomServiceImpl().getBinder();
            }
        }

    }

Telecom系统初始化,主要工作是新建一个TelecomSystem的类,在这个类中,会对整个Telecom服务的相关类都初始化


    static void initializeTelecomSystem(Context context) {
            if (TelecomSystem.getInstance() == null) {

                final NotificationManager notificationManager =
                        (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
                // 用于获取联系人
                contactInfoHelper = new ContactInfoHelper(context);
                // 新建一个单例模式的对象
                TelecomSystem.setInstance(new TelecomSystem(....));
            }
            ....
        }
    }

构造一个单例TelecomSystem对象,会创建许多和通话有关的类


     public TelecomSystem(
                Context context,
                /* 用户未接来电通知类(不包括已接或者拒绝的电话) */
                MissedCallNotifierImplFactory missedCallNotifierImplFactory,
                /* 查询来电信息 */
                CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
                /* 耳机接入状态监听 */
                HeadsetMediaButtonFactory headsetMediaButtonFactory,
                /* 距离传感器管理 */
                ProximitySensorManagerFactory proximitySensorManagerFactory,
                /* 通话时电话管理 */
                InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
                /* 音频服务管理 */
                AudioServiceFactory audioServiceFactory,
                /* 蓝牙设备管理 */
                BluetoothPhoneServiceImplFactory bluetoothPhoneServiceImplFactory,
                BluetoothVoIPServiceImplFactory bluetoothVoIPServiceImplFactory,
                /* 查询所有超时信息 */
                Timeouts.Adapter timeoutsAdapter,
                /* 响铃播放 */
                AsyncRingtonePlayer asyncRingtonePlayer,
                /* 电话号码帮助类 */
                PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
                /* 通话时阻断通知 */
                InterruptionFilterProxy interruptionFilterProxy) {
            mContext = context.getApplicationContext();
            // 初始化telecom相关的feature
            TelecomFeature.makeFeature(mContext);
            // 初始化telecom的数据库
            TelecomSystemDB.initialize(mContext);
            // 创建一个PhoneAccount注册管理类
            mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext);
            ....
            // 初始化通话管家,正是它负责与上层UI的交互
            mCallsManager = new CallsManager(
                    mContext, mLock, mContactsAsyncHelper,
                    callerInfoAsyncQueryFactory, mMissedCallNotifier,
                    mPhoneAccountRegistrar, headsetMediaButtonFactory,
                    proximitySensorManagerFactory, inCallWakeLockControllerFactory,
                    audioServiceFactory, bluetoothManager,
                    wiredHeadsetManager, systemStateProvider,
                    defaultDialerAdapter, timeoutsAdapter,AsyncRingtonePlayer,
                    phoneNumberUtilsAdapter,  interruptionFilterProxy);

            CallsManager.initialize(mCallsManager);
            // 注册需要接收的广播    
            mContext.registerReceiver(mUserSwitchedReceiver, USER_SWITCHED_FILTER);
            mContext.registerReceiver(mUserStartingReceiver, USER_STARTING_FILTER);
            mContext.registerReceiver(mFeatureChangedReceiver, FEATURE_CHANGED_FILTER);
            mContext.registerReceiver(mEmergencyReceiver, EMERGENCY_STATE_CHANGED);
            ....    
            // 所有来电与去电的处理中转站
            mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager);
            // 创建一个TelecomServiceImpl用于调用TelecomService的接口
            mTelecomServiceImpl = new TelecomServiceImpl(
                    mContext, mCallsManager, mPhoneAccountRegistrar,
                    new CallIntentProcessor.AdapterImpl(),
                    new UserCallIntentProcessorFactory() {
                        @Override
                        public UserCallIntentProcessor create(Context context, UserHandle userHandle) {
                            return new UserCallIntentProcessor(context, userHandle);
                        }
                    },
                    defaultDialerAdapter,
                    new TelecomServiceImpl.SubscriptionManagerAdapterImpl(),
                    mLock);
            // 执行特定的初始化操作
            initialize(mContext);
        }
    }

 

5. 核心 Listener 的回调机制【核心类:CallsManager】

在解析拨号流程和来电流程的过程中,遇见了各式各样的Listener 消息回调。本节将重点解析 Telecom 中的 Listener 消息处理机制

 /packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

1) CallsManagerListener 接口:

在TelecomSystem 初始化过程中创建CallsManager 对象时,将同步创建C llsManagerlistener 对象,并注册Listener 消息通知,查看CallsManager 类的构造方法

监听通话的一系列状态

    public interface CallsManagerListener {
        void onCallAdded(Call call);
        void onCallRemoved(Call call);
        void onCallStateChanged(Call call, int oldState, int newState);
        void onConnectionServiceChanged(
                Call call,
                ConnectionServiceWrapper oldService,
                ConnectionServiceWrapper newService);
        void onIncomingCallAnswered(Call call);
        void onIncomingCallRejected(Call call, boolean rejectWithMessage, String textMessage);
        void onCallAudioStateChanged(CallAudioState oldAudioState, CallAudioState newAudioState);
        void onRingbackRequested(Call call, boolean ringback);
        void onIsConferencedChanged(Call call);
        void onIsVoipAudioModeChanged(Call call);
        void onVideoStateChanged(Call call, int previousVideoState, int newVideoState);
        void onCanAddCallChanged(boolean canAddCall);
        void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile);
        void onHoldToneRequested(Call call);
        void onExternalCallChanged(Call call, boolean isExternalCall);
        void onDisconnectedTonePlaying(boolean isTonePlaying);
        void onConnectionTimeChanged(Call call);
        void onConferenceStateChanged(Call call, boolean isConference);
    }

在Telecom 应用加载的初始化过程中,将创建CallsManagerListener 对象,并增加到CallsManager 对象的 mlisteners 列表中;而通话的相关状态或属性发生改变时, CallsManager 将遍历mlisteners 列表,进行on XXX的消息回调,其代码逻辑总结如下:

Ca llsManagerlistener 接口定义在Ca ll sManager 类中, CallsManagerListenerBase 类实现了此接口的所有方法,而且这些方法都没有任何的业务逻辑代码。在面向对象编程中,使用多态的一种典型方式是子类可根据业务需要选择父类中的方法进行重写。

CallsManagerlistenerBase 所有子类的作用及重写的方法, 总结如表4-1 所示。

2) Call.Listener

拨号流程或是来电流程中,都会创建com.android.server.telecom. Call 对象,此类中定义了Listener 接口,主要有以下几个方法:

-------Call 类
106       * Listener for events on the call.
107       */
108      @VisibleForTesting
109      public interface Listener {
110          void onSuccessfulOutgoingCall(Call call, int callState);
111          void onFailedOutgoingCall(Call call, DisconnectCause disconnectCause);
112          void onSuccessfulIncomingCall(Call call);

---------
151      public abstract static class ListenerBase implements Listener {
152          @Override
153          public void onSuccessfulOutgoingCall(Call call, int callState) {}
154          @Override
155          public void onFailedOutgoingCall(Call call, DisconnectCause disconnectCause) {}
-------CallsManager类
------------
151  @VisibleForTesting
152  public class CallsManager extends Call.ListenerBase

CallsManager 作为Call.Listener 接口的子类,由Call 对象触发mlistenersCall 对象变化的消息回调, CallsManager 对象将通过自己的 mlisteners ,继续发出Call 对象变化的消息回调,而这一次的消息回调将接收并处理12 个对象;因此,可以将CallsManager 看作Call 对象变化 Listener 消息回调的消息中转站,将Call. Listener 和CallsManagerlistener 这两个Listener 紧密联系在一起。

3) CallsManager 工作机制

CallsManager工作机制简图

上图大致包含了CallsManager、Call、CallsManagerListener的工作机制:
Telecom启动之时就创建了CallsManager,而CallsManager在构造器内就将通话相关功能类注册到了监听列表中。在发生通话时(MT或MO),CallsManager首先创建出Call并回调所有观察者的对应方法,在Call状态更新时,会回调CallsManager相关方法,然后CallsManager会对Call进行相关处理,并会回调所有观察者的对应方法。 

4) CreateConnectionResponse

CreateConnectionResponse 接口定义了两个方法: handleCreateConnectionSuccess 和handleCreateConnectionFailure ,

它总共有两个子类: Call 和CreateConnectionProcessor ,

Call 和CreateConnectionProcessor  都是 CreateConnectionResponse 接口对象。

不论拨号流程还是来电流程, Telecom 在Call 对象创建完成后, 都调用其 startCreateConnection 方法最终完成绑定 IConnectionService 服务相关的操作;在此过程中将涉及CreateConnectionResponse 接口对象的创建和传递过程,代码框架总结如下。

5)总结 Listener 消息

在Telecom 应用中主要处理两种消息类型:顺时针方向下发的通话控制消息 和 逆时针方向上报的通话状态变化消息。

而Listener 消息回调承载着上报消息的业务处理逻辑,其应用场景是ConnectionServiceWrapper 的Adapter 服务对象接收到TeleService 应用的接口调用,


通知当前Connection 和Call 的状态或属性发生的变化,再经过一系列的Listener 消息回调处理,最终由lnCallController 创建ParcelableCall 对象,使用 llnCallService 服务接口调用发送给Dialer 应用。

可见这些Listener 消息处理在Telecom 应用中的重要性,继续对CallsManager.Listener、Call.Listener 和 CreateConnectionResponse 三个核心消息回调的分析结果进行汇总和总结,形成Telecom 应用中消息回调的全貌

两条消息回调通道的调用过程,都会调用CallsManager 对象的setCallState 方法更新Telecom应用中的Call 属性

调用过程如下:

//第-条消息回调通道的调用过程【Telephony上报】
ConnectionServiceWrapper . mAdapter.handleCreateConnectionComplete
-> mPendingResponses(CreateConnectionProcessor) . handleCreateConnectionSuccess
- > mCallResponse (Call). handleCreateConnectionSuccess

- > mListeners(CallsManager) . onSuccessfulXXXCall->setCallState

//第二条消息回调通道的调用过程【与InCallui交互】
ConnectionServiceWrapper . mAdapter.setActive
- > mCallsManager . markCallAsActive >setCallState
//CallsManager 对象的调用过程
CallsManager.setCallState
- > InCallController.onCallStateChanged - > updateCall- >inCallService.updateCall

6)耳机事件

关注 MediaSession 类

链接 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值