Android系统启动流程

Tip

本文主要介绍Android系统重启动到Home启动的过程,下面是本人整理的时序图(由于图片比较大,你们可以保存到本地放大看):


Android系统启动流程.jpg

而下文也将对照时序图的顺序进行分析。

Init进程的启动

image.png

上图是Linux系统的启动流程,而Android是基于Linux开发的,所以也符合它的启动流程。我们可以看到Init进程是由内核系统fock出来的。该进程的入口文件在
init.cpp#main(/system/core/init/init.cpp)

bool waiting_for_exec = false;
int main(int argc, char** argv) {
    ...
    // 创建一些文件夹,并挂载设备,这些是和 Linux 相关的
    if (is_first_stage) {
        mount();
        mkdir();
    }
    /*解析init.rc配置文件
     *配置文件位于system/core/rootdir/init.rc中
     *在解析配置文件中会启动zygote进程
     */
    init_parse_config_file("/init.rc");
    ...
    while (true) {
        if (!waiting_for_exec) {
            execute_one_command();
            restart_processes();
        }
      ...
    //阻塞 等待事件发生
    int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
    }
}

init.cpp的main函数会先去解析init.rc配置文件,我们这里不深入分析,反正解析完配置文件以后,我们会得到一个带启动的进程列表,然后进入死循环执行启动进程,那waiting_for_exec是在什么时候被置为true的呢?其实是在service_start()方法中,下文会分析到,现在我们先略过。
init.cpp#restart_processes

static void restart_processes()
{
    process_needs_restart = 0;
    service_for_each_flags(SVC_RESTARTING,
                           restart_service_if_needed);
}

其中service_for_each_flags的声明在init.h中,实现在init_parse.cpp中:

init.h#service_for_each_flags
void service_for_each_flags(unsigned matchflags,void (*func)(struct service *svc));

init_parse.cpp#service_for_each_flags
void service_for_each_flags(unsigned matchflags,void (*func)(struct service *svc))
{
    struct listnode *node;
    struct service *svc;
    list_for_each(node, &service_list) {
        svc = node_to_item(node, struct service, slist);
        if (svc->flags & matchflags) {
            func(svc);
        }
    }
}

检查service_list中的所有服务,对于带有SVC_RESTARTING标志的服务,则都会调用其相应的restart_service_if_needed。

init.cpp#restart_service_if_needed

//如果有必要的话重启服务
static void restart_service_if_needed(struct service *svc)
{
    time_t next_start_time = svc->time_started + 5;

    if (next_start_time <= gettime()) {
        svc->flags &= (~SVC_RESTARTING);
        //启动服务
        service_start(svc, NULL);
        return;
    }

    if ((next_start_time < process_needs_restart) ||
        (process_needs_restart == 0)) {
        process_needs_restart = next_start_time;
    }
}

init.cpp#service_start

void service_start(struct service *svc, const char *dynamic_args)
{
    ...
    //创建一个新的进程
    pid_t pid = fork();
     ...
    //启动上文中新fork出来的进程
    execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
}

通过fork和execve我们会进入app_main(zygote)进程。

阶段总结

image.png

app_main(zygote)进程的启动

该进程的入口文件位于
app_main.cpp(/frameworks/base/cmds/app_process/app_main.cpp)

int main(int argc, char* const argv[])
{
     ...
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    
   if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        }
    ...
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
       ...
    }
}

当我们的命令中包含--zygote的时候,我们就会调用到ZygoteInit。
AndroidRuntime.cpp#start(D:\Android\FrameworkSource\frameworks\base\core\jni)

     ...
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
//如果java虚拟机已经被创建并启动则直接返回
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    ...
    //指明要调用的类,这里涉及到jni调用
    jclass startClass = env->FindClass(slashClassName);
    ...
    //得到com.android.internal.os.ZygoteInit 的main方法的id
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
    ...
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
    ...

通过上文的JNI调用我们就进入到Java的世界了
ZygoteInit#main(frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

//由app_main(zygote)进程通过jni的方式调用
public static void main(String argv[]) {
          ...
          try {
            //注册ZygoteSocket
            registerZygoteSocket(socketName);
          ...
          //预加载类和资源
            preload();
          ...
            if (startSystemServer) {
                //启动SystemServer进程,属于行的进程下文会详细分析
                startSystemServer(abiList, socketName);
            }
            runSelectLoop(abiList); //进入循环模式
            closeServerSocket();
          ...
          } catch (MethodAndArgsCaller caller) {
            caller.run();
          }
        
}

