相关文章:

ATMS中去pause Activity A.

目录

ATMS拉起新进程

这个流程相对复杂一点,并不是一直调用下来,中间做了几次往Handler转发的操作.我的理解是:

  1. 平衡负载,把不同的逻辑运行到不同的线程上,可以及时释放binder线程的运行资源.
  2. 及时释放锁资源.启动新进程相对是个耗时的任务,而在ActivityStarter.execute,是持有了Android中的com.android.server.wm.WindowManagerGlobalLock锁的.转发到其他线程去处理也可以尽快其他逻辑,及时释放锁资源.

堆栈

startProcessAsync:5617, ActivityTaskManagerService
resumeTopActivityInnerLocked:1684, ActivityStack (com.android.server.wm)
resumeTopActivityUncheckedLocked:1511, ActivityStack (com.android.server.wm)
resumeFocusedStacksTopActivities:2299, RootWindowContainer (com.android.server.wm)
startActivityInner:1731, ActivityStarter (com.android.server.wm)
startActivityUnchecked:1521, ActivityStarter (com.android.server.wm)
executeRequest:1186, ActivityStarter (com.android.server.wm)
execute:669, ActivityStarter (com.android.server.wm)
startActivityAsUser:1100, ActivityTaskManagerService (com.android.server.wm)
startActivityAsUser:1072, ActivityTaskManagerService (com.android.server.wm)
startActivity:1047, ActivityTaskManagerService (com.android.server.wm)
onTransact:1422, IActivityTaskManager$Stub (android.app)
execTransactInternal:1154, Binder (android.os)
execTransact:1123, Binder (android.os)
startProcessLocked:1988, ProcessList (com.android.server.am)
startProcessLocked:1943, ProcessList (com.android.server.am)
startProcessLocked:2319, ProcessList (com.android.server.am)
startProcessLocked:2441, ProcessList (com.android.server.am)
startProcessLocked:3170, ActivityManagerService (com.android.server.am)
startProcess:19641, ActivityManagerService$LocalService (com.android.server.am)
accept:-1, -$$Lambda$qMFJUmfG50ZSjk7Tac67xBia0d4 (com.android.server.wm)
doInvoke:360, PooledLambdaImpl (com.android.internal.util.function.pooled)
invoke:201, PooledLambdaImpl (com.android.internal.util.function.pooled)
run:97, OmniFunction (com.android.internal.util.function.pooled)
handleCallback:938, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loop:223, Looper (android.os)
run:67, HandlerThread (android.os)
run:44, ServiceThread (com.android.server)

这个堆栈和上一篇文件中ATMS中去pause Activity A.是一样的.在AMTS调用Activity A 去执行Pause后. 就会检查待启动的Activity B是否已经有进程了.

resumeTopActivityInnerLocked:1684, ActivityStack

if (pausing) {
if (next.attachedToProcess()) {
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, false /* updateOomAdj */,
false /* addPendingTopUid */);
} else if (!next.isProcessRunning()) {
// Since the start-process is asynchronous, if we already know the process of next
// activity isn't running, we can start the process earlier to save the time to wait
// for the current activity to be paused.
final boolean isTop = this == taskDisplayArea.getFocusedStack();
mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
isTop ? "pre-top-activity" : "pre-activity");
}
if (lastResumed != null) {
lastResumed.setWillCloseOrEnterPip(true);
}
return true;
}

mAtmService.startProcessAsync :调用ATMS的startProcessAsync

startProcessAsync:5617, ActivityTaskManagerService

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
String hostingType) {
try {
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
isTop, hostingType, activity.intent.getComponent());
mH.sendMessage(m);
}
}

这里就是简单的新建了一个PooledLambda的message,然后通过mH发送出去了,这个mH对象的线程是android.display.

startProcess:19641, ActivityManagerService$LocalService (com.android.server.am)

上一节发送了一个ActivityManagerInternal::startProcess到mH的handler去执行.mAmInternal 获取的代码 mAmInternal = LocalServices.getService(ActivityManagerInternal.class);对应ActivityManagerService.所以这里实际是会执行到startProcess:19641, ActivityManagerService,这里只是简单调用startProcessLocked

startProcessLocked:3170, ActivityManagerService

final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
keepIfLarge, null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}

这里很简单的调用ProcessList的startProcessLocked.

startProcessLocked:2441, ProcessList

@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
Runnable crashHandler) {
long startTime = SystemClock.uptimeMillis();
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
// If we are in the background, then check to see if this process
// is bad. If so, we will just silently fail.
if (mService.mAppErrors.isBadProcessLocked(info)) {
if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ "/" + info.processName);
return null;
}
} else {
// When the user is explicitly starting a process, then clear its
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ "/" + info.processName);
mService.mAppErrors.resetProcessCrashTimeLocked(info);
if (mService.mAppErrors.isBadProcessLocked(info)) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mService.mAppErrors.clearBadProcessLocked(info);
if (app != null) {
app.bad = false;
}
}
}
}
  1. 首先判断当前待启动的进程是否是isolated的,这里是非isolated进程,那么进程就是可以复用的,所以从当前的进程查看是否有相同名称,以及相同uid的进程,有的话那么直接返回这个进程
  2. 如果是从后台启动且进程是badProcess,那么直接返回;如果是前台启动的且badprocess,那么clearBadProcessLocked.并把app的bad值设置为false.
