Android框架简介--启动过程--大体流程

Android设备的启动必须经历3个阶段,即Boot Loader,Linux Kernel和Android系统服务。严格来讲Android系统实际上是运行于Linux 内核上的一系列用户进程,并不算一个严格意义上的操作系统。一般面试问及启动流程都是从init进程开始


启动过程.png

重要的系统进程

第一个系统进程--init

init进程的pid值为0.通过解析init.rc脚本来构建出系统的初始运行形态,Android系统的native服务程序大多是在对应的rc脚本中描述并被相继启动。列举下几个由init进程启动的native进程

native 服务 代码位置 描述
MediaServer frameworks/av/media/mediaserver/main_mediaserver.cpp
frameworks/av/media/mediaserver/mediaserver.rc
mediaservice服务,mediaplayer的服务端
AudioServer frameworks/av/media/audioserver/main_audioserver.cpp
frameworks/av/media/audioserver/audioserver.rc
启动AudioFlinger和AudioPolicyService
SurfaceFlinger frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
frameworks/native/services/surfaceflinger/surfaceflinger.rc
显示系统
ServiceManager /frameworks/native/cmds/servicemanager/service_manager.c
/frameworks/native/cmds/servicemanager/servicemanager.rc
注册binder的服务

这些服务启动的方式都差不多,以surfaceflinger为例:

LOCAL_INIT_RC

在frameworks/native/services/surfaceflinger/Android.mk中有如下的变量

LOCAL_INIT_RC := surfaceflinger.rc

编译宏LOCAL_INIT_RC用于将服务相关的RC文件编译到相应位置。上面的Android.mk通过LOCAL_INIT_RC将对应的surfaceflinger.rc编译到/system/etc/init目录中

解析对应的rc文件

是在system\core\init\init.cpp里面的main函数解析这些rc文件

std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/init.rc");
        parser.set_is_system_etc_init_loaded(
                parser.ParseConfig("/system/etc/init"));
        parser.set_is_vendor_etc_init_loaded(
                parser.ParseConfig("/vendor/etc/init"));
        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
    } else {
        parser.ParseConfig(bootscript);
        parser.set_is_system_etc_init_loaded(true);
        parser.set_is_vendor_etc_init_loaded(true);
        parser.set_is_odm_etc_init_loaded(true);
    }

service执行

init进程解析init.rc后,会将相应的action 放到队列中,之后会按action在action_queue这个队列中的顺序去执行操作

我们先看下surfaceflinger.rc的定义

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote

surfaceflinger属于class core
调用class_start命令的地方在init.rc中,当执行boot action的时候,顺序执行就能执行到这个命令,首先启动的core一级别的服务

on boot
    # Start standard binderized HAL daemons
    class_start hal

    class_start core

on nonencrypted
    class_start main
    class_start late_start

init进程最后会通过fork的方式去启动服务

孵化进程 -- Zygote

Android中大多数应用进程和系统进程都是通过Zygote进程来生成。Zygote为孵化的应用程序提供了几个基础资源:常用类,JNI函数,主题资源,共享库

Zygote主要做两件事:孵化应用进程,启动SystemServer.

Zygote启动后的大体流程如下:

Zygote启动.png

Zygote启动过程分为native世界和java世界
native层的入口在
frameworks/base/cmds/app_process/app_main.cpp
java层的入口在
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

native层主要就是创建虚拟机,之后进入java世界,java层主要做四件事:注册socket,预加载资源,启动System Server,进入Loop循环。最后就是在loop循环中监听SystemServer的socket连接。

Android的“系统服务” -- SystemServer

SystemServer提供了众多的用java语言编写的系统服务,像AMS,PMS,以及WMS等都只是运行在system_server这个进程中的线程
SystemServer的路径在
frameworks/base/services/java/com/android/server/SystemServer.java
入口就是main函数

    public static void main(String[] args) {
        new SystemServer().run();
    }

java的服务可以分成三类:

  • BootstrapServices
    Installer, AMS, Power Manager,Display Manager,PMS等
  • CoreServices
    DropBoxManagerService, BatteryService, UsageStatsService,WebViewUpdateService
  • OtherServices
    这类数量最多,包括一些我们经常接触的如WMS,InputManagerService

SystemServer启动的服务很多,服务间也会有相互依赖的情况,为了解决依赖的时序问题,SystemServer主要通过分批启动和分阶段启动来处理。

主要利用了SystemServiceManager的startBootPhase(),
下面的图片拷贝自http://gityuan.com/2016/02/20/android-system-server-2/

system_server_boot_process.jpg

这些启动阶段会穿插在各项的服务启动序列中。 startBootPhase会去回调用service的onBootPhase方法,对应的servcie才会去执行对应的操作

 public void startBootPhase(final int phase) {
        if (phase <= mCurrentPhase) {
            throw new IllegalArgumentException("Next phase must be larger than previous");
        }
        mCurrentPhase = phase;

        Slog.i(TAG, "Starting phase " + mCurrentPhase);

                    service.onBootPhase(mCurrentPhase);

启动Launcher

在PHASE_SYSTEM_SERVICES_READY 之后,SystemServer会调用AMS的systemReady的方法, 改方法中就回去执行startactivity的流程

//phase480 && 500
      mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
      mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
      
      ...
      mActivityManagerService.systemReady(() -> {

             //phase550
             mSystemServiceManager.startBootPhase(
                     SystemService.PHASE_ACTIVITY_MANAGER_READY);
             ...
             //phase600
             mSystemServiceManager.startBootPhase(
                     SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
          }
      }
    }
 public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
        traceLog.traceBegin("PhaseActivityManagerReady");
        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(currentUserId, "systemReady");

}

AMS的systemReady会先执行参数Runnable,主要执行几个servcie的systemRunning方法,之后会去启动Launcher,Launcher启动后,会回调AMS的activityIdle, 最终会调用到AMS的finishBooting(),进入阶段Phase1000。

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

推荐阅读更多精彩内容