每个进程在AMS侧对应有一个ProcessRecord。这些ProcessRecord是通过ProcessMap来管理的。
第一部分:进程启动
进程的启动的入口函数是AMS.startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge)。在前面的文章中知道,当启动Activity、Service、getContentProvider时如果目标进程未启动,那么就需要调用startProcessLocked()来启动目标进程。
step 1、AMS.startProcessLocked()
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge); //①获取进程记录块
} else {
// If this is an isolated process, it can't re-use an existing process.
app = null;
}
…………
if (app == null) {
app = newProcessRecordLocked(info, processName, isolated); //②创建一个ProcessRecord进程记录块,并保存在mProcessNames中
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
mProcessNames.put(processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, mProcessStats);
}
……………
startProcessLocked(app, hostingType, hostingNameStr); //③真正进程启动函数
return (app.pid != 0) ? app : null;
}
接着分析startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) 函数。
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
if (app.pid > 0 && app.pid != MY_PID) {
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.setPid(0);
}
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
"startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app); //①如果mProcessesOnHold中记录着正在启动的ProcessRecord,那么直接移除。
updateCpuStats();
try {
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
final PackageManager pm = mContext.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName); //②获取Gid信息,在进程启动时使用
if (Environment.isExternalStorageEmulated()) {
if (pm.checkPermission(
android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
app.info.packageName) == PERMISSION_GRANTED) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
}
}
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
/*
* Add shared application GID so applications can share some
* resources like shared libraries
*/
if (permGids == null) {
gids = new int[1];
} else {
gids = new int[permGids.length + 1];
System.arraycopy(permGids, 0, gids, 1, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
}
…………
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, null); //③启动进程(Process.start())
BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
synchronized (bs) {
if (bs.isOnBattery()) {
bs.getProcessStatsLocked(app.uid, app.processName).incStartsLocked();
}
}
if (app.persistent) {
Watchdog.getInstance().processStarted(app.processName, startResult.pid);
}
app.setPid(startResult.pid); //④将进程启动返回的结果初始化ProcessRecord。
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
} catch (RuntimeException e) {
// XXX do better error recovery.
app.setPid(0);
Slog.e(TAG, "Failure starting process " + app.processName, e);
}
}
step 2、Process.start()
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,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
start函数直接调用Process.startViaZygote()-->zygoteSendArgsAndGetResult(),从名字可以看出,进程是从Zygote中孵化出来的。
step 3、zygoteSendArgsAndGetResult()
private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
throws ZygoteStartFailedEx {
openZygoteSocketIfNeeded();
try {
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
sZygoteWriter.write(Integer.toString(args.size()));
sZygoteWriter.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
}
sZygoteWriter.flush();
// Should there be a timeout on this?
ProcessStartResult re