Android系统学习-启动篇

381 阅读7分钟

前言

对于Android系统的启动,从手机直观上看,大概经历几个步骤:

  • 按下开机键
  • 出现启动动画
  • 稍等若干秒,出现锁屏界面
  • 解锁之后,进入桌面

这篇文章就从源码的角度出发,揭露这些环节发生时,系统都是如何操作的。

一、系统启动

1.1 Linux 系统的启动

了解Android系统启动之前,先简要描述一下Linux系统的启动过程:

  1. 内核的引导。

    • 当系统开机之后,BIOS会进行开机自检
    • 运行Bootloader
    • 首先读入 /boot 目录下的内核文件,启动init进程
  2. 运行 init。

    • 读取 /etc/inittab 文件, 启动各种系统服务
    • 在Ubuntu系统中,init进程会读取 /etc/init.d /etc/init /etc/rcS.d 目录中的文件来启动系统服务
  3. 系统初始化。

  4. 建立终端 。

  5. 用户登录系统

1.2 Android系统的启动

按照官方描述,Android系统架构共分五层,自上到下依次为:

  • 应用层 - apps
  • 应用框架层 - Framework
  • 系统运行库层- Native Libraries
  • 硬件抽象层 - HAL
  • Linux内核层

既然采用了Linux内核,那么Android系统的起始动作跟Linux无异,但由于Android手机属于嵌入式设备,并没有使用BIOS,取而代之的是 Bootloader —— 系统启动加载器,由Bootloader加载内核,再由内核启动init 进程。

二、第一个进程-init

2.1 初始化

作为内核启动后创建的第一个进程,init的进程号为1 ,源码位于/System/core/init.cpp , 其中main函数,负责一些初始化工作,将代码简化后,大致如下:

int main(int argc, char** argv) {
    
    //  初始化Kernel日志
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";
​
    //初始化属性服务
    property_init();
​
    // 设置关于SELinux的内容
    SelinuxSetupKernelLogging();
    SelabelInitialize();
    SelinuxRestoreContext();
    
    // 创建epoll句柄
    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
 
    //监控子进程异常的信号处理函数
    sigchld_handler_init();
​
    //启动属性服务
    start_property_service();
​
   //解析init.rc文件,以便后续启动系统服务。
    LoadBootScripts(am, sm);
    
    epoll_event ev;
    // 等待I/O事件
    int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
​
    return 0;
}

2.2 解析init.rc

在上面一节的main函数中,有个LoadBootScripts函数,用来解析init.rc。

static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser = CreateParser(action_manager, service_list);
    //获取ro.boot.init_rc配置,如果不存在则读取 /init.rc 文件
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}
​

init.rc 是由Android Init Language 定义的配置文件,由init进程解析用来执行命令或者创建系统核心服务等。

init.rc包含4种状态类别

  • Actions
  • Commands
  • Services
  • Options

下面列举一些在init.rc中进行的操作:

  • 创建目录
    mkdir /data/local/tmp 0771 shell shell
    mkdir /data/local/traces 0777 shell shell
    mkdir /data/data 0771 system system
    mkdir /data/app-private 0771 system system
    mkdir /data/app-ephemeral 0771 system system
  • 启动服务

    service ueventd /sbin/ueventd
        class core
        critical
        seclabel u:r:ueventd:s0
        shutdown critical
    ​
    service console /system/bin/sh
        class core
        console
        disabled
        user shell
        group shell log readproc
        seclabel u:r:shell:s0
        setenv HOSTNAME console

    其中还引入了其他rc文件,其中有一个非常重要的就是 import /init.${ro.zygote}.rc , 这个服务就是大名鼎鼎的 Zygote, 内容为:

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
        class main
        priority -20
        user root
        group root readproc reserved_disk
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart audioserver
        onrestart restart cameraserver
        onrestart restart media
        onrestart restart netd
        onrestart restart wificond
        writepid /dev/cpuset/foreground/tasks
    

    启动Zygote

    根据上节所述, rc文件的解析会调用到 parser.ParseConfig ,接下来就是对所有服务的添加工作,代码简化后如下:

    bool Parser::ParseConfig(const std::string& path, size_t* parse_errors) {
        return ParseConfigFile(path, parse_errors);
    }
    bool Parser::ParseConfigFile(const std::string& path, size_t* parse_errors) {
        config_contents->push_back('\n');  // TODO: fix parse_config.
        ParseData(path, *config_contents, parse_errors);
        return true;
    }
    ​
    void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {
    ​
       for (;;) {
           switch (next_token(&state)) {
               case T_EOF:
                   return;
               case T_NEWLINE:
                    jstate.line++;
                    section_parser->ParseSection(std::move(args), filename, state.line);
                    section_parser->EndSection();
                  
           }
        }
    }
    Result<Success> ServiceParser::EndSection() {
        if (service_) {
            service_list_->AddService(std::move(service_));
        }
    ​
        return Success();
    }
    void ServiceList::AddService(std::unique_ptr<Service> service) {
        services_.emplace_back(std::move(service));
    }
    std::vector<std::unique_ptr<Service>> services_;
    

    可以看出当实例化一个Server之后,会加入services_的链表中。

    继续分析。

    init.rc中有一个操作是 class_start , 它对应的实现在 buildins.cpp 中

     {"class_start",             {1,     1,    {false,  do_class_start}}},
    

    do_class_start及后续操作简化如下 :