registerZygoteSocket

private static void registerZygoteSocket(String socketName) {
    if (sServerSocket == null) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            ...
        }

        try {
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc); //设置文件描述符
            sServerSocket = new LocalServerSocket(fd); //创建Socket的本地服务端
        } catch (IOException ex) {
            ...
        }
    }
}

preload

//预加载位于/system/etc/preloaded-classes文件中的类
    preloadClasses();
    //预加载资源,包含drawable和color资源
    preloadResources();
    //预加载OpenGL
    preloadOpenGL();
    //通过System.loadLibrary()方法,
    //预加载"android","compiler_rt","jnigraphics"这3个共享库
    preloadSharedLibraries();
    //预加载 文本连接符资源
    preloadTextResources();
    //仅用于zygote进程,用于内存共享的进程
    WebViewFactory.prepareWebViewInZygote();

zygote进程内加载了preload()方法中的所有资源,当需要fork新进程时,采用copy on write技术,如下:

image.png

startSystemServer(略过,下文会分析,属于主流程)

runSelectLoop

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    //sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0]
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
             //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            ...
        }
        
        for (int i = pollFds.length - 1; i >= 0; --i) {
            //采用I/O多路复用机制,当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;
            // 否则进入continue,跳出本次循环。
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                //即fds[0],代表的是sServerSocket,则意味着有客户端连接请求;
                // 则创建ZygoteConnection对象,并添加到fds。
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor()); //添加到fds.
            } else {
                //i>0,则代表通过socket接收来自对端的数据,并执行相应操作
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i); //处理完则从fds中移除该文件描述符
                }
            }
        }
    }
}

Zygote采用高效的I/O多路复用机制,保证在没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。

runOnce

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        //读取socket客户端发送过来的参数列表
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        ...
        return true;
    }
    ...

    try {
        //将binder客户端传递过来的参数,解析成Arguments对象格式
        parsedArgs = new Arguments(args);
        ...
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (Exception e) {
        ...
    }

    try {
        if (pid == 0) {
            //子进程执行
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            //进入子进程流程
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        } else {
            //父进程执行
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

阶段总结

Zygote启动过程的调用流程图


image.png

1.解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法;
2.调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数;
3.通过JNI方式调用ZygoteInit.main(),第一次进入Java世界;
4.registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求;
5.preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高app启动效率;
6.zygote完毕大部分工作,接下来再通过startSystemServer(),fork得力帮手system_server进程,也是上层framework的运行载体。
7.zygote功成身退,调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。

最后,介绍给通过cmd命令,来fork新进程来执行类中main方法的方式:(启动后进入RuntimeInit.main)

app_process [可选参数] 命令所在路径 启动的类名 [可选参数]

SystemServer初始化

由上文可知,SystemServer由Zygote fork生成的,改进程名为system_server,该进程承载着framework的核心服务。启动SystemServer起点是调用startSystemServer(),下面是system_server的启动流程:

image.png

上图前4步骤(即颜色为紫色的流程)运行在是Zygote进程,从第5步(即颜色为蓝色的流程)ZygoteInit.handleSystemServerProcess开始是运行在新创建的system_server,这是fork机制实现的(fork会返回2次)。
startSystemServer
startSystemServer会进入开启SystemServer进程阶段,下文会详细分析

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        ...
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
          ZygoteConnection.Arguments parsedArgs = null;
    int pid;
    try {
        //用于解析参数,生成目标格式
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        // fork子进程,该进程是system_server进程【见小节2】
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
      //进入子进程system_server
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        // 完成system_server进程剩余的工作 【见小节5】
        handleSystemServerProcess(parsedArgs);
    }
    return true;
    }

startSystemServer函数主要的作用是准备参数并fork新进程,从上面可以看出system server进程参数信息为uid=1000,gid=1000,进程名为sytem_server,从zygote进程fork新进程后,需要关闭zygote原有的socket。另外,对于有两个zygote进程情况,需等待第2个zygote创建完成。

forkSystemServer流程

Zygote.java(frameworks/base/core/java/com/android/internal/os/Zygote.java)#forkSystemServer

public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

nativeForkSystemServer()方法是本地方法在AndroidRuntime.cpp中注册的,调用com_android_internal_os_Zygote.cpp中的register_com_android_internal_os_Zygote()方法建立native方法的映射关系。

nativeForkSystemServer(com_android_internal_os_Zygote.cpp)

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
  //fork子进程
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL);
  if (pid > 0) {
      // zygote进程,检测system_server进程是否创建
      gSystemServerPid = pid;
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
          //当system_server进程死亡后,重启zygote进程
          RuntimeAbort(env);
      }
  }
  return pid;
}