else {   // if (isolated)
// If this is an isolated process, it can't re-use an existing process.
app = null;
}

如果是isolated性质的进程,则不能复用,直接新启动一个.


ProcessRecord precedence = null;
if (app != null && app.pid > 0) {
if ((!knownToBeDead && !app.killed) || app.thread == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
checkSlow(startTime, "startProcess: done, added package to proc");
return app;
}

如果上一步找到了一个可用的app.并且这个app的thread为空,并且这个app不是已经死亡或者正在被kill的进程,那么说明之前已经有一个这样的进程,我们直接使用即可

            // An application record is attached to a previous process,
// clean it up now.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app);
checkSlow(startTime, "startProcess: bad proc running, killing");
ProcessList.killProcessGroup(app.uid, app.pid);
checkSlow(startTime, "startProcess: done killing old proc"); Slog.wtf(TAG_PROCESSES, app.toString() + " is attached to a previous process");
// We are not going to re-use the ProcessRecord, as we haven't dealt with the cleanup
// routine of it yet, but we'd set it as the precedence of the new process.
precedence = app;
app = null;
}

如果前面已经找到了一个进程,但是这个进程是之前遗留的出错进程,那么直接杀死它.

        if (app == null) {
checkSlow(startTime, "startProcess: creating new process record");
app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
app.crashHandler = crashHandler;
app.isolatedEntryPoint = entryPoint;
app.isolatedEntryPointArgs = entryPointArgs;
if (precedence != null) {
app.mPrecedence = precedence;
precedence.mSuccessor = app;
}
checkSlow(startTime, "startProcess: done creating new process record");
}

前面找到的进程有问题,或者没有找到进程,那么这里new一个ProcessRecord对象出来.

   else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
checkSlow(startTime, "startProcess: added package to existing proc");
}

虽然存在ProcessRecord,但是这个ProcessRecord并没有实际拉起来过(!pid>0),那么这里就把待启动的app相关信息给它.

        // If the system is not ready yet, then hold off on starting this
// process until it is.
if (!mService.mProcessesReady
&& !mService.isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mService.mProcessesOnHold.contains(app)) {
mService.mProcessesOnHold.add(app);
}
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
"System not ready, putting on hold: " + app);
checkSlow(startTime, "startProcess: returning with proc on hold");
return app;
}

系统没有启动好,这个时候就先不实际去启动进程了

        checkSlow(startTime, "startProcess: stepping in to startProcess");
final boolean success =
startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
checkSlow(startTime, "startProcess: done starting proc!");
return success ? app : null;

调用startProcessLocked执行后续部分.

总结一下:这里就是看系统有没有可以复用的ProcessRecord.

startProcessLocked:2319, ProcessList

final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
false /* mountExtStorageFull */, abiOverride);
}

直接转发了

startProcessLocked:1943, ProcessList

boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
boolean mountExtStorageFull, String abiOverride) {
if (app.pendingStart) {
return true;
}

如果暂时不需要启动的,那么直接返回.

        long startTime = SystemClock.uptimeMillis();
if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
checkSlow(startTime, "startProcess: removing from pids map");
mService.removePidLocked(app);
app.bindMountPending = false;
mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
checkSlow(startTime, "startProcess: done removing from pids map");
app.setPid(0);
app.startSeq = 0;
}

如果待启动的app已经有pid了.这个时候先清理一下信息.

TODO:前面已经判断过了pid的值,这个值为什么还会出现>0的情况?

        try {
try {
final int userId = UserHandle.getUserId(app.uid);
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
} 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 {
checkSlow(startTime, "startProcess: getting gids from package manager");
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DIRECT_BOOT_AUTO, app.userId);
if (StorageManager.hasIsolatedStorage() && mountExtStorageFull) {
mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
} else {
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
app.info.packageName);
}
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}

获取一些APP需要mount哪些内存地址的信息

                // Remove any gids needed if the process has been denied permissions.
// NOTE: eventually we should probably have the package manager pre-compute
// this for us?
if (app.processInfo != null && app.processInfo.deniedPermissions != null) {
for (int i = app.processInfo.deniedPermissions.size() - 1; i >= 0; i--) {
int[] denyGids = mService.mPackageManagerInt.getPermissionGids(
app.processInfo.deniedPermissions.valueAt(i), app.userId);
if (denyGids != null) {
for (int gid : denyGids) {
permGids = ArrayUtils.removeInt(permGids, gid);
}
}
}
} gids = computeGidsForProcess(mountExternal, uid, permGids);
}

处理拒绝权限:把被拒绝的权限重gids中移除

            app.mountMode = mountExternal;