Result<Success> do_class_start(const BuiltinArguments& args) {
    for (const auto& service : ServiceList::GetInstance()) {
         auto result = service->StartIfNotDisabled();
     
    }
    return Success();
}
​
Result<Success> Service::StartIfNotDisabled() {
    return Start();
}
​
Result<Success> Service::Start() {
    pid_t pid = -1;
    if (namespace_flags_) {
        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
    } else {
        pid = fork();
    }
​
    if (pid == 0) {
        if (!ExpandArgsAndExecv(args_)) {
            PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
        }
    }
    return Success();
}

我们可以清楚的看到,do_class_start实际上就是遍历ServiceList获取每一个要创建的服务,调用service->start(), 最终使用fork() 在子进程中 执行execv函数来启动服务。

而这, 其中就包括Zygote。

三、Zygote-程序孵化器

Zygote的职责有很多,大体上可以的可以分为:

  • 创建虚拟机ART : 负责给app提供运行时环境
  • 创建SystemServer: 负责管理各种Framework层的Service
  • 创建APP

3.1 main函数

int main(int argc, char* const argv[])
{
    //创建虚拟机
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
​
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

根据代码列出main函数的逻辑:

  • 创建虚拟机

  • 由于后续Zygote会fork出若干子进程,所以会根据参数判断当前进程的类型:

    • --zygote: zygote父进程
    • -start-system-server: SystemServer进程
    • --application: APP进程
  • 启动虚拟机: runtime.start

3.2 虚拟机的启动

根据前文描述,在Zygote的main函数中,执行了Runtime的start:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
​
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
  
  
    startVm(&mJavaVM, &env, zygote) ;
   
​
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
 
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",  "([Ljava/lang/String;)V");
  
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
​
    free(slashClassName);
    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}
  • startVm() : 启动虚拟机,创建Java运行时环境。
  • 通过运行时提供的JNI,接口执行 className 中的 main 方法,className为com.android.internal.os.ZygoteInit

经过上面的过程,正式将代码的执行环境从C++ 切换到了 Java环境, 下面我们分析ZygoteInit.main()

3.3 ZygoteInit

由上文可知,ZygoteInit 类是虚拟机世界调用的第一个Java 类,我们一起来看看它都做了什么。

首选来看 main 方法, 简化后的伪代码如下:

public static void main(String argv[]) {
    // 注册一个命名socket
    ZygoteServer zygoteServer = new ZygoteServer();
    zygoteServer.registerServerSocketFromEnv(socketName);
​
    //预加载
    preload(bootTimingsTraceLog);
    // 执行一次gc
    gcAndFinalize();
  
    // fork SystemServer进程
    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
    r.run();
​
    // 循环等待事件。
    zygoteServer.runSelectLoop(abiList);
    
    // 关闭socket
    zygoteServer.closeServerSocket();
}
  • registerServerSocketFromEnv

    在main函数的起始处注册了一个命名socket,了解linux编程的同学应该都知道,这是一个进程间通信的方式,而通信的另一方就是 负责管理和创建APP的 ActivityManagerSevice 。

    通过命令

    netstat -na
    

    可以看到这里创建的socket

unix  2      [ ACC ]     STREAM     LISTENING        25970 /dev/socket/zygote
  • preload: 预加载操作,主要的功能包括:

    • 加载基础的Java类,类的列表存储在 /system/etc/preloaded-classes 文件中
    • 加载基础资源,包括preloadDrawables 和 preloadColorStateLists
    • 加载HAL层、OpenGL、libandroid.so等底层库

    我们可以在启动时 通过Logcat过滤Zygote日志,查看preload的过程:

    09-06 08:38:05.352   800   800 I Zygote  : Lazily preloading resources.
    09-06 08:38:05.352   800   800 D Zygote  : begin preload
    09-06 08:38:05.352   800   800 I Zygote  : Installing ICU cache reference pinning...
    09-06 08:38:05.352   800   800 I Zygote  : Preloading ICU data...
    09-06 08:38:05.357   800   800 I Zygote  : Preloading classes...
    09-06 08:38:05.612   800   800 I Zygote  : ...preloaded 6535 classes in 255ms.
    09-06 08:38:05.742   800   800 I Zygote  : Preloading resources...
    09-06 08:38:05.768   800   800 I Zygote  : ...preloaded 64 resources in 26ms.
    09-06 08:38:05.770   800   800 I Zygote  : ...preloaded 41 resources in 2ms.
    09-06 08:38:05.966   800   800 I Zygote  : Preloading shared libraries...
    09-06 08:38:05.973   800   800 I Zygote  : Uninstalled ICU cache reference pinning...
    09-06 08:38:05.973   800   800 I Zygote  : Installed AndroidKeyStoreProvider in 0ms.
    09-06 08:38:05.977   800   800 I Zygote  : Warmed up JCA providers in 3ms.
    09-06 08:38:05.977   800   800 D Zygote  : end preload
    
  • gcAndFinalize() : 封装了System.gc(),主动执行一次GC操作

  • forkSystemServer() : 创建SystemServer进程,下文会详细介绍

  • runSelectLoop() : 监听SocketServer,循环读取消息

代码如下:

Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    fds.add(mServerSocket.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;
        }
        Os.poll(pollFds, -1);
        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 {
                ZygoteConnection connection = peers.get(i);
                final Runnable command = connection.processOneCommand(this);
            }
        }
    }
}