当system_server进程创建失败时,将会重启zygote进程。这里需要注意,对于Android 5.0以上系统,有两个zygote进程,分别是zygote、zygote64两个进程,system_server的父进程,一般来说64位系统其父进程是zygote64进程。

1.当kill system_server进程后,只重启zygote64和system_server,不重启zygote;
2.当kill zygote64进程后,只重启zygote64和system_server,也不重启zygote;
3.当kill zygote进程,则重启zygote、zygote64以及system_server。

ForkAndSpecializeCommon

static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jstring instructionSet, jstring dataDir) {
  SetSigChldHandler(); //设置子进程的signal信号处理函数
  pid_t pid = fork(); //fork子进程
  if (pid == 0) {
    //进入子进程
    DetachDescriptors(env, fdsToClose); //关闭并清除文件描述符

    if (!is_system_server) {
        //对于非system_server子进程,则创建进程组
        int rc = createProcessGroup(uid, getpid());
    }
    SetGids(env, javaGids); //设置设置group
    SetRLimits(env, javaRlimits); //设置资源limit

    int rc = setresgid(gid, gid, gid);
    rc = setresuid(uid, uid, uid);

    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
    SetSchedulerPolicy(env); //设置调度策略

     //selinux上下文
    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);

    if (se_info_c_str == NULL && is_system_server) {
      se_name_c_str = "system_server";
    }
    if (se_info_c_str != NULL) {
      SetThreadName(se_name_c_str); //设置线程名为system_server,方便调试
    }
    UnsetSigChldHandler(); //设置子进程的signal信号处理函数为默认函数
    //等价于调用zygote.callPostForkChildHooks()
    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
                              is_system_server ? NULL : instructionSet);
    ...

  } else if (pid > 0) {
    //进入父进程,即zygote进程
  }
  return pid;
}

fork()创建新进程,采用copy on write方式,这是linux创建进程的标准方法,会有两次return,对于pid==0为子进程的返回,对于pid>0为父进程的返回。 到此system_server进程已完成了创建的所有工作,接下来开始了system_server进程的真正工作。在前面startSystemServer()方法中,zygote进程执行完forkSystemServer()后,新创建出来的system_server进程便进入handleSystemServerProcess()方法。关于fork(),可查看理解Android进程创建流程

HandleSystemServerProcess流程

ZygoteInit.java#handleSystemServerProcess

private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

       ...
//此处systemServerClasspath环境变量主要有/system/framework/目录下的services.jar,ethernet-service.jar, wifi-service.jar这3个文件
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
        //执行dex优化操作
        performSystemServerDexOpt(systemServerClasspath);
    }
        //之前传进来的invokeWith为null,走eles逻辑
        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
            }

            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
        } else {
          //通过类加载器加载指定目录下的类并调用 RuntimeInit.zygoteInit
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
                Thread.currentThread().setContextClassLoader(cl);
            }
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }
    }

ZygoteInit.java#performSystemServerDexOpt

private static void performSystemServerDexOpt(String classPath) {
    final String[] classPathElements = classPath.split(":");
    //创建一个与installd的建立socket连接
    final InstallerConnection installer = new InstallerConnection();
    //执行ping操作,直到与installd服务端连通为止
    installer.waitForConnection();
    final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();

    try {
        for (String classPathElement : classPathElements) {
            final int dexoptNeeded = DexFile.getDexOptNeeded(
                    classPathElement, "*", instructionSet, false /* defer */);
            if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                //以system权限,执行dex文件优化
                installer.dexopt(classPathElement, Process.SYSTEM_UID, false,
                        instructionSet, dexoptNeeded);
            }
        }
    } catch (IOException ioe) {
        throw new RuntimeException("Error starting system_server", ioe);
    } finally {
        installer.disconnect(); //断开与installd的socket连接
    }
}

将classPath字符串中的apk,分别进行dex优化操作。真正执行优化工作通过socket通信将相应的命令参数,发送给installd来完成。

zygoteInit流程

RuntimeInit#zygoteInit(frameworks/base/core/java/com/android/internal/os/RuntimeInit.java)

 public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        //重定向日志
        redirectLogStreams();
        //通用组件初始化
        commonInit();
    //本地Zygote初始化 native方法
        nativeZygoteInit();
        //android第一个app应用初始化
        applicationInit(targetSdkVersion, argv, classLoader);
    }

