关闭

Telephony之进程与实体(原)

标签: TelephonyAndroidFramework
2326人阅读 评论(0) 收藏 举报
分类:

一、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中,都能得到体现


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:283958次
    • 积分:3366
    • 等级:
    • 排名:第10025名
    • 原创:63篇
    • 转载:0篇
    • 译文:0篇
    • 评论:103条
    最新评论