Android系统揭秘(五)-应用程序启动

53 阅读5分钟

其中Android 10的ActivityManagerInternal实现者是AMS
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java(android10,11)

@Override public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName) { try { ... synchronized (ActivityManagerService.this) { 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); } }

可以知道,应用程序由AMS的startProcessLocked方法启动

AMS发送启动应用程序进程请求

android 8-9时序图:
img
android 10-11时序图:
img
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ...

try { try { final int userId = UserHandle.getUserId(app.uid); AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } //获取要创建的应用程序进程的用户ID int uid = app.uid; int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; if (!app.isolated) { int[] permGids = null; try { checkTime(startTime, "startProcess: getting gids from package manager"); final IPackageManager pm = AppGlobals.getPackageManager(); permGids = pm.getPackageGids(app.info.packageName, MATCH_DEBUG_TRIAGED_MISSING, app.userId); StorageManagerInternal storageManagerInternal = LocalServices.getService( StorageManagerInternal.class); mountExternal = storageManagerInternal.getExternalStorageMountMode(uid, app.info.packageName); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); }

/*

  • Add shared application and profile GIDs so applications can share some
  • resources like shared libraries and access user-wide resources */ // 对gids进行创建和赋值 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)); }

.... if (entryPoint == null) entryPoint = "android.app.ActivityThread"; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); ProcessStartResult startResult; if (hostingType.equals("webview_service")) { startResult = startWebView(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, entryPointArgs); } else { //启动应用程序进程 startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs); } ... } catch (RuntimeException e) { Slog.e(TAG, "Failure starting process " + app.processName, e); forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, UserHandle.getUserId(app.userId), "start failure"); } }

若是android 10之后则通过ProcessList启动

@GuardedBy("this") 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 */); }

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

@GuardedBy("mService") boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks, boolean mountExtStorageFull, String abiOverride) { .... return startProcessLocked(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); } catch (RuntimeException e) { ... return false; } }

接下来使用Process->start()方法启动
frameworks/base/core/java/android/os/Process.java

public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { return zygoteProcess.start(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, zygoteArgs); }

Process则是调用ZygoteProcess来启动

frameworks/base/core/java/android/os/ZygoteProcess.java

public final Process.ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, 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方法

private Process.ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] extraArgs) throws ZygoteStartFailedEx { ArrayList argsForZygote = new ArrayList();

// --runtime-args, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) { argsForZygote.add("--enable-jni-logging"); } ...

synchronized(mLock) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } }

这个方法把参数封成数组,并获取Zygote连接,一起发给了zygoteSendArgsAndGetResult方法
我们先看下获取Zygote连接的openZygoteSocketIfNeeded方法

/**

  • Tries to open socket to Zygote process if not already open. If
  • already open, does nothing. May block and retry. Requires that mLock be held. */ @GuardedBy("mLock") private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");

if (primaryZygoteState == null || primaryZygoteState.isClosed()) { try { // 与Zygote进程建立连接 primaryZygoteState = ZygoteState.connect(mSocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } } // 判断abi是否匹配 if (primaryZygoteState.matches(abi)) { return primaryZygoteState; }

// 不匹配则尝试Zygote辅模式 if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(mSecondarySocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } }

if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; }

throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }

然后看下zygoteSendArgsAndGetResult方法

@GuardedBy("mLock") private static Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList args) throws ZygoteStartFailedEx { try {

int sz = args.size(); for (int i = 0; i < sz; i++) { if (args.get(i).indexOf('\n') >= 0) { throw new ZygoteStartFailedEx("embedded newlines not allowed"); } }

final BufferedWriter writer = zygoteState.writer; final DataInputStream inputStream = zygoteState.inputStream;

writer.write(Integer.toString(args.size())); writer.newLine();

for (int i = 0; i < sz; i++) { String arg = args.get(i); writer.write(arg); writer.newLine(); }

writer.flush();

// Should there be a timeout on this? Process.ProcessStartResult result = new Process.ProcessStartResult();

result.pid = inputStream.readInt(); result.usingWrapper = inputStream.readBoolean();

if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }

它会向ZygoteState写入数据

android 10之后则是在attemptZygoteSendArgsAndGetResult方法写入

@GuardedBy("mLock") private Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList args) throws ZygoteStartFailedEx { ... String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";

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

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. Process.ProcessStartResult result = new Process.ProcessStartResult(); result.pid = zygoteInputStream.readInt(); result.usingWrapper = zygoteInputStream.readBoolean();

if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); }

return result; } catch (IOException ex) { zygoteState.close(); Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "

  • ex.toString()); throw new ZygoteStartFailedEx(ex); } }

Zygote 接收请求并创建应用程序进程

然后我们分析下Zygote接收请求步骤

先看下时序图:

img

在系统启动一节我们分析了Zygote的启动,其中有个Runnable frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer();

... final Runnable caller; try { ...

String socketName = "zygote";

// 等待AMS caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { zygoteServer.closeServerSocket(); }

if (caller != null) { caller.run(); } }

runSelectLoop方法是一个循环器,接收来自AMS的消息

frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

Runnable runSelectLoop(String abiList) { ArrayList fds = new ArrayList(); ArrayList peers = new ArrayList();

fds.add(mServerSocket.getFileDescriptor()); peers.add(null);

while (true) { ... for (int i = pollFds.length - 1; i >= 0; --i) { if ((pollFds[i].revents & POLLIN) == 0) { continue; }

if (i == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { try { ZygoteConnection connection = peers.get(i); final Runnable command = connection.processOneCommand(this);

... } catch (Exception e) { ... } } } } }

收到命令时交由Zygote连接的processOneCommand方法(Android 8.0为runOnce)处理,其他版本代码细节有所不同,但流程一样

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

Runnable processOneCommand(ZygoteServer zygoteServer) { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors;

try { // 获取应用启动参数 args = readArgumentList(); // Android 10 之后的获取参数代码 //args = Zygote.readArgumentList(mSocketReader); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { throw new IllegalStateException("IOException on command socket", ex); }

... // fork创建应用程序进程 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet, parsedArgs.appDataDir);

try { if (pid == 0) { // 子进程 zygoteServer.setForkChild();

zygoteServer.closeServerSocket(); IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null;

return handleChildProc(parsedArgs, descriptors, childPipeFd); } else { // 父进程 IoUtils.closeQuietly(childPipeFd); childPipeFd = null; handleParentProc(pid, descriptors, serverPipeFd); return null; } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }

可以看到Zygote先获取启动参数,然后通过fork创建进程,然后若pi返回0,则开始处理应用程序进程。其中Android 10 之后通过Zygote类获取参数,其他没什么变化

private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd) { ...

// End of the postFork event. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.remainingArgs);

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

七大模块学习资料:如NDK模块开发、Android框架体系架构…

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群: **第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。 **第二,**开发几年,不知道如何进阶更进一步,比较迷茫。 **第三,**到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!

由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。如有需要获取完整的资料文档的朋友点击我的【GitHub】免费获取。