Android AMS启动App进程原理分析

Hana ·
更新时间:2024-09-20
· 1364 次阅读

目录

1 系统fork进程分析

1.1 fork函数分析

1.2 system_server进程启动流程

1.2.1 SystemServer run方法分析

2 AMS职责分析

2.1 App启动流程分析

2.1.1 app进程创建

2.1.2 app进程启动流程分析

2.1.3 ActivityThead分析

1 系统fork进程分析

我们知道,Zygote进程创建的第一个进程就是system_server进程,这个进程的主要作用就是管理服务,例如我们常见的AMS、WMS、PMS等,同时为App进程提供服务支持

1.1 fork函数分析

这里我们拿forkSystemServer方法对应的JNI函数进行分析,在上一节中已经分析了会调用ForkCommon函数进行进程创建,我们看在这个方法中,调用了fork函数。

static pid_t ForkCommon(JNIEnv* env, bool is_system_server, const std::vector<int>& fds_to_close, const std::vector<int>& fds_to_ignore) { SetSignalHandlers(); // Curry a failure function. auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote", nullptr, _1); // Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. BlockSignal(SIGCHLD, fail_fn); // Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close(); stats_log_close(); // If this is the first fork for this zygote, create the open FD table. If // it isn't, we just need to check whether the list of open files has changed // (and it shouldn't in the normal case). if (gOpenFdTable == nullptr) { gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, fail_fn); } else { gOpenFdTable->Restat(fds_to_ignore, fail_fn); } android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level(); //调用fork函数,创建进程 pid_t pid = fork(); if (pid == 0) { // The child process. PreApplicationInit(); // Clean up any descriptors which must be closed immediately DetachDescriptors(env, fds_to_close, fail_fn); // Invalidate the entries in the USAP table. ClearUsapTable(); // Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. gOpenFdTable->ReopenOrDetach(fail_fn); // Turn fdsan back on. android_fdsan_set_error_level(fdsan_error_level); } else { ALOGD("Forked child process %d", pid); } // We blocked SIGCHLD prior to a fork, we unblock it here. UnblockSignal(SIGCHLD, fail_fn); return pid; }

fork函数最终返回了一个pid,在这里会对pid判断,这里伙伴们需要注意,虽然fork只会执行一次,但是在返回值上会有两次返回,这是什么原因呢

因为我们在fork进程的时候,我们会在父进程中执行fork函数,同时会将父进程的信息全部拷贝一份,包括堆栈信息,也就是代码会在子进程中再次执行一次,所以从现象上来看,在forkSystemServer方法执行时,会有两次返回,一次是从父进程返回,一次从子进程中返回,那么如何判断是在哪个进程呢?

在ForkCommon函数中给了我们答案,当pid = 0时,因为在子进程中没有创建进程,因此返回0;而在父进程中则是会返回创建的子进程pid;如果返回一个负值,那么说明创建进程失败了

ZygoteInit # forkSystemServer /* For child process */ if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); return handleSystemServerProcess(parsedArgs); }

因此,在ZygoteInit调用forkSystemServer之后,会判断其返回值,如果pid = 0,那么就说明创建进程成功了,而且是子进程,那么就会执行handleSystemServerProcess方法,此时运行在system_server进程

1.2 system_server进程启动流程 private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) { //...... if (parsedArgs.mInvokeWith != null) { String[] args = parsedArgs.mRemainingArgs; // If we have a non-null system server class path, we'll have to duplicate the // existing arguments and append the classpath to it. ART will handle the classpath // correctly when we exec a new process. if (systemServerClasspath != null) { String[] amendedArgs = new String[args.length + 2]; amendedArgs[0] = "-cp"; amendedArgs[1] = systemServerClasspath; System.arraycopy(args, 0, amendedArgs, 2, args.length); args = amendedArgs; } WrapperInit.execApplication(parsedArgs.mInvokeWith, parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion, VMRuntime.getCurrentInstructionSet(), null, args); throw new IllegalStateException("Unexpected return from WrapperInit.execApplication"); } else { ClassLoader cl = getOrCreateSystemServerClassLoader(); if (cl != null) { Thread.currentThread().setContextClassLoader(cl); } /* * Pass the remaining arguments to SystemServer. */ return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mDisabledCompatChanges, parsedArgs.mRemainingArgs, cl); } /* should never reach here */ }

具体调用链会执行ZygoteInit的zygoteInit方法,在这个方法中,又会执行RuntimeInit的applicationInit方法。

public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) { if (RuntimeInit.DEBUG) { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); } Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); RuntimeInit.redirectLogStreams(); RuntimeInit.commonInit(); ZygoteInit.nativeZygoteInit(); return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv, classLoader); }