runSelectLoop主要做的工作包括:

  • 使用Os.poll的方式,监听ZygoteServer创建的Socket [ poll 是linux网络多路复用的一种,其他还有select,epoll]。
  • 不断监听新创建的socket
  • 如果接收到消息,调用 processOneCommand 执行

四、 SystemServer

4.1 创建

由上文可知,SystemServer的创建时由ZygoteInit来完成的 ,伪代码如下:

 private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) {
​
    // 准备SystemServer 的参数 
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
        "com.android.server.SystemServer",
    };
    int pid;
​
    // fork SystemServer 进程
    pid = Zygote.forkSystemServer(
            parsedArgs.uid, parsedArgs.gid,
            parsedArgs.gids,
            parsedArgs.runtimeFlags,
            null,
            parsedArgs.permittedCapabilities,
            parsedArgs.effectiveCapabilities);
​
    /* For child process */
    if (pid == 0) {
        // 处理SystemServer进程
        return handleSystemServerProcess(parsedArgs);
    }
​
    return null;
}

参数解析:

  • setuid ,setgid : 设置UID和GID为1000, 我们可以通过查看 /proc/pid/status,来查看SystemServer的UID GID的值
  • nice-name : 修改进程名为 system_server
  • com.android.server.SystemServer: 设置SystemServer进程对应的Java类

常用UID:

#define AID_ROOT             0  /* traditional unix root user */
#define AID_SYSTEM        1000  /* * system server anches. */
#define AID_SHELL         2000  /* adb and debug shell user */// 用户层APP的UID大于 10000

4.2 准备

handleSystemServerProcess:

private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
​
    //修改进程名为 system_server
    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }
​
    //   
    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    performSystemServerDexOpt(systemServerClasspath);
    prepareSystemServerProfile(systemServerClasspath);
  
    ClassLoader cl = null;
    cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
    Thread.currentThread().setContextClassLoader(cl);
  
    return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
​
  • Process.setArgV0 : 修改进程名为 system_server
blueline:/ $ ps -ef |grep system_server
system        1161   794 5 08:38:03 ?     02:17:13 system_server
  • performSystemServerDexOpt : 获取SYSTEMSERVERCLASSPATH变量,并进行DexOpt操作。

    根据env命令可得该环境变量包含以下Jar文件:

     SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar:/system/framework/com.android.location.provider.jar
    

    获取Jar文件后,调用DexOpt操作,继续追踪代码,最终调用 installd 服务的 run_dex2oat 操作。

  • prepareSystemServerProfile : 根据环境变量 生成相应目录下的 prof 文件。

  • createPathClassLoader: 创建PathClassLoader
  • ZygoteInit.zygoteInit : 准备工作结束之后,执行zygoteInit