RuntimeInit#commonInit

private static final void commonInit() {
    // 设置默认的未捕捉异常处理方法
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

    // 设置市区,中国时区为"Asia/Shanghai"
    TimezoneGetter.setInstance(new TimezoneGetter() {
        @Override
        public String getId() {
            return SystemProperties.get("persist.sys.timezone");
        }
    });
    TimeZone.setDefault(null);

    //重置log配置
    LogManager.getLogManager().reset();
    new AndroidConfig();

    // 设置默认的HTTP User-agent格式,用于 HttpURLConnection。
    String userAgent = getDefaultUserAgent();
    System.setProperty("http.agent", userAgent);

    // 设置socket的tag,用于网络流量统计
    NetworkManagementSocketTagger.install();
}

AndroidRuntime.cpp#com_android_internal_os_RuntimeInit_nativeZygoteInit

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) {
    //此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的
    gCurRuntime->onZygoteInit();
}

[–>app_main.cpp]

irtual void onZygoteInit() {
    sp<ProcessState> proc = ProcessState::self();
    proc->startThreadPool(); //启动新binder线程
}

ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver(),在binder系列文章中的注册服务(addService)详细这两个方法的执行原理。

RuntimeInit.java#applicationInit

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
    //true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用
    nativeSetExitWithoutCleanup(true);

    //设置虚拟机的内存利用率参数值为0.75
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

    final Arguments args;
    try {
        args = new Arguments(argv); //解析参数
    } catch (IllegalArgumentException ex) {
        return;
    }

    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    //调用startClass的static方法 main() 
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

RuntimeInit.java#invokeStaticMain

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl = Class.forName(className, true, classLoader);
    ...

    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        ...
    } catch (SecurityException ex) {
        ...
    }

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        ...
    }

    //通过抛出异常,回到ZygoteInit.main()。这样做好处是能清空栈帧,提高栈帧利用率。
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

还记得在zygote进程的ZygoteInit.java的以下代码吗?

public static void main(String argv[]) {
    try {
        startSystemServer(abiList, socketName);//启动system_server
        ....
    } catch (MethodAndArgsCaller caller) {
        caller.run(); //
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}

很明显当我们抛出MethodAndArgsCaller异常时会调用 caller.run()方法。

public static class MethodAndArgsCaller extends Exception implements Runnable {

    public void run() {
        try {
            //根据传递过来的参数,可知此处通过反射机制调用的是SystemServer.main()方法
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InvocationTargetException ex) {
            Throwable cause = ex.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            }
            throw new RuntimeException(ex);
        }
    }
}

代码比较简单,就是通过反射调用SystemServer类的main()方法。

SystemServer启动(/frameworks/base/services/java/com/android/server/SystemServer.java)

SystemServer#main

 public static void main(String[] args) {
        //创建了一个SystemServer对象
        new SystemServer().run();
    }

SystemServer#run

private void run() {
    //当系统时间比1970年更早,就设置当前系统时间为1970年
    if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
        SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
    }

    //变更虚拟机的库文件,对于Android 6.0默认采用的是libart.so
    SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

    if (SamplingProfilerIntegration.isEnabled()) {
        ...
    }

    //清除vm内存增长上限,由于启动过程需要较多的虚拟机内存空间
    VMRuntime.getRuntime().clearGrowthLimit();

    //设置内存的可能有效使用率为0.8
    VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
    // 针对部分设备依赖于运行时就产生指纹信息,因此需要在开机完成前已经定义
    Build.ensureFingerprintProperty();

    //访问环境变量前,需要明确地指定用户
    Environment.setUserRequired(true);

    //确保当前系统进程的binder调用,总是运行在前台优先级(foreground priority)
    BinderInternal.disableBackgroundScheduling(true);
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
    android.os.Process.setCanSelfBackground(false);

    // 主线程looper就在当前线程运行
    Looper.prepareMainLooper();

    //加载android_servers.so库,该库包含的源码在frameworks/base/services/目录下
    System.loadLibrary("android_servers");

    //检测上次关机过程是否失败,该方法可能不会返回
    performPendingShutdown();

    //初始化系统上下文 
    createSystemContext();

    //创建系统服务管理
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    //将mSystemServiceManager添加到本地服务的成员sLocalServiceObjects
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);


    //启动各种系统服务
    try {
        startBootstrapServices(); // 启动引导服务
        startCoreServices();      // 启动核心服务
        startOtherServices();     // 启动其他服务
    } catch (Throwable ex) {
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    }

    //用于debug版本,将log事件不断循环地输出到dropbox(用于分析)
    if (StrictMode.conditionallyEnableDebugLogging()) {
        Slog.i(TAG, "Enabled StrictMode for system server main thread.");
    }
    //一直循环执行
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

