版本
Android 7.0
我们知道,数据业务是依赖于PhoneApp的,因此它的基础类应该是在PhoneApp被加载后创建。
在PhoneApp的onCreate函数中:
@Override
public void onCreate() {
//根据进程号判断用户,每个用户分配的可用进程号为100000
//小于100000为主用户
if (UserHandle.myUserId() == 0) {
// We are running as the primary user, so should bring up the global phone state.
mPhoneGlobals = new PhoneGlobals(this);
//这里是我们关注的,数据和语音所需的基础类在这里创建
mPhoneGlobals.onCreate();
//这个具体的用处没研究过,网上的参考信息是处理PSTN呼叫
mTelephonyGlobals = new TelephonyGlobals(this);
mTelephonyGlobals.onCreate();
}
}
我们看看PhoneGlobals的onCreate函数,目前我们只关注数据业务会用到的类:
public void onCreate() {
............
//CallManager通话先关,初始时为null
if (mCM == null) {
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);
..........
//Phone进程对外的服务端,其它进程通过Binder调用PhoneInterfaceManager的接口
phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
..........
}
............
}
接下来我们看看PhoneFactory.makeDefaultPhones的内容。
public static void makeDefaultPhones(Context context) {
makeDefaultPhone(context);
}
public static void makeDefaultPhone(Context context) {
synchronized (sLockProxyPhones) {
//确保只调用一次
if (!sMadeDefaults) {
sContext = context;
//管理硬件资源用的
TelephonyDevController.create();
..........
//用于对外通知phone进程的一些状态
sPhoneNotifier = new DefaultPhoneNotifier();
//判断是单卡手机还是双卡,现在一般都是双卡了
int numPhones = TelephonyManager.getDefault().getPhoneCount();
int[] networkModes = new int[numPhones];
sPhones = new Phone[numPhones];
sCommandsInterfaces = new RIL[numPhones];
sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];
for (int i = 0; i < numPhones; i++) {
networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;
..........
//一个phone对象,有一个对应RIL(无线电接口层)
sCommandsInterfaces[i] = new RIL(context, networkModes[i],
cdmaSubscription, i);
}
//管理卡相关的信息,个人认为偏向于管理抽象化的卡信息,例如subId之类的
SubscriptionController.init(context, sCommandsInterfaces);
//管理卡相关的信息,个人认为偏向于管理实际的卡信息,例如卡中具体的内容
sUiccController = UiccController.make(context, sCommandsInterfaces);
//这里是android 7.0比较大的一个改进
//在android 6.0及以前,对于不同的通信类型分别存在GsmPhone和CdmaPhone
//在之前的版本中,插cdma卡的phone,在cdma网络和gsm网络间迁移(4g与2g迁移)时,将会发生phone切换
//例如4g迁移到2g时,必须销毁cdmaphone,然后新建gsmphone;对象的开销和新建引入开销,还可能有隐藏的内存泄露
for (int i = 0; i < numPhones; i++) {
//创建实际Phone对象的过程
Phone phone = null;
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
phone = new GsmCdmaPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_GSM,
TelephonyComponentFactory.getInstance());
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
phone = new GsmCdmaPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_CDMA_LTE,
TelephonyComponentFactory.getInstance());
}
........
sPhones[i] = phone;
}
//预定义的默认phone,为phone0
sPhone = sPhones[0];
sCommandsInterface = sCommandsInterfaces[0];
//sms相关的,暂不关注
............
//用于更新卡信息的类
sSubInfoRecordUpdater = new SubscriptionInfoUpdater(context,
sPhones, sCommandsInterfaces);
//仅让SubscriptionController获取到新创建的phone
SubscriptionController.getInstance().updatePhonesAvailability(sPhones);
//开始监听IMS服务
for (int i = 0; i < numPhones; i++) {
sPhones[i].startMonitoringImsService();
}
//获取TelephonyRegistry的binder通信代理, TelephonyRegistry按观察者模式为其观察者提供phone的信息
ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(
ServiceManager.getService("telephony.registry"));
SubscriptionController sc = SubscriptionController.getInstance();
//新增类,专注于监听卡的变化,然后通知给观察者
sSubscriptionMonitor = new SubscriptionMonitor(tr, sContext, sc, numPhones);
//新增类,在Android7.0中, 管理DDS(动态数据卡切换)的DctController被移除了
//原来DctController中的内部类TelephonyFactory被单独抽成了一个文件
//管理DDS逻辑的内容,被抽取成了PhoneSwitcher类
sPhoneSwitcher = new PhoneSwitcher(MAX_ACTIVE_PHONES, numPhones,
sContext, sc, Looper.myLooper(), tr, sCommandsInterfaces,
sPhones);
//在android7.0中,PhoneProxy类已经被移除了
//此处ProxyController的定位不是很清晰,看接口多与RadioCapability有关
sProxyController = ProxyController.getInstance(context, sPhones,
sUiccController, sCommandsInterfaces, sPhoneSwitcher);
//原来作为DctController的子类,在android7.0中,终于独挡一面,成为一个独立的类
//TelephonyNetworkFactory用于将数据业务纳入到整个android的网络管理框架中
//通过NetworkFactory,数据业务和ConnectivityService衔接起来了
sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];
for (int i = 0; i < numPhones; i++) {
sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
sPhoneSwitcher, sc, sSubscriptionMonitor, Looper.myLooper(),
sContext, i, sPhones[i].mDcTracker);
}
}
}
}
这里我们暂时不继续分析每个对象的内部如何初始化,等后续分析具体的流程涉及到时,再作分析。
最后介绍一些前面提到的PhoneInterfaceManager的初始化。
static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
synchronized (PhoneInterfaceManager.class) {
if (sInstance == null) {
sInstance = new PhoneInterfaceManager(app, phone);
} else {
Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
}
return sInstance;
}
}
private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
//初始化内部变量
........
publish();
}
private void publish() {
if (DBG) log("publish: " + this);
ServiceManager.addService("phone", this);
}
其实上面代码最值得关注的就是publish函数了,由于PhoneInterfaceManager继承了ITelephony.Stub(PhoneApp定义了ITelephony.aidl),因此上面的代码相当于将PhoneApp的Binder服务注册到ServiceManager中。于是,其它进程可以通过Binder通信,调用PhoneInterfaceManager提供的接口(当然是由权限检查的)。
结束语
这一篇blog实际上并没有太多深入的内容,其目的在于为之后介绍数据业务作一个铺垫。整个数据业务涉及的类非常多,从UI跨越了整个框架,并通过RIL及芯片商提供的库,最终与modem通信。因此,这里先简单描述一下,一些类初始化的情况。