4.2 运行

上文分析到SystemServer进行一些准备工作,最后调用了zygoteInit

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }
​
    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit();
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

这里的工作有三个

  • RuntimeInit.commonInit(): 主要是进行了Java异常相关的初始化 .
protected static final void commonInit() {
    LoggingHandler loggingHandler = new LoggingHandler();
    Thread.setUncaughtExceptionPreHandler(loggingHandler);
    Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
}
  • ZygoteInit.nativeZygoteInit(): Native函数,对应onZygoteInit,创建native线程池,作用是用于Binder通信。
void onZygoteInit()
{
  sp<ProcessState> proc = ProcessState::self();
  proc->startThreadPool();
}
  • RuntimeInit.applicationInit: 通过PathClassLoader和className ,通过反射调用SystemServer.main函数。

    protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
           Class<?> cl;
           // className = com.android.server.SystemServer
           cl = Class.forName(className, true, classLoader);
           Method  m = cl.getMethod("main", new Class[] { String[].class });
           return m.invoke(null, new Object[] { mArgs });
    }
    

4.3 SystemServer.main

简化后的代码:

static void main(String[] args) {
      new SystemServer().run();
}
private void run() {
​
       // Increase the number of binder threads in system_server
       BinderInternal.setMaxThreads(sMaxBinderThreads);
​
       Looper.prepareMainLooper();
       Looper.getMainLooper().setSlowLogThresholdMs(
               SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
​
       // 加载 android_servers库
       System.loadLibrary("android_servers");
​
​
       // 初始化 SystemContext
       createSystemContext();
​
       //  创建 SystemServiceManager
       mSystemServiceManager = new SystemServiceManager(mSystemContext);
       mSystemServiceManager.setStartInfo(mRuntimeRestart,
               mRuntimeStartElapsedTime, mRuntimeStartUptime);
       LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
​
      
       startBootstrapServices();
       startCoreServices();
       startOtherServices();
       SystemServerInitThreadPool.shutdown();
​
        // Loop forever.
        Looper.loop();
}
​
  • BinderInternal.setMaxThreads(sMaxBinderThreads) : 设置Binder线程池支持的最大线程数,sMaxBinderThreads= 31;

    可以通过ps -T -p 来查看SystemServer Binder线程池中的线程,可以看到线程的名称是用Binder:pid_count来命名的.

//shell命令 
blueline:/ $ ps -T -p 9835 |grep Binder
system        9835  9860  9742 4849920 301604 0                   0 S Binder:9835_1
system        9835  9861  9742 4849920 301604 0                   0 S Binder:9835_2
system        9835  9970  9742 4849920 301604 0                   0 S Binder:9835_3
system        9835 10098  9742 4849920 301604 0                   0 S Binder:9835_4
system        9835 10139  9742 4849920 301604 0                   0 S Binder:9835_5
system        9835 10267  9742 4849920 301604 0                   0 S Binder:9835_6
system        9835 10356  9742 4849920 301604 0                   0 S Binder:9835_7
system        9835 10398  9742 4849920 301604 0                   0 S Binder:9835_8
system        9835 12364  9742 4849920 301604 0                   0 S Binder:9835_9
  • Looper.prepareMainLooper() : 创建一个主线程的looper
  • SystemServiceManager: 负责对所有系统服务的管理,包括 创建、启动 等等。
  • startBootstrapServices(); startCoreServices() ; startOtherServices();

分别负责启动 Boot、Core、Other 三种类型的 Services

4.4 各种Services的启动

上节说到 SystemServer 的末尾启动了 系统的Services,包括三种类型,Boot、Core、Other,共100+, 这里我们拿 BootServiceManager中的 Installd 来举例说明其创建和启动过程。

// SystemServiceManager为 SystemServer创建的服务管理对象
Installer installer = mSystemServiceManager.startService(Installer.class);
​
//SystemServiceManager.java: 
public <T extends SystemService> T startService(Class<T> serviceClass) {
    final String name = serviceClass.getName();
    final T service;
    Constructor<T> constructor = serviceClass.getConstructor(Context.class);
    service = constructor.newInstance(mContext);
    startService(service);
    return service;
}
​
// 由ArrayList来存储所有启动的service
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
public void startService(@NonNull final SystemService service) {
    // Register it.
    mServices.add(service);
    service.onStart();
}
​
// Installer.java
public class Installer extends SystemService {
    @Override
    public void onStart() {
      connect();
    }
​
    private void connect() {
        // ServiceManager 是系统服务涉及的另一个重要的类
        IBinder binder = ServiceManager.getService("installd");
        // 监听服务销毁,触发时重连
        binder.linkToDeath(new DeathRecipient() {
            @Override
            public void binderDied() {
                connect();
            }
        }, 0);
      
        // Installer中的 Binder服务实例
        mInstalld = IInstalld.Stub.asInterface(binder);
    }
}

由上面的代码可以看到,启动一个Installer SystemService的过程大致为:

  • 通过传入的Class调用构造方法创建一个Installer的实例,然后将实例加入一个ArrayList中
  • 调用installer中的onstart方法,进而调用connect()方法
  • connect中出现了一个 ServiceManager ,并调用getService 取得了 binder实例
  • 调用linkToDeath,意思是监听服务的死亡,如果死亡就会回调, 然后再回调中重新走次connect操作.
  • 将binder实例转换成 mInstalld 。

4.5 ServiceManager

ServiceManager部分关键代码:

public final class ServiceManager {
    private static IServiceManager sServiceManager;
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
    private static IServiceManager getIServiceManager() {
            // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
            return sServiceManager;
    }
​
    public static IBinder getService(String name) {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(rawGetService(name));
        }
    }
​
    public static void addService(String name, IBinder service, boolean allowIsolated,  int dumpPriority) {
        getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
    }
}

