在 《Android无线电信息管理开篇准备工作》 一文中,表明了 PhoneInterfaceManager 和 SubscriptionController 运行在 phone 进程(com.android.phone)中,因此,此文章,先引领读者简单认识一下 phone 以及 PhoneInterfaceManager 和 SubscriptionController 的创建过程。
一般情况下,phone 的源码在 AOSP 的路径是:
packages/services/Telephony/
一般情况下,phone 所依赖的 framework 源码路径是:
frameworks/opt/telephony/
frameworks/base/telephony/
一般情况下,phone 的产物是:
TeleService.apk
一般情况下,放置在手机的路径是:
/system/priv-app/TeleService/
Phone 是一个 App 的形式运行在 Android 系统,所以 phone 具有生命。当然 phone 是一个特殊的 app,它没有 launcher 入口,更多的是作为一个“service”的身份在工作。但是 phone 不是完全没有 UI 的代码,但是它的 UI 一般是通过系统其它 APP 启动。如在拨号器中启动通话设置,如下图:
Phone 是 Android 手机里面一个非常核心的 APP,因此,在 AndroidManifest.xml 中,必须有如下配置:
android:persistent="true"
让 phone 持久化运行在 Android 系统中。
Phone 是 Android 手机里面一个非常核心的 APP,没有了 phone,就无法进行一切的无线电业务,例如通话,短信等等。
首先,必须了解 phone 在无线电业务中所处的位置,如下图:
由上图可知,Phone 在上层是业务中枢,对上层业务,Phone 需要与其它无线电业务模块进行通信,如通话模块,短信模块,数据上网模块;往下,Phone 需要与 RILC 进行通信,在这里,Phone 端有 RILJ 模块,RILJ 和 RILC 通过 socket 进行通信;Modem 就是和有线上网的猫是实现一样的功能,Modem 是手机与基站进行通信的设备。关于 RIL 和 Modem,会因为芯片厂商的不同,往往有很大的区别,笔者不在本文在阐述这些模块,读者如果感兴趣,可以查阅相关资料。
因此,我们可以想象得到,以一个通话业务为例,其流程必定是:
在上文中,提到 phone 是一个持久化的应用,因此,在手机开机启动的过程中,在 ActivityManagerService 等系统服务启动完毕后,会启动 persistent 的 app。Phone 在此时就被启动起来。
在 APP 的启动过程中,会先实例化 Applicaiton 对象,代表整个 App 最高的对象。这些对于 APP 开发者而言,是多么的熟悉,因为在 Manifest.xml 中,你必须指定应用的 Application。Phone 的 application 标签信息如下:
.....
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/phoneAppLabel"
.....
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
.....
这里,先啰嗦一下 defaultToDeviceProtectedStorage 和 directBootAware 属性,这两个属性和 Android 的文件级加密有关,读者可以阅读《Android加密之文件级加密》一文了解它们。
从 phone 的 manifest.xml 文件中的 application 标签可以知道,Phone 对 Application 对象就行了继承,命名为 PhoneApp。
public class PhoneApp extends Application {
PhoneGlobals mPhoneGlobals;
@Override
public void onCreate() {
.....
mPhoneGlobals = new PhoneGlobals(this);
mPhoneGlobals.onCreate();
mTelephonyGlobals = new TelephonyGlobals(this);
mTelephonyGlobals.onCreate();
.....
}
}
这个类定义在文件 packages/services/Telephony/src/com/android/phone/PhoneApp.java 中。
在上面的代码中,依次实例化了 PhoneGlobals 和 TelephonyGlobals 对象,然后调用各自的 onCreate() 方法。
接着看 PhoneGlobals 的过程
public void onCreate() {
.....
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);
.....
phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
.....
}
这个方法定义在文件 packages/services/Telephony/src/com/android/phone/PhoneGlobals.java 中。
调用 PhoneInterfaceManager 的 init() 方法初始化 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;
}
}
这个方法定义在文件 packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java 中。
接着看 PhoneInterfaceManager 的构造方法
private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
mApp = app;
mPhone = phone;
mCM = PhoneGlobals.getInstance().mCM;
.....
publish();
}
这个方法定义在文件 packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java 中。
接着看 publish()
private void publish() {
if (DBG) log("publish: " + this);
ServiceManager.addService("phone", this);
}
这个方法定义在文件 packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java 中。
在 publish() 中,把 PhoneInterfaceManager 添加到 System service 中,标签是 phone。读者不了解 System Server 的,可以阅读《Android系统之System Server大纲》一文。
回到 PhoneGlobals 的 onCreate 方法,接着看 makeDefaultPhones()
public static void makeDefaultPhone(Context context) {
.....
//根据SIM卡的配置,实例化Phone对象
int numPhones = TelephonyManager.getDefault().getPhoneCount();
sPhones = new Phone[numPhones];
for (int i = 0; i < numPhones; i++) {
Phone phone = null;
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
phone = telephonyComponentFactory.makePhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_GSM,
telephonyComponentFactory.getInstance());
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
phone = telephonyComponentFactory.makePhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_CDMA_LTE,
telephonyComponentFactory.getInstance());
}
sPhones[i] = phone;
}
// 初始化 SubscriptionController
SubscriptionController.init(context, sCommandsInterfaces);
.....
}
这个方法定义在文件 frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneFactory.java 中。
接着看 init 方法
public static SubscriptionController init(Context c, CommandsInterface[] ci) {
synchronized (SubscriptionController.class) {
if (sInstance == null) {
//实例化对象
sInstance = new SubscriptionController(c);
} else {
}
return sInstance;
}
}
这个方法定义在文件 frameworks/opt/telephony/src/java/com/android/internal/telephony/SubscriptionController.java 中。
如上面的代码,new 一个 SubscriptionController 的实例对象,接着看构造方法
protected SubscriptionController(Context c) {
//调用了 init
init(c);
}
这个方法定义在文件 frameworks/opt/telephony/src/java/com/android/internal/telephony/SubscriptionController.java 中。
继续接着看 init 方法
protected void init(Context c) {
mContext = c;
mCM = CallManager.getInstance();
mTelephonyManager = TelephonyManager.from(mContext);
.....
if(ServiceManager.getService("isub") == null) {
//添加到 System Server
ServiceManager.addService("isub", this);
}
}
这个方法定义在文件 frameworks/opt/telephony/src/java/com/android/internal/telephony/SubscriptionController.java 中。
如上面的代码,在 init 方法中,把 SubscriptionController 添加到 System service 中,标签是 isub。
在本文初步了解 Phone 的作用,Phone 在手机中的重要性,Phone 所完成的业务,以及运行在 phone 进程中的 PhoneInterfaceManager 和 SubscriptionController 的创建过程,它们在 System service 中的标签分别是 “phone” 和 “isub”。