本文源代码基于 Android 7.0。
一个进程里可以运行多个 app,一个 app 也可以运行在多个进程中,通过配置 Android:process 属性来决定。进程对 Android 来说非常重要,承载着 Android 的四大组件,影响着系统的正常运转。
目录:
- 四大组件与进程
- 进程启动的全过程
- 启动过程图
1. 四大组件与进程
Activity, Service, ContentProvider, BroadcastReceiver 这四大组件,在启动的过程,当其所承载的进程不存在时需要调用startProcessLocked 先创建进程。
- 1.1 Activity
启动 Activity 过程:调用 startActivity,该方法经过层层调用,最终会调用 ActivityStackSupervisor.startSpecificActivityLocked() ,当 activity 所属进程还没启动的情况下,则需要创建相应的进程。
/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// 获取 ProcessRecord
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (app != null && app.thread != null) {
// 进程已创建
return;
}
// 进程没创建,去创建进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
代码中的 mService 为 ActivityManagerService。
- 1.2 Service
启动服务过程:调用 startService,该方法经过层层调用,最终会调用 ActiveServices.bringUpServiceLocked(),
当 Service 进程没有启动的情况 (app==null),则需要创建相应的进程。
/base/services/core/java/com/android/server/am/ActiveServices.java
private final String bringUpServiceLocked(...){
...
ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app == null) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
...
}
}
...
}
mAm 为 ActivityManagerService。
- 1.3 ContentProvider
ContentProvider 处理过程:调用 ContentResolver.query() 该方法经过层层调用,最终会调用到 AcitivtyManagerService.getContentProviderImpl(),当 ContentProvider 所对应进程不存在,则需要创建新进程。
/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final ContentProviderHolder getContentProviderImpl(...) {
...
ProcessRecord proc = getProcessRecordLocked(cpi.processName, cpr.appInfo.uid, false);
if (proc != null && proc.thread != null) {
... //进程已创建
} else {
proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, 0, "content provider",
new ComponentName(cpi.applicationInfo.packageName,cpi.name),
false, false, false);
}
...
}
- 1.4 Broadcast
广播处理过程:调用 sendBroadcast,该方法经过层层调用,最终会调用到 BroadcastQueue.processNextBroadcast(),
当 BroadcastReceiver 所对应的进程尚未启动,则创建相应进程。
/base/services/core/java/com/android/server/am/BroadcastQueue.java
final void processNextBroadcast(boolean fromMsg) {
...
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
if (app != null && app.thread != null) {
... //进程已创建
return
}
if ((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
"broadcast", r.curComponent,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
== null) {
...
}
...
}
mService 为 ActivityManagerService。
- 1.5 启动进程
/base/services/core/java/com/android/server/am/ActivityManagerService.java
四大组件所在应用首次启动时,会调用 startProcessLocked()。
/**
* 在ActivityManagerService.java 启动进程有4个同名不同参数的重载方法StartProcessLocked
*/
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
}
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */,
null /* entryPoint */, null /* entryPointArgs */);
}
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
//...
}
- 1.6 进程创建触发时机
大多数情况下,app 都是单进程架构,对于多进程架构的 app 一般是通过在 AndroidManifest.xml 中 android:process 属性来实现的:
- 当 android:process 属性值以 ":" 开头,则代表进程是私有的,只有该 app 可以使用,其他应用无法访问。
- 当 android:process 属性值不以 ":" 开头,则代表的是全局型进程,但是这种情况需要注意的是进程名必须包含 "." 字符。
/base/core/java/android/content/pm/PackageParser.java
PackageParser.java 来解析 AndroidManiefst.xml 过程就明白进程名的命名要求:
private static String buildCompoundName(String pkg,
CharSequence procSeq, String type, String[] outError) {
String proc = procSeq.toString();
char c = proc.charAt(0);
if (pkg != null && c == ':') {
if (proc.length() < 2) {
outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
+ ": must be at least two characters";
return null;
}
String subName = proc.substring(1);
String nameError = validateName(subName, false, false);
if (nameError != null) {
outError[0] = "Invalid " + type + " name " + proc + " in package "
+ pkg + ": " + nameError;
return null;
}
return (pkg + proc).intern();
}
String nameError = validateName(proc, true, false);
if (nameError != null && !"system".equals(proc)) {
outError[0] = "Invalid " + type + " name " + proc + " in package "
+ pkg + ": " + nameError;
return null;
}
return proc.intern();
}
单进程 App:
- 对于这种情况,那么 app 首次启动某个组件时,比如通过调用 startActivity 来启动某个 app,则先会触发创建该 app 进程,然后再启动该 Activity。此时该 app 进程已创建,那么后续再该 app 中内部启动同一个 activity 或者其他组件,则都不会再创建新进程 (除非该 app 进程被系统所杀掉)。
多进程 App:
- 对于这种情况,那么每个配置过 android:process 属性的组件的首次启动,则都分别需要创建进程。再次启动同一个activity,则不会再创建新进程 (除非该 app 进程被系统所杀掉),但如果启动的是其他组件,则还需要再次判断其所对应的进程是否存在。
- 1.7 小结
Activity,Service,ContentProvider,BroadcastReceiver 这四大组件在启动时,当所承载的进程不存在时,包括多进程的情况,则都需要创建。进程的创建过程交由系统进程 system_server 来完成的。
systemserver 进程中调用 startProcessLocked 方法,该方法最终通过 socket 方式,将需要创建新进程的消息告知 Zygote 进程,并阻塞等待 Socket 返回新创建进程的 pid。Zygote 进程接收到 systemserver 发送过来的消息,则通过 fork 的方法,将zygote 自身进程复制生成新的进程,并将 ActivityThread 相关的资源加载到新进程 app process,这个进程可能是用于承载activity 等组件。
创建完新进程后 fork 返回两次,在新进程 app process 向 servicemanager 查询 systemserver 进程中 Binder 服务端 ActivityManagerSerivce,获取相对应的 Client 端,也就是 ActivityManagerProxy。有了这一对 Binder c/s 对,那么 app process便可以通过 Binder 向跨进程 systemserver 发送请求,即 attachApplication()。
systemserver 进程接收到相应 Binder 操作后,经过多次调用,利用 ApplicationThreadProxy 向 app process 发送 Binder 请求, 即 bindApplication。systemserver 拥有 ApplicationThreadProxy/ActivityManagerSerivce,每一个新创建的进程都会有一个相应的 ApplicationThreadProxy/ActivityManagerSerivce,从而可以跨进程进行相互通信,这便是进程创建过程的完整生态链。
2. 进程启动的全过程
从 ActivityManagerService.startProcessLocked() 开始。
- 2.1 ActivityManagerService.startProcessLocked()
/base/services/core/java/com/android/server/am/ActivityManagerService.java
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
if (!isolated) {
//根据进程名和uid检查相应的ProcessRecord
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
// 如果当前处于后台进程,检查当前进程是否处于bad进程列表
if (mBadProcesses.get(info.processName, info.uid) != null) {
return null;
}
} else {
// 当用户明确地启动进程,则清空crash次数,以保证其不处于bad进程直到下次再弹出crash对话框。
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
mBadProcesses.remove(info.processName, info.uid);
if (app != null) {
app.bad = false;
}
}
}
} else {
// 对于孤立进程,无法再利用已存在的进程
app = null;
}
// 当存在ProcessRecord,且已分配pid(正在启动或者已经启动),
// 且caller并不认为该进程已死亡或者没有thread对象attached到该进程.则不应该清理该进程
if (app != null && app.pid > 0) {
if (!knownToBeDead || app.thread == null) {
//如果这是进程中新package,则添加到列表
app.addPackage(info.packageName, info.versionCode, mProcessStats);
return app;
}
//当ProcessRecord已经被attached到先前的一个进程,则杀死并清理该进程
killProcessGroup(app.info.uid, app.pid);
handleAppDiedLocked(app, true, true);
}
String hostingNameStr = hostingName != null? hostingName.flattenToShortString() : null;
if (app == null) {
// 创建新的Process Record对象
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
return null;
}
app.crashHandler = crashHandler;
} else {
// 如果这是进程中新package,则添加到列表
app.addPackage(info.packageName, info.versionCode, mProcessStats);
}
// 当系统未准备完毕,则将当前进程加入到mProcessesOnHold
if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
return app;
}
// 启动进程
startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
return (app.pid != 0) ? app : null;
}
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride,
String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
//当app的pid大于0且不是当前进程的pid,则从mPidsSelfLocked中移除该app.pid
if (app.pid > 0 && app.pid != MY_PID) {
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.setPid(0);
}
//从mProcessesOnHold移除该app
mProcessesOnHold.remove(app);
updateCpuStats(); //更新cpu统计信息
try {
try {
if (AppGlobals.getPackageManager().isPackageFrozen(app.info.packageName)) {
// 当前package已被冻结,则抛出异常
throw new RuntimeException("Package " + app.info.packageName + " is frozen!");
}
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
//通过Package Manager获取gids
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName, app.userId);
MountServiceInternal mountServiceInternal = LocalServices.getService(
MountServiceInternal.class);
mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
// 添加共享app和gids,用于app直接共享资源
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[2];
} else {
gids = new int[permGids.length + 2];
System.arraycopy(permGids, 0, gids, 2, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
//根据不同参数,设置相应的debugFlags
...
app.gids = gids;
app.requiredAbi = requiredAbi;
app.instructionSet = instructionSet;
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
// 请求Zygote创建新进程[见3.3]
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
...
if (app.persistent) {
Watchdog.getInstance().processStarted(app.processName, startResult.pid);
}
//重置ProcessRecord的成员变量
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
app.killed = false;
app.killedByAm = false;
// 将新创建的进程加入到mPidsSelfLocked
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
//延迟发送消息PROC_START_TIMEOUT_MSG
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
} catch (RuntimeException e) {
app.setPid(0); //进程创建失败,则重置pid
}
}
根据不同参数,设置相应的 debugFlags,比如在 AndroidManifest.xml 中设置 androidd:debuggable 为 true,代表 app 运行在debug 模式,则增加 debugger 标识以及开启 JNI check 功能,调用 Process.start 来创建新进程。
- 2.2 Process.start()
/base/core/java/android/os/Process
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 abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
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,
String abi,
String instructionSet,
String appDataDir,
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 ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
argsForZygote.add("--enable-safemode");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
argsForZygote.add("--enable-debugger");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
argsForZygote.add("--enable-checkjni");
}
if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
argsForZygote.add("--generate-debug-info");
}
if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) {
argsForZygote.add("--always-jit");
}
if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {
argsForZygote.add("--native-debuggable");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
//TODO optionally enable debuger
//argsForZygote.add("--enable-debugger");
// --setgroups is a comma-separated list
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");
int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}
if (seInfo != null) {
argsForZygote.add("--seinfo=" + seInfo);
}
if (instructionSet != null) {
argsForZygote.add("--instruction-set=" + instructionSet);
}
if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
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.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.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");
}
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
Process.start() 是通过 socket 通信告知 Zygote 创建 fork 子进程,这边调用 ZygoteState 来发送消息,ZygoteState 定义如下:
public static class ZygoteState {
final LocalSocket socket;
final DataInputStream inputStream;
final BufferedWriter writer;
final List<String> abiList;
boolean mClosed;
//...
}
创建新进程后将 ActivityThread 类加载到新进程,并调用 ActivityThread.main() 方法。
- 2.3 ActivityThread.main()
/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
//性能统计默认是关闭的
SamplingProfilerIntegration.start();
//将当前进程所在userId赋值给sCurrentUser
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
AndroidKeyStoreProvider.install();
//确保可信任的CA证书存放在正确的位置
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//创建主线程的Looper对象, 该Looper是不运行退出
Looper.prepareMainLooper();
//创建ActivityThread对象
ActivityThread thread = new ActivityThread();
//建立Binder通道
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// 当设置为true时,可打开消息队列的debug log信息
if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop(); //消息循环运行
throw new RuntimeException("Main thread loop unexpectedly exited");
}
创建主线程的 Looper 对象:该 Looper 是不运行退出,也就是说主线程的 Looper 是在进程创建完成时自动创建完成,如果子线程也需要创建 handler 通信过程,那么就需要手动创建 Looper 对象,并且每个线程只能创建一次。
创建 ActivityThread 对象:
public final class ActivityThread {
final ApplicationThread mAppThread = new ApplicationThread();
final Looper mLooper = Looper.myLooper();
final H mH = new H();
}
该过程会初始化几个很重要的变量:
- mAppThread = new ApplicationThread()
- mLooper = Looper.myLooper()
- mH = new H(),H 继承于 Handler,用于处理组件的生命周期
attach 过程是当前主线程向 system_server 进程通信的过程,将 thread 信息告知 ActivityThreadService。接下来还会进一步说明该过程,sMainThreadHandler 通过 getHandler(),获取的对象便是 mH,这就是主线程的 handler 对象。之后主线程调用Looper.loop(),进入消息循环状态,当没有消息时主线程进入休眠状态,一旦有消息到来则唤醒主线程并执行相关操作。
- 2.4 ActivityThread.attach()
/base/core/java/android/app/ActivityThread.java
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
// 开启虚拟机的jit即时编译功能
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
// 获取ActivityManagerProxy对象
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
// 调用基于IActivityManager接口的Binder通道
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
// 观察是否快接近heap的上限
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
mSomeActivitiesChanged = false;
try {
// 当已用内存超过最大内存的3/4,则请求释放内存空间
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
}
}
}
});
} else {
...
}
// 添加dropbox日志到libcore
DropBox.setReporter(new DropBoxReporter());
// 添加Config回调接口
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
synchronized (mResourcesManager) {
if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(newConfig)) {
mPendingConfiguration = newConfig;
sendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
}
}
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
});
}
对于非系统 attach 的处理流程:
- 创建线程来开启虚拟机的 jit 即时编译。
- 通过 binder,调用到 ActivityManagerService.attachApplication(),其参数 mAppThread 的数据类型为 ApplicationThread。
- 观察是否快接近 heap 的上限,当已用内存超过最大内存的3/4,则请求释放内存空间。
- 添加 dropbox 日志到 libcore。
- 添加 Config 回调接口。
- 2.5 ActivityManagerService.attachApplication()
/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
// ActivityManagerNative调用attachApplication
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
// 根据pid获取ProcessRecord
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
if (pid > 0 && pid != MY_PID) {
// ProcessRecord为空,则杀掉该进程
Process.killProcessQuiet(pid);
} else {
try {
// 退出新建进程的Looper
thread.scheduleExit();
} catch (Exception e) {
}
}
return false;
}
// 还刚进入attach过程,此时thread应该为null, 若不为null则表示该app附到上一个进程,则立刻清空
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}
final String processName = app.processName;
try {
// 绑定死亡通知
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
// 重新启动进程
startProcessLocked(app, "link fail", processName);
return false;
}
// 重置进程信息
app.makeActive(thread, mProcessStats); // 执行完该语句,则app.thread便不再为空
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
// app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
}
if (!normalMode) {
Slog.i(TAG, "Launching preboot mode app: " + app);
}
if (DEBUG_ALL) Slog.v(
TAG, "New app record " + app
+ " thread=" + thread.asBinder() + " pid=" + pid);
try {
// 获取应用appInfo
ApplicationInfo appInfo = app.instrumentationInfo != null
? app.instrumentationInfo : app.info;
// 绑定应用
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
// 更新进程LRU队列
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
// 每当bind操作失败,则重启启动进程, 此处有可能会导致进程无限重启
startProcessLocked(app, "bind fail", processName);
return false;
}
//...
if (badApp) {
// 杀掉bad应用
app.kill("error during init", true);
handleAppDiedLocked(app, false, true);
return false;
}
if (!didSomething) {
// 更新adj的值
updateOomAdjLocked();
}
return true;
}
- 根据 pid 从 mPidsSelfLocked 中查询到相应的 ProcessRecord 对象 app。
- 当 app==null,意味着本次创建的进程不存在,则直接返回。
- 还刚进入 attach 过程,此时 thread 应该为 null,若不为 null 则表示该 app 附到上一个进程,则调用 handleAppDiedLocked 清理。
- 绑定死亡通知,当进程 pid 死亡时会通过 binder 死亡回调,来通知 system_server 进程死亡的消息。
- 重置 ProcessRecord 进程信息,此时 app.thread 也赋予了新值,便不再为空。
- app 进程存在正在启动中的 provider,则超时 10s 后发送 CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG 消息。
- 调用 thread.bindApplication 绑定应用进程。
- 处理 Provider,Activity,Service,Broadcast 相应流程。
- 2.6 ApplicationThreadProxy.bindApplication()
最终会通过 Binder 调用到 ApplicationThreadNative.onTransact() 的 BIND_APPLICATION_TRANSACTION 分支。
/base/core/java/android/app/ApplicationThreadNative.java
case BIND_APPLICATION_TRANSACTION:
{
// ...
HashMap<String, IBinder> services = data.readHashMap(null);
Bundle coreSettings = data.readBundle();
bindApplication(packageName, info, providers, testName, profilerInfo, testArgs,
testWatcher, uiAutomationConnection, testMode, enableBinderTracking,
trackAllocation, restrictedBackupMode, persistent, config, compatInfo, services,
coreSettings);
return true;
}
- 2.7 ActivityThread$ApplicationThread.bindApplication()
/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends ApplicationThreadNative {
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
// 将services缓存起来, 减少binder检索服务的次数
ServiceManager.initServiceCache(services);
}
// 发送消息H.SET_CORE_SETTINGS
setCoreSettings(coreSettings);
// 初始化AppBindData
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
// ...
sendMessage(H.BIND_APPLICATION, data);
}
}
ActivityThread.H 收到消息后,会调用 handleBindApplication():
private class H extends Handler {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
- 2.8 ActivityThread.handleBindApplication()
/base/core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
...
//设置进程名, 也就是说进程名是在进程真正创建以后的BIND_APPLICATION过程中才取名
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());
if (data.persistent) {
//低内存设备, persistent进程不采用硬件加速绘制,以节省内存使用量
if (!ActivityManager.isHighEndGfx()) {
HardwareRenderer.disable(false);
}
}
//重置时区
TimeZone.setDefault(null);
Locale.setDefault(data.config.locale);
//更新系统配置
mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
applyCompatConfiguration(mCurDefaultDisplayDpi);
//获取LoadedApk对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
// 创建ContextImpl上下文
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if (!Process.isIsolated()) {
final File cacheDir = appContext.getCacheDir();
if (cacheDir != null) {
System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
}
//用于存储产生/编译的图形代码
final File codeCacheDir = appContext.getCodeCacheDir();
if (codeCacheDir != null) {
setupGraphicsSupport(data.info, codeCacheDir);
}
}
...
//当处于调试模式,则运行应用生成systrace信息
boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(appTracingAllowed);
//初始化 默认的http代理
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
}
if (data.instrumentationName != null) {
...
} else {
mInstrumentation = new Instrumentation();
}
//FLAG_LARGE_HEAP则清除内存增长上限
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
} else {
dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
}
try {
// 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象[见小节3.14]
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
if (!data.restrictedBackupMode) {
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
mInstrumentation.onCreate(data.instrumentationArgs);
//调用Application.onCreate()回调方法.
mInstrumentation.callApplicationOnCreate(app);
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
在 handleBindApplication() 的过程中,会同时设置以下两个值:
- LoadedApk.mApplication
- ActivityThread.mInitialApplication
2.9 ActivityThread.getPackageInfoNoCheck()
/base/core/java/android/app/ActivityThread.java
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true, false);
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
ref = null;
} else if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (mSystemThread && "android".equals(aInfo.packageName)) {
packageInfo.installSystemApplicationInfo(aInfo,
getSystemContext().mPackageInfo.getClassLoader());
}
if (differentUser) {
} else if (includeCode) {
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
上面过程为创建 LoadedApk 对象。
- 2.10 LoadedApk.makeApplication()
/base/core/java/android/app/LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
// 创建 ContextImpl 对象
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// 反射创建 Application 对象
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
// 设置mApplication对象值
mApplication = app;
if (instrumentation != null) {
try {
// 回调 Application 的 onCreate() 方法
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
return app;
}
获取 ClassLoader,根据 ActivityThread 创建 ContextImpl,然后调用 mActivityThread.mInstrumentation.newApplication(),传入参数 ClassLoader, "android.app.Application" 和 ContextImpl。
- 2.11 Instrumentation.newApplication() & callApplicationOnCreate()
/base/core/java/android/app/Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
3. 启动过程图