Android从启动到ActivityThread的流程分析

在android中当启动一个新进程时,会经过一系列的函数调用与处理走到ActivityThread类的main函数。下面从源码的角度逐步分析这个过程。

1,在frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java中

typescript 复制代码
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
	mService.startProcessAsync(r, knownToBeDead, isTop,
			isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
			: HostingRecord.HOSTING_TYPE_ACTIVITY);
}

2,在frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java中

arduino 复制代码
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,String hostingType) {
	final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
            mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
            isTop, hostingType, activity.intent.getComponent()); //该消息封装了对ActivityManagerInternal::startProcess方法的调用,会走到AMS的startProcess函数
    mH.sendMessage(m);
}

上面的代码通过消息启动AMS中的startProcess函数。

3,在frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中

arduino 复制代码
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
	boolean isTop, String hostingType, ComponentName hostingName) { //该函数所在的类为LocalService,重写抽象类ActivityManagerInternal中的startProcess函数,它是由ATMS中startProcessAsync函数通过Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess执行到该函数
	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 */); // 在同步块内部,调用startProcessLocked方法来实际启动进程
	}
}

上面的函数调用startProcessLocked

java 复制代码
@GuardedBy("this")
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 */,	
            false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,	
            null /* sdkSandboxClientAppPackage */,	
            null /* ABI override */, null /* entryPoint */,	
            null /* entryPointArgs */, null /* crashHandler */);// 调用ProcessList类的startProcessLocked函数	
}

上面的函数调用ProcessList类的startProcessLocked函数。

4,在frameworks/base/services/core/java/com/android/server/am/ProcessList.java中

arduino 复制代码
public final class ProcessList {
	boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,String abiOverride) {
	final String entryPoint = "android.app.ActivityThread";
	return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
				runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
				instructionSet, invokeWith, startUptime, startElapsedTime);
	}
	
	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) {
			
			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, 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;
	        }
	}
}

上面的代码中设置entryPoint = "android.app.ActivityThread",以参数的形式进行传递进一步调用到startProcess函数。

arduino 复制代码
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) {
		regularZygote = true;
	    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。

5,在frameworks/base/core/java/android/os/Process.java中

less 复制代码
public class Process {
	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);
	}
}

6,在frameworks/base/core/java/android/os/ZygoteProcess.java中

less 复制代码
/*package*/ class ZygoteStartFailedEx extends Exception {
	
	public final Process.ProcessStartResult start(@NonNull final String processClass,
	                                              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>>
	                                                      allowlistedDataInfoList,
	                                              boolean bindMountAppsData,
	                                              boolean bindMountAppStorageDirs,
	                                              @Nullable String[] zygoteArgs) {
	    // TODO (chriswailes): Is there a better place to check this value?
	    if (fetchUsapPoolEnabledPropWithMinInterval()) {
	        informZygotesOfUsapPoolStatus();
	    }
	
	    try {
	        return startViaZygote(processClass, niceName, uid, gid, gids,
	                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
	                abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
	                packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
	                pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,
	                bindMountAppStorageDirs, zygoteArgs);
	    } catch (ZygoteStartFailedEx ex) {
	        Log.e(LOG_TAG,
	                "Starting VM process through Zygote failed");
	        throw new RuntimeException(
	                "Starting VM process through Zygote failed", ex);
	    }
	}
}

上面的代码调用startViaZygote函数。

java 复制代码
private Process.ProcessStartResult startViaZygote {
	synchronized(mLock) { // 将这段代码放入synchronized(mLock)块中,确保了即使在多线程环境中,与Zygote的通信也是线程安全的。这防止了多个线程同时尝试启动应用程序进程时可能出现的冲突或不一致。
        // 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);// zygoteSendArgsAndGetResult方法负责将启动参数发送给Zygote进程,并返回启动结果
    }
}