checkSlow(startTime, "startProcess: building args");
if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
uid = 0;
}
int runtimeFlags = 0;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
// Also turn on CheckJNI for debuggable apps. It's quite
// awkward to turn on otherwise.
runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; // Check if the developer does not want ART verification
if (android.provider.Settings.Global.getInt(mService.mContext.getContentResolver(),
android.provider.Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE, 1) == 0) {
runtimeFlags |= Zygote.DISABLE_VERIFIER;
Slog.w(TAG_PROCESSES, app + ": ART verification disabled");
}
}
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || mService.mSafeMode) {
runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
}
if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL) != 0) {
runtimeFlags |= Zygote.PROFILE_FROM_SHELL;
}
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
if ("1".equals(genDebugInfoProperty) || "true".equals(genDebugInfoProperty)) {
runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
}
String genMiniDebugInfoProperty = SystemProperties.get("dalvik.vm.minidebuginfo");
if ("1".equals(genMiniDebugInfoProperty) || "true".equals(genMiniDebugInfoProperty)) {
runtimeFlags |= Zygote.DEBUG_GENERATE_MINI_DEBUG_INFO;
}
if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
runtimeFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
}
if ("1".equals(SystemProperties.get("debug.assert"))) {
runtimeFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
if ("1".equals(SystemProperties.get("debug.ignoreappsignalhandler"))) {
runtimeFlags |= Zygote.DEBUG_IGNORE_APP_SIGNAL_HANDLER;
}
if (mService.mNativeDebuggingApp != null
&& mService.mNativeDebuggingApp.equals(app.processName)) {
// Enable all debug flags required by the native debugger.
runtimeFlags |= Zygote.DEBUG_ALWAYS_JIT; // Don't interpret anything
runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info
runtimeFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; // Disbale optimizations
mService.mNativeDebuggingApp = null;
} if (app.info.isEmbeddedDexUsed()
|| (app.info.isPrivilegedApp()
&& DexManager.isPackageSelectedToRunOob(app.pkgList.mPkgList.keySet()))) {
runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
} if (!disableHiddenApiChecks && !mService.mHiddenApiBlacklist.isDisabled()) {
app.info.maybeUpdateHiddenApiEnforcementPolicy(
mService.mHiddenApiBlacklist.getPolicy());
@ApplicationInfo.HiddenApiEnforcementPolicy int policy =
app.info.getHiddenApiEnforcementPolicy();
int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
if ((policyBits & Zygote.API_ENFORCEMENT_POLICY_MASK) != policyBits) {
throw new IllegalStateException("Invalid API policy: " + policy);
}
runtimeFlags |= policyBits; if (disableTestApiChecks) {
runtimeFlags |= Zygote.DISABLE_TEST_API_ENFORCEMENT_POLICY;
}
} String useAppImageCache = SystemProperties.get(
PROPERTY_USE_APP_IMAGE_STARTUP_CACHE, "");
// Property defaults to true currently.
if (!TextUtils.isEmpty(useAppImageCache) && !useAppImageCache.equals("false")) {
runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
} runtimeFlags |= decideGwpAsanLevel(app); String invokeWith = null;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// Debuggable apps may include a wrapper script with their library directory.
String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
if (new File(wrapperFileName).exists()) {
invokeWith = "/system/bin/logwrapper " + wrapperFileName;
}
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
} String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
if (requiredAbi == null) {
requiredAbi = Build.SUPPORTED_ABIS[0];
} String instructionSet = null;
if (app.info.primaryCpuAbi != null) {
instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
} app.gids = gids;
app.setRequiredAbi(requiredAbi);
app.instructionSet = instructionSet; // If instructionSet is non-null, this indicates that the system_server is spawning a
// process with an ISA that may be different from its own. System (kernel and hardware)
// compatililty for these features is checked in the decideTaggingLevel in the
// system_server process (not the child process). As TBI is only supported in aarch64,
// we can simply ensure that the new process is also aarch64. This prevents the mismatch
// where a 64-bit system server spawns a 32-bit child that thinks it should enable some
// tagging variant. Theoretically, a 32-bit system server could exist that spawns 64-bit
// processes, in which case the new process won't get any tagging. This is fine as we
// haven't seen this configuration in practice, and we can reasonable assume that if
// tagging is desired, the system server will be 64-bit.
if (instructionSet == null || instructionSet.equals("arm64")) {
runtimeFlags |= decideTaggingLevel(app);
}

处理传递到zygote的一些配置

            // the per-user SELinux context must be set
if (TextUtils.isEmpty(app.info.seInfoUser)) {
Slog.wtf(ActivityManagerService.TAG, "SELinux tag not defined",
new IllegalStateException("SELinux tag not defined for "
+ app.info.packageName + " (uid " + app.uid + ")"));
}
final String seInfo = app.info.seInfo
+ (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
final String entryPoint = "android.app.ActivityThread"; return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
}

调用startProcessLocked 去处理.

startProcessLocked:1991, ProcessList

boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
app.pendingStart = true;
app.killedByAm = false;
app.removed = false;
app.killed = false;
if (app.startSeq != 0) {
Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
+ " with non-zero startSeq:" + app.startSeq);
}
if (app.pid != 0) {
Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
+ " with non-zero pid:" + app.pid);
}

处理一些异常情况

        app.mDisabledCompatChanges = null;
