本文轉(zhuǎn)載自:深度詳解 Android R(11.0)Activity 啟動過程
本文基于Android 11.0源碼分析
前言
??繼續(xù)上一篇分析Activity啟動過程纲熏。
3.AMS向Zygote進程發(fā)送創(chuàng)建應用進程ActivityThread的過程
3.1 時序圖
3.2 ActivityTaskManagerService啟動進程
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
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.
// 發(fā)送Handler消息來啟動進程秃诵,以避免在持有ATMS鎖的情況下調(diào)用AMS時可能發(fā)生的死鎖
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);
}
}
方法中需要發(fā)送Handler消息來啟動進程,在獲取Message消息對象時跟我們平時的使用方式不太一樣弯菊,這里是用到PooledLambda#obtainMessage()函數(shù)疮丛,代碼如下:
// frameworks/base/core/java/com/android/internal/util/function/pooled/PooledLambda.java
static <A, B, C, D, E, F> Message obtainMessage(
HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
null, null, null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
可以看到這是一個靜態(tài)函數(shù)焕数,可以在接口外部直接被調(diào)用,這是Java 1.8的新特性跪楞,被static或default修飾的接口方法可以有默認實現(xiàn)缀去,感興趣的童鞋可以自行查閱哈。接口里面使用了經(jīng)典的lambda定義方式甸祭,這個泛型的定義巧妙的將我們的函數(shù)以及需要傳入的參數(shù)類型連接起來缕碎,第一個傳入的lambda接口跟后面的參數(shù)類型緊密有關(guān),調(diào)用這個函數(shù)的時候直接將需要傳入的參數(shù)一并傳入池户。這里需要提到的是lambda里面的中間接口是一種隱藏式的存在咏雌,我們在調(diào)用的過程中可以直接匿名忽略掉,上面的調(diào)用實例就是如此校焦,直接使用了::符號 直接鏈接到目標函數(shù) startProcess()赊抖。
??所以語法含義是調(diào)用ActivityManagerInternal類的startProcess() 方法,后面的那些變量就是傳遞到startProcess()方法的入?yún)⒄洹>唧w的再說就偏離主題了氛雪,感興趣的可以自行查閱,簡要說明就是這里通過acquire()函數(shù)獲取到一個PooledRunnable實例耸成,又通過它的recycleOnUse()函數(shù)得到一個PooledLambdaImpl(實現(xiàn)了PooledLambda接口)的實例报亩,所以當我們后續(xù)再調(diào)用sendMessage()的時候這個PooledRunnable的run()方法會得到執(zhí)行,也即ActivityManagerInternal#startProcess()方法墓猎。
??ActivityManagerInternal是一個抽象類,它是Activity管理本地服務(wù)接口的赚楚,它的實現(xiàn)為AMS的內(nèi)部類LocalService毙沾,在AMS啟動的過程,通過LocalServices#addService()注冊到LocalServices宠页,此類的使用方式與ServiceManager相似左胞,不同之處在于寇仓,此處注冊的服務(wù)不是Binder對象,并且只能在同一進程(system_server進程)中使用烤宙。也就是說ActivityManagerInternal實現(xiàn)類LocalService是system_server進程的本地服務(wù)Service遍烦,通過本地服務(wù)注冊到LocalServices中,而AMS也是運行在system_server進程躺枕,因此可以直接使用LocalService服猪。
??LocalServices可以理解為是一個公開緩存池,內(nèi)部使用ArrayMap來存儲本地服務(wù)對象拐云。system_server進程中每個服務(wù)都可以通過LocalServices#addService()注冊到LocalServices中罢猪,需要使用存儲的LocalService時通過 LocalServices#getService()獲取注冊的本地服務(wù)。
3.3 ActivityManagerService
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
public final class LocalService extends ActivityManagerInternal {
......
@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 */, true /* keepIfLarge */);
}
} 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, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
keepIfLarge, null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
}
startProcess()方法調(diào)用AMS#startProcessLocked()方法叉瘩,并返回ProcessRecord實例記錄管理啟動進程的信息膳帕。
3.4 ProcessList
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
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) {
......
// ProcessRecord記錄每個進程的信息,進程名薇缅、uid等
ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkSlow(startTime, "startProcess: stepping in to startProcess");
final boolean success =
startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
checkSlow(startTime, "startProcess: done starting proc!");
return success ? app : null;
}
---------------------------------------------------------------------
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
false /* mountExtStorageFull */, abiOverride);
}
---------------------------------------------------------------------
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
boolean mountExtStorageFull, String abiOverride) {
......
try {
app.gids = gids;
app.setRequiredAbi(requiredAbi);
app.instructionSet = instructionSet;
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
// 配置新創(chuàng)建進程的啟動文件:ActivityThread危彩,經(jīng)過層層封裝后經(jīng)Socket傳輸?shù)絑ygote進程
// Zygote進程fork出新進程后要加載啟動的類文件名
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
}
......
}
---------------------------------------------------------------------
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 startTime) {
......
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
......
} else {
try {
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startTime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
}
......
return app.pid > 0;
}
}
---------------------------------------------------------------------
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 {
......
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});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
// We can't isolate app data and storage data as parent zygote already did that.
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,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} 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, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
經(jīng)過調(diào)用4個startProcessLocked()方法后,調(diào)用到了startProcess()方法泳桦,然后在startProcess()方法里做了一個判斷汤徽,根據(jù)不同的參數(shù)調(diào)用不同的方法啟動進程,這里跟進Process#start()繼續(xù)追蹤源碼蓬痒。
3.5 Process
// frameworks/base/core/java/android/os/Process.java
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
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);
}
ZYGOTE_PROCESS是ZygoteProcess在Process類中的靜態(tài)實例泻骤,所以流程調(diào)用走到Process#start()方法繼續(xù)進程的啟動流程。
3.6 ZygoteProcess
// 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,
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) {
// TODO (chriswailes): Is there a better place to check this value?
if (fetchUsapPoolEnabledPropWithMinInterval()) {
informZygotesOfUsapPoolStatus();
}
try {
// 繼續(xù)調(diào)用startViaZygote梧奢,即通過Zygote來啟動進程
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
}
......
}
---------------------------------------------------------------------
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 Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
// 創(chuàng)建字符串列表argsForZygote狱掂,將應用進程的啟動參數(shù)保存在argsForZygote中
// 包括uid、gid亲轨、targetSdkVersion趋惨、應用程序進程啟動文件:android.app.ActivityThread等參數(shù)
ArrayList<String> argsForZygote = new ArrayList<>();
...... // 添加各種參數(shù)值
argsForZygote.add(processClass);
......
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.
// 調(diào)用zygoteSendArgsAndGetResult(),將傳入的應用進程的啟動參數(shù)argsForZygote寫入到ZygoteState中
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags, argsForZygote);
}
}
ZygoteProcess#start()方法中惦蚊,繼續(xù)調(diào)用 ZygoteProcess#startViaZygote() 方法器虾,即通過Zygote來啟動進程,方法流程如下:
建字符串列表argsForZygote蹦锋,將應用進程的啟動參數(shù)保存在argsForZygote列表中兆沙,包括uid、gid莉掂、targetSdkVersion葛圃、應用進程的啟動文件:android.app.ActivityThread等參數(shù)。
調(diào)用ZygoteProcess#openZygoteSocketIfNeeded() 方法,如果與Zygote進程的socket連接未開啟库正,則嘗試開啟曲楚,可能會產(chǎn)生阻塞和重試。連接調(diào)用的是ZygoteState#connect() 方法褥符,ZygoteState是ZygoteProcess的內(nèi)部類龙誊。
調(diào)用ZygoteProcess#zygoteSendArgsAndGetResult() 方法,向Zygote進程發(fā)送參數(shù)列表喷楣,啟動一個新的子進程并返回子進程的pid趟大。注意:當前實現(xiàn)將參數(shù)列表中的換行符替換為空格。
3.7 ZygoteProcess開啟socket連接
// frameworks/base/core/java/android/os/ZygoteProcess.java
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
try {
//與Zygote進程建立Socket連接
attemptConnectionToPrimaryZygote();
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
if (mZygoteSecondarySocketAddress != null) {
// The primary zygote didn't 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);
}
-------------------------------------------------------
private static class ZygoteState implements AutoCloseable {
......
// 上面Primary抡蛙、Secondary都是調(diào)用ZygoteState.connect()方法來創(chuàng)建一個使用給定Zygote socket 地址的 Socket 連接
static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
@Nullable LocalSocketAddress usapSocketAddress)
throws IOException {
DataInputStream zygoteInputStream;
BufferedWriter zygoteOutputWriter;
final LocalSocket zygoteSessionSocket = new LocalSocket();
if (zygoteSocketAddress == null) {
throw new IllegalArgumentException("zygoteSocketAddress can't be null");
}
try {
zygoteSessionSocket.connect(zygoteSocketAddress);
zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
zygoteOutputWriter =
new BufferedWriter(
new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
} catch (IOException ex) {
try {
zygoteSessionSocket.close();
} catch (IOException ignore) { }
throw ex;
}
// socket护昧、DataInputStream、BufferedWriter封裝成 ZygoteState 對象供外部調(diào)用
return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
getAbiList(zygoteOutputWriter, zygoteInputStream));
}
}
ZygoteProcess#openZygoteSocketIfNeeded()方法粗截,打開與Zygote進程的socket連接惋耙,如果連接未建立,則嘗試調(diào)用ZygoteState#connect()方法創(chuàng)建一個使用給定Zygote socket地址的Socket連接熊昌,然后連接到Zygote的遠程服務(wù)端绽榛,同時創(chuàng)建BufferedWriter和DataInputStream進行參數(shù)數(shù)據(jù)的傳輸與讀取,最后將socket婿屹、DataInputStream灭美、BufferedWriter等封裝成ZygoteState對象供外部調(diào)用。
3.8 ZygoteProcess發(fā)送請求參數(shù)
// frameworks/base/core/java/android/os/ZygoteProcess.java
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
throws ZygoteStartFailedEx {
......
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());
}
}
return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}
-----------------------------------
// 用來fork出一個新的應用進程
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();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
// 創(chuàng)建進程
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) {
// 進程創(chuàng)建失敗
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);
}
}
ZygoteProcess#attemptZygoteSendArgsAndGetResult()方法中使用創(chuàng)建的ZygoteState中保存的BufferedWriter和DataInputStream來進行Socket通信昂利,通過它們進行數(shù)據(jù)流的傳輸與讀取操作届腐。system_server 進程通過BufferedWriter將參數(shù)寫給Zygote進程的socket的server端,然后阻塞等待Zygote進程的socket返回pid和usingWrapper后封裝到 ProcessStartResult蜂奸。
4.Zygote進程接收請求fork并啟動應用進程ActivityThread的過程
4.1 時序圖
4.2 Zygote進程啟動犁苏、解析Socket傳入的參數(shù)
??Android系統(tǒng)底層是基于Linux 的,和Linux一樣扩所,init進程是Linux系統(tǒng)用戶進程的第一個進程围详,它是由Linux內(nèi)核(kenerl)啟動的,用來啟動屬性服務(wù)(類似Windows中的注冊表)祖屏、啟動進程助赞。其它所有的用戶進程都是init 進程的子進程,我們接下來分析的Zygote進程也是由init進程而創(chuàng)建的袁勺,Zygote如何啟動這里暫不討論雹食,Zygote啟動之后會調(diào)用ZygoteInit#main()方法,所以我們先從main()方法來看socket創(chuàng)建和消息讀取期丰。代碼如下:
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
......
Runnable caller;
try {
......
// 解析參數(shù)
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
......
zygoteServer = new ZygoteServer(isPrimaryZygote);
......
// 調(diào)用 runSelectLoop() 開啟Loop循環(huán)來監(jiān)聽client socket發(fā)來的消息
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the command.
// 子進程的啟動
if (caller != null) {
caller.run();
}
}
方法中新建ZygoteServer實例對象群叶,調(diào)用ZygoteServer#runSelectLoop()方法開啟loop無限循環(huán)來監(jiān)聽client socket發(fā)來的消息漠嵌,當接收到創(chuàng)建新進程的請求時,立即喚醒并執(zhí)行相應工作盖呼。如果fork出系統(tǒng)進程,則加入到列表化撕,然后繼續(xù)阻塞等待几晤;如果fork出子進程,則退出loop循環(huán)植阴,返回創(chuàng)建的應用子進程蟹瘾,并執(zhí)行子進程的啟動。
4.3 ZygoteServer開啟Loop循環(huán)監(jiān)聽Socket
// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
mUsapPoolSupported = true;
fetchUsapPoolPolicyProps();
}
--------------------------------------------------------------
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
// mZygoteSocket是服務(wù)端的socket對象掠手,也就是Zygote進程所在socket放在fds[0]位置
socketFDs.add(mZygoteSocket.getFileDescriptor());
// 剛開始默認 peers[0] = null
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
// 開啟輪詢等待
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
if (mUsapPoolEnabled) {
usapPipeFDs = Zygote.getUsapPipeFDs();
pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
int pollIndex = 0;
......
int pollTimeoutMs;
if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
pollTimeoutMs = -1;
} else {
long elapsedTimeMs = System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;
if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
pollTimeoutMs = -1;
} else if (elapsedTimeMs <= 0) {
pollTimeoutMs = mUsapPoolRefillDelayMs;
} else {
pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
}
}
int pollReturnValue;
try {
// 處理輪詢狀態(tài)憾朴,當pollFds有事件到來則往下執(zhí)行,否則阻塞在這里
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
if (pollReturnValue == 0) {
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} else {
boolean usapPoolFDRead = false;
// 倒序處理喷鸽,即優(yōu)先處理已建立連接的信息众雷,后處理新建連接的請求
while (--pollIndex >= 0) {
// 采用I/O多路復用 epoll 機制,當接收到客戶端請求到來做祝,則往下執(zhí)行砾省;否則跳出本次循環(huán)
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// Zygote server socket
// pollIndex==0 表示有新的客戶端請求連接到來,調(diào)用server socket端的 accpet 函數(shù)建立通信連接
// zygote 進程與 system server 進程建立了連接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
// 加入到 peers 和 fds, 即開始下一次監(jiān)聽
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
// socket連接成功之后從Zygote服務(wù)器的socket接受到的 Session socket
try {
ZygoteConnection connection = peers.get(pollIndex);
final Runnable command = connection.processOneCommand(this);
// TODO (chriswailes): Is this extra check necessary?
if (mIsForkChild) {
......
return command;
} else {
// 如果不是fork子進程則關(guān)閉連接混槐,刪除當前 fd 消息
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
} catch (Exception e) {
......
} finally {
......
mIsForkChild = false;
}
}
}
......
}
......
}
}
runSelectLoop()方法中獲取zygoteSendArgsAndGetResult()方法中傳輸過來的應用進程的啟動參數(shù)等编兄,即和Zygote進程建立起連接,其方法流程如下:
開啟Loop死循環(huán)監(jiān)聽socket事件声登,沒有連接時就阻塞在那里狠鸳,當有連接到來時喚醒繼續(xù)往下執(zhí)行。
pollIndex==0時悯嗓,說明收到請求連接的事件件舵,請求和Zygote建立socket連接,調(diào)用acceptCommandPeer()方法創(chuàng)建ZygoteConnection對象绅作,并調(diào)用mZygoteSocket#accept()方法建立socket 連接芦圾,然后添加到監(jiān)聽列表peers中,等待與該socket有關(guān)的命令的到來俄认。
pollIndex < usapPoolEventFDIndex時个少,表示是已經(jīng)連接的socket上的命令到來,此時調(diào)用ZygoteConnection#processOneCommand()方法來接收客戶端傳輸過來的應用進程的啟動參數(shù)眯杏,并執(zhí)行進程創(chuàng)建工作夜焦,處理完后,就會斷開與客戶端的連接岂贩,并把用于連接的socket從監(jiān)聽列表peers中移除茫经。
4.4 ZygoteConnection
// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
String[] args;
try {
// 逐行讀取 client 端通過socketwrite過來的啟動參數(shù)(字符串數(shù)組)
args = Zygote.readArgumentList(mSocketReader);
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
......
int pid;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
// 將數(shù)據(jù)解析成ZygoteArguments格式
ZygoteArguments parsedArgs = new ZygoteArguments(args);
......
int[][] rlimits = null;
if (parsedArgs.mRLimits != null) {
rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
}
int[] fdsToIgnore = null;
if (parsedArgs.mInvokeWith != null) {
try {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
} catch (ErrnoException errnoEx) {
throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
}
}
// 將client端fd和server端fd存入fdsToClose數(shù)組中,然后fd置為null
int [] fdsToClose = { -1, -1 };
FileDescriptor fd = mSocket.getFileDescriptor();
if (fd != null) {
fdsToClose[0] = fd.getInt$();
}
fd = zygoteServer.getZygoteSocketFileDescriptor();
if (fd != null) {
fdsToClose[1] = fd.getInt$();
}
// 調(diào)用forkAndSpecialize()方法來fork子進程
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.mWhitelistedDataInfoList,
parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
// in child
// pid = 0表示創(chuàng)建成功,則進入子進程中卸伞,即應用程序進程
zygoteServer.setForkChild();
// 關(guān)閉socket連接
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 進入子進程執(zhí)行相關(guān)操作
return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in handleParentProc.
// pid < 0表示創(chuàng)建失敗抹镊,則進入父進程返回消息給client socket表示啟動失敗
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
// 進入父進程執(zhí)行相關(guān)操作
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
該方法主要作用如下:
讀取system_server端socket寫入的數(shù)據(jù),并將存入字符串數(shù)組的數(shù)據(jù)封裝成ZygoteArguments格式荤傲。
調(diào)用Zygote#forkAndSpecialize()方法來fork子進程垮耳,并返回pid,這里的pid并非是進程id遂黍,而是返回結(jié)果值终佛,0表示創(chuàng)建成功,-1則失敗雾家。
子進程創(chuàng)建成功后進入子進程執(zhí)行铃彰。
4.5 Zygote創(chuàng)建子進程(native 層創(chuàng)建)
// frameworks/base/core/java/com/android/internal/os/Zygote.java
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[] whitelistedDataInfoList,
boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
ZygoteHooks.preFork();
// 通過 JNI 調(diào)用 native 層方法
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, whitelistedDataInfoList, 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) {
NetworkUtils.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;
}
方法中調(diào)用native層的nativeForkAndSpecialize()方法創(chuàng)建進程,然后返回進程的pid(父進程中芯咧,返回新建的子進程的pid牙捉,子進程中,則返回0敬飒,出現(xiàn)錯誤時返回負數(shù))鹃共,具體native層的源碼就不跟了,大致看了一下過程:
調(diào)用Linux的fork()方法創(chuàng)建進程驶拱,設(shè)置進程的主線程的name霜浴,如果是null或者system_server,則為system_server蓝纲。
調(diào)用CallStaticVoidMethod()方法返回Zygote#callPostForkChildHooks()方法處理fork子線程之后的gc/線程池管理等操作阴孟。
4.6 ZygoteConnection#handleChildProc()
// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
// 關(guān)閉socket連接
closeSocket();
// 設(shè)置應用進程的name名
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) {
// 初始化Zygote
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}
該方法就是進入子進程執(zhí)行不同的初始化操作,因為已經(jīng)fork()成功税迷,關(guān)閉socket連接等釋放資源永丝,設(shè)置應用進程的name,最后調(diào)用 ZygoteInit#zygoteInit()方法初始化Zygote箭养。
4.7 ZygoteInit#zygoteInit()
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
......
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
// 進程初始化配置慕嚷,如設(shè)置異常捕獲Handler、時區(qū)毕泌、重置 LogManager 等等
RuntimeInit.commonInit();
// native 層初始化 -- 打開/dev/binder驅(qū)動喝检,映射內(nèi)核的地址空間,創(chuàng)建binder線程用于IPC通信
ZygoteInit.nativeZygoteInit();
// 創(chuàng)建的Runnable對象
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
方法流程如下:
日志流重定向撼泛,將系統(tǒng)輸出和系統(tǒng)錯誤重定向到Android日志挠说。
進程初始化配置,如設(shè)置異常捕獲Handler愿题、時區(qū)损俭、重置 LogManager 等等蛙奖。
native層初始化,打開/dev/binder驅(qū)動杆兵,映射內(nèi)核的地址空間雁仲,創(chuàng)建binder線程用于IPC通信。
調(diào)用RuntimeInit#applicationInit()方法琐脏,返回創(chuàng)建的Runnable對象伯顶。
4.8 RuntimeInit#applicationInit()
// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
// 如果應用程序調(diào)用了System.exit()方法立即終止進程,可能會導致剩余的運行線程在進程實際退出之前崩潰
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);
}
----------------------------------------------------------
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
// 待加載的類骆膝、這里是指ActivityThread,也就是我們第三節(jié)中在ProcessList中指明的entryPoint
Class<?> cl;
try {
// 加載android.app.ActivityThread類
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className, ex);
}
// 獲取 main 方法
Method m;
try {
// 獲取 ActivityThread#main()函數(shù)
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException("Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException("Problem getting static main on " + className, ex);
}
// 判斷main方法是不是public并且static類型
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);
}
// 返回Caller灶体,即本小節(jié)第一部分的ZygoteInit.main()中的caller
return new MethodAndArgsCaller(m, argv);
}
applicationInit()方法中首先做了一個System.exit()的保護阅签,防止退出進程時發(fā)生crash,設(shè)置targetSDKVersion等參數(shù)蝎抽,最后調(diào)用findStaticMain()方法去加載ActivityThread類以及方法政钟。
??findStaticMain()方法中通過ClassLoader加載獲取目標類ActivityThread,后獲取其靜態(tài)main方法樟结,然后封裝成MethodAndArgsCaller對象返回养交,MethodAndArgsCaller實現(xiàn)了Runnable 接口。即返回到《4.2 Zygote進程啟動瓢宦、解析Socket傳入的參數(shù)》 這節(jié)中ZygoteInit#main()方法的caller碎连,如果caller=null會調(diào)用這個Runnable的run()方法。
4.9 RuntimeInit#MethodAndArgsCaller
// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
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 {
// 這里會調(diào)用new MethodAndArgsCaller()的第一個參數(shù)的方法
// 也就是ActivityThread#main()函數(shù)
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
......
}
}
}
MethodAndArgsCaller#run() 方法中使用了invoke反射調(diào)用驮履,至此ActivityThread的main()方法得以執(zhí)行鱼辙,應用進程也就成功啟動ActivityThread。
4.10 小結(jié)
??Zygote 進程啟動流程:
init進程為用戶空間(相對于內(nèi)核空間)的第一個進程玫镐,根據(jù)init.rc啟動Zygote進程倒戏。
Zygote進程啟動步驟:創(chuàng)建虛擬機、注冊JNI恐似、執(zhí)行ZygoteInit#main()方法杜跷。
Zygote進程啟動system_server進程(Zygote 啟動的第一個進程),這個本小節(jié)沒有具體分析矫夷。
Zygote創(chuàng)建socket連接通道葛闷,阻塞并等待新建進程的指令到來,通過fork新建用戶進程双藕。
Zygote新加了一個優(yōu)化進程創(chuàng)建的機制孵运,UsapPool-池化機制,是預先緩存了幾個進程蔓彩。