在看applicationInit方法之前,首先先看一下ZygoteInit中的nativeZygoteInit,这个方法比较重要,我们跟进看一下。

private static native void nativeZygoteInit();

这是一个native方法,我们看下C++的代码

int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env) { const JNINativeMethod methods[] = { { "nativeZygoteInit", "()V", (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit }, }; return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit", methods, NELEM(methods)); }

最终执行的是AndroidRuntime的onZygoteInit函数。

virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); }

如果有熟悉Binder源码的伙伴,这里其实就是会创建Binder驱动并启动Binder线程池,所以这里就有一个面试题,Binder驱动是什么时候启动的?其实就是在fork进程成功之后,处理进程启动的时候完成的,具体函数就是在ZygoteInit的nativeZygoteInit方法。

protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) { // If the application calls System.exit(), terminate the process // immediately without running any shutdown hooks. It is not possible to // shutdown an Android application gracefully. Among other things, the // Android runtime shutdown hooks close the Binder driver, which can cause // leftover running threads to crash before the process actually exits. nativeSetExitWithoutCleanup(true); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges); final Arguments args = new Arguments(argv); // The end of of the RuntimeInit event (see #zygoteInit). Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); // Remaining arguments are passed to the start class's static main return findStaticMain(args.startClass, args.startArgs, classLoader); }

这个方法最终执行findStaticMain方法,这个方法的其实很简单,就是通过反射的方式去查找对应的className的main方法,像我们现在是启动system_server进程,所以查找的就是system_server的main方法,最终去执行对应的main方法,这样system_server进程就已经启动了。

public static void main(String[] args) { new SystemServer().run(); }

我们可以看到,SystemServer的main方法,就是创建一个SystemServer对象并执行其run方法。

1.2.1 SystemServer run方法分析 private void run() { TimingsTraceAndSlog t = new TimingsTraceAndSlog(); try { //启动服务之前的初始化操作 t.traceBegin("InitBeforeStartServices"); // ...... // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); // Increase the number of binder threads in system_server BinderInternal.setMaxThreads(sMaxBinderThreads); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); Looper.getMainLooper().setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); // Initialize native services. System.loadLibrary("android_servers"); // Allow heap / perf profiling. initZygoteChildHeapProfiling(); // Debug builds - spawn a thread to monitor for fd leaks. if (Build.IS_DEBUGGABLE) { spawnFdLeakCheckThread(); } // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. createSystemContext(); // ...... // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime); mDumper.addDumpable(mSystemServiceManager); // ...... } finally { t.traceEnd(); // InitBeforeStartServices } // Start services. try { t.traceBegin("StartServices"); startBootstrapServices(t); startCoreServices(t); startOtherServices(t); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } finally { t.traceEnd(); // StartServices } //...... // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }

在system_server的run方法中

我们看到有创建Looper对象,因为作为一个进程,首先不会执行完成之后立刻结束,包括前面在分析idle、init、zygote进程时,都是创建死循环处理消息,所以system_server也是如此。再往下看,我们看到执行了createSystemContext方法,看注释是创建了系统的上下文。 private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); mSystemContext.setTheme(DEFAULT_SYSTEM_THEME); final Context systemUiContext = activityThread.getSystemUiContext(); systemUiContext.setTheme(DEFAULT_SYSTEM_THEME); }

创建系统的ServiceManager,用来管理系统服务,也就是后续的三个比较重要的方法,都需要使用SystemServiceManager来启动服务。

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) { t.traceBegin("startBootstrapServices"); // ...... // Activity manager runs the show. t.traceBegin("StartActivityManager"); // TODO: Might need to move after migration to WM. ActivityTaskManagerService atm = mSystemServiceManager.startService( ActivityTaskManagerService.Lifecycle.class).getService(); mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mWindowManagerGlobalLock = atm.getGlobalLock(); t.traceEnd(); // ...... }

这里我就拿启动AMS来做介绍,其实与startBootstrapServices同级的三个方法内部都是通过SystemServiceManager来启动服务,所以我们看一下SystemServiceManager的startService方法具体实现:

public void startService(@NonNull final SystemService service) { // Register it. mServices.add(service); // Start it. long time = SystemClock.elapsedRealtime(); try { service.onStart(); } catch (RuntimeException ex) { throw new RuntimeException("Failed to start service " + service.getClass().getName() + ": onStart threw an exception", ex); } warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart"); }

其实所有startService最终都会调用这个方法,传值为SystemService对象,其实无论是AMS、WMS还是其他的系统服务,都是继承SystemService,因此在SystemServiceManager中有一个mServices List来收集这些系统服务,最终启动就是调用SystemService的onStart方法。

/** * Called when the system service should publish a binder service using * {@link #publishBinderService(String, IBinder).} */ public abstract void onStart();

我们看下SystemService对于onStart方法的定义,当调用这个方法的时候,会调用publishBinderService将其注册binder service中。

protected final void publishBinderService(String name, IBinder service, boolean allowIsolated, int dumpPriority) { ServiceManager.addService(name, service, allowIsolated, dumpPriority); }

如果熟悉Binder进程间通信的伙伴,我们通常喜欢叫ServiceManager为大管家,是因为ServiceManager属于Binder中用于管理各类服务的对象,尤其是涉及到跨进程通信。

所以这里有几个对象,我们需要分清楚一些:

SystemServer:Zygote fork出来的一个进程,主要用来管理各类服务;

SystemService:所有系统服务的父类,例如AMS、WMS、PKMS等都是这个大类的子类;

SystemServiceManager:属于SystemServer进程,在SystemServer进程启动时创建,SystemServer真正用于管理服务的类,其中startService方法用于启动服务;

ServiceManager:系统服务大管家,用于跨进程通信,例如app进程想要与AMS通信,那么就需要通过ServerManager来完成进程间通信。

如此一来,SystemServer进程也就启动完成了。

2 AMS职责分析

前面对于SystemServer的启动流程分析中,我们知道会启动AMS服务,其实在Android10之前,AMS是会管理Activity、Service、广播、Provider四大组件的启动,但是因为职责太多,在Android10之后,专门使用ActivityTaskManagerService(ATMS)来管理Activity的启动。

2.1 App启动流程分析

如果有做过Launcher的伙伴,应该明白当我们点击一个APP ICON的时候,就会启动一个app,这时APP的启动方式有很多,例如通过包名启动、通过scheme启动,那么从点击ICON到APP展示首页,这个过程是如何完成的呢?这里AMS就起到作用了。

因为当我们启动一个app的时候,无论是通过包名还是scheme,都是启动的Activity;例如我们通过包名启动,那么就会启动在Manifest清单文件中,标注android.intent.category.LAUNCHER的Activity;

<activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>

如果是通过scheme启动,那么也是启动标注这个scheme的Activity,所以当app启动的时候,也是启动Activity,所以最终我们还是继续分析Activity的启动流程,但是对于app进程是如何创建的,我们首先需要了解其中的原理。

2.1.1 app进程创建

通过前面的分析,我们知道app启动其实也是Activity的启动,所以肯定涉及到ATMS的职责,所以当启动一个app(Activity)的时候,system_server进程首先会判断当前要启动的这个进程是否存在,如果不存在,那么就需要通知Zygote进程去fork app进程

所以这里就涉及到了system_server进程与Zygote进程间通信,我们知道当Zygote进程初始化的时候,创建了ZygoteServer对象,也就是socket,所以system_server通过socket发送消息通知Zygote去fork app进程。

ATMS # startProcessAsync

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop, String hostingType) { try { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:" + activity.processName); } // 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 { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } }

在这个方法中,我们看到是调用ActivityManagerInternal # startProcess方法,这个就是真正去启动app进程的方法,我们跟进看一下,具体怎么发送socket消息的。

AMS # LocalService #startProcess

@Override public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName) { try { if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:" + processName); } 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 */); } } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } } final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated) { return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); }

这里我们发现有两个比较重要的对象:ProcessRecord和mProcessList;

其中ProcessRecord,顾名思义就是进程的记录类,用来记录这些进程的信息,包括与App进程通信的IApplicationThread Binder对象;

mProcessList则是一个列表,因为进程启动需要ATMS来通知Zygote,因此ATMS需要管理多个进程,因此使用mProcessList用来存储多个ProcessRecord,而且是按照最近使用最少原则(NLU)进行处理,记录各个进程的信息。

所以最终在启动进程的时候,就是调用了mProcessList的startProcessLocked方法,第一个参数就是进程名。最终调用的就是android.os.Process的start方法。

Tools for managing OS processes

对于Process相信伙伴们也不会陌生,我们在杀进程或者获取进程id的时候都会使用到其中的方法,官方给出的解释就是管理系统进程的工具类。

android.os.Process # start

public static ProcessStartResult start(@NonNull final String processClass, @Nullable final String niceName, int uid, int gid, @Nullable int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, @Nullable String seInfo, @NonNull String abi, @Nullable String instructionSet, @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, int zygotePolicyFlags, boolean isTopApp, @Nullable long[] disabledCompatChanges, @Nullable Map<String, Pair<String, Long>> pkgDataInfoMap, @Nullable Map<String, Pair<String, Long>> whitelistedDataInfoMap, boolean bindMountAppsData, boolean bindMountAppStorageDirs, @Nullable String[] zygoteArgs) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, zygoteArgs); }

我们看到Process的start方法,最终调用的是ZYGOTE_PROCESS的start方法,那么ZYGOTE_PROCESS是什么呢?

public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();

它是一个ZygoteProcess对象,官方解释如下:

Maintains communication state with the zygote processes. This class is responsible for the sockets opened to the zygotes and for starting processes on behalf of the Process class.

主要是用于维持与Zygote进程的通信,这个类的职责就是打开Zygote进程的socket并创建进程。

所以走到这里,就进入到了与Zygote进程进行socket通信的过程了。在通信之前,会封装一系列关于进程相关的参数,最终调用attemptZygoteSendArgsAndGetResult方法与Zygote进程进行通信。

private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult( ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx { try { final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter; final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream; //进行socket通信 zygoteWriter.write(msgStr); zygoteWriter.flush(); // 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) { 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启动流程的分析,在ZygoteServer创建之后,就会调用runSelectLoop方法进行死循环,当接收到Socket消息之后,就会处理消息,最终调用forkAndSpecialize方法来创建一个进程。这里就与第一小节中介绍的一致,当创建进程之后,会判断fork返回的pid是否为0。

static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) { ZygoteHooks.preFork(); int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp, pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs, bindMountAppStorageDirs); if (pid == 0) { // Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); // If no GIDs were specified, don't make any permissions changes based on groups. if (gids != null && gids.length > 0) { NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids)); } } // Set the Java Language thread priority to the default value for new apps. Thread.currentThread().setPriority(Thread.NORM_PRIORITY); ZygoteHooks.postForkCommon(); return pid; } 2.1.2 app进程启动流程分析

前面我们介绍,在ATMS中通过Socket通信通知Zygote创建一个app进程之后,后续app进程启动流程如何,我们接着往下看。

当发送指令告诉Zygote创建进程之后,如果创建子进程成功,那么此时pid == 0,会进入到if代码块中,调用handleChildProc方法。

// 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); try { if (pid == 0) { // in child zygoteServer.setForkChild(); zygoteServer.closeServerSocket(); IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote); } else { // In the parent. A pid < 0 indicates a failure and will be handled in // handleParentProc. IoUtils.closeQuietly(childPipeFd); childPipeFd = null; handleParentProc(pid, serverPipeFd); return null; } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); }

ZygoteConnection # handleChildProc

private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor pipeFd, boolean isZygote) { /* * By the time we get here, the native code has closed the two actual Zygote * socket connections, and substituted /dev/null in their place. The LocalSocket * objects still need to be closed properly. */ closeSocket(); Zygote.setAppProcessName(parsedArgs, TAG); // End of the postFork event. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (parsedArgs.mInvokeWith != null) { WrapperInit.execApplication(parsedArgs.mInvokeWith, parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.mRemainingArgs); // Should not get here. throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { if (!isZygote) { return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mDisabledCompatChanges, parsedArgs.mRemainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit( parsedArgs.mRemainingArgs /* classLoader */); } } }

我们看到最终还是调用ZygoteInit的zygoteInit方法,这里我们可以回到第一小节中,其实最终调用的就是App进程的main方法,也就是ActivityThread的main函数

这里先简单总结一下,无论是forkSystemServer还是fork普通进程,其实最终都是判断pid是否为0,因为这里决定着进程是否创建成功,如果进程创建成功,才会有后续的流程,调用handlexx方法。

调用handleXX方法,最终都是调用ZygoteInit中的zygoteInit方法;

在zygoteInit方法中,会调用ZygoteInit的nativeZygoteInit方法,会开启Binder驱动,创建Binder线程池;

调用RuntimeInit的applicationInit方法,最终调用的就是某个类的main方法,例如forkSystemServer中,会调用SystemServer的main方法;通过ATMS启动进程,会调用ActivityThread的main方法。

2.1.3 ActivityThead分析

前面我们提到了,当Zygote fork出app进程之后,就会调用ActivityThread的main方法,这里就是进入到我们熟悉的App进程启动中了。

public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); // Install selective syscall interception AndroidOs.install(); // 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 final 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 "seq=114" 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())); } } } ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }

这个方法大家很熟悉,首先也是创建looper,保证app进程不会退出;其次就是创建了ActivityThread对象,并调用了其中的attach方法。

在attch方法中,有一段核心代码:

final IActivityManager mgr = ActivityManager.getService(); try { mgr.attachApplication(mAppThread, startSeq); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); }

它会调用IActivityManager(也就是AMS在app进程的代理对象)的attachApplication方法,mAppThread就是ApplicationThread对象,这个属于app进程的代理对象,会丢给AMS使用。

final ApplicationThread mAppThread = new ApplicationThread();

就这样,App进程持有AMS端的代理,AMS端也会持有App进程的代理,双方就可以通过Binder完成进程间的通信。

其实在App进程中,可以通过ServiceManager来获取AMS的代理对象的,

private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };

通过源码便可以得知,获取AMS的代理对象之后,就可以调用它的方法,例如attachApplication,而且还是一个接口类,可以通过动态代理的方式Hook AMS相关的方法调用。

ActivityManagerService # attachApplication

@Override 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); } }

