h5网站建设方案,最新网页设计教程,凡科网的网站建设怎么做,国外网页设计网站Android应用程序进程的启动过程 导语
到这篇文章为止#xff0c;我们已经简要地了解过了Android系统的启动流程了#xff0c;其中比较重要的内容有Zygote进程的启动和SystemService以及Launcher的启动#xff0c;接下来我们将要学习的是Android应用程序的启动过程#xff…Android应用程序进程的启动过程 导语
到这篇文章为止我们已经简要地了解过了Android系统的启动流程了其中比较重要的内容有Zygote进程的启动和SystemService以及Launcher的启动接下来我们将要学习的是Android应用程序的启动过程这篇文章将会比较简单地介绍这个过程下面是一张个人总结出来的流程图
ActivityManagerService向Zygote服务发送请求
其实在之前Zygote服务启动的过程中我们已经提到了这个Zygote服务将会创建出一个Socket来用于给ActivityManagerService使用应用程序进程的启动就需要ActivityManagerService来给Zygote的服务端发送请求。
首先我们介绍ProcessRecord类这个类是Android系统中用于表示应用程序进程的数据结构。每当应用程序启动时系统都会为其创建一个ProcessRecord对象来跟踪该进程的状态和信息。
具体来说在ActivityMangerService中也是通过这个类来启动进程的来看看这个方法 GuardedBy(mService)boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,String abiOverride) {if (app.isPendingStart()) {return true;}final long startUptime SystemClock.uptimeMillis();final long startElapsedTime SystemClock.elapsedRealtime();if (app.getPid() 0 app.getPid() ! ActivityManagerService.MY_PID) {checkSlow(startUptime, startProcess: removing from pids map);mService.removePidLocked(app.getPid(), app);app.setBindMountPending(false);mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);checkSlow(startUptime, startProcess: done removing from pids map);app.setPid(0);app.setStartSeq(0);}// Clear any residual death recipient link as the ProcessRecord could be reused.app.unlinkDeathRecipient();app.setDyingPid(0);if (DEBUG_PROCESSES mService.mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,startProcessLocked removing on hold: app);mService.mProcessesOnHold.remove(app);checkSlow(startUptime, startProcess: starting to update cpu stats);mService.updateCpuStats();checkSlow(startUptime, startProcess: done updating cpu stats);try {final int userId UserHandle.getUserId(app.uid);try {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;boolean externalStorageAccess false;if (!app.isolated) {int[] permGids null;try {checkSlow(startUptime, startProcess: getting gids from package manager);final IPackageManager pm AppGlobals.getPackageManager();permGids pm.getPackageGids(app.info.packageName,MATCH_DIRECT_BOOT_AUTO, app.userId);StorageManagerInternal storageManagerInternal LocalServices.getService(StorageManagerInternal.class);mountExternal storageManagerInternal.getExternalStorageMountMode(uid,app.info.packageName);externalStorageAccess storageManagerInternal.hasExternalStorageAccess(uid,app.info.packageName);if (pm.checkPermission(Manifest.permission.INSTALL_PACKAGES,app.info.packageName, userId) PackageManager.PERMISSION_GRANTED) {Slog.i(TAG, app.info.packageName is exempt from freezer);app.mOptRecord.setFreezeExempt(true);}} catch (RemoteException e) {throw e.rethrowAsRuntimeException();}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, externalStorageAccess);}app.setMountMode(mountExternal);checkSlow(startUptime, startProcess: building args);if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {uid 0;}int runtimeFlags 0;...........app.setGids(gids);app.setRequiredAbi(requiredAbi);app.setInstructionSet(instructionSet);ApplicationInfo definingAppInfo;if (hostingRecord.getDefiningPackageName() ! null) {definingAppInfo new ApplicationInfo(app.info);definingAppInfo.packageName hostingRecord.getDefiningPackageName();definingAppInfo.uid uid;} else {definingAppInfo app.info;}runtimeFlags | Zygote.getMemorySafetyRuntimeFlags(definingAppInfo, app.processInfo, instructionSet, mPlatformCompat);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);final String entryPoint android.app.ActivityThread;return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,instructionSet, invokeWith, startUptime, startElapsedTime);} catch (RuntimeException e) {Slog.e(ActivityManagerService.TAG, Failure starting process app.processName, e);mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),false, false, true, false, false, app.userId, start failure);return false;}}这里截取了部分代码其实这个方法里做的主要就是获取到了应用程序的一些信息比如Gid,Uid等然后把获取到的信息设置到要启动的App中 app.setGids(gids);app.setRequiredAbi(requiredAbi);app.setInstructionSet(instructionSet);然后最后还需要调用一层重载方法开始正式进行进程的启动 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 startUptime, long startElapsedTime) {............try {final Process.ProcessStartResult startResult startProcess(hostingRecord,entryPoint, app,uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,requiredAbi, instructionSet, invokeWith, startUptime);handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,startSeq, false);} catch (RuntimeException e) {Slog.e(ActivityManagerService.TAG, Failure starting process app.processName, e);app.setPendingStart(false);mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),false, false, true, false, false, app.userId, start failure);}return app.getPid() 0;}}这里它又会调用到startProcess和handleProcessStartedLocked方法startProcessLocked 方法用于启动新的进程而 handleProcessStartedLocked 方法用于处理进程启动完成后的回调更新进程状态并通知其他模块有关进程启动完成的事件。这两个方法共同协作以实现进程的启动和管理。
在这里我们主要还是看进程的启动所以着重来看startProcess方法这个方法又将调用到Process的start方法
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.getDisabledCompatChanges(), pkgDataInfoMap,allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,new String[]{PROC_START_SEQ_IDENT app.getStartSeq()});所以接下来看Process的start方法这个方法又会调转到ZygoteProcess的start方法并继续跳转到startViaZygote方法中我们接下来看一看这个方法
private Process.ProcessStartResult startViaZygote(NonNull final String processClass,Nullable final String niceName,final int uid, final int gid,Nullable final int[] gids,int runtimeFlags, int mountExternal,int targetSdkVersion,Nullable String seInfo,NonNull String abi,Nullable String instructionSet,Nullable String appDataDir,Nullable String invokeWith,boolean startChildZygote,Nullable String packageName,int zygotePolicyFlags,boolean isTopApp,Nullable long[] disabledCompatChanges,Nullable MapString, PairString, LongpkgDataInfoMap,Nullable MapString, PairString, LongallowlistedDataInfoList,boolean bindMountAppsData,boolean bindMountAppStorageDirs,Nullable String[] extraArgs)throws ZygoteStartFailedEx {ArrayListString argsForZygote new ArrayList();// --runtime-args, --setuid, --setgid,// and --setgroups must go firstargsForZygote.add(--runtime-args);argsForZygote.add(--setuid uid);argsForZygote.add(--setgid gid);argsForZygote.add(--runtime-flags runtimeFlags);if (mountExternal Zygote.MOUNT_EXTERNAL_DEFAULT) {argsForZygote.add(--mount-external-default);} else if (mountExternal Zygote.MOUNT_EXTERNAL_INSTALLER) {argsForZygote.add(--mount-external-installer);} else if (mountExternal Zygote.MOUNT_EXTERNAL_PASS_THROUGH) {argsForZygote.add(--mount-external-pass-through);} else if (mountExternal Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {argsForZygote.add(--mount-external-android-writable);}argsForZygote.add(--target-sdk-version targetSdkVersion);// --setgroups is a comma-separated listif (gids ! null gids.length 0) {final StringBuilder sb new StringBuilder();sb.append(--setgroups);final int sz gids.length;for (int i 0; i sz; i) {if (i ! 0) {sb.append(,);}sb.append(gids[i]);}argsForZygote.add(sb.toString());}..........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);}}
这个变量名argsForZygote的数组显然是用作传参用的这个方法做的主要也就是创建一个字符串列表argsForZygote并将应用程序的启动参数保存在这个列表中最后调用zygoteSendArgsAndGetResult方法将其传给zygote执行这实际上就是达到了AMS向zygote发送请求的目的
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {try {final BufferedWriter zygoteWriter zygoteState.mZygoteOutputWriter;final DataInputStream zygoteInputStream zygoteState.mZygoteInputStream;zygoteWriter.write(msgStr);zygoteWriter.flush();Process.ProcessStartResult result new Process.ProcessStartResult();result.pid zygoteInputStream.readInt();result.usingWrapper zygoteInputStream.readBoolean();if (result.pid 0) {throw new ZygoteStartFailedEx(fork() failed);}return result;} catch (IOException ex) {zygoteState.close();Log.e(LOG_TAG, IO Exception while communicating with Zygote - ex.toString());throw new ZygoteStartFailedEx(ex);}}在这个过程中会调用到上面这个方法将应用参数的启动数据等写入zygote中实际上就是向zygote发送了请求了。里面出现的ZygoteState类就是用于表示与Zygote的通信状况的。
再回到之前的
zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),zygotePolicyFlags,argsForZygote);这里的请求就是通过第一个参数其实也是方法的socket传达的我们来看一看这个方法 private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {try {attemptConnectionToPrimaryZygote();if (primaryZygoteState.matches(abi)) {return primaryZygoteState;}if (mZygoteSecondarySocketAddress ! null) {// The primary zygote didnt match. Try the secondary.attemptConnectionToSecondaryZygote();if (secondaryZygoteState.matches(abi)) {return secondaryZygoteState;}}} catch (IOException ioe) {throw new ZygoteStartFailedEx(Error connecting to zygote, ioe);}throw new ZygoteStartFailedEx(Unsupported zygote ABI: abi);}实际上就是根据abi参数来建立与Zygote的Socket连接其实就是根据Zygote的启动脚本类型来建立不同的连接这里我们就不深入了。
所以到目前为止ActivityManagerService就成功地读取应用程序的相关信息并将其打包发给Zygote请求Zygote创建进程了接下来我们看Zygote是如何响应AMS的请求的。
Zygote服务创建应用程序的进程
在之前的文章中其实我们已经提到过了,Zygote将在创建完自身的Socket后等待AMS的请求具体是在ZygoteInit的main方法中
caller zygoteServer.runSelectLoop(abiList);其实这个方法里还是继续跳转我们直接跳过中间步骤来到最终调用到的ZygoteConnection方法中
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {ZygoteArguments parsedArgs;try (ZygoteCommandBuffer argBuffer new ZygoteCommandBuffer(mSocket)) {while (true) {try {parsedArgs ZygoteArguments.getInstance(argBuffer);//1-----1} .........if (parsedArgs.mInvokeWith ! null || parsedArgs.mStartChildZygote|| !multipleOK || peer.getUid() ! Process.SYSTEM_UID) {// Continue using old code for now. TODO: Handle these cases in the other path.pid Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,parsedArgs.mBindMountAppStorageDirs);//2-----2try {if (pid 0) {// in childzygoteServer.setForkChild();zygoteServer.closeServerSocket();IoUtils.closeQuietly(serverPipeFd);serverPipeFd null;return handleChildProc(parsedArgs, childPipeFd,parsedArgs.mStartChildZygote);//3--------3} else {IoUtils.closeQuietly(childPipeFd);childPipeFd null;handleParentProc(pid, serverPipeFd);return null;}} finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);}} else {ZygoteHooks.preFork();Runnable result Zygote.forkSimpleApps(argBuffer,zygoteServer.getZygoteSocketFileDescriptor(),peer.getUid(), Zygote.minChildUid(peer), parsedArgs.mNiceName);if (result null) {// parent; we finished some number of forks. Result is Boolean.// We already did the equivalent of handleParentProc().ZygoteHooks.postForkCommon();// argBuffer contains a command not understood by forksimpleApps.continue;} else {// child; result is a Runnable.zygoteServer.setForkChild();Zygote.setAppProcessName(parsedArgs, TAG); // ??? Necessary?return result;}}}}........}方法很长我们主要看注释出的三处第一处的
parsedArgs ZygoteArguments.getInstance(argBuffer);方法显然是将我们之间通过AMS发送过来的启动参数给获取出来了。接着注释二处通过zygote将要启动的应用程序的进程就已经fork出来了到此为止实际上要启动的进程已经被创建出来了只不过创建出来后我们还需要将这个进程进行一些处理所以接下来会调用到注释三处的handleChildProc方法到了这里之后又会跳转具体来说会跳转到ZygoteInit.zygoteInit方法这个方法我们在之前的Zygote的启动中也提到过它首先会启动进程的Binder进程池这样这个进程就可以与其他进程进行Binder进程间通信了然后它会执行具体类的main方法。在这里他将会启动ActivityThread的main方法。
这个ActivityThread类是Android系统中的核心类之一它负责管理应用程序的主线程UI线程以及应用程序的生命周期和消息处理。每个应用程序在启动时都会创建一个ActivityThread实例并在该实例的主线程中执行应用程序的主要逻辑。ActivityThread类的主要职责包括 应用程序的初始化在ActivityThread的main()方法中会创建Application实例并调用其onCreate()方法来进行应用程序的初始化工作。 管理Activity的生命周期ActivityThread负责跟踪和管理应用程序中所有Activity的生命周期。它会接收来自系统的生命周期回调消息并分发给相应的Activity进行处理例如调用Activity的onCreate()、onStart()、onResume()等方法。 处理消息和事件ActivityThread通过一个消息循环机制处理来自系统和应用程序的消息和事件。它会接收并分发消息给对应的Handler进行处理例如处理用户界面事件、处理来自其他组件的消息等。 启动Activity和ServiceActivityThread负责启动应用程序中的Activity和Service组件。它会接收来自系统的启动请求并负责创建和启动相应的组件实例。 处理窗口和界面更新ActivityThread负责处理窗口和界面的更新操作包括创建和管理窗口、更新界面布局、处理用户界面事件等。
那么接下来我们就来简单看看它的main方法
public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ActivityThreadMain);// Install selective syscall interceptionAndroidOs.install();CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);// Call per-process mainline module initialization.initializeMainlineModules();Process.setArgV0(pre-initialized);Looper.prepareMainLooper();// Find the value for {link #PROC_START_SEQ_IDENT} if provided on the command line.// It will be in the format seq114long 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()));}}}ActivityThread thread new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler null) {sMainThreadHandler thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, ActivityThread));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException(Main thread loop unexpectedly exited);}可以看到这个main方法中会自动创建出一个消息Looper和一个默认的Handler然后会自动开启消息队列的循环使它可以处理消息。接下来Activity就将由ActivityThread管理启动了这就已经完成了应用程序进程的启动了。
总结
最后再来回顾一下上面那张总结图 这就是应用程序进程的启动过程。