if (mPlatformCompat != null) {
app.mDisabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
}
final long startSeq = app.startSeq = ++mProcStartSeqCounter;
app.setStartParams(uid, hostingRecord, seInfo, startTime);
app.setUsingWrapper(invokeWith != null
|| Zygote.getWrapProperty(app.processName) != null);
mPendingStarts.put(startSeq, app);

待启动进程信息,放到PendingStarts中

        if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
mService.mProcStartHandler.post(() -> handleProcessStart(
app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
requiredAbi, instructionSet, invokeWith, startSeq));
return true;
} else {
try {
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startTime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} catch (RuntimeException e) {
Slog.e(ActivityManagerService.TAG, "Failure starting process "
+ app.processName, e);
app.pendingStart = false;
mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
false, false, true, false, false, app.userId, "start failure");
}
return app.pid > 0;
}
}

根据配置异步或者同步启动线程.

同步和异步流程是差不多的,但是异步复杂一点,我们直接看异步流程.这里通过mService.mProcStartHandler.post(() -> handleProcessStart( app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal, requiredAbi, instructionSet, invokeWith, startSeq));直接post了一个runable到procStart的线程.

handleProcessStart:2055, ProcessList

private void handleProcessStart(final ProcessRecord app, final String entryPoint,
final int[] gids, final int runtimeFlags, int zygotePolicyFlags,
final int mountExternal, final String requiredAbi, final String instructionSet,
final String invokeWith, final long startSeq) {
// If there is a precede instance of the process, wait for its death with a timeout.
// Use local reference since we are not using locks here
final ProcessRecord precedence = app.mPrecedence;
if (precedence != null) {
final int pid = precedence.pid;
long now = System.currentTimeMillis();
final long end = now + PROC_KILL_TIMEOUT;
try {
Process.waitForProcessDeath(pid, PROC_KILL_TIMEOUT);
// It's killed successfully, but we'd make sure the cleanup work is done.
synchronized (precedence) {
if (app.mPrecedence != null) {
now = System.currentTimeMillis();
if (now < end) {
try {
precedence.wait(end - now);
} catch (InterruptedException e) {
}
}
}
if (app.mPrecedence != null) {
// The cleanup work hasn't be done yet, let's log it and continue.
Slog.w(TAG, precedence + " has died, but its cleanup isn't done");
}
}
} catch (Exception e) {
// It's still alive...
Slog.wtf(TAG, precedence.toString() + " refused to die, but we need to launch "
+ app);
}
}

如果ProcessRecord对应有个先启动过的进程,这里先kill掉

todo:整个流程kill了几次,为什么呢?什么情况会出现到这里还存在上一次启动的进程没有杀死的情况?同步为什么不需要这样判断呢?

        try {
final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
entryPoint, app, app.startUid, gids, runtimeFlags, zygotePolicyFlags,
mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith,
app.startTime); synchronized (mService) {
handleProcessStartedLocked(app, startResult, startSeq);
}
}

调用startProcess去实际启动进程,handleProcessStartedLocked处理进程启动后的信息.

startProcess:2296, ProcessList

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
int mountExternal, String seInfo, String requiredAbi, String instructionSet,
String invokeWith, long startTime) {
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkSlow(startTime, "startProcess: asking zygote to start proc");
final boolean isTopApp = hostingRecord.isTopApp();
if (isTopApp) {
// Use has-foreground-activities as a temporary hint so the current scheduling
// group won't be lost when the process is attaching. The actual state will be
// refreshed when computing oom-adj.
app.setHasForegroundActivities(true);
}

如果是位于最上面的APP,那么先设置为has-foreground-activities,防止oom 杀死它?

            Map<String, Pair<String, Long>> pkgDataInfoMap;
Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
boolean bindMountAppStorageDirs = false;
boolean bindMountAppsData = mAppDataIsolationEnabled
&& (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
&& mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info); // Get all packages belongs to the same shared uid. sharedPackages is empty array
// if it doesn't have shared uid.
final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
app.info.packageName, app.userId);
final String[] targetPackagesList = sharedPackages.length == 0
? new String[]{app.info.packageName} : sharedPackages; pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
if (pkgDataInfoMap == null) {
// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
// tmp free pass.
bindMountAppsData = false;
} // Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so
// it won't be mounted twice.
final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps);
for (String pkg : targetPackagesList) {
whitelistedApps.remove(pkg);
} whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
whitelistedApps.toArray(new String[0]), uid);
if (whitelistedAppDataInfoMap == null) {
// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
// tmp free pass.
bindMountAppsData = false;
} int userId = UserHandle.getUserId(uid);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
if (needsStorageDataIsolation(storageManagerInternal, app)) {
bindMountAppStorageDirs = true;
if (pkgDataInfoMap == null ||
!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
app.processName)) {
// Cannot prepare Android/app and Android/obb directory or inode == 0,
// so we won't mount it in zygote, but resume the mount after unlocking device.
app.bindMountPending = true;
bindMountAppStorageDirs = false;
}
} // If it's an isolated process, it should not even mount its own app data directories,
// since it has no access to them anyway.
if (app.isolated) {
pkgDataInfoMap = null;
whitelistedAppDataInfoMap = null;
}