@GuardedBy("mLock") // 带有@GuardedBy("mLock")注解,表示这个方法在被调用时,必须持有名为mLock的锁。这是为了保证线程安全,防止在并发环境下出现数据不一致的情况。
private Process.ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)throws ZygoteStartFailedEx {
	return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr); // 返回一个Process.ProcessStartResult对象,该对象包含了启动结果,如新启动的进程ID(如果启动成功)或相关的错误信息(如果启动失败)
}

private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
        ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
    try {
		 // zygoteState是一个封装了与Zygote进程通信所需的状态信息的对象,包括用于向Zygote发送数据的BufferedWriter(mZygoteOutputWriter)和用于从Zygote接收数据的DataInputStream(mZygoteInputStream)
        final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
        final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
		 // 使用zygoteState.mZygoteOutputWriter(BufferedWriter类型)将消息字符串msgStr写入到与Zygote进程通信的socket中。
        zygoteWriter.write(msgStr); // msgStr是要发送给Zygote的消息字符串,包含了启动新进程所需的参数。
		 // 调用flush()方法确保所有待写数据都被发送到Zygote进程。这一步是发送socket信号的关键,它告诉Zygote进程有新的数据可以读取。
        zygoteWriter.flush(); // 发送socket信号

        // 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(); // 创建一个Process.ProcessStartResult对象result,用于存储从Zygote接收到的启动结果。
		 // 使用zygoteState.mZygoteInputStream(DataInputStream类型)从socket中读取新进程的PID(进程ID)和usingWrapper标志
        result.pid = zygoteInputStream.readInt(); // 读socket结果
        result.usingWrapper = zygoteInputStream.readBoolean(); // usingWrapper标志表示是否使用了包装器进程

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

7,在frameworks/base/core/java/com/android/internal/os/ZygoteServer.java中

scss 复制代码
class ZygoteServer {
	Runnable runSelectLoop(String abiList) {
		while (true) {
			int pollReturnValue;
		    try {
		    	// 处理轮询状态,当pollFDs有事件到来则向下执行,否则阻塞在这里.这个函数会阻塞当前线程直到有文件描述符就绪(即发生了某个事件,如可读、可写或异常)或达到了超时时间pollTimeoutMs。如果调用成功,pollReturnValue将包含就绪的文件描述符的数量
		        pollReturnValue = Os.poll(pollFDs, pollTimeoutMs); 
		    } catch (ErrnoException ex) {
		        throw new RuntimeException("poll failed", ex);
		    }
		    
		    if (pollReturnValue == 0) { // 如果pollReturnValue为0,表示在超时时间内没有文件描述符就绪,或者进行了非阻塞轮询但没有文件描述符就绪
				...
			} else {
				while (--pollIndex >= 0) {// 采用倒序处理,先处理已经建立的连接请求,这个优先是后面建立的连接请求在有数据到来时是优先处理
		            if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
		                continue;
		            }
		        
		            if (pollIndex == 0) { // socketFDs[0]代表的是mZygoteSocket因为它最先加入
		                // Zygote server socket
		                ZygoteConnection newPeer = acceptCommandPeer(abiList); // pollIndex为0,表示这是Zygote服务器的socket,此时会调用acceptCommandPeer()来接受新的连接请求,并将新连接加入监听列表。
		                peers.add(newPeer);// 加入的peers和socketFDs,下一次也开始监听
		                socketFDs.add(newPeer.getFileDescriptor());
		            } else if (pollIndex < usapPoolEventFDIndex) {
						ZygoteConnection connection = peers.get(pollIndex); // 对于非Zygote服务器socket的文件描述符(即pollIndex大于0),会获取对应的ZygoteConnection对象,并调用其processCommand()方法来处理接收到的命令。
		                boolean multipleForksOK = !isUsapPoolEnabled()
		                        && ZygoteHooks.isIndefiniteThreadSuspensionSafe();// 检查是否允许多个fork操作,然后执行相应的命令
		                final Runnable command =
		                        connection.processCommand(this, multipleForksOK);// 进行进程处理:创建进程,调用ZygoteConnection类的processCommand函数
					}
				}
			}
		}
	}
}