在这个方法中,最终调用的是attachApplicationLocked方法,在这个方法中,主要作用就是:

调用ApplicationThread的bindApplication方法,这里会通过Handler发送消息,用于创建和初始化Application对象;

private void handleBindApplication(AppBindData data) { // ...... // probably end up doing the same disk access. Application app; final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy(); try { // 创建Application对象,调用Application的attach方法 app = data.info.makeApplication(data.restrictedBackupMode, null); // ...... // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { // 注册 ContentProvicer 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. try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { // 调用Application的onCreate方法 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), 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); } } // ...... }

所以调用bindApplication方法,主要分为3步:创建Application对象,调用其attach方法、注册Contentprovider、调用Application的onCreate方法。

所以如果想要在Application的onCreate方法执行之前做一些事情,可以放在Contentprovider中处理,但是会影响启动速度。

为ProcessRecord的mThread属性赋值,也就ApplicationThread,用于与App进程通信。

public void makeActive(IApplicationThread thread, ProcessStatsService tracker) { mProfile.onProcessActive(thread, tracker); mThread = thread; mWindowProcessController.setThread(thread); }

将新创建的ProcessRecord添加到ProcessList中。

final void updateLruProcessLocked(ProcessRecord app, boolean activityChange, ProcessRecord client) { mProcessList.updateLruProcessLocked(app, activityChange, client); }

其实在AMS中就是维护了一组ProcessRecord,每个ProcessRecord中都持有这个进程的AppThread Binder对象

那么到这里,当Application的onCreate方法执行完成之后,app的进程就已经启动完成了,我们总结一下:

当点击Launcher入口准备启动App时,首先会向AMS发起启动Activity的请求,此时AMS会判断当前进程是否存在,如果不存在,那么就会向Zygote进程发送socket消息,把要创建的进程信息给到Zygote进程;

Zygote进程解析进程信息参数之后,会fork一个子进程,启动Binder并创建Binder线程池,然后调用ActivityThread的main方法;

在ActivityThread的main方法中,创建Looper,并调用ActivityThread的attach方法;

在调用ActivityThread的attach方法时,其实会调用到AMS代理对象的attachApplication方法,进入到SystemServer进程中处理;

在SystemServer进程中,AMS最终会调用attachApplicationLocked方法,在这个方法中会执行AppThread的bindApplication方法,在这个方法中,会创建Application对象,最终执行Application的onCreate方法;

当执行完Application的onCreate方法之后,App进程算是启动了,此时会对App进程对应的ProcessRecord对象调用makeActive赋值处理,然后将其添加到ProcessList当中。

这就是AMS创建app进程的全流程,既然App进程已经启动了。

以上就是Android AMS启动App进程原理分析的详细内容,更多关于Android AMS启动App的资料请关注软件开发网其它相关文章!



ams app Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号