计算需要绑定的目录信息等.

            final Process.ProcessStartResult startResult;
if (hostingRecord.usesWebviewZygote()) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app); // We can't isolate app data and storage data as parent zygote already did that.
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}

分为不同的情况启动不同的zygote虚拟机

todo:这几种具体有什么分别?

startProcess:2296, ProcessList

调用到ZygoteProcess的start

start:372, ZygoteProcess

调用 startViaZygote启动进程.

todo:具体怎么调用到虚拟机,后续再开篇文章分析.

新进程调用attachApplication时,系统resume待启动的Activity

堆栈信息

obtain:94, ResumeActivityItem (android.app.servertransaction)
realStartActivityLocked:856, ActivityStackSupervisor (com.android.server.wm)
startActivityForAttachedApplicationIfNeeded:1965, RootWindowContainer (com.android.server.wm)
lambda$5fbF65VSmaJkPHxEhceOGTat7JE:-1, RootWindowContainer (com.android.server.wm)
apply:-1, -$$Lambda$RootWindowContainer$5fbF65VSmaJkPHxEhceOGTat7JE (com.android.server.wm)
doInvoke:315, PooledLambdaImpl (com.android.internal.util.function.pooled)
invoke:201, PooledLambdaImpl (com.android.internal.util.function.pooled)
apply:78, OmniFunction (com.android.internal.util.function.pooled)
forAllActivities:3620, ActivityRecord (com.android.server.wm)
forAllActivities:1331, WindowContainer (com.android.server.wm)
forAllActivities:1324, WindowContainer (com.android.server.wm)
attachApplication:1944, RootWindowContainer (com.android.server.wm)
attachApplication:6890, ActivityTaskManagerService$LocalService (com.android.server.wm)
attachApplicationLocked:5378, ActivityManagerService (com.android.server.am)
attachApplication:5458, ActivityManagerService (com.android.server.am)

上一步进程已经从zygote启动,并且调用attchApplication,这个调用就会到AMS中

attachApplication:5458, ActivityManagerService

public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}

简单的获取调用者的pid 和 uid ,然后就调用attachApplicationLocked(thread, callingPid, callingUid, startSeq);

attachApplicationLocked:5378, ActivityManagerService

这个函数是应用进程起来后,第一次调用到系统.系统需要做比较多的工作,我们这里分段来查看

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) { // Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
long bindApplicationTimeMillis;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
if (app != null && (app.startUid != callingUid || app.startSeq != startSeq)) {
String processName = null;
final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
if (pending != null) {
processName = pending.processName;
}
final String msg = "attachApplicationLocked process:" + processName
+ " startSeq:" + startSeq
+ " pid:" + pid
+ " belongs to another existing app:" + app.processName
+ " startSeq:" + app.startSeq;
Slog.wtf(TAG, msg);
// SafetyNet logging for b/131105245.
EventLog.writeEvent(0x534e4554, "131105245", app.startUid, msg);
// If there is already an app occupying that pid that hasn't been cleaned up
cleanUpApplicationRecordLocked(app, false, false, -1,
true /*replacingPid*/);
removePidLocked(app);
app = null;
}
} else {
app = null;
}

首先到系统的mPidsSelfLocked去查找是否进程号是否已经对应了一个ProcessRecord .如果系统已经这个ProcessRecord,并且这个启动序号seq,uid和当前进程不一致,说明该进程之前用于过其他的APP.那么这个时候就调用cleanUpApplicationRecordLocked(app, false, false, -1, true /*replacingPid*/); 清理一下相关信息.

继续往下看

        // It's possible that process called attachApplication before we got a chance to
// update the internal state.
if (app == null && startSeq > 0) {
final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
if (pending != null && pending.startUid == callingUid && pending.startSeq == startSeq
&& mProcessList.handleProcessStartedLocked(pending, pid, pending
.isUsingWrapper(),
startSeq, true)) {
app = pending;
}
}

上一个获取的ProcessReord app变量两种情况下可能为空 1. 该进程还没有加到mPidsSelfLocked里面.2 该进程号在mPidsSelfLocked可以找到,但是并不是当前进程. 这个时候就需要从 mProcessList.mPendingStarts中去获取这个pending的ProcessRecord.

继续往下看

        if (app == null) {
Slog.w(TAG, "No pending application record for pid " + pid
+ " (IApplicationThread " + thread + "); dropping process");
EventLogTags.writeAmDropProcess(pid);
if (pid > 0 && pid != MY_PID) {
killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
mProcessList.noteAppKill(app, ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
ApplicationExitInfo.SUBREASON_UNKNOWN, "attach failed");
} else {
try {
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return false;
}

如果mPidsSelfLocked 中没有, mProcessList.mPendingStarts也没有,说明这个进程不是系统拉起来的.那么就不该拉起它来. 如果这个进程不是系统进程,那么直接杀死这个进程.如果是系统进程,就直接退出这个线程了.

        // If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}

看注释即可,按道理这里应该不会这样.不确定是否pending中获取的是否也有这个情况.

        if (DEBUG_ALL) Slog.v(
TAG, "Binding process pid " + pid + " to record " + app); 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);
mProcessList.startProcessLocked(app,
new HostingRecord("link fail", processName),
ZYGOTE_POLICY_FLAG_EMPTY);
return false;
}