上面的代码调用了ZygoteConnection类的processCommand函数进行创建进程等处理.

8,在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java中

ini 复制代码
class ZygoteConnection {
	Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
    	pid = Zygote.forkAndSpecialize(...); //fork进程
    	if (pid == 0) {
    		zygoteServer.setForkChild();
            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            return handleChildProc(parsedArgs, childPipeFd,parsedArgs.mStartChildZygote); //处理子进程
    	}
    }
}

上面的代码返回handleChildProc函数。

typescript 复制代码
private Runnable handleChildProc(ZygoteArguments parsedArgs,FileDescriptor pipeFd, boolean isZygote) {
	if (!isZygote) {//当前不是Zygote进程本身(!isZygote),则返回一个Runnable,该Runnable将调用ZygoteInit.zygoteInit方法来初始化并运行应用进程
        return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, null /* classLoader */);
	}
}

9,在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中

scss 复制代码
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();//启动Binder,方法在AndroidRuntime.cpp中注册
    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);
}

上面的代码调用applicationInit函数。

10,在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中

vbnet 复制代码
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {
	 final Arguments args = new Arguments(argv);
	 return findStaticMain(args.startClass, args.startArgs, classLoader);
}

protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {
	Class<?> cl;
	cl = Class.forName(className, true, classLoader); // 使用Class.forName(className, true, classLoader)加载指定的类。这里的true表示在加载类的同时初始化该类.
	Method m;
	m = cl.getMethod("main", new Class[] { String[].class });// 通过反射拿到对应类的main方法的method对象
	int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { // 检查找到的main方法是否同时是public和static的。如果不是,则抛出运行时异常,因为main方法必须同时满足这两个条件才能被正确调用。
        throw new RuntimeException("Main method is not public and static on " + className);
    }
	return new MethodAndArgsCaller(m, argv);
}

static class MethodAndArgsCaller implements Runnable {
	// 第一个参数为类对象,方法是static的话可以是null,第二个参数是一个对象数组,包含了调用方法时所使用的参数,这里只有一个元素,即mArgs字符串数组,它被包装在一个新的对象数组中,因为invoke方法要求第二个参数是Object...(可变参数)类型。
	mMethod.invoke(null, new Object[] { mArgs }); 
}

经过上面的步骤就会调用到ActivityThread的main方法。

11,在frameworks/base/core/java/android/app/ActivityThread.java中

scala 复制代码
public final class ActivityThread extends ClientTransactionHandlerimplements ActivityThreadInternal {
	public static void main(String[] args) {
    	Looper.prepareMainLooper();
    	ActivityThread thread = new ActivityThread();
    	thread.attach(false, startSeq); //调用ActivityThread的attach方法,第一个参数为false,表示不是system server进程,tartSeq参数用于传递启动序列号,可能用于调试或跟踪目的
    	Looper.loop();
    }
}

经过以上步骤就走到了ActivityThread类的main函数中。

相关推荐
麦克尔.马2 小时前
一个安卓鸿蒙化工具
android·华为·harmonyos
国通快递驿站3 小时前
理解JVM中的死锁:原因及解决方案
android·java·jvm·spring·诊断
锋风4 小时前
哔哩哔哩直播链接报403解决办法
android
西瓜本瓜@5 小时前
在Android中fragment的生命周期
android·开发语言·android studio·kt
老哥不老7 小时前
MySQL安装教程
android·mysql·adb
xcLeigh8 小时前
html实现好看的多种风格手风琴折叠菜单效果合集(附源码)
android·java·html
图王大胜9 小时前
Android SystemUI组件(07)锁屏KeyguardViewMediator分析
android·framework·systemui·锁屏
InsightAndroid9 小时前
Android通知服务及相关概念
android
aqi0011 小时前
FFmpeg开发笔记(五十四)使用EasyPusher实现移动端的RTSP直播
android·ffmpeg·音视频·直播·流媒体