voidstartProcessAsync(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); } finally { ... } }
@Override publicvoidstartProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName){ try { ... synchronized (ActivityManagerService.this) { // If the process is known as top app, set a hint so when the process is // started, the top priority can be applied immediately to avoid cpu being // preempted by other processes before attaching the process of top app. startProcessLocked(processName, info, knownToBeDead, 0/* intentFlags */, new HostingRecord(hostingType, hostingName, isTop), ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false/* allowWhileBooting */, false/* isolated */, true/* keepIfLarge */); } } finally { ... } }
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) { //先通过进程名和uid查找相应App的ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
//如果是由后台进程发起的 startProcess //判断启动进程是否为 bad process,如果是,直接启动失败返回 //这里 bad process 的定义为:短时间内连续崩溃两次以上的进程 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)) { returnnull; } } 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. //如果是用户显式的要求启动进程,则会清空启动进程的崩溃次数,将启动进程从 bad process 列表中移除 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; } } } } else { // If this is an isolated process, it can't re-use an existing process. app = null; }
// We don't have to do anything more if: // (1) There is an existing application record; and // (2) The caller doesn't think it is dead, OR there is no thread // object attached to it so we know it couldn't have crashed; and // (3) There is a pid assigned to it, so it is either starting or // already running. ProcessRecord precedence = null; //如果已经存在了对应App的ProcessRecord,并且分配了pid if (app != null && app.pid > 0) { //如果进程没有死亡或者进程还未绑定binder线程,说明进程是正常运行状态或正在启动中 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 this is a new package in the process, add the package to the list //将要启动的包信息记录在ProcessRecord中(Android多个App可以运行在同一个进程中) app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); return app; }
// An application record is attached to a previous process, // clean it up now. //App绑定在之前的一个进程上了,杀死并清理这个进程 ProcessList.killProcessGroup(app.uid, app.pid);
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; }
//没有找到对应的ProcessRecord if (app == null) { //新创建一个ProcessRecord对象 app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); returnnull; } app.crashHandler = crashHandler; app.isolatedEntryPoint = entryPoint; app.isolatedEntryPointArgs = entryPointArgs; if (precedence != null) { app.mPrecedence = precedence; precedence.mSuccessor = app; } } else { //存在对应的ProcessRecord,但进程尚未启动或已被清理 // If this is a new package in the process, add the package to the list //将要启动的包信息记录在ProcessRecord中 app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); }
// If the system is not ready yet, then hold off on starting this // process until it is. //如果系统尚未准备好(开机中或system_server进程崩溃重启中),将其先添加到等待队列中 if (!mService.mProcessesReady && !mService.isAllowedWhileBooting(info) && !allowWhileBooting) { if (!mService.mProcessesOnHold.contains(app)) { mService.mProcessesOnHold.add(app); } return app; }
// 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? //从刚刚过去的App申请权限中剔除进程所被拒绝的权限 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); } //设置挂载模式 app.mountMode = mountExternal; //工厂测试进程 if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) { uid = 0; } //进程启动参数(传递到Zygoto) int runtimeFlags = 0; //如果manifest中设置了android:debuggable 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"); } } ... //设置各种高进程启动参数
String invokeWith = null; //如果manifest中设置了android:debuggable //使用logwrapper工具捕获stdout信息 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); } }
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";
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 { finalboolean 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); }
// 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}); } elseif (hostingRecord.usesAppZygote()) { final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
// --setgroups is a comma-separated list if (gids != null && gids.length > 0) { final StringBuilder sb = new StringBuilder(); sb.append("--setgroups=");
finalint 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); }
if (invokeWith != null) { argsForZygote.add("--invoke-with"); argsForZygote.add(invokeWith); }
if (startChildZygote) { argsForZygote.add("--start-child-zygote"); }
if (packageName != null) { argsForZygote.add("--package-name=" + packageName); }
if (isTopApp) { argsForZygote.add(Zygote.START_AS_TOP_APP_ARG); } if (pkgDataInfoMap != null && pkgDataInfoMap.size() > 0) { StringBuilder sb = new StringBuilder(); sb.append(Zygote.PKG_DATA_INFO_MAP); sb.append("="); boolean started = false; for (Map.Entry<String, Pair<String, Long>> entry : pkgDataInfoMap.entrySet()) { if (started) { sb.append(','); } started = true; sb.append(entry.getKey()); sb.append(','); sb.append(entry.getValue().first); sb.append(','); sb.append(entry.getValue().second); } argsForZygote.add(sb.toString()); } if (allowlistedDataInfoList != null && allowlistedDataInfoList.size() > 0) { StringBuilder sb = new StringBuilder(); sb.append(Zygote.ALLOWLISTED_DATA_INFO_MAP); sb.append("="); boolean started = false; for (Map.Entry<String, Pair<String, Long>> entry : allowlistedDataInfoList.entrySet()) { if (started) { sb.append(','); } started = true; sb.append(entry.getKey()); sb.append(','); sb.append(entry.getValue().first); sb.append(','); sb.append(entry.getValue().second); } argsForZygote.add(sb.toString()); }
if (bindMountAppStorageDirs) { argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS); }
if (bindMountAppsData) { argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS); }
if (disabledCompatChanges != null && disabledCompatChanges.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--disabled-compat-changes=");
int sz = disabledCompatChanges.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(disabledCompatChanges[i]); }
argsForZygote.add(sb.toString()); }
argsForZygote.add(processClass);
if (extraArgs != null) { Collections.addAll(argsForZygote, extraArgs); }
synchronized(mLock) { // The USAP pool can not be used if the application will not use the systems graphics // driver. If that driver is requested use the Zygote application start path. return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), zygotePolicyFlags, argsForZygote); } }
/* * See com.android.internal.os.ZygoteArguments.parseArgs() * 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. */ //构建出符合zygote解析规则的参数(argc + argv) String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";
//USAP机制 if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) { try { return attemptUsapSendArgsAndGetResult(zygoteState, msgStr); } catch (IOException ex) { // If there was an IOException using the USAP pool we will log the error and // attempt to start the process through the Zygote. Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - " + ex.getMessage()); } }
// Always read the entire result from the input stream to avoid leaving // bytes in the stream for future process starts to accidentally stumble // upon. Process.ProcessStartResult result = new Process.ProcessStartResult(); result.pid = zygoteInputStream.readInt(); result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) { thrownew ZygoteStartFailedEx("fork() failed"); }
// CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. //资源关闭检测器 CloseGuard.setEnabled(false);
//初始化用户环境 Environment.initForCurrentUser();
// Make sure TrustedCertificateStore looks in the right place for CA certificates //设置CA证书搜索位置 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir);
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line. // It will be in the format "seq=114" //查找startSeq参数 long startSeq = 0; if (args != null) { for (int i = args.length - 1; i >= 0; --i) { if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) { startSeq = Long.parseLong( args[i].substring(PROC_START_SEQ_IDENT.length())); } } } //创建App进程ActivityThread实例 ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq);
//设置全局Handler if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); }
privatevoidattach(boolean system, long startSeq){ sCurrentActivityThread = this; mConfigurationController = new ConfigurationController(this); mSystemThread = system; if (!system) { //非系统ActivityThread //预设进程名 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); //处理一些错误异常需要使用ActivityThread,将其传入 RuntimeInit.setApplicationObject(mAppThread.asBinder()); //AMS代理binder对象 final IActivityManager mgr = ActivityManager.getService(); try { //执行AMS.attachApplication方法 mgr.attachApplication(mAppThread, startSeq); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } // Watch for getting close to heap limit. //每次GC时检测内存,如果内存不足则会尝试释放部分不可见的Activity BinderInternal.addGcWatcher(new Runnable() { @Overridepublicvoidrun(){ if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { ActivityTaskManager.getService().releaseSomeActivities(mAppThread); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } }); } else { //系统ActivityThread ... }
//处理ConfigChanged相关逻辑(屏幕旋转之类) ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> { synchronized (mResourcesManager) { // We need to apply this change to the resources immediately, because upon returning // the view hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResources(globalConfig, null/* compat */)) { mConfigurationController.updateLocaleListFromAppContext( mInitialApplication.getApplicationContext());
// This actually changed the resources! Tell everyone about it. final Configuration updatedConfig = mConfigurationController.updatePendingConfiguration(globalConfig); if (updatedConfig != null) { sendMessage(H.CONFIGURATION_CHANGED, globalConfig); mPendingConfiguration = updatedConfig; } } } }; ViewRootImpl.addConfigCallback(configChangedCallback); }
privatebooleanattachApplicationLocked(@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) { //通过pid查找PidMap中存在的ProcessRecord //对应着handleProcessStartedLocked方法中执行的中的mService.addPidLocked方法 //在进程同步启动模式下,这里应该是必能取到的 synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } //如果此ProcessRecord对不上App的ProcessRecord,则将其清理掉 if (app != null && (app.startUid != callingUid || app.startSeq != startSeq)) { ... // 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; }
// It's possible that process called attachApplication before we got a chance to // update the internal state. //在进程异步启动模式下,有可能尚未执行到handleProcessStartedLocked方法 //所以从PidMap中无法取到相应的ProcessRecord //这时候从ProcessList.mPendingStarts这个待启动列表中获取ProcessRecord 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; } }
// If this application record is still attached to a previous // process, clean it up now. //如果ProcessRecord绑定了其他的ApplicationThread,则需要清理这个进程 if (app.thread != null) { handleAppDiedLocked(app, true, true); }
// We carefully use the same state that PackageManager uses for // filtering, since we use this flag to decide if we need to install // providers when user is unlocked later app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
// We deprecated Build.SERIAL and it is not accessible to // Instant Apps and target APIs higher than O MR1. Since access to the serial // is now behind a permission we push down the value. //序列号(Android 8.0后不可再通过Build.SERIAL获取序列号) final String buildSerial = (!appInfo.isInstantApp() && appInfo.targetSdkVersion < Build.VERSION_CODES.P) ? sTheRealBuildSerial : Build.UNKNOWN;
//自动化测试 final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); if (mPlatformCompat != null) { mPlatformCompat.resetReporting(app.info); } final ProviderInfoList providerList = ProviderInfoList.fromList(providers); //调用ApplicationThread.bindApplication方法 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); } elseif (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); } ...
// Make app active after binding application or client may be running requests (e.g // starting activities) before it is ready. //ProcessRecord保存ApplicationThread代理对象 app.makeActive(thread, mProcessStats); //更新进程使用情况 mProcessList.updateLruProcessLocked(app, false, null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { //出现错误,杀死进程 app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); app.kill("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true); handleAppDiedLocked(app, false, true); returnfalse; }
// Remove this record from the list of starting applications. //从persistent启动列表中移除此ProcessRecord //persistent是manifest中application标签下的一个属性 //设置了此属性代表此App会跟随系统启动而启动 mPersistentStartingProcesses.remove(app);
// See if the top visible activity is waiting to run in this process... //检查是否有Activity等待启动 if (normalMode) { try { didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); } catch (Exception e) { badApp = true; } }
// Find any services that should be running in this process... //检查是否有Services等待启动 if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { badApp = true; } }
// Check if a next-broadcast receiver is in this process... //检查是否有广播接收器需要启动 if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { // If the app died trying to launch the receiver we declare it 'bad' badApp = true; } }
... //备份相关
//以上几步发生异常,杀死App进程 if (badApp) { app.kill("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true); handleAppDiedLocked(app, false, true); returnfalse; }
if (!didSomething) { //更新进程OOM等级 updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN); }
privatevoidhandleBindApplication(AppBindData data){ // Register the UI Thread as a sensitive thread to the runtime. //将UI线程注册成JIT敏感线程 VMRuntime.registerSensitiveThread(); ...
mProfiler = new Profiler(); ... //性能分析相关
// send up app name; do this *before* waiting for debugger //设置进程名 Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, data.appInfo.packageName, UserHandle.myUserId()); VMRuntime.setProcessPackageName(data.appInfo.packageName);
// Pass data directory path to ART. This is used for caching information and // should be set before any application code is loaded. //设置进程数据目录 VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);
//性能分析相关 if (mProfiler.profileFd != null) { mProfiler.startProfiling(); }
// If the app is Honeycomb MR1 or earlier, switch its AsyncTask // implementation to use the pool executor. Normally, we use the // serialized executor as the default. This has to happen in the // main thread so the main looper is set right. //当App的targetSdkVersion小于等于 3.1 (12) 时,AsyncTask使用线程池实现 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }
// Let the util.*Array classes maintain "undefined" for apps targeting Pie or earlier. //当App的targetSdkVersion大于等于 10 (29) 时,针对Android SDK提供的容器(SparseArray等) //如果index越界,会主动抛ArrayIndexOutOfBoundsException异常 //(之前数组越界的行为未被定义) UtilConfig.setThrowExceptionForUpperArrayOutOfBounds( data.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q);
// Prior to P, internal calls to decode Bitmaps used BitmapFactory, // which may scale up to account for density. In P, we switched to // ImageDecoder, which skips the upscale to save memory. ImageDecoder // needs to still scale up in older apps, in case they rely on the // size of the Bitmap without considering its density. ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;
/* * Before spawning a new process, reset the time zone to be the system time zone. * This needs to be done because the system time zone could have changed after the * the spawning of this process. Without doing this this process would have the incorrect * system time zone. */ //设置时区 TimeZone.setDefault(null);
/* * Set the LocaleList. This may change once we create the App Context. */ LocaleList.setDefault(data.config.getLocales());
//更新Configuration synchronized (mResourcesManager) { /* * Update the system configuration since its preloaded and might not * reflect configuration changes. The configuration object passed * in AppBindData can be safely assumed to be up to date */ mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi;
// This calls mResourcesManager so keep it within the synchronized block. applyCompatConfiguration(mCurDefaultDisplayDpi); }
//性能分析器代理JVM(JVMTI) if (agent != null) { handleAttachAgent(agent, data.info); }
/** * Switch this process to density compatibility mode if needed. */ //在manifest,supports-screens标签中设置了android:anyDensity //详见:https://developer.android.com/guide/topics/manifest/supports-screens-element#any if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { //指示App包含用于适应任何屏幕密度的资源 mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); } //设置默认密度 updateDefaultDensity();
/* 设置 12/24 小时时间制 */ final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24); Boolean is24Hr = null; if (use24HourSetting != null) { is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE; } // null : use locale default for 12/24 hour formatting, // false : use 12 hour format, // true : use 24 hour format. DateFormat.set24HourTimePref(is24Hr);
//debug模式 if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) { // XXX should have option to change the port. Debug.changeDebugPort(8100); if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) { Slog.w(TAG, "Application " + data.info.getPackageName() + " is waiting for the debugger on port 8100...");
/** * Initialize the default http proxy in this process for the reasons we set the time zone. */ //设置默认HTTP代理 final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { // In pre-boot mode (doing initial launch to collect password), not // all system is up. This includes the connectivity service, so don't // crash if we can't get it. final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { Proxy.setHttpProxySystemProperty(service.getProxyForNetwork(null)); } catch (RemoteException e) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw e.rethrowFromSystemServer(); } }
// Instrumentation info affects the class loader, so load it before // setting up the app context. //准备自动化测试信息 final InstrumentationInfo ii; if (data.instrumentationName != null) { try { ii = new ApplicationPackageManager( null, getPackageManager(), getPermissionManager()) .getInstrumentationInfo(data.instrumentationName, 0); } catch (PackageManager.NameNotFoundException e) { thrownew RuntimeException( "Unable to find instrumentation info for: " + data.instrumentationName); }
// Install the Network Security Config Provider. This must happen before the application // code is loaded to prevent issues with instances of TLS objects being created before // the provider is installed. //网络安全设置 NetworkSecurityConfigProvider.install(appContext);
// Continue loading instrumentation. if (ii != null) { //如果设置了自动化测试,实例化指定的自动化测试类 ApplicationInfo instrApp; try { instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0, UserHandle.myUserId()); } catch (RemoteException e) { instrApp = null; } if (instrApp == null) { instrApp = new ApplicationInfo(); } ii.copyTo(instrApp); instrApp.initForUser(UserHandle.myUserId()); final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false);
// The test context's op package name == the target app's op package name, because // the app ops manager checks the op package name against the real calling UID, // which is what the target package name is associated with. final ContextImpl instrContext = ContextImpl.createAppContext(this, pi, appContext.getOpPackageName());
final ComponentName component = new ComponentName(ii.packageName, ii.name); mInstrumentation.init(this, instrContext, appContext, component, data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
if (mProfiler.profileFile != null && !ii.handleProfiling && mProfiler.profileFd == null) { mProfiler.handlingProfiling = true; final File file = new File(mProfiler.profileFile); file.getParentFile().mkdirs(); Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); } } else { //直接实例化Instrumentation mInstrumentation = new Instrumentation(); mInstrumentation.basicInit(this); }
//调整应用可用内存上限 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { // Small heap, clamp to the current growth limit and let the heap release // pages after the growth limit to the non growth limit capacity. b/18387825 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); }
// Allow disk access during application and provider setup. This could // block processing ordered broadcasts, but later processing would // probably end up doing the same disk access. Application app; final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy(); try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. //创建Application app = data.info.makeApplication(data.restrictedBackupMode, null);
// Propagate autofill compat state //设置自动填充功能 app.setAutofillOptions(data.autofillOptions);
// don't bring up providers in restricted mode; they may depend on the // app's custom Application class //在非受限模式下启动ContentProvider if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); } }
// Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. //执行onCreate方法(默认Instrumentation实现为空方法) try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { ... } //执行Application的onCreate方法 try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { ... } } finally { // If the app targets < O-MR1, or doesn't change the thread policy // during startup, clobber the policy to maintain behavior of b/36951662 if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1 || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) { StrictMode.setThreadPolicy(savedPolicy); } }
// Preload fonts resources //预加载字体资源 FontsContract.setApplicationContextForResources(appContext); if (!Process.isIsolated()) { try { final ApplicationInfo info = getPackageManager().getApplicationInfo( data.appInfo.packageName, PackageManager.GET_META_DATA /*flags*/, UserHandle.myUserId()); if (info.metaData != null) { finalint preloadedFontsResource = info.metaData.getInt( ApplicationInfo.METADATA_PRELOADED_FONTS, 0); if (preloadedFontsResource != 0) { data.info.getResources().preloadFonts(preloadedFontsResource); } } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
try { //初始化ContextClassLoader final java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals("android")) { initializeJavaContextClassLoader(); }
// Rewrite the R 'constants' for all library apks. //Android共享库资源ID动态映射 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers( false, false); for (int i = 0, n = packageIdentifiers.size(); i < n; i++) { finalint id = packageIdentifiers.keyAt(i); if (id == 0x01 || id == 0x7f) { continue; }