SystemServer启动

本文基于安卓6.0源码,对systemserver进程的启动与管理的基本过程进行介绍。
从Zygote进程初始化ZygoteInit.main()中调用startSystemServer()fork出子进程开始。
SystemServer负责启动和管理整个java framework,包含ActivityManager,WindowManager,PackageManager以及PowerManager等。

在一号进程init(),解析init.rc文件,并启动其中的Zygote服务,会调用ZygoteInit.main()方法,在其中先fork出SystemServer进程,fork出进程之后根据pid分别处理子进程与父进程。在子进程中将复制过来的socket关闭(fork规则:读时共享,写时复制)。

init完成之后,抛出ZygoteInit.MethodAndArgsCaller(m, argv)异常后,抓取该异常执行到caller.run()然后反射调用SysemServer.main()方法启动SystemServer。

在SysemServer.main()中,会直接调用SystemServer.run()方法启动SystemServer。

Start! GO

1、SystemServer启动概览

SystemServer.run()方法中会调用到SystemServer启动的全部方法,最重要的几点步骤总结如下:

  1. 准备主线程Looper
  2. 加载android_servers.so库
  3. 初始化系统上下文
  4. 启动80多种系统服务
  5. 进入Looper.loop()状态,等待其他线程通过handler发送消息到主线再进行处理。
SystemServer.java
    private void run() {
        //设置最早时间戳,不能早于1970年。安卓时间戳的计算是从1970年开始的。
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }
 
       //设置语言相关
        if (!SystemProperties.get("persist.sys.language").isEmpty()) {
            final String languageTag = Locale.getDefault().toLanguageTag();
 
            SystemProperties.set("persist.sys.locale", languageTag);
            SystemProperties.set("persist.sys.language", "");
            SystemProperties.set("persist.sys.country", "");
            SystemProperties.set("persist.sys.localevar", "");
        }
 
        //正式开始SystemServer进程的启动,Here we go!
      
        Slog.i(TAG, "Entered the Android system server!");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
...
 
        //确保当前系统进程的binder调用,总是运行在前台优先级(foreground priority)
        BinderInternal.disableBackgroundScheduling(true);
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
 
        //1:准备主线程Looper
        Looper.prepareMainLooper();
 
        //2:加载android_servers.so库
        System.loadLibrary("android_servers");
 
        //检测上次关机过程是否失败,该方法可能不会返回
        performPendingShutdown();
 
        //3:初始化系统上下文
        createSystemContext();
 
        // 创建系统服务管理(mSystemServiceManager),并将该管理加入到本地服务(LocalServices)
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
 
        //4:启动服务
        //启动引导服务也可以说是关键服务,最重要的服务。包括AMS,PKMS,DisplayManagerService等。核心服务与其他服务会被这些服务所依赖,所以需要先启动这些引导服务。startBootstrapServices()
        //启动核心服务,包括WindowManagerService,InputManagerService等。
        //启动其他的服务,startOtherServices()
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }
...
 
        //5:进入Looper.loop()状态,等待其他线程通过handler发送消息到主线再进行处理。
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

2、初始化系统上下文

SystemServer.createSystemContext()
private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
//设置一下系统主题
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

2.1 ActivityThread activityThread = ActivityThread.systemMain()

ActivityThread.systemMain()
    public static ActivityThread systemMain() {
//低内存上不开启硬件加速,因为会增加过多的开销。这里可以不必在意,关注系统上下文初始化过程即可。
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(true);
        } else {
            HardwareRenderer.enableForegroundTrimming();
        }
 
        ActivityThread thread = new ActivityThread();
//这里thread.attach(true),ActivityThread的attach函数是任何进程创建过程中都会调用的。
//需要注意的是,app创建时调用的是attach(false),进入attach()函数之后,会根据是否是系统进程判断,执行逻辑会大不相同。
        thread.attach(true);
        return thread;
    }

下面看一下attach函数,这里仅需要了解即可。我会在application的启动过程中详细介绍attach流程。

  1. 创建mInstrumentation
  2. 创建appContenx
  3. 创建application
ActivityThread.attach()
private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
 //如果是用户进程,这里会直接调用AMS的代理的attachApplication(mAppThread)。把自身的mApplicationThread类型的成员变量(mAppThread),直接传递过去。
 //这里还是关注系统进程的执行逻辑
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
//1:先创建一个mInstrumentation,它是ActivityThread的成员,每一个ActicityThread对象都有一个mInstrumentation。
//我的理解是,使用该类可以去控制和观察application及activity生命周期。
//这里知道一下即可,不必要太关注。
                mInstrumentation = new Instrumentation();
//2:创建appContenx,ContextImpl类是Activity.java,ContextWrapper.java中方法的实现类。
//比如startActivity(),start/bindService(),sendBroadcast()等方法都是在该类中实现的。
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
//3:然后是makeApplication,即创建application。
//每一个进程只有一个application,可以在makeApplication()中看到,如果application不为空,会直接返回,而不会新创建application。
//这里暂时还不是特别明白,以后再深究。
//在makeApplication()调用了 instrumentation.callApplicationOnCreate(app),这里调用了onCreate()实际上调用的application.onCreate(),以后再深究吧。
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }
...
 }

2.2 mSystemContext = activityThread.getSystemContext()

创建系统上下文,简单的单例模式。

ActivityThread.getSystemContext()
//简单的单例模式,创建系统上下文   
public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                mSystemContext = ContextImpl.createSystemContext(this);
            }
            return mSystemContext;
        }
    }

3、启动服务

启动服务过程中,安卓将这些服务分为3类。

  • 第一类:startBootstrapServices(),启动系统关键服务。这些服务是安卓系统中最关键的服务,其他服务可能依赖于这些服务的创建,是开机启动中最紧急需要启动的服务。
  • 第二类 :startCoreServices(),启动核心服务。系统中的核心服务,缺少这些服务手机基本无法使用。
  • 第三类:startOtherServices(),启动其余的服务。除非必要,我们自己开发的普通系统服务都应该放在这里启动。

在这些服务的最后,一定都会调用serviceManager.addService()方法,将这些服务注册到serviceManager中,等待调用。

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

推荐阅读更多精彩内容