本文代码基于Android 9.0
概述
这里讲的PhoneApp启动过程其实是讲Telephony应用框架层的启动过程。Phone实例是Telephony框架对象,可以向该对象发起各种通讯相关的请求,Phone对象是Telephony整个框架的核心,负责与抽象出的中间层RIL交互,进而间接与modem端进行交互。
Phone对象是在PhoneApp这个application初始化过程中被创建的。
Telephony应用层
PhoneApp简介
首先PhoneApp的主要功能是什么呢?
- 负责实例化创建Telephony应用框架层(phone),且和phone一起运行在com.android.phone进程中
- 管理(CallManager),控制通话相关的UI、功能操作、业务逻辑实现
这里我们需要知道,Android系统中多个应用程序(Apk)是可以运行在同一个进程中的,PhoneApp就是这样,连同Stk、SMSProvider、TelephonyProvider等模块都运行在com.android.phone进程中(简称phone进程)。
Phone相关业务
业务名称 | 业务功能 |
---|---|
CDMA 业务 | 支持CDMA业务的手机 |
GSM 业务 | 支持GSM业务的手机 |
IMS业务 | 支持IMS业务的手机 |
EUICC业务 | 支持EUICC的手机,embedded SIM,嵌入式SIM卡 |
MBMS业务 | MBMS:Multimedia Broadcast Multicast Service,多媒体广播多播业务 |
CAT业务 | STK相关业务的支持 |
DataConnection | 数据连接相关的业务 |
SIP业务 | Session Initiation Protocol,VoLTE,ViLTE,VoWifi |
Phone的作用
- 注册监听事件,及时上报消息(Call状态变化、Service状态变化、新来电等等)
- 间接的为其他类提供跟modem交互的服务
PhoneApp的启动流程
请看下面流程图:
根据此图可看出PhoneApp应用的整个启动过程以及其在启动后具体做了哪些工作,接下来我们根据这个类图进行PhoneApp启动流程梳理:
PhoneApp的路径是:packages\services\Telephony,我们来看看它的AndroidManifest.xml内容:
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/phoneAppLabel"
android:icon="@mipmap/ic_launcher_phone"
android:allowBackup="false"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
......
</application>
- persistent属性的作用:开机时被系统自动初始化;该模块所在的进程(com.android.phone)由于任何原因被kill掉之后,都会自动重启(这种情况只针对系统内置app,第三方安装的app不会被重启)
- directBootAware属性的作用:该属性使得用户在加密状态(未解锁)下能够正常使用一些手机功能,如闹钟、接电话等,但不允许访问私有应用数据
系统在启动时会先启动SystemService,SystemService会启动各种系统服务,包括AMS:
private void startBootstrapServices() {
......
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer);
......
}
而ActivityManagerService的SystemReady方法中就有一个启动PersistentApps的方法,且该应用还需要MATCH_DIRECT_BOOT_AWARE,而PhoneApp正满足此需求:
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
......
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
......
}
由此可见,PhoneApk会在系统启动起来的时候由系统自动启动,启动后会先执行PhoneApp的onCreate()方法:
public class PhoneApp extends Application {
PhoneGlobals mPhoneGlobals;
TelephonyGlobals mTelephonyGlobals;
public PhoneApp() {
}
@Override
public void onCreate() {
if (UserHandle.myUserId() == 0) {
// We are running as the primary user, so should bring up the
// global phone state.
mPhoneGlobals = new PhoneGlobals(this);// 创建PhoneGlobals,即Phone的全局状态
mPhoneGlobals.onCreate();
// 创建TelephonyGlobals,即Telephony应用的全局状态
// TelephonyGlobals在整个工程中没看到使用的地方,类中只是创建个实例和初始化TtyMananger,看解释是与PSTN call相关
mTelephonyGlobals = new TelephonyGlobals(this);
mTelephonyGlobals.onCreate();
}
}
}
PhoenApp的onCreate()方法主要创建了mPhoneGlobals对象和mTelephonyGlobals对象,并执行了两个对象的onCreate()方法,接下来的流程也将围绕这两个对象的onCreate展开:
public void onCreate() {
if (VDBG) Log.v(LOG_TAG, "onCreate()...");
ContentResolver resolver = getContentResolver();
// Cache the "voice capable" flag.
// This flag currently comes from a resource (which is
// overrideable on a per-product basis):
// 缓存 "voice capable" 标志,来自资源文件的配置
sVoiceCapable = getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
if (mCM == null) {
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);// 初始化telephony framework
// Start TelephonyDebugService After the default phone is created.
Intent intent = new Intent(this, TelephonyDebugService.class);
startService(intent);
mCM = CallManager.getInstance();// 实例化通话管理类CallManager,并把phone注册进去
for (Phone phone : PhoneFactory.getPhones()) {
mCM.registerPhone(phone);
}
// Create the NotificationMgr singleton, which is used to display
// status bar icons and control other status bar behavior.
notificationMgr