ServiceManager是服务管理中另一个重要的类, 主要管理的类型是 Binder , 它由几个重要的操作:

  • getIServiceManager:获得对应的native端实例
  • getService : 获取当前Binder Service
  • addService : 将BinderService 加入到Binder列表中,由ServiceManagerNative管理。

4.6 小结

在SystemServer这一章中涉及了几个重要的类,且命名看起来相似度很高,不好区分,简单的总结一下:

  • SystemServer : 由Zygote fork出的子进程,作为容纳所有系统服务的'容器'
  • SystemService : 作为抽象类, 每一个系统服务都实现了SystemService
  • SystemServiceManager : 管理SystemService类型的服务,使用ArrayList数据结构
  • ServiceManager: 负责管理Binder服务 , 每一个系统服务都包含至少一个Binder实例,而Binder主要解决进程间的通信。
  • ServiceManagerNative: ServiceManager的本地类,又C++实现。

五、 SystemUI

在开头我们讲过,我们开机看到的第一个应用是 锁屏界面 (实际上是开机动画,这里暂不做讲解), 那么它又是如果启动的呢?答案是SystemUI

5.1 SystemUI的启动

 private void startOtherServices() {
     ...
     mActivityManagerService.systemReady(() -> {
          startSystemUi(context, windowManagerF);
     }
     ...                                    
 }
                                         
 static final void startSystemUi(Context context, WindowManagerService windowManager) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
                "com.android.systemui.SystemUIService"));
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //Slog.d(TAG, "Starting service: " + intent);
    context.startServiceAsUser(intent, UserHandle.SYSTEM);
    windowManager.onSystemUiStarted();
}
    

startOtherServices有一段代码, 在等待mActivityManagerService服务准备完毕之后,调用startSystemUI, 而在startSystemUi中 看到了 作为应用开发中比较熟悉的 startServiceAsUser 方法,启动的服务就是 SystemUI ,包名为com.android.systemui

5.2 锁屏服务启动

在启动SystemUI之后,启动了一系列UI组件,其中包括了 StatusBar ,看一下StatusBar中的代码

public class StatusBar extends SystemUI  {
 @Override
   public void start() {
    startKeyguard();
   }
}

最终我们找到了 startKeyguard , 而这个Keyguard ,锁屏服务了。

六 总结

这篇文章,我们讲述了总按下开机键到启动锁屏服务的整个流程,这里简单归纳一下:

  1. 开机,启动Bootloader
  2. 加载Linux内核,启动Init进程
  3. 解析init.rc,启动Zygote进程
  4. Zygote创建SystemServer
  5. SystemServer初始化系统服务,包括AcitvityManagerService ,PackageManagerService等等
  6. AcitvityManagerService初始化完成,回调启动SystemUI服务
  7. SystemUI调用startKeyguard , 显示锁屏。

参考

  1. 《Android进阶解密》
  2. 贴出的系统源码,大部分基于Android9.0

\