初识com.android.phone

前置文章

  1. 《Android系统之System Server大纲》
  2. 《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 启动。如在拨号器中启动通话设置,如下图:

com.android.smspush什么意思 com.android.phone是什么软件_android

Phone 是 Android 手机里面一个非常核心的 APP,因此,在 AndroidManifest.xml 中,必须有如下配置:

android:persistent="true"

让 phone 持久化运行在 Android 系统中。

Phone的作用

Phone 是 Android 手机里面一个非常核心的 APP,没有了 phone,就无法进行一切的无线电业务,例如通话,短信等等。

Phone对外业务

首先,必须了解 phone 在无线电业务中所处的位置,如下图:

com.android.smspush什么意思 com.android.phone是什么软件_telephony_02

由上图可知,Phone 在上层是业务中枢,对上层业务,Phone 需要与其它无线电业务模块进行通信,如通话模块,短信模块,数据上网模块;往下,Phone 需要与 RILC 进行通信,在这里,Phone 端有 RILJ 模块,RILJ 和 RILC 通过 socket 进行通信;Modem 就是和有线上网的猫是实现一样的功能,Modem 是手机与基站进行通信的设备。关于 RIL 和 Modem,会因为芯片厂商的不同,往往有很大的区别,笔者不在本文在阐述这些模块,读者如果感兴趣,可以查阅相关资料。

因此,我们可以想象得到,以一个通话业务为例,其流程必定是:

com.android.smspush什么意思 com.android.phone是什么软件_phone_03

Phone业务

  1. CDMA 业务(支持CDMA的手机)
  2. GSM 业务(支持GSM的手机)
  3. IMS业务(支持IMS的手机)
  4. EUICC业务(支持EUICC的手机。embedded SIM,嵌入式SIM卡)
  5. MBMS业务(MBMS:Multimedia Broadcast Multicast Service,多媒体广播多播业务)
  6. CAT业务(STK等在线业务)
  7. 数据连接业务
  8. 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大纲》一文。

时序图

com.android.smspush什么意思 com.android.phone是什么软件_telephony_04

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。

时序图

com.android.smspush什么意思 com.android.phone是什么软件_android_05

总结

在本文初步了解 Phone 的作用,Phone 在手机中的重要性,Phone 所完成的业务,以及运行在 phone 进程中的 PhoneInterfaceManager 和 SubscriptionController 的创建过程,它们在 System service 中的标签分别是 “phone” 和 “isub”。