初识com.android.phone
初识com.android.phone
前置文章
- 《Android系统之System Server大纲》
- 《Android无线电信息管理开篇准备工作》
前言
在 《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概要
Phone 是一个 App 的形式运行在 Android 系统,所以 phone 具有生命。当然 phone 是一个特殊的 app,它没有 launcher 入口,更多的是作为一个“service”的身份在工作。但是 phone 不是完全没有 UI 的代码,但是它的 UI 一般是通过系统其它 APP 启动。如在拨号器中启动通话设置,如下图:
Phone 是 Android 手机里面一个非常核心的 APP,因此,在 AndroidManifest.xml 中,必须有如下配置:
android:persistent="true"
让 phone 持久化运行在 Android 系统中。
Phone的作用
Phone 是 Android 手机里面一个非常核心的 APP,没有了 phone,就无法进行一切的无线电业务,例如通话,短信等等。
Phone对外业务
首先,必须了解 phone 在无线电业务中所处的位置,如下图:
由上图可知,Phone 在上层是业务中枢,对上层业务,Phone 需要与其它无线电业务模块进行通信,如通话模块,短信模块,数据上网模块;往下,Phone 需要与 RILC 进行通信,在这里,Phone 端有 RILJ 模块,RILJ 和 RILC 通过 socket 进行通信;Modem 就是和有线上网的猫是实现一样的功能,Modem 是手机与基站进行通信的设备。关于 RIL 和 Modem,会因为芯片厂商的不同,往往有很大的区别,笔者不在本文在阐述这些模块,读者如果感兴趣,可以查阅相关资料。
因此,我们可以想象得到,以一个通话业务为例,其流程必定是:
Phone业务
- CDMA 业务(支持CDMA的手机)
- GSM 业务(支持GSM的手机)
- IMS业务(支持IMS的手机)
- EUICC业务(支持EUICC的手机。embedded SIM,嵌入式SIM卡)
- MBMS业务(MBMS:Multimedia Broadcast Multicast Service,多媒体广播多播业务)
- CAT业务(STK等在线业务)
- 数据连接业务
- SIP业务(Session Initiation Protocol,VoLTE,ViLTE)
Phone的启动
在上文中,提到 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创建过程
调用 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大纲》一文。
时序图
SubscriptionController的创建过程
回到 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”。
更多相关文章
- Android Studio R.java文件在哪
- android 反编译:解决xml二进制文件
- android获取各种系统路径的方法
- Android中实现下载和解压zip文件功能代码分享
- android 应用如何获取系统权限 以及root系统方法
- Android 和 JS 交互时调用不成功解决方法
- android应用程序最小化的处理方法
- Android新线程中更新主线程UI中的View方法汇总
- Android文件解压工具类