注册死亡回调,这样在由于oom,apk自己crash等异常死亡的时候,系统有机会来执行相关的清理工作.

        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
mOomAdjuster.setAttachingSchedGroupLocked(app);
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, 0, false);
app.hasShownUi = false;
app.setDebugging(false);
app.setCached(false);
app.killedByAm = false;
app.killed = false;

一些变量的初始化工作


mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

移除进程启动超时的消息

        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg,
ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS);
}

generateApplicationProvidersLocked从PMS中获取对应进程名的provider信息.并把相关信息保存到mProviderMap,以及进程的pubProviders中.

        final BackupRecord backupTarget = mBackupTargets.get(app.userId);
try {
int testMode = ApplicationThreadConstants.DEBUG_OFF;
if (mDebugApp != null && mDebugApp.equals(processName)) {
testMode = mWaitForDebugger
? ApplicationThreadConstants.DEBUG_WAIT
: ApplicationThreadConstants.DEBUG_ON;
app.setDebugging(true);
if (mDebugTransient) {
mDebugApp = mOrigDebugApp;
mWaitForDebugger = mOrigWaitForDebugger;
}
}

设置新启动的ProcessRecord app的debug状态

            boolean enableTrackAllocation = false;
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
enableTrackAllocation = true;
mTrackAllocationApp = null;
}

当前APP是否需要跟踪内存分配情况

            // If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
if (backupTarget != null && backupTarget.appInfo.packageName.equals(processName)) {
isRestrictedBackupMode = backupTarget.appInfo.uid >= FIRST_APPLICATION_UID
&& ((backupTarget.backupMode == BackupRecord.RESTORE)
|| (backupTarget.backupMode == BackupRecord.RESTORE_FULL)
|| (backupTarget.backupMode == BackupRecord.BACKUP_FULL));
}

当前进程是否拉起来只是用于备份操作.

            final ActiveInstrumentation instr = app.getActiveInstrumentation();

            if (instr != null) {
notifyPackageUse(instr.mClass.getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "
+ processName + " with config "
+ app.getWindowProcessController().getConfiguration());
ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
app.compat = compatibilityInfoForPackage(appInfo);

todo : 没看太懂

            ProfilerInfo profilerInfo = null;
String preBindAgent = null;
if (mProfileData.getProfileApp() != null
&& mProfileData.getProfileApp().equals(processName)) {
mProfileData.setProfileProc(app);
if (mProfileData.getProfilerInfo() != null) {
// Send a profiler info object to the app if either a file is given, or
// an agent should be loaded at bind-time.
boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null
|| mProfileData.getProfilerInfo().attachAgentDuringBind;
profilerInfo = needsInfo
? new ProfilerInfo(mProfileData.getProfilerInfo()) : null;
if (mProfileData.getProfilerInfo().agent != null) {
preBindAgent = mProfileData.getProfilerInfo().agent;
}
}
} else if (instr != null && instr.mProfileFile != null) {
profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false,
null, false);
}
if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
// We need to do a debuggable check here. See setAgentApp for why the check is
// postponed to here.
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
String agent = mAppAgentMap.get(processName);
// Do not overwrite already requested agent.
if (profilerInfo == null) {
profilerInfo = new ProfilerInfo(null, null, 0, false, false,
mAppAgentMap.get(processName), true);
} else if (profilerInfo.agent == null) {
profilerInfo = profilerInfo.setAgent(mAppAgentMap.get(processName), true);
}
}
} if (profilerInfo != null && profilerInfo.profileFd != null) {
profilerInfo.profileFd = profilerInfo.profileFd.dup();
if (TextUtils.equals(mProfileData.getProfileApp(), processName)
&& mProfileData.getProfilerInfo() != null) {
clearProfilerLocked();
}
}

进程性能分析相关的东西配置

            if (mActiveInstrumentation.size() > 0 && instr == null) {
for (int i = mActiveInstrumentation.size() - 1;
i >= 0 && app.getActiveInstrumentation() == null; i--) {
ActiveInstrumentation aInstr = mActiveInstrumentation.get(i);
if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
if (aInstr.mTargetProcesses.length == 0) {
// This is the wildcard mode, where every process brought up for
// the target instrumentation should be included.
if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
app.setActiveInstrumentation(aInstr);
aInstr.mRunningProcesses.add(app);
}
} else {
for (String proc : aInstr.mTargetProcesses) {
if (proc.equals(app.processName)) {
app.setActiveInstrumentation(aInstr);
aInstr.mRunningProcesses.add(app);
break;
}
}
}
}
}
}

todo

            // If we were asked to attach an agent on startup, do so now, before we're binding
// application code.
if (preBindAgent != null) {
thread.attachAgent(preBindAgent);
}
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
thread.attachStartupAgents(app.info.dataDir);
}

在系统调用APP的BindApplication之前,会调用attachAgentattachStartupAgents.这里是可以有一些工作在bindApplication之前做的.

            // Figure out whether the app needs to run in autofill compat mode.
