Telephony之进程与实体(原)

原创 2014年10月17日 11:29:22

一、Telephony进程


        整个Framework层的Telephony框架运行在一个叫做Phone(com.android.phone)的进程中。而这个进程是在packages\services\Telephony模块中被创建的(Android4.4平台)。并且该模块在AndroidManifest.xml中有如下关键的声明:
        <application android:name="PhoneApp"
            android:persistent="true"
            android:label="@string/phoneAppLabel"
            android:icon="@mipmap/ic_launcher_phone"
            android:supportsRtl="true">
        这个声明创建了一个名叫“PhoneApp”的application,并且确定了他的name、label、icon等信息,而且将该application的persistent属性置为true。那么这个persistent属性的作用是什么呢?
        这里的persistent属性具备两个关键作用:
        1、该模块会在开机时被系统自动初始化;
        2、该模块所在的进程(com.android.phone)由于任何原因被kill掉之后,都会自动重启;

        以上两点是十分必要的,他保证/导致了两个效果:
        1、所有Application层和Framework层中与Telephony相关的操作,包括各种Service的创建、与RIL层交互的RILJ的初始化等,都是通过Phone进程创建的;
        2、Phone进程由于任何原因被kill掉后,都会发生重新搜网的动作;


二、Telephony实体对象


        前面介绍了Telephony的框架和进程,那么当发生具体的某个通讯请求,比如打电话、发短信时,该如何操作呢?
        这里要引入一个非常重要的对象:Phone对象。该对象可以看做是Telephony框架的实体,可以向该对象发起各种通讯相关的请求,可以说,Phone对象是Telephony整个框架的核心,他负责与RIL层的交互。
        而这个Phone对象就是在PhoneApp这个application初始化过程中被创建的。我们就从入口开始,来查看Phone进程的创建过程:
        在PhoneApp的onCreate()方法中,会new出PhoneGlobals的对象,并接着调用该对象的onCreate方法:
        @PhoneApp.java
        public void onCreate() {
            if (UserHandle.myUserId() == 0) {
                mPhoneGlobals = new PhoneGlobals(this);
                mPhoneGlobals.onCreate();
            }
        }
        接下来我们来看PhoneGlobals的onCreate过程:
        @PhoneGlobals
        public void onCreate() {
            if (phone == null) {
                //创建Phone对象
                PhoneFactory.makeDefaultPhones(this);
                phone = PhoneFactory.getDefaultPhone();

                //初始化CallManager
                mCM = CallManager.getInstance();
                mCM.registerPhone(phone);

                //初始化NotificationMgr,用于状态栏通知
                notificationMgr = NotificationMgr.init(this);

                //初始化CallController
                callController = CallController.init(this, callLogger, callGatewayManager);

                //得到铃声控制
                ringer = Ringer.init(this, bluetoothManager);
                audioRouter = new AudioRouter(this, bluetoothManager, wiredHeadsetManager, mCM);

                //初始化callCommandService
                callCommandService = new CallCommandService(this, mCM, callModeler, dtmfTonePlayer, audioRouter);

                //初始化PhoneInterfaceManager
                phoneMgr = PhoneInterfaceManager.init(this, phone, callHandlerServiceProxy);

                //初始化CallNotifer,响铃等动作在这里面完成
                notifier = CallNotifier.init(this, phone, ringer, callLogger, callStateMonitor, bluetoothManager, callModeler);

                //注册SIM卡状态监听
                IccCard sim = phone.getIccCard();
                if (sim != null) {
                    sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null);
                }
            }
        }
        从以上代码可以看出,PhoneGlobals的初始化过程中要先通过PhoneFactory的makeDefaultPhones()方法创建Phone对象,接着完成了一系列与Telephony相关的重要服务的初始化,比如CallManager、NotificationMgr、CallCommandService、PhoneInterfaceManager、CallNotifier等。
        我们现在只关心Phone对象的创建过程,也就是PhoneFactory的makeDefaultPhones过程:
        @PhoneFactory.java
        public static void makeDefaultPhones(Context context) {
            makeDefaultPhone(context);
        }
        public static void makeDefaultPhone(Context context) {
            synchronized(Phone.class) {
                if (!sMadeDefaults) {
                    //创建DefaultPhoneNotifier,负责通知Phone的状态
                    sPhoneNotifier = new DefaultPhoneNotifier();

                    //得到当前的网络类型
                    int networkMode = Settings.Global.getInt(context.getContentResolver(), Settings.Global.PREFERRED_NETWORK_MODE, preferredNetworkMode);
                    //根据当前网络类型来创建RILJ,负责Framework与RIL层交互
                    sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);

                    //创建UiccController并间接创建UiccCard、UiccCardApplication、IccFileHandler、IccRecords、CatService等服务
                    UiccController.make(context, sCommandsInterface);

                    //根据当前的Phone类型创建不同的PhoneProxy
                    int phoneType = TelephonyManager.getPhoneType(networkMode);
                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                        //GSMPhone
                        sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier));
                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                        switch (TelephonyManager.getLteOnCdmaModeStatic()) {
                            case PhoneConstants.LTE_ON_CDMA_TRUE:
                                //CDMALTEPhone
                                sProxyPhone = new PhoneProxy(new CDMALTEPhone(context, sCommandsInterface, sPhoneNotifier));
                                break;
                            case PhoneConstants.LTE_ON_CDMA_FALSE:
                            default:
                                //CDMAPhone
                                sProxyPhone = new PhoneProxy(new CDMAPhone(context, sCommandsInterface, sPhoneNotifier));
                                break;
                        }
                    }
                }
            }
        }
        经过上面两段代码,我们看到了Phone对象的创建过程:
        1、先创建DefaultPhoneNotifier对象,该对象的作用是监听RIL层发过来的Phone状态变化;
        2、针对当前的网络类型创建不同的Java层RIL,即RILJ;
        3、拿到RILJ之后,就要利用DefaultPhoneNotifier和RILJ并根据当前的Phone类型(GSM/CDMA)来创建不同的Phone对象(GSMPhone/CDMALTEPhone/CDMAPhone);

        4、再用3中拿到的Phone创建PhoneProxy对象,这个代理对象才是可以直接使用的Phone对象;


