一、写在前面
接前面两篇:Android Zygote进程启动源码和Android SystemServer进程启动源码,继续对Android通过Zygote进程fork子进程进程相关源码进行学习。
在阅读源码之前有一些基础知识需要简单的了解一下。首先所知道的是SystemServer进程是通过LocalSocket而非Binder通信的方式发送请求给Zygote进程以fork出子进程的,因此这里就衍生出了两个问题需要弄清楚了才能继续往下看。
1、问题1-为什么使用LocalSocket发送请求而不是通过Binder?
答:可参考博客,简单来说有如下两个原因:
- 时序问题:Zygote进程与ServiceManager进程交互以注册或者获取Binder对象的时候,ServiceManger相关进程成不一定初始化完成;
- 多线程问题:Binder是基于多线程的。如果 Zygote 进程是多线程的,子进程会继承多个线程的状态,这可能会导致子进程状态混乱,影响应用程序的正确运行。
2、问题2-LocalSocket如何使用
如下给出LocalSocket客户端和服务端基本实现,对其基本实现有所了解才能更好的理解源码实现。
2.1 服务端实现
public class LocalSocketServer extends Thread {
private static final String SOCKET_NAME = "my_socket_name";
private LocalServerSocket serverSocket;
public LocalSocketServer() {
try {
serverSocket = new LocalServerSocket(SOCKET_NAME);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
// 监听连接请求,这里就会一直等待客户端发送数据过来
LocalSocket socket = serverSocket.accept();
Log.d("LocalSocketDemo", "Server: Connection accepted.");
// 接收来自客户端数据
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int length = inputStream.read(buffer);
String receivedData = new String(buffer, 0, length);
Log.d("LocalSocketDemo", "Server: Received data: " + receivedData);
// 发送数据给客户端
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello, Client!".getBytes());
// 关闭连接
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 客户端实现
public class LocalSocketClient extends AsyncTask<Void, Void, String> {
private static final String SOCKET_NAME = "my_socket_name";
@Override
protected String doInBackground(Void... params) {
try {
// 创建 LocalSocket 对象并连接到服务端
LocalSocket socket = new LocalSocket();
socket.connect(new LocalSocketAddress(SOCKET_NAME));
Log.d("LocalSocketDemo", "Client: Connection established.");
// 发送数据给服务端
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello, Server!".getBytes());
// 等待服务端发送数据回来
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int length = inputStream.read(buffer);
String receivedData = new String(buffer, 0, length);
Log.d("LocalSocketDemo", "Client: Received data: " + receivedData);
// 关闭连接
socket.close();
return receivedData;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
}
}
二、Zygote实现-server端
1、入口(ZygoteInit.main)
如下是ZygoteInit.main函数创建LocalServerSocket以及监听SystemServer请求创建子进程相关代码片段,详细的可至Android Zygote进程启动源码。
public static void main(String[] argv) {
......
//在类ZygoteServer的构造函数中会创建对应的LocalServerSocket以及USAP进程池(提前初始化一批进程)相关LocalServerSocket
zygoteServer = new ZygoteServer(isPrimaryZygote);
......
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
//死循环监听客户端Socket请求
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal 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();
}
}
2、LocalServerSocket创建
2.1 ZygoteServer构造函数
如下代码通过调用函数createManagedSocketFromInitSocket以创建对应的LocalServerSocket,只是传入进去的SOCKET_NAM不同而已。主要涉及到如下两个SOCKET_NAM:
-
zygote:用于创建与SystemServer交互的LocalServerSocket;
-
usap_pool_primary:创建UASP进程池相关的LocalServerSocket,对于UASP可参考Android Framework | 一种新型的应用启动机制:USAP,这里暂时不涉及。
ZygoteServer(boolean isPrimaryZygote) { mUsapPoolEventFD = Zygote.getUsapPoolEventFD(); //判断当前是否是Zygote进程,该值与init.zygote64.rc中的--socket-name=zygote有关 //这里当然为true if (isPrimaryZygote) { //创建LocalSocketServer mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME); //创建UASP进程池相关LocalServerSocket 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(); }
2.2 createManagedSocketFromInitSocket
如下代码首先根据传递进去的socketName获取到对应的文件描述符,接着通过创建的文件描述对象创建LocalServerSocket对象并返回。
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
//构造完整的SocketName = ANDROID_SOCKET_zygote
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//获取对应文件描述符
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
}
try {
//创建文件描述符对象
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
//根据文件描述对象创建LocalServerSocket对象
return new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}
3、runSelectLoop
如下代码首先获取到与Socket相关的文件描述符,然后通过Os.poll监听对应文件状态是否发生变化,如果文件有可读事件就绪则唤醒Zygote进程并监听连接请求,最后处理来自于SystemServer的请求以创建新的进程。
Os.poll:用于从一组文件描述符中轮询系统事件队列,该函数接收两个参数StructPollfd(监听的文件描述符、事件等)数组以及超时时间,超时时间如果为-1则表示需要一直等待直到对应文件描述符中有对应事件发生。好处:当没有socket接入的时候,Zygote进程会被阻塞而进入休眠,以腾出了cpu时间片供其他进程使用。当socket接入则唤醒进程进入到accept,等待数据的接入。这样就大大的提升了其中的资源利用率。
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
//将与SystemServer通信的Socket对应文件描述符存入到list中,以便后续通过Os.poll监听对应文件是否发生了可读事件以唤醒Zygote进程
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
while (true) {
//省略UASP相关
......
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
//判断UASP能力是否开启,这里默认不开启
if (mUsapPoolEnabled) {
usapPipeFDs = Zygote.getUsapPipeFDs();
pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
int pollIndex = 0;
//用于后续调用Os.poll以监听对应Socket文件描述符文件状态
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
//表示对socket对应文件描述符进行监听时,检查是否有可读事件已经就绪
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
final int usapPoolEventFDIndex = pollIndex;
......
//省略UASP相关
int pollTimeoutMs;
//获取Os.poll阻塞超时时间
//这里默认UASP功能关闭,因此超时时间为-1,表示永久等待,直到有可读事件发生
if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
pollTimeoutMs = -1;
} else {
......
}
int pollReturnValue;
try {
//当前分析场景下:pollTimeoutMs = -1
//开始阻塞Zygote进程,直到socket对应文件描述符有可读事件就绪,则会唤醒Zygote进程
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
//表示达到了超时时间或者出现了非阻塞轮询并且传递进去的文件描述符都没有就绪则返回0
if (pollReturnValue == 0) {
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} else {
boolean usapPoolFDRead = false;
while (--pollIndex >= 0) {
//判断对应文件是否有可读事件发生
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
//监听连接请求,具体可参考上述一中socket使用
if (pollIndex == 0) {
// Zygote server socket
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
//处理来自SystemServer端的请求
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
try {
ZygoteConnection connection = peers.get(pollIndex);
//判断Zygote进程中子线程是否全部停止
boolean multipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
//处理请求
final Runnable command =
connection.processCommand(this, multipleForksOK);
......
} catch (Exception e) {
......
}
......
} else {
......
}
}
......
}
}
}
3.1 监听请求(LocalServerSocket.accept)
如下代码就比较简单了,直接通过调用LocalServerSocket.accept以监听客户端请求,当请求到来的时候则获取OutputStream以给客户端回执pid等消息。
private ZygoteConnection acceptCommandPeer(String abiList) {
try {
//mZygoteSocket则为上述2.2中创建的LocalServerSocket对象
//通过调用该对象的accept函数监听SystemServer进程的请求,该处也会阻塞当前线程直到客户端发来请求
return createNewConnection(mZygoteSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
//直接创建ZygoteConnection对象并返回
protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
throws IOException {
return new ZygoteConnection(socket, abiList);
}
ZygoteConnection(LocalSocket socket, String abiList) throws IOException {
mSocket = socket;
this.abiList = abiList;
//用于后续给客户端回执新建进程pid等信息
mSocketOutStream = new DataOutputStream(socket.getOutputStream());
//用于设置客户端读取数据的超时时间
mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
try {
//用于获取连接到本地 Unix 套接字(Local Socket)的远程进程的用户 ID(uid)、组 ID(gid)和进程 ID(pid)等信息,以进行安全验证
peer = mSocket.getPeerCredentials();
} catch (IOException ex) {
Log.e(TAG, "Cannot read peer credentials", ex);
throw ex;
}
isEof = false;
}
3.2 处理请求(processCommand)
如下代码就稍显复杂了,首先解析SystemServer传递过来的参数,然后做预加载相关处理,接着判断client端是否有权限访问LocalServerSocket,接着调用函数Zygote.forkAndSpecialize
以fork子进程,最后调用到对应应用ActivityThread.main
函数中。
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
ZygoteArguments parsedArgs;
//获取SystemServer传递过来的参数
try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
while (true) {
try {
//解析SystemServer传递过来的参数
parsedArgs = ZygoteArguments.getInstance(argBuffer);
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
if (parsedArgs == null) {
isEof = true;
return null;
}
int pid;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
//省略其他相关请求处理
......
//预加载处理
if (parsedArgs.mPreloadDefault) {
handlePreload();
return null;
}
//省略掉特定应用预加载处理请求
......
if (parsedArgs.mPermittedCapabilities != 0
|| parsedArgs.mEffectiveCapabilities != 0) {
throw new ZygoteSecurityException("Client may not specify capabilities: "
+ "permitted=0x" + Long.toHexString(parsedArgs.mPermittedCapabilities)
+ ", effective=0x"
+ Long.toHexString(parsedArgs.mEffectiveCapabilities));
}
//检测client uid和gid是否合法
Zygote.applyUidSecurityPolicy(parsedArgs, peer);
Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
......
if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
|| !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
//开始fork子进程,后续实现和SystemServer进程创建有点类似
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 {
//子进程fork成功
if (pid == 0) {
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//最后调用到ZygoteInit.zygoteInit函数中并通过反射获取到对应应用ActivityThread对象,并调用其main函数
return handleChildProc(parsedArgs, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
//返回新建进程pid等信息给到SystemServer
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
//该处实现暂时不涉及到
//采用了进程复用的方式fork子进程
//即在 Zygote 进程中创建一个模板应用程序进程,并在需要创建新的应用程序进程时,通过复制模板进程来快速创建新的进程,这种方式能够提高性能和效率
} else {
ZygoteHooks.preFork();
Runnable result = Zygote.forkSimpleApps(argBuffer,
zygoteServer.getZygoteSocketFileDescriptor(),
peer.getUid(), Zygote.minChildUid(peer), parsedArgs.mNiceName);
......
}
}
}
// Handle anything that may need a ZygoteCommandBuffer after we've released ours.
......
}
3.3 子进程fork(Zygote.forkAndSpecialize)
如下代码与forkSystemServer代码基本相同,只是对应函数参数以及最终调用到native层函数不一致。
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();
//调用到native层以调用fork函数创建新进程
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs,
bindMountAppStorageDirs);
//当前处于新创建的子进程中
if (pid == 0) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
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;
}
3.4 进程创建成功(handleChildProc)
如下函数最终会调用到ZygoteInit.zygoteInit
中,该函数最终会通过反射调用到对应应用的ActivityThread.main
函数中,具体可参考Android SystemServer进程启动源码;这里需要注意的是ClassLoader为null,是因为ActivityThread类已经被预加载到当前进程的虚拟机中了,所以不需要新建ClassLoader。
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
//关闭从Zygote继承过来的监听客户端连接请求相关socket
closeSocket();
//设置当前进程名
Zygote.setAppProcessName(parsedArgs, TAG);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.mInvokeWith != null) {
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.mRemainingArgs);
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
if (!isZygote) {
//最终会调用到这里,该函数就很熟悉了,在SystemServer进程启动也有所涉及
//注意这里的classLoader为null,是因为ActivityThread类已经被预加载到当前虚拟机中了,所以不需要新建ClassLoader
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(
parsedArgs.mRemainingArgs /* classLoader */);
}
}
}
三、SystemServer实现-client端
对于四大组件如何触发应用进程的创建,这里不会涉及,直接进入到Process.start流程。
1、Process.start
如下代码比较简单,就是参数有点多;因此对该函数中部分参数进行了注释。
/**
* processClass:进程入口类
* niceName:进程名
* uid:应用uid
* gid:应用进程group id
* runtimeFlags:新进程的运行时标志位。这个参数主要用于控制进程的一些运行时行为,例如是否启用追踪模式、是否允许 JIT 编译等
* mountExternal:是否挂载外部存储。如果设置为 1,则表示挂载外部存储;如果设置为 0,则表示不挂载外部存储
* targetSdkVersion:目标 SDK 版本号
* seInfo:SELinux信息
* abi:指定启动当前进程abi。abi用于定义操作系统和 Android 应用程序之间的接口,以确保应用程序可以在不同的 CPU 架构和操作系统版本上运行
* appDataDir:应用data目录
* invokeWith:Zygote通过命令行启动时的参数,一般不会用到
* packageName:包名
* zygotePolicyFlags:用于决定如何启动应用
* isTopApp:启动的进程是否处于前台,以给应用设置高优先级
* disabledCompatChanges:禁用应用进程对特定API的访问
*/
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);
}
2、ZYGOTE_PROCESS.start
public final Process.ProcessStartResult start(
//省略参数
......) {
// UASP相关,暂时不管
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) {
......
}
}
3、startViaZygote
如下代码就是将各种参数添加到ArrayList中,接着调用函数openZygoteSocketIfNeeded
以创建client端LocalSocket并尝试连接到服务端(Zygote进程)。最后调用函数zygoteSendArgsAndGetResult
将各种参数转换为String并发送给Zygote进程。
private Process.ProcessStartResult startViaZygote(//省略参数
......
)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<>();
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
......
//省略各种参数添加,在Zygote中会通过相同的方式进行解析
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags,
argsForZygote);
}
}
3.1 LocalSocket创建、连接到LocalServerSocket(openZygoteSocketIfNeeded)
如下代码主要用于创建Client端的LocalSocket并通过创建的LocalSocket连接到LocalServerSocket(zygote进程),最后通过创建的LocalSocket获取到数据传输I/O流。
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
try {
attemptConnectionToPrimaryZygote();
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
......
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
private void attemptConnectionToPrimaryZygote() throws IOException {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
//将指定的 API 接口从 API 拒绝列表中排除,使得这些接口可以在应用程序中继续使用
maybeSetApiDenylistExemptions(primaryZygoteState, false);
//设置应用程序访问隐藏API日志的采样率
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
}
static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
@Nullable LocalSocketAddress usapSocketAddress)
throws IOException {
DataInputStream zygoteInputStream;
BufferedWriter zygoteOutputWriter;
//创建Client端LocalSocket
final LocalSocket zygoteSessionSocket = new LocalSocket();
if (zygoteSocketAddress == null) {
throw new IllegalArgumentException("zygoteSocketAddress can't be null");
}
try {
//mZygoteSocketAddress = new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED);
//连接到Zygote进程中的LocalServerSocket
zygoteSessionSocket.connect(zygoteSocketAddress);
//获取接收Zygote进程回调信息I/O流
zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
//获取传递参数给Zygote进程I/O流
zygoteOutputWriter = new BufferedWriter(
new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
} catch (IOException ex) {
try {
zygoteSessionSocket.close();
} catch (IOException ignore) { }
throw ex;
}
//创建对象并返回
return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
getAbiList(zygoteOutputWriter, zygoteInputStream));
}
4、参数整理(zygoteSendArgsAndGetResult)
如下代码主要就是检查参数的合法性,并将参数拼接为String以便后续通过I/O发送给Zygote进程。
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
throws ZygoteStartFailedEx {
//判断各个参数的合法性,即任何参数都不能包含换行符和tab符
for (String arg : args) {
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("Embedded newlines not allowed");
} else if (arg.indexOf('\r') >= 0) {
throw new ZygoteStartFailedEx("Embedded carriage returns not allowed");
}
}
//将参数转换为字符串,String.join底层会逐个遍历列表args,并拼接为字符串
String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";
//UASP相关
if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
try {
return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
} catch (IOException ex) {
Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
+ ex.getMessage());
}
}
return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}
5、参数发送、数据接收(attemptZygoteSendArgsAndGetResult)
如下代码也很简单,就是将参数发送给Zygote进程,并接收Zygote进程返回回来的pid等信息,最后返回最终结果。
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
//获取发送参数I/O流
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
//获取数据接收I/O流
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
//将参数发送给Zygote进程
zygoteWriter.write(msgStr);
zygoteWriter.flush();
//接收Zygote进程发送回来的数据
Process.ProcessStartResult result = new Process.ProcessStartResult();
//新建进程pid
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
四、总结
如上即为Android应用进程启动大体源码分析了。其中Zygote进程相关代码(Server端)理解稍微难一点,而SystemServer进程相关代码(Client端)则稍显简单了许多。不过不论是Server端还是Client端只要将一中LocalSocket的使用方式搞明白了,那其实整体理解起来也不是很难,只是其中有很多细节需要细细想一下才行。