AutofillOptions autofillOptions = null;
if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
final AutofillManagerInternal afm = LocalServices.getService(
AutofillManagerInternal.class);
if (afm != null) {
autofillOptions = afm.getAutofillOptions(
app.info.packageName, app.info.longVersionCode, app.userId);
}
}

APP 的自动填充用到的一些操作

            ContentCaptureOptions contentCaptureOptions = null;
if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
final ContentCaptureManagerInternal ccm =
LocalServices.getService(ContentCaptureManagerInternal.class);
if (ccm != null) {
contentCaptureOptions = ccm.getOptionsForPackage(app.userId,
app.info.packageName);
}
}

内容捕捉的一些东西.具体还不是很清楚

            bindApplicationTimeMillis = SystemClock.elapsedRealtime();
mAtmInternal.preBindApplication(app.getWindowProcessController());
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
if (mPlatformCompat != null) {
mPlatformCompat.resetReporting(app.info);
}
final ProviderInfoList providerList = ProviderInfoList.fromList(providers);

bindApplication之前ATMS要做些处理.

            if (app.isolatedEntryPoint != null) {
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
} else if (instr2 != null) {
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
} else {
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
}
if (profilerInfo != null) {
profilerInfo.closeFd();
profilerInfo = null;
} // Make app active after binding application or client may be running requests (e.g
// starting activities) before it is ready.
app.makeActive(thread, mProcessStats);
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
mProcessList.updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
// We need kill the process group here. (b/148588589)
Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
app.kill("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
handleAppDiedLocked(app, false, true);
return false;
}

调用新进程的BindApplication,新进程在这个过程中做不少的事情.我们单独开一篇文章将这个.

        // Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
"Attach application locked removing on hold: " + app);
mProcessesOnHold.remove(app); boolean badApp = false;
boolean didSomething = false;

mPersistentStartingProcesses,mProcessesOnHold移除这个进程信息,因为我们已经把它拉起来了.并且执行了BindApplication,此时APP已经可以开始工作了.

        // See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}

从堆栈可以看到resume Activity就是从这里离进入的.

        // Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}

看看是否有服务需要从这个进程启动.

        // Check if a next-broadcast receiver is in this process...
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}

是否有有序广播需要发送给它?

        // Check whether the next backup agent is in this process...
if (!badApp && backupTarget != null && backupTarget.app == app) {
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
"New app is backup target, launching agent for " + app);
notifyPackageUse(backupTarget.appInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
try {
thread.scheduleCreateBackupAgent(backupTarget.appInfo,
compatibilityInfoForPackage(backupTarget.appInfo),
backupTarget.backupMode, backupTarget.userId);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
badApp = true;
}
}

是否下一个备份的app是它?

        if (badApp) {
app.kill("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
handleAppDiedLocked(app, false, true);
return false;
}

如果前面出错了就杀死这个进程.

        if (!didSomething) {
updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
}

更新oom信息

attachApplication:6890, ActivityTaskManagerService$LocalService

我们分析的是attach->resume的流程,所以还是回到主线,继续往下看.

public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
try {
return mRootWindowContainer.attachApplication(wpc);
}
}
}

简单的调用mRootWindowContainerattachApplication

attachApplication:1944, RootWindowContainer

 boolean attachApplication(WindowProcessController app) throws RemoteException {
final String processName = app.mName;
boolean didSomething = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
final ActivityStack stack = display.getFocusedStack();
if (stack == null) {
continue;
} mTmpRemoteException = null;
mTmpBoolean = false; // Set to true if an activity was started.
final PooledFunction c = PooledLambda.obtainFunction(
RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity());
stack.forAllActivities(c);
c.recycle();
if (mTmpRemoteException != null) {
throw mTmpRemoteException;
}
didSomething |= mTmpBoolean;
}
if (!didSomething) {
ensureActivitiesVisible(null, 0, false /* preserve_windows */);
}
return didSomething;
}

对于每个显示区域焦点堆栈中的所有Acitivity调用startActivityForAttachedApplicationIfNeeded.

当前的显示区域的焦点堆栈就是待启动的Activity所在的堆栈了

跳过一些lambda操作

startActivityForAttachedApplicationIfNeeded:1965, RootWindowContainer

 private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
WindowProcessController app, ActivityRecord top) {
try {
if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
true /*checkConfig*/)) {
mTmpBoolean = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ top.intent.getComponent().flattenToShortString(), e);
mTmpRemoteException = e;
return true;
}
return false;
}

简单的调用mStackSupervisor.realStartActivityLocked,从名字可以看到这里是真的要去拉起新的Activity了.