LocalServices通过用静态Map变量sLocalServiceObjects,来保存以服务类名为key,以具体服务对象为value的Map结构。

SystemServer#performPendingShutdown

private void performPendingShutdown() {
    final String shutdownAction = SystemProperties.get(
            ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
    if (shutdownAction != null && shutdownAction.length() > 0) {
        boolean reboot = (shutdownAction.charAt(0) == '1');

        final String reason;
        if (shutdownAction.length() > 1) {
            reason = shutdownAction.substring(1, shutdownAction.length());
        } else {
            reason = null;
        }
        // 当"sys.shutdown.requested"值不为空,则会重启或者关机
        ShutdownThread.rebootOrShutdown(null, reboot, reason);
    }
}

SystemServer#createSystemContext

private void createSystemContext() {
    //创建system_server进程的上下文信息
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    //设置主题
    mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}

理解Application创建过程已介绍过createSystemContext()过程, 该过程会创建对象有ActivityThread,Instrumentation, ContextImpl,LoadedApk,Application。

SystemServer#startBootstrapServices

private void startBootstrapServices() {
    //阻塞等待与installd建立socket通道
    Installer installer = mSystemServiceManager.startService(Installer.class);

    //启动服务ActivityManagerService
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);

    //启动服务PowerManagerService
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

    //初始化power management
    mActivityManagerService.initPowerManagement();

    //启动服务LightsService
    mSystemServiceManager.startService(LightsService.class);

    //启动服务DisplayManagerService
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    //Phase100: 在初始化package manager之前,需要默认的显示.
    mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

    //当设备正在加密时,仅运行核心
    String cryptState = SystemProperties.get("vold.decrypt");
    if (ENCRYPTING_STATE.equals(cryptState)) {
        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        mOnlyCore = true;
    }

    //启动服务PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();

    //启动服务UserManagerService,新建目录/data/user/
    ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());

    AttributeCache.init(mSystemContext);

    //设置AMS
    mActivityManagerService.setSystemProcess();

    //启动传感器服务
    startSensorService();
}

该方法创建的服务有:ActivityManagerService, PowerManagerService, LightsService, DisplayManagerService, PackageManagerService, UserManagerService, sensor服务。

SystemServer#startCoreServices

private void startCoreServices() {
    //启动服务BatteryService,用于统计电池电量,需要LightService.
    mSystemServiceManager.startService(BatteryService.class);

    //启动服务UsageStatsService,用于统计应用使用情况
    mSystemServiceManager.startService(UsageStatsService.class);
    mActivityManagerService.setUsageStatsManager(
            LocalServices.getService(UsageStatsManagerInternal.class));

    mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

    //启动服务WebViewUpdateService
    mSystemServiceManager.startService(WebViewUpdateService.class);
}

创建的服务有:BatteryService,UsageStatsService,WebViewUpdateService
SystemServer#startOtherServices

private void startOtherServices() {
        ...
        SystemConfig.getInstance();
        mContentResolver = context.getContentResolver(); // resolver
        ...
        mActivityManagerService.installSystemProviders(); //provider
        mSystemServiceManager.startService(AlarmManagerService.class); // alarm
        // watchdog
        watchdog.init(context, mActivityManagerService); 
        inputManager = new InputManagerService(context); // input
        wm = WindowManagerService.main(...); // window
        inputManager.start();  //启动input
        mDisplayManagerService.windowManagerAndInputReady();
        ...
        mSystemServiceManager.startService(MOUNT_SERVICE_CLASS); // mount
        mPackageManagerService.performBootDexOpt();  // dexopt操作
        ActivityManagerNative.getDefault().showBootMessage(...); //显示启动界面
        ...
        statusBar = new StatusBarManagerService(context, wm); //statusBar
        //dropbox
        ServiceManager.addService(Context.DROPBOX_SERVICE,
                    new DropBoxManagerService(context, new File("/data/system/dropbox")));
         mSystemServiceManager.startService(JobSchedulerService.class); //JobScheduler
         lockSettings.systemReady(); //lockSettings

        //phase480 和phase500
        mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
        mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
        ...
        // 准备好window, power, package, display服务
        wm.systemReady();
        mPowerManagerService.systemReady(...);
        mPackageManagerService.systemReady();
        mDisplayManagerService.systemReady(...);
        
        //下文会详细分析
        mActivityManagerService.systemReady(new Runnable() {
            public void run() {
              ...
            }
        });
    }

