一、Telephony进程
- <application android:name="PhoneApp"
- android:persistent="true"
- android:label="@string/phoneAppLabel"
- android:icon="@mipmap/ic_launcher_phone"
- android:supportsRtl="true">
这里的persistent属性具备两个关键作用:
1、该模块会在开机时被系统自动初始化;
2、该模块所在的进程(com.android.phone)由于任何原因被kill掉之后,都会自动重启;
以上两点是十分必要的,他保证/导致了两个效果:
1、所有Application层和Framework层中与Telephony相关的操作,包括各种Service的创建、与RIL层交互的RILJ的初始化等,都是通过Phone进程创建的;
2、Phone进程由于任何原因被kill掉后,都会发生重新搜网的动作;
二、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
- 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);
- }
- }
- }
我们现在只关心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;
- }
- }
- }
- }
- }
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实体对象本质
我们应该考虑到,Android的通讯机制要解决的一个非常重要的问题就是,不同网络制式、不同运营商之间的差异。GSM的通讯协议和CDMA、LTE协议是存在很大差异的,他们的Modem不同、支持的网络命令、协议也都不同,因此Telephony必须将Phone对象抽象出来,构建一个屏蔽了不同协议的Phone对象,也就是这里的PhoneProxy。开发者无需关注当前用户使用的到底是GSMPhone还是CDMAPhone,当需要向Phone发送请求时,只需要用统一的命令对PhoneProxy发起请求即可,由PhoneProxy来完成指令的差异化处理。
这个思想贯穿了整个Android的通讯机制,无论是RIL层、还是Telephony中,都能得到体现。