realStartActivityLocked:856, ActivityStackSupervisor

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException { if (!mRootWindowContainer.allPausedActivitiesComplete()) {
return false;
}

这里会查看是否所有的需要pause的Activity是否执行完成了,没有的话还需要等待Activity的Pause.保证同时只有一个Activity处于Resumed状态.

        final Task task = r.getTask();
final ActivityStack stack = task.getStack(); // Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken); final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken, r.createFixedRotationAdjustmentsIfNeeded())); // Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem); // Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);

前面有部分代码没看太懂,后面主要就是scheduleTransactionLaunchActivityItemResumeActivityItem 传递到新启动的进程去执行了.

ATMS中去拉起新的进程,并在新进程启动后调用attachApplication时,resume待启动的Activity的更多相关文章

  1. 怎样理解在函数中声明var x = y = 1后调用函数时, x是局部变量, y是全局变量

    下面这段代码在执行的时候, 打印的结果是1, Error: undefined; function fn() { var x = y = 1; } fn(); console.log(y); // 1 ...

  2. linux的0号进程和1号进程

    linux的 0号进程 和 1 号进程 Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2) * idle进程由系统自动创 ...

  3. ATMS中去pause Activity A.

    上文写完之后,感觉这个部分写的还是不清晰,本文继续补充一下. 首先还是看堆栈. obtain:78, PauseActivityItem (android.app.servertransaction) ...

  4. 1.1 Linux中的进程 --fork、孤儿进程、僵尸进程、文件共享分析

    操作系统经典的三态如下: 1.就绪态 2.等待(阻塞) 3.运行态 其转换状态如下图所示: 操作系统内核中会维护多个队列,将不同状态的进程加入到不同的队列中,其中撤销是进程运行结束后,由内核收回. 以 ...

  5. linux进程学习-创建新进程

    init进程将系统启动后,init将成为此后所有进程的祖先,此后的进程都是直接或间接从init进程“复制”而来.完成该“复制”功能的函数有fork()和clone()等. 一个进程(父进程)调用for ...

  6. 生产环境中mysql+keepalive双主模式,keepalive守护进程实现双主切换提供数据库服务

    mysql+keepalive实现浮动地址自动切换,由于keepalive无自带健康检查功能,所以必须自动编写健康检查守护进程(监控DB1和DB2数据库的监控状态,来保证浮动地址双机自动切换.) 一, ...

  7. 进程,多进程,进程与程序的区别,程序运行的三种状态,multiprocessing模块中的Process功能,和join函数,和其他属性,僵尸与孤儿进程

    1.进程 什么是进程: 一个正在被运行的程序就称之为进程,是程序具体执行的过程,是一种抽象概念,进程来自操作系统 2.多进程  多个正在运行的程序 在python中实现多线程的方法 from mult ...

  8. v77.01 鸿蒙内核源码分析(消息封装篇) | 剖析LiteIpc(上)进程通讯内容 | 新的一年祝大家生龙活虎 虎虎生威

    百篇博客分析|本篇为:(消息封装篇) | 剖析LiteIpc进程通讯内容 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁 ...

  9. Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解

    Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解 (本文转自: http://blog.csdn.net/yinhaide/article/details/44756 ...

随机推荐

  1. WPF权限控制——【3】数据库、自定义弹窗、表单验证

    你相信"物竞天择,适者生存"这样的学说吗?但是我们今天却在提倡"尊老爱幼,救死扶伤",帮助并救护弱势群体:第二次世界大战期间,希特勒认为自己是优等民族,劣势民族 ...

  2. Python学习笔记_斐波那契数列

    """ 1.生成100项斐波那契数列 2.求第n项斐波那契数列的值是多少 3.给定终止值,生成此前斐波那契数列 """ # 求第n项斐波那契 ...

  3. 从微信小程序到鸿蒙js开发【11】——页面路由

    目录: 1.router.push()&wx.navigateTo() 2.router.replace()&wx.redirectTo() 3.router.back()&w ...

  4. where & having 关键字

    where和having都是做条件筛选的 where执行的时间比having要早 where后面不能出现组函数 having后面可以出现组函数 where语句要跟在from后面 ,where 不能单独 ...

  5. socket短连接太多,accept次数很多导致主线程CPU占满,工作线程CPU占用率低

    1.使用epoll的ET模式: 2.开启reuseport方法: Linux 最新SO_REUSEPORT特性:http://www.mamicode.com/info-detail-2201958. ...

  6. 剑指 Offer 52. 两个链表的第一个公共节点 + 链表 + 第一个公共结点 + 双指针

    剑指 Offer 52. 两个链表的第一个公共节点 Offer_52 题目详情 题解分析 可以使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结 ...

  7. HDOJ-1540(线段树+较复杂的单点修改和区间查询)

    Tunnel Warfare HDOJ-1540 这题关于线段树的操作有一定的难度,需要较好的思维能力. 关于题目的详细解答已经在代码中体现了. #include<iostream> #i ...

  8. Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件

    封面:洛小汐 作者:潘潘 若不是生活所迫,谁愿意背负一身才华. 前言 上节我们介绍了 < Mybatis系列全解(四):全网最全!Mybatis配置文件 XML 全貌详解 >,内容很详细( ...

  9. Java I/O流 04

    I/O流·其他流 序列流 * A:什么是序列流 * 序列流可以把多个字节输入流整合成一个,从序列流中读取数据时,将从被整合的第一个流开始,读完后再读下一个 * B:使用方式 * 整合两个:Sequen ...

  10. 《Asp.Net Core3 + Vue3入坑教程》 - Vue 1.使用vue-cli创建vue项目

    简介 <Asp.Net Core3 + Vue3入坑教程> 此教程适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 目录 & ...