SystemServer启动各种服务中最后的一个环节便是AMS.systemReady(),详见ActivityManagerService启动过程.

到此, System_server主线程的启动工作总算完成, 进入Looper.loop()状态,等待其他线程通过handler发送消息到主线再处理。

服务启动阶段

关于服务启动阶段的详情请参考Android系统启动-SystemServer#服务启动阶段部分
SystemServiceManager的startBootPhase()贯穿system_server进程的整个启动过程

image.png

其中PHASE_BOOT_COMPLETED=1000,该阶段是发生在Boot完成和home应用启动完毕。系统服务更倾向于监听该阶段,而不是注册广播ACTION_BOOT_COMPLETED,从而降低系统延迟。

各个启动阶段所在源码的大致位置

public final class SystemServer {

    private void startBootstrapServices() {
      ...
      //phase100
      mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
      ...
    }

    private void startCoreServices() {
      ...
    }

    private void startOtherServices() {
      ...
      //phase480 && 500
      mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
      mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
      
      ...
      mActivityManagerService.systemReady(new Runnable() {
         public void run() {
             //phase550
             mSystemServiceManager.startBootPhase(
                     SystemService.PHASE_ACTIVITY_MANAGER_READY);
             ...
             //phase600
             mSystemServiceManager.startBootPhase(
                     SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
          }
      }
    }
}

桌面应用启动过程

通过上文我们知道当所有的服务启动完成以后我们调用了 mActivityManagerService.systemReady(),下面我们进入到其内部看看做了哪些操作
ActivityManagerService#systemReady

 public void systemReady(final Runnable goingCallback) {
    synchronized(this) {
            if (mSystemReady) {
                // If we're done calling all the receivers, run the next "boot phase" passed in
                // by the SystemServer
                if (goingCallback != null) {
                    goingCallback.run();
                }
                return;
            }
    }
       ...
      //启动桌面应用程序
      startHomeActivityLocked(mCurrentUserId, "systemReady");
       ...
}

ActivityManagerService#startHomeActivityLocked

boolean startHomeActivityLocked(int userId, String reason) {
        ...
        Intent intent = getHomeIntent();
         ...
        mStackSupervisor.startHomeActivity(intent, aInfo, reason);
         ...  
    }

Intent getHomeIntent() {
        //通过隐式调用intent
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

<pre>

这里getHomeIntent加了一个Intent.CATEGORY_HOME的Category,系统的Launcher这个Activity正好有这个android.intent.category.HOME的Category,这个文件在/packages/apps/Launcher2/AndroidManifest.xml

<application
        android:name="com.android.launcher2.LauncherApplication"
        android:label="@string/application_name"
        android:icon="@mipmap/ic_launcher_home"
        android:hardwareAccelerated="true"
        android:largeHeap="@bool/config_largeHeap"
        android:supportsRtl="true">
        <activity
            android:name="com.android.launcher2.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:resumeWhilePausing="true"
            android:theme="@style/Theme"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="nosensor">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>
</application>

所以这里是隐式的启动了Launcher,接着调用mStackSupervisor的startHomeActivity方法

ActivityStackSupervisor#startHomeActivity(/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java))

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
        ...
        startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo,
                null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,
                null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,
                null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,
                0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,
                false /* componentSpecified */,
                null /* outActivity */, null /* container */,  null /* inTask */);
       
    }

这里调用了startActivityLocked方法,其实这个方法就是我们平时调用startActivity方法之后会调用的方法了,至此桌面就被启动起来了。

总结

关于Android系统从开机到启动桌面大概的过程如下:

1.启动linux内核,fork第一个进程init
2.init进程解析init.rc文件,然后fork出众多进程,zygote进程是其中之一
3.zygote进程启动的虚拟机,从C++环境切换到Java环境,并fork出system_server进程
4.SystemServer启动众多的系统Service如ActivityManagerService,WindowMangerService等
5.ActivityManagerService启动桌面Activity Luncher

参考

Android M系统启动流程
Android系统启动-概述
Android系统启动-Init篇
Android系统启动-zygote篇
Android系统启动-SystemServer上篇
Android系统启动-SystemServer下篇
深入理解init
深入理解 Zygote

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269