之前解决一个开机搜网慢的问题时,发现由于Phone进程起来以后才会主动连接RILD,因而在一定程度上Phone进程启动的时间会影响网络状态注册的快慢。适当的将Phone进程提前,可以将网络注册时间提前一点,让状态栏中信号显示的时间提前。那么,Android中作为系统的核心进程之一,Phone进程是如何启动的了?
RIL运行机制请参考: http://blog.csdn.net/jason_wzn/article/details/53232022
Telephony最开始创建的是PhoneFactory
对象,直接搜索源码,可以看到在PhoneGlobals.java
创建时,会调用PhoneFactory
对Telephony进行初始化操作:
/**
* Global state for the telephony subsystem when running in the primary
* phone process.
*/
public class PhoneGlobals extends ContextWrapper {
public void onCreate() {
Log.v(LOG_TAG, "[email protected]_SVC : PhoneApp OnCrate");
// CallManager为空
if (mCM == null) {
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);
// 创建CallManager实例
mCM = CallManager.getInstance();
for (Phone phone : PhoneFactory.getPhones()) {
mCM.registerPhone(phone);
}
....
}
}
那么,PhoneGlobals
又是在哪里创建的了?再次搜索代码,可以看到在同一文件目录下,有一个PhoneApp.java
文件:
@Override
public void onCreate() {
Log.d("PhoneApp", "onCreate");
if (UserHandle.myUserId() == 0) {
// 创建PhoneGlobals实例
mPhoneGlobals = new PhoneGlobals(this);
mPhoneGlobals.onCreate();
mTelephonyGlobals = new TelephonyGlobals(this);
mTelephonyGlobals.onCreate();
} else {
Log.d("PhoneApp", "Phone app is created as userid not 0, there‘s no PhoneApp() Instance");
}
....
}
那么,PhoneApp
这个类又是什么时候创建的?我们知道,每一个Android应用都有一个Application
与之对应,它是在应用启动过程中创建的,但是在这里搜索所有的源码,也无法看到PhoneApp
创建的地方。实在想不出来,找了下度娘,才发现了真正启动Phone进程的地方。
打开Phone进程所在的源码路径: /android/applications/sources/services/Telephony/
,查看应用对应的AndroidManefest.xml
文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.phone"
android:versionCode="1"
android:versionName="1.0.0"
coreApp="true"
android:sharedUserId="android.uid.phone"
android:sharedUserLabel="@string/phoneAppLabel" >
.....
<application android:name="PhoneApp"
android:persistent="true"
android:hardwareAccelerated="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>
</manifest>
在application
标签下面,可以看到android:persistent="true"
这个属性值,看一看官方的文档怎么解释的:
android:persistent
Whether or not the application should remain running at all times — “true” if it should, and “false” if not. The default value is “false”. Applications should not normally set this flag; persistence mode is intended only for certain system applications.
由此可见,Phone应用是系统常驻进程,一旦起来后就会一直运行,不会被杀死。对于这类常驻进程,ActivityManagerService
(以下简称AMS)会对其做特殊处理。在SystemServer
初始化完系统的核心服务后,其会调用AMS的systemReady(Runnable r)
函数:
public void systemReady(final Runnable goingCallback) {
synchronized (this) {
// Only start up encryption-aware persistent apps; once user is
// unlocked we‘ll come back around and start unaware apps
// 正是在这里,PhoneApp被创建!
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
// Start up initial activity.
mBooting = true;
// Enable home activity for system user, so that the system can always boot
if (UserManager.isSplitSystemUser()) {
ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
try {
AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
startHomeActivityLocked(currentUserId, "systemReady");
}
}
启动所有PackageManager.MATCH_DIRECT_BOOT_AWARE
标志为true
的应用:
private void startPersistentApps(int matchFlags) {
synchronized (this) {
try {
//获取系统所有常驻应用程序信息
final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
for (ApplicationInfo app : apps) {
if (!"android".equals(app.packageName)) {
//加载应用
addAppLocked(app, false, null /* ABI override */);
}
}
} catch (RemoteException ex) {
}
}
}
//添加应用程序进程到LRU列表中,并创建进程
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
String abiOverride) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(info.processName, info.uid, true);
} else {
app = null;
}
if (app == null) {
app = newProcessRecordLocked(info, null, isolated, 0);
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
....
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
//启动应用
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app, "added application", app.processName, abiOverride,
null /* entryPoint */, null /* entryPointArgs */);
}
return app;
}
准备创建应用进程:
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
Process.ProcessStartResult startResult = null;
if(userid>0 && (bbcId>0 && userid == bbcId) && app.info.bbcseinfo!=null){
//启动进程
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.bbcseinfo, app.info.bbccategory, app.info.accessInfo,
requiredAbi, instructionSet,
app.info.dataDir, mountKnoxPoint, entryPointArgs);
}esle{
...
}
}
调用Process.start()
,创建一个新的进程ActivityThread
,Phone进程就运行在该进程当中:
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
int category,
int accessInfo,
String abi,
String instructionSet,
String appDataDir,
boolean mountKnoxPoint,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo, category, accessInfo,
abi, instructionSet, appDataDir, mountKnoxPoint, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
发送消息到zygote的socket端口,请求创建新的进程:
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
int category,
int accessInfo,
String abi,
String instructionSet,
String appDataDir,
boolean mountKnoxPoint,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
....
if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}
....
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
//发送消息到zygote的socket端口,请求创建新的进程
if (Zygote.isEnhancedZygoteASLREnabled) {
....
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
// End of isEnhancedZygoteASLREnabled case
} else {
// Original case
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
}
这样Phone进程就创建启动完成了。整个流程看下来,研究Android系统,源码是王道,但要深入理解系统背后的设计,还是需要从把基本的概念梳理清楚,才能更好的理解系统背后设计的逻辑。