在上一篇文章深入理解Android 之 Activity啓動流程中,應用程序根Activity的啓動過程通過系統源碼梳理了一遍,其中還有一個細節便是Android每個應用都是都是一個應用進程,而應用進程不會憑空產生,本文則通過系統源碼繼續探究Android應用程序進程啓動流程(文中源碼基於Android 10 )。
首先照例還是先看一個腦圖,在自己大腦中能產生初步印象
ActivityManagerService請求Zygote啓動應用程序進程
AMS處理啓動應用程序基本數據
- 上一篇文章第二小節分析中提到了ActivityStackSupervisor的startSpecificActivityLocked的方法
frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Activity應用程序進程是否已經準備好
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) { //1
try {
realStartActivityLocked(r, wpc, andResume, checkConfig); //2
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
.......
}
.......
try {
.......
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held. Hnadler發消息 避免死鎖
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());//3
mService.mH.sendMessage(msg);
}
........
}
- 由以前源碼註釋1和2如果應用程序進程已經存在,則繼續啓動Activity邏輯,否則來到註釋3出,我們看到關鍵部分ActivityManagerInternal::startProcess,"::"是Java 8 新增特性,相當於調用了ActivityManagerInternal的startProcess方法,而ActivityManagerInternal(frameworks/base/core/java/android/app/ActivityManagerInternal.java)是一個抽象類,它是Activity管理器本地服務接口,它的實現爲AMS的內部類LocalService,它註冊在AMS啓動的過程,通過LocalServices(frameworks/base/core/java/com/android/server/LocalServices.java)註冊,此類的使用方式與ServiceManager相似,不同之處在於,此處註冊的服務不是Binder對象,並且只能在同一進程(SystemServer進程)中使用。也就是說ActivityManagerInternal實現類LocalService是SystemServer進程的本地服務Service,通過本地服務註冊到LocalServices中,而AMS也是運行在SystemServer進程,則可以直接使用LocalService。所以註釋3處調用了LocalService的startProcess方法
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public void startProcess(String processName, ApplicationInfo info,
boolean knownToBeDead, 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) {
startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
new HostingRecord(hostingType, hostingName),
false /* allowWhileBooting */, false /* isolated */,
true /* keepIfLarge */);//
}
}
.......
}
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */); //2
}
- 由以上源碼註釋1處調用了startProcessLocked方法,由註釋2處則調用了 ProcessList的 startProcessLocked方法,ProcessList是處理Activity進程的管理類,接着往下看
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
..........
if (app == null) {
checkSlow(startTime, "startProcess: creating new process record");
app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);//1
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
app.crashHandler = crashHandler;
app.isolatedEntryPoint = entryPoint;
app.isolatedEntryPointArgs = entryPointArgs;
checkSlow(startTime, "startProcess: done creating new process record");
}
.....
final boolean success = startProcessLocked(app, hostingRecord, abiOverride);//2
checkSlow(startTime, "startProcess: done starting proc!");
return success ? app : null;
}
- 由以上代碼,註釋1處創建了ProcessRecord對象,它保存了當前正在運行的特定進程的完整信息,也就是需要啓動的應用程序進程,接着註釋2繼續調用startProcessLocked方法
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
/**
* @return {@code true} if process start is successful, false otherwise.
* @param app
* @param hostingRecord
* @param disableHiddenApiChecks
* @param abiOverride
*/
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
boolean disableHiddenApiChecks, boolean mountExtStorageFull,
String abiOverride) {
try {
....
int uid = app.uid;//1
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
......
/*
*添加共享的應用程序和配置文件GID,以便應用程序可以共享 某些資源(如共享庫)並訪問用戶範圍的資源
*/
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[3];
} else {
gids = new int[permGids.length + 3];
System.arraycopy(permGids, 0, gids, 3, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid)); //2
.......
}
......
final String entryPoint = "android.app.ActivityThread";//3
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);//4
} catch (RuntimeException e) {
.......
}
}
boolean startProcessLocked(HostingRecord hostingRecord,
String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
.......
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
mService.mProcStartHandler.post(() -> {
try {
final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);//5
synchronized (mService) {
handleProcessStartedLocked(app, startResult, startSeq);
}
} catch (RuntimeException e) {
.....
});
return true;
} else {
try {
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
invokeWith, startTime);//6
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} catch (RuntimeException e) {
........
}
return app.pid > 0;
}
}
- 由以上代碼註釋1處獲取了應用程序的用戶id,註釋2出獲取了用戶組ID,爲應用程序進程提供用戶組資源訪問權限,註釋3處給entryPoint賦值爲android.app.ActivityThread,先記住這個值,後續分析還會繼續提起它;註釋4處接着調用了startProcessLocked方法,在該方法中註釋5和6最終都是調用了ProcessList類的startProcess方法,接着往下看
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
/**
* The currently running application zygotes.
*/
final ProcessMap<AppZygote> mAppZygotes = new ProcessMap<AppZygote>();
/**
* The processes that are forked off an application zygote.
*/
final ArrayMap<AppZygote, ArrayList<ProcessRecord>> mAppZygoteProcesses =
new ArrayMap<AppZygote, ArrayList<ProcessRecord>>();
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
try {
.......
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,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});//1
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*useUsapPool=*/ false,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});//2
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});//3
}
....
return startResult;
}
......
}
- 由以上代碼,startProcess方法會根據當前啓動的是什麼進程處理不同的邏輯,註釋1是啓動webview進程,註釋2處理用戶AppZygote,而註釋3處纔是出路新創建的應用程序進程,也就是調用了Process類的start方法,Process是
用於管理操作系統進程的工具類,接着看它的start方法
Process 處理啓動參數到Zygote進程
frameworks/base/core/java/android/os/Process.java
/**
* State associated with the zygote process.
* @hide
*/
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess(); //1
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,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
/*useUsapPool=*/ true, zygoteArgs);//2
}
- 由以上代碼,結合註釋1和註釋2則調用了ZygoteProcess類的start方法,ZygoteProcess保持與Zygote 的通信狀態。 此類負責對Zygote 打開套接字,並代表Porcess啓動進程。接着看到ZygoteProcess類的start方法
frameworks/base/core/java/android/os/ZygoteProcess.java
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,
boolean useUsapPool,
@Nullable String[] zygoteArgs) {
.....
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, useUsapPool, zygoteArgs);//1
}
.....
}
- 由以上代碼註釋1,又調用了ZygoteProcess類的start方法,接着往下看
frameworks/base/core/java/android/os/ZygoteProcess.java
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,
boolean useUsapPool,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<>();//1
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.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_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
argsForZygote.add("--mount-external-full");
}
.......
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),
useUsapPool,
argsForZygote);//2
}
}
- 由以上代碼,註釋1處創建了一個集合argsForZygote用來保存啓動應用程序進程參數,接着又調用了zygoteSendArgsAndGetResult方法,而該方法第一個參數又調用了openZygoteSocketIfNeeded方法
frameworks/base/core/java/android/os/ZygoteProcess.java
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args)
throws ZygoteStartFailedEx {
.......
if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) {
try {
return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);//1
} 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());
}
}
return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);//2
}
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
try {
attemptConnectionToPrimaryZygote();//3
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
if (mZygoteSecondarySocketAddress != null) {
// The primary zygote didn't match. Try the secondary.
attemptConnectionToSecondaryZygote();//4
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
}
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
- 由以上代碼,註釋1處和註釋2都傳入了zygoteState,它代表的是ZygoteState類,它是ZygoteProcess靜態內部類,保存了與 Zygote 進行通信的狀態,而它的返回是由openZygoteSocketIfNeeded方法處理的,所以看到註釋3和註釋4分別調用了attemptConnectionToPrimaryZygote方法和attemptConnectionToSecondaryZygote方法,這和Zygote進程啓動加載的配置文件有關,這裏就不展開了,兩個方法邏輯基本相同,直接看到其中一個attemptConnectionToPrimaryZygote方法
frameworks/base/core/java/android/os/ZygoteProcess.java
/**
* Creates a ZygoteState for the primary zygote if it doesn't exist or has been disconnected.
*/
@GuardedBy("mLock")
private void attemptConnectionToPrimaryZygote() throws IOException {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);//1
maybeSetApiBlacklistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
}
}
- 由註釋1調用ZygoteState的connect方法來打開Socket連接,mZygoteSocketAddress則是名稱爲zygote的 Socket 服務
ActivityManagerService請求Zygote啓動應用程序進程時序圖
- 本小節最後還是通過時序圖來對上面的步驟進行回顧
Zygote啓動應用程序進程
- 經過上一小節分析,AMS最終是通過Socket方式進程間通信請求到了Zygote進程。Zygote英文爲受精卵的意思,它啓動過程創建了Android 虛擬機,其他應用程序進程則通過fork複製Zygote來創建應用程序進程,比如AMS服務所在的SystemServer進程,關於Zygote進程進程的啓動過程細節又是另一部分內容了,本文則先只分析應用程序進程啓動的過程,接下來從ZygoteInit的main方法開始
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
@UnsupportedAppUsage
public static void main(String argv[]) {
.....
Runnable caller;//1
try {
........
boolean startSystemServer = false;//2
String zygoteSocketName = "zygote";//3
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {//4
startSystemServer = true;
}
.......
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
......
Zygote.initNativeState(isPrimaryZygote);//5
.....
zygoteServer = new ZygoteServer(isPrimaryZygote);//6
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); //7
}
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);//8
}
.......
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run(); //9
}
}
由以上是縮短精簡的ZygoteInit的main方法,註釋1處創建了一個Runnable類型的請求對象代表此次請求Zygote獲取應用進程的對象;結合註釋2、4和7如果是Android系統啓動過程,則會啓動核心進程SystemServer,否則是啓動其他應用程序進程,註釋3出設置Socket連接名稱爲zygote,註釋5出則初始化了Zygote的狀態環境,包括支持套接字的環境,安全環境等,同時也包括Socket連接的名稱爲zygote;註釋6創建了ZygoteServer對象,它可以理解爲Zygote支持Socket進程通信的服務端,而在註釋8的 runSelectLoop 方法則是Zygote進程等待接收AMS請求啓動應用程序進程的關鍵方法,註釋9先放着,接着往下看
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
......
while (true) {
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// Zygote server socket
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket 從Zygote服務器套接字接受會話套接字
try {
ZygoteConnection connection = peers.get(pollIndex);
final Runnable command = connection.processOneCommand(this); //1
......
return command;
}
.......
}
- 由以上代碼,通過一個死循環等待接收請求,註釋1處則調用了ZygoteConnection的processOneCommand方法,接着往下看
獲取應用程序進程
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
/**
* Reads one start command from the command socket. If successful, a child is forked and a
* {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
* process. {@code null} is always returned in the parent process (the zygote).
*
* If the client closes the socket, an {@code EOF} condition is set, which callers can test
* for by calling {@code ZygoteConnection.isClosedByPeer}.
*/
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
ZygoteArguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = Zygote.readArgumentList(mSocketReader);//1
....
}
......
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.mTargetSdkVersion); //2
try {
if (pid == 0) { //3
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, 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, descriptors, serverPipeFd);
return null;
}
}
......
}
- 由以上代碼註釋1處獲取了啓動應用程序進程的參數,看到註釋2處,直接調用了Zygote類的forkAndSpecialize方法
frameworks/base/core/java/com/android/internal/os/Zygote.java
/**
* Forks a new VM instance. The current VM must have been started
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
*/
public 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,
int targetSdkVersion) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir);//1
return pid;
}
- 由以上代碼註釋1處,通過Native方法nativeForkAndSpecialize與底層通信複製fork出應用即將要啓動的應用程序進程,本文則關注大致流程,底層Native實現則不再繼續展開,有興趣朋友可以繼續跟進frameworks/base/core/jni/com_android_internal_os_Zygote.cpp查看。根據forkAndSpecialize方法的註釋也可以明白,該方法返回0則爲child,也就是應用程序進程,-1則爲父進程,所以這裏再次回到ZygoteConnection的processOneCommand方法,啓動的是應用程序進程,則在註釋3出pid=0 此時已經處於應用程序進程了,接着繼續調用ZygoteConnection的
handleChildProc方法
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
..........
} else {
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */); //1
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}
- 由以上源碼,啓動的是應用程序進程則會走到註釋1處調用ZygoteInit類的zygoteInit方法
創建應用程序的ActivityThread
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, 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();//1
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); //2
}
- 由以上源碼,註釋1出的Native方法會創建當前應用程序進程的Binder線程池,則當前應用程序就擁有了Binder通信的能力,註釋2處接着調用了RuntimeInit的applicationInit方法
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
......
final Arguments args = new Arguments(argv); //1
......
return findStaticMain(args.startClass, args.startArgs, classLoader);2
}
- 由以上代碼,註釋1處處理AMS請求中傳遞過來的參數,這其中就包括android.app.ActivityThread,也就是註釋2處args.startClass代表的值,接着繼續看findStaticMain方法
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);//1
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });//2
}
......
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
return new MethodAndArgsCaller(m, argv);
}
- 由以上代碼,註釋1處反射獲取了android.app.ActivityThread,也就是應用程序進程的ActivityThread,註釋2處獲取了ActivityThread的main方法,然後返回了Runnable對象爲MethodAndArgsCaller
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
/**
* Helper class which holds a method and arguments and can call them. This is used as part of
* a trampoline to get rid of the initial process setup stack frames.
*/
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs }); //1
}
...
}
}
- 由以上代碼,註釋1處代表應用程序進程ActivityThread的main方法,結合本小節開頭的從ZygoteInit的main方法的註釋9,目前已經處於應用程序進程,則會調用Runnable類型caller的run方法,也就是MethodAndArgsCaller的run方法,由以上代碼註釋1處,則會調用ActivityThread的main方法,而ActivityThread作爲每個應程序主線程的管理類,到此,應用程序進程啓動完成,接着上一篇文章,當ATMS與應用程序Binder通信通過IApplicationThread爲ActivityThread的內部類,然後調用ActivityThread的performLaunchActivity方法來啓動Activity。
Zygote啓動應用程序進程時序圖
- 本小節最後還是通過時序圖來對上面的步驟進行回顧
總結
啓動過程涉及的進程
- 結合上一篇文章深入理解Android 之 Activity啓動流程,總結出如下應用程序進程啓動涉及的幾個進程間調用的關係圖
參考
- 書籍《Android 進階解密》
- Android源碼地址