Android系统启动完成后,会启动第一Android应用Launcher。之后在用户操作下启动其他的应用程序。这两个流程大体一致,本文主要分析启动Launcher的启动流程。
Android系统源码版本:9.0.0_r3
整体流程图如下:
Zygote启动流程
Android Kernel启动后启动第一个进程init,init将解析init.*.rc文件启动进程zygote。
/system/core/rootdir/init.zygote32_64.rc
1 service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
2 class main
3 priority -20
4 user root
5 group root readproc reserved_disk
6 socket zygote stream 660 root system
7 onrestart write /sys/android_power/request_state wake
8 onrestart write /sys/power/state on
9 onrestart restart audioserver
10 onrestart restart cameraserver
11 onrestart restart media
12 onrestart restart netd
13 onrestart restart wificond
14 writepid /dev/cpuset/foreground/tasks
15
16 service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
17 class main
18 priority -20
19 user root
20 group root readproc reserved_disk
21 socket zygote_secondary stream 660 root system
22 onrestart restart zygote
23 writepid /dev/cpuset/foreground/tasks
init启动的程序app_process32或app_process64 跟--zygote 参数表明启动的是zygote进程。这里的app_process32 、app_process64 表示32位zygote进程和64位zygote进程,用于兼容包含so库为32位的应用启动。其实在Android环境中我们是可以用app_proccess*去运行一个Dalvik格式的java字节码文件,就像在台式机上用java运行字节码一样。 zygote启动之后将完成ART虚拟机的创建工作并运行com.android.internal.os.ZygoteInit。关键内容如下所示
/frameworks/base/cmds/app_process/app_main.cpp
349 if (zygote) {
350 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
351 } else if (className) {
352 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
353 } else {
354 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
355 app_usage();
356 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
357 }
在com.android.internal.os.ZygoteInit中会完成Android环境中Framework关键Java类文件的加载工作。创建本地套接字用ZygoteServer管理,通过fork调用创建子进程system_server进程。开启本地套接字ZygoteServer的监听功能即运行runSelectLoop方法监听是否有新套接字或读写事件发生。
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
750 public static void main(String argv[]) {
751 ZygoteServer zygoteServer = new ZygoteServer();
752
832 if (startSystemServer) {
833 Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
834
835
836
837 if (r != null) {
838 r.run();
839 return;
840 }
841 }
842
843 Log.i(TAG, "Accepting command socket connections");
844
845
846
847 caller = zygoteServer.runSelectLoop(abiList);
848 } catch (Throwable ex) {
849 Log.e(TAG, "System zygote died with exception", ex);
850 throw ex;
851 } finally {
852 zygoteServer.closeServerSocket();
853 }
854
855
856
857 if (caller != null) {
858 caller.run();
859 }
860 }
在这里本地套接字即UDS(Unix Domain Socket),其实就是一种进程间通信方式,像Nginx,MySQL中都UDS用来做进程间通信。Android进程间通信方式比Linux多了Binder这种进程间通信方式。本文不会详细讲解Binder,只要知道Binder其实就是用于两个不同进程间通信即可,跟管道、信号量、UDS没有本质的不同。
system_server进程启动流程
system_server进程将调用com.android.server.SystemServer,SystemnServer将启动各个重要的服务,代码如下
/frameworks/base/services/java/com/android/server/SystemServer.java
427 try {
428 traceBeginAndSlog("StartServices");
429 startBootstrapServices();
430 startCoreServices();
431 startOtherServices();
432 SystemServerInitThreadPool.shutdown();
433 } catch (Throwable ex) {
434 Slog.e("System", "******************************************");
435 Slog.e("System", "************ Failure starting system services", ex);
436 throw ex;
437 } finally {
438 traceEnd();
439 }
启动的服务有ActivityManagerService、WindowManagerService、PackageManagerService、InputManagerService、BluetoothManagerService等服务类。 其中PackageManagerService将完成对手机上已安装的应用程序的解析,如解析Apk安装位置、Manifest信息,资源文件、类文件路径等。
system_server启动完毕后调用AMS的systemReady方法,发送启动Launcher的Intent,PMS将找到Launcher的安装路径,调用AMS的startProcess。startProcess经过一系列调用最终使用UDS与zygote进程通信,发送相应的命令,让zygote创建子进程。AMS将返回的子进程pid和与之关联app信息放入mPidsSelfLocked成员变量中。代码如下
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
4530 private boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
4531 long expectedStartSeq, boolean procAttached) {
4532
4598 synchronized (mPidsSelfLocked) {
4599 this.mPidsSelfLocked.put(pid, app);
4600 if (!procAttached) {
4601 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
4602 msg.obj = app;
4603 mHandler.sendMessageDelayed(msg, usingWrapper
4604 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
4605 }
4606 }
4607 checkTime(app.startTime, "startProcess: done updating pids map");
4608 return true;
4609 }
应用进程启动流程
在这里ZygoteServer的本地套接字监听到有消息到来时将fork一个新的子进程,这新的子进程就继承了zygote进程的资源如已经创建好的ART虚拟机,这样能够加快应用的创建启动。 关键代码如下
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
123 Runnable processOneCommand(ZygoteServer zygoteServer) {
124 String args[];
125 Arguments parsedArgs = null;
126 FileDescriptor[] descriptors;
127
128 try {
129 args = readArgumentList();
130 descriptors = mSocket.getAncillaryFileDescriptors();
131 } catch (IOException ex) {
132 throw new IllegalStateException("IOException on command socket", ex);
133 }
134
146 parsedArgs = new Arguments(args);
147
148
231
232 fd = null;
233
234 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
235 parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
236 parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
237 parsedArgs.instructionSet, parsedArgs.appDataDir);
238
240 if (pid == 0) {
241
242 zygoteServer.setForkChild();
243
244 zygoteServer.closeServerSocket();
245 IoUtils.closeQuietly(serverPipeFd);
246 serverPipeFd = null;
247
248 return handleChildProc(parsedArgs, descriptors, childPipeFd,
249 parsedArgs.startChildZygote);
250 } else {
251
252
253 IoUtils.closeQuietly(childPipeFd);
254 childPipeFd = null;
255 handleParentProc(pid, descriptors, serverPipeFd);
256 return null;
257 }
258
262 }
在子进程中将解析其他进程(system_server)发过来的参数,运行指定的类。通常这个类就是ActivityThread,这个子进程就是我们新启动的应用进程,当前这个进程还不知道要到哪里去加载应用程序对应字节码和资源文件。当ActivityThread启动后将与system_server 进行进程间通信(Binder),调用AMS相关函数。代码如下:
6478 private void attach(boolean system, long startSeq) {
6479 sCurrentActivityThread = this;
6480 mSystemThread = system;
6481 if (!system) {
6482 ViewRootImpl.addFirstDrawHandler(new Runnable() {
6483 @Override
6484 public void run() {
6485 ensureJitEnabled();
6486 }
6487 });
6488 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
6489 UserHandle.myUserId());
6490 RuntimeInit.setApplicationObject(mAppThread.asBinder());
6491 final IActivityManager mgr = ActivityManager.getService();
6492 try {
6493 mgr.attachApplication(mAppThread, startSeq);
6494 } catch (RemoteException ex) {
6495 throw ex.rethrowFromSystemServer();
6496 }
在6493行 ActivityThread调用mgr.attachApplication,由于Binder机制将调用AMS的attachApplication方法。
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
7932 public final void attachApplication(IApplicationThread thread, long startSeq) {
7933 synchronized (this) {
7934 int callingPid = Binder.getCallingPid();
7935 final int callingUid = Binder.getCallingUid();
7936 final long origId = Binder.clearCallingIdentity();
7937 attachApplicationLocked(thread, callingPid, callingUid, startSeq);
7938 Binder.restoreCallingIdentity(origId);
7939 }
7940 }
attachApplication方法中将获取正在启动进程的pid,通过pid在mPidsSelfLocked中查找到要启动程序的信息,将要启动程序的信息通过Binder进程间通信(即IApplicationThread相关方法)发送给应用进程,由应用进程去加载相应的类。
应用进程加载完成后告知AMS,AMS将控制应用进程启动Activity,此后AMS下达命令,应用进程执行,执行完成后告知AMS。应用进程就像一个提线木偶一样受到AMS的制约。(现在的插件化技术,就是Hook掉对应的接口,欺骗AMS完成插件中四大组件的加载,即常说的欺上瞒下)
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,
7573 int pid, int callingUid, long startSeq) {
7574
7575
7576
7577
7578 ProcessRecord app;
7579 long startTime = SystemClock.uptimeMillis();
7580 if (pid != MY_PID && pid >= 0) {
7581 synchronized (mPidsSelfLocked) {
7582 app = mPidsSelfLocked.get(pid);
7583 }
7584 } else {
7585 app = null;
7586 }
7587
7588
7589
7590 if (app == null && startSeq > 0) {
7591 final ProcessRecord pending = mPendingStarts.get(startSeq);
7592 if (pending != null && pending.startUid == callingUid
7593 && handleProcessStartedLocked(pending, pid, pending.usingWrapper,
7594 startSeq, true)) {
7595 app = pending;
7596 }
7597 }
7598
7599 if (app == null) {
7600 Slog.w(TAG, "No pending application record for pid " + pid
7601 + " (IApplicationThread " + thread + "); dropping process");
7602 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
7603 if (pid > 0 && pid != MY_PID) {
7604 killProcessQuiet(pid);
7605
7606 } else {
7607 try {
7608 thread.scheduleExit();
7609 } catch (Exception e) {
7610
7611 }
7612 }
7613 return false;
7614 }
|