三、Telephony实体对象本质


        从第二节的代码可以看到,我们拿到的Phone对象(PhoneProxy)其实是一个“代理”的Phone对象,为什么要这样做呢?为什么不直接用GSMPhone或者CDMAPhone呢?
        我们应该考虑到,Android的通讯机制要解决的一个非常重要的问题就是,不同网络制式、不同运营商之间的差异。GSM的通讯协议和CDMA、LTE协议是存在很大差异的,他们的Modem不同、支持的网络命令、协议也都不同,因此Telephony必须将Phone对象抽象出来,构建一个屏蔽了不同协议的Phone对象,也就是这里的PhoneProxy。开发者无需关注当前用户使用的到底是GSMPhone还是CDMAPhone,当需要向Phone发送请求时,只需要用统一的命令对PhoneProxy发起请求即可,由PhoneProxy来完成指令的差异化处理。

        这个思想贯穿了整个Android的通讯机制,无论是RIL层、还是Telephony中,都能得到体现


版权声明:本文为博主原创文章,未经博主允许不得转载。

BroadcastReceiver之实现锁屏、解锁例子

好久没有写android的小例子了,由于前几天写了一篇关于Intent.Action的文章,有朋友私信问我关于ACTION_SCREEN_ON和ACTION_SCREEN_OFF还有ACTION_US...

Binder源码分析之ServiceManager(原)

ServiceManager作为Native层Service的管理员,有着极其重要的作用,主要表现两个方面:         1、对于服务端来说,系统所有的服务提供者都需要向ServiceManage...

(N)Telephony分析(一)之zygote进程启动

Android是基于Linux系统的,而init进程是Linux系统的第一进程,因此,需要分析zygote的启动,首先就需要查看init进程的启动 /system/core/init/init.cp...

Telephony之GsmCallTracker(原)

在前一篇《Telephony之进程与实体》中我们分析了,Application如果要发起通话相关的动作,可以通过Telephony的实体对象,也就是Phone对象来发起请求,而Phone对象就会通话相...

Telephony之PhoneInterfaceManager(原)

一、概述         PhoneInterfaceManager是一个Service,在被创建时通过ServiceManager注册自己,他作为Telephony对外的接口,可以接受其他进程向T...

Telephony之TelephonyRegistry(原)

一、TelephonyRegistry概述         TelephonyRegistry的作用是检测当前Radio的状态,包括通话、短信、数据连接等状态,当这些状态发生改变时,通知所有向他注册...

Android之Telephony各文件解释

摘要:   1 frameworks/base/telephony/java/android/telephony/cdma为使用CDMA具体的电话功能提供的API。  1.1) CdmaCellLoc...
  • mydots
  • mydots
  • 2015年09月29日 09:32
  • 663

Android4.4 Telephony流程分析——GsmServiceStateTracker管理网络服务状态

本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。 本文主要介绍GsmServiceStateTracker是怎么管理网络的?手机开机后...

Android4.4 Telephony流程分析——SIM卡开机时的初始化

本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。 本文主要介绍MTK Android开机时,SIM卡的Framework部分初始化过程。 先...

Sofia_3gx 系统启动和telephony验证流程

为了3Gx项目正常power on,简单整理了工厂板子上电到telephone基本功能验证的基本流程。希望基于整理的内容,在遇到实际问题的时候,能够快速定位出当前板子卡在那一步,便于下面进一步定位解决...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Telephony之进程与实体(原)
举报原因:
原因补充:

(最多只允许输入30个字)