系统相关
首页 > 系统相关> > Android 9(P) 核心服务和关键进程启动

Android 9(P) 核心服务和关键进程启动

作者:互联网

       Android P 核心服务和关键进程启动


前言

  在前面三个篇章Android P之init进程启动源码分析我们主要介绍了init进程启动,并在最后一个篇章中介绍了init进程执行Action的内容和顺序,并在boot 和 nonencrypted Action 中启动了 core、main、late-start class 的 service。本来想直接介绍一下最重要的的zygote服务,但是为了对Android P的整个启动流程有个更加深的理解,所以还是从整体上把控来介绍Android P核心服务和关键进程启动流程,后续再专门再写一个篇章或者系列介绍zygote进程启动的流程。本章节将重点介绍开机中比较关键的 service,这些service 异常将会导致开机失败。

注意:本文演示的代码是Android P高通msm8953平台源码。涉及的源码如下:

frameworks/native/services/surfaceflinger/*
frameworks/base/cmds/bootanimation/*
frameworks/base/cmds/app_process/*
frameworks/native/cmds/servicemanager/*
frameworks/base/services/core/java/com/android/server/SystemService.java
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/native/services/surfaceflinger/surfaceflinger.rc
frameworks/base/cmds/bootanimation/bootanim.rc
system/hwservicemanager/hwservicemanager.rc
system/hwservicemanager/*


一. Surfaceflinger服务的启动和bootanimation服务执行流程


1.1 Surfaceflinger服务的启动

  Android终端boot logo展示完毕以后,呈现给用户的就是开机动画了,开机动画从 surfaceflinger 进程启动后开始执行到launcher 启动完成后退出。那么在本章节中将来讲讲非常重要的surfaceflinger 服务的启动流程,仅仅是启动流程啊,因为surfaceflinger服务非常的复杂牵涉到Android的图像系统,这个太复杂了,我连门都没有入。我太难了。

  Surfaceflinager service属于class core,在init执行boot action阶段被启动,surfaceflinger如果因为异常启动则会触发zygote重启。所以在Android启动阶段如果出现zygote重启问题,可以关注下surfaceflinger是否启动正常。

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
    writepid /dev/stune/foreground/tasks
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

  Surfaceflinger 启动的定义的rc文件路径在frameworks/native/services/surfaceflinger/surfaceflinger.rc,surfaceflinger 服务的实现不是本篇文章介绍的重点,因为这个牵涉的东西太多了,感兴趣的可以自己查看相关资料.这里主要介绍 surfaceflinger 如何启动 bootanim service 的,即启动我们的开机动画流程。


1.2 Bootanim 服务执行流程

  Bootanim service也是定义在class core中的,但是它的默认状态是disable的,即在init执行boot action阶段不会被启动,其rc的配置如下所示:

#该文件定义在frameworks/base/cmds/bootanimation/bootanim.rc
service bootanim /system/bin/bootanimation
    class core animation
    user graphics
    group graphics audio
    disabled
    oneshot
    writepid /dev/stune/top-app/tasks

1.2.1 Bootanim 服务的启动

  那么bootanim究竟是那里启动的呢,众里寻他千百度,原来启动入口是在 surfaceflinger::init 方法中:

//该代码定义在frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中
void SurfaceFlinger::init() {
	......
	    // Inform native graphics APIs whether the present timestamp is supported:
    if (getHwComposer().hasCapability(
            HWC2::Capability::PresentFenceIsNotReliable)) {
        mStartPropertySetThread = new StartPropertySetThread(false);
    } else {
        mStartPropertySetThread = new StartPropertySetThread(true);
    }
    	property_get("vold.decrypt", voldDecryptBuf, "");
	if(!strcmp(voldDecryptBuf, "trigger_restart_framework")){
		//运行StartPropertySetThread
		if (mStartPropertySetThread->Start() != NO_ERROR) {
			ALOGE("Run StartPropertySetThread failed!");
		}
	}
	......
}

  让我们继续看下StartPropertySetThread做了些什么,该代码定义在frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp中:

status_t StartPropertySetThread::Start() {
    return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
}

bool StartPropertySetThread::threadLoop() {
    // Set property service.sf.present_timestamp, consumer need check its readiness
    property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
    // Clear BootAnimation exit flag
    property_set("service.bootanim.exit", "0");
    // Start BootAnimation if not started
    property_set("ctl.start", "bootanim");
    // Exit immediately
    //注意这里返回的是false,所以thredLoop只会执行一次,
    return false;
}

  通过对前面篇章对init进程启动的分析我们知道了ctl.start的功能,Android的设计者在这里是通过 propertyservice ctrl msg 启动 bootanim servce,并设置 service.bootanim.exit 为 0,该属性值决定开机动画是否退出。

  关于bootanimation的启动流程可以用下面的图示来客观的演示,这个流程并不是很复杂大伙可以自行学习,本文只是讲解关键进程的启动不涉及关键进程具体的分析。
在这里插入图片描述

1.2.2 Bootanim 服务的终止

  在BootAnimation的android()会重复播放 android 默认动画,并在每次播放后都执行 checkExit 来读取service.bootanim.exit 属性值,当 service.bootanim.exit 属性值为 1 时会执行 requestExit 将mExitPending 值设置为 ture,退出循环播放。Bootanim 执行结束退出。该代码定义在frameworks//base/cmds/bootanimation/BootAnimation.cpp中。

bool BootAnimation::android()
{
    ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
            elapsedRealtime());
    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");

    mCallbacks->init({});

    // clear screen
    glShadeModel(GL_FLAT);
    glDisable(GL_DITHER);
    glDisable(GL_SCISSOR_TEST);
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    eglSwapBuffers(mDisplay, mSurface);

    glEnable(GL_TEXTURE_2D);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
    const GLint yc = (mHeight - mAndroid[0].h) / 2;
    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);

    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
            updateRect.height());
    // Blend state
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    const nsecs_t startTime = systemTime();
    do {
        nsecs_t now = systemTime();
        double time = now - startTime;
        float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
        GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
        GLint x = xc - offset;

        glDisable(GL_SCISSOR_TEST);
        glClear(GL_COLOR_BUFFER_BIT);

        glEnable(GL_SCISSOR_TEST);
        glDisable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
        glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);
        glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);

        glEnable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);

        EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
        if (res == EGL_FALSE)
            break;

        // 12fps: don't animate too fast to preserve CPU
        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
        if (sleepTime > 0)
            usleep(sleepTime);

        checkExit();//检测是否需要退出
    } while (!exitPending());

    glDeleteTextures(1, &mAndroid[0].name);
    glDeleteTextures(1, &mAndroid[1].name);
    return false;
}

static const char EXIT_PROP_NAME[] = "service.bootanim.exit";

void BootAnimation::checkExit() {
    // Allow surface flinger to gracefully request shutdown
    char value[PROPERTY_VALUE_MAX];
    property_get(EXIT_PROP_NAME, value, "0");
    int exitnow = atoi(value);
    if (exitnow) {
        requestExit();
        mCallbacks->shutdown();
    }
}

  那这个service.bootanim.exit的值是啥时候被置为1的呢,这里就不卖关子了当 android 系统桌面应用被启动后并且进入 Idle 状态时会通知 surfaceflinger 将 service.bootanim.exit 设置为 1,这个过程就比较复杂了牵涉到adnroid App的启动,跨进程的通信等等(这里就不细讲了)。关于该流程的大致的流程图如下:
在这里插入图片描述

  让我们来直接看SurfaceFlinger::bootFinished函数,该代码定义在frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中。

void SurfaceFlinger::bootFinished()
{
    if (mStartPropertySetThread->join() != NO_ERROR) {
        ALOGE("Join StartPropertySetThread failed!");
    }
    const nsecs_t now = systemTime();
    const nsecs_t duration = now - mBootTime;
    ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );

    // wait patiently for the window manager death
    const String16 name("window");
    sp<IBinder> window(defaultServiceManager()->getService(name));
    if (window != 0) {
        window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
    }

    if (mVrFlinger) {
      mVrFlinger->OnBootFinished();
    }

    // stop boot animation
    // formerly we would just kill the process, but we now ask it to exit so it
    // can choose where to stop the animation.
    property_set("service.bootanim.exit", "1");//千山万水,终于到了这一步了,这里将关闭bootanim 

    const int LOGTAG_SF_STOP_BOOTANIM = 60110;
    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));

    sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
        readPersistentProperties();
        mBootStage = BootStage::FINISHED;
    });
    postMessageAsync(readProperties);
}

在该函数中我们可以看到将 属性service.bootanim.exit 设置为 1。通过前面的分支我们知道bootanim 进程在 checkExit 时检测到 service.bootanim.exit=1 时退出循环播放。所以如果在Android终端启动过程中中出现动画不结束的情况,可以根据上面的流程检测看是在那个环节出现了问题。



二. ServiceManager的启动

  关于servicemanager进程的功能和源码解析可以具体参考Android Binder入门指南之servicemanager守护进程,里面有详细的从源码和Binder角度讲解了servicemanager在Android系统中功能和作用,在这里只会简单的一笔带过,重点讲解启动流程。

  ServiceManager service属于class core,所以会在init执行boot action阶段被启动。servicemanager被称为服务总管,足见其在Android中的重要性,servicemanager的启动异常将会导致zygote,surfaceflinger,media主要系统服务重启。而且该service被标识为critical服务,当在4分钟内重启次数超过4次则系统将会进入recovery模式。ServiceManager 是Binder 机制的守护进程,用来管理 android 各种服务,并向 client 提供查询 server 远程接口的方法。

  Servicemanager的rc文件路径为frameworks/native/cmds/servicemanager/servicemanager.rc,其逻辑为:

    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm 
    onrestart restart cameraserver
    onrestart restart keystore
    onrestart restart gatekeeperd
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

2.1 ServiceManager功能简介

  虽然ServiceManager源码我们这里不重点分析,但是我们还是简单说一下该服务的基本功能,servicemanager的源码路径是frameworks/native/cmds/servicemanager/service_manager.c,其在启动过程中主要做了如下三件事:

int main(int argc, char** argv)
{
    struct binder_state *bs;
    union selinux_callback cb;
    char *driver;

    if (argc > 1) {
        driver = argv[1];
    } else {
        driver = "/dev/binder";
    }

    bs = binder_open(driver, 128*1024);
	......
    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
    ......
binder_loop(bs, svcmgr_handler); //进入binder循环

  Binder机制是Android系统的核心机制,同时也是想更深入学习Android系统必须克服的知识点之一,这个东西不是一两句话能解释清楚的,大家如果感兴趣可以参见Android Binder入门指南系列有非常详尽的分析。本文重点关注开机流程,不再展开。svcmgr_handler 提供了 search、add、get service 请求对应的处理方法。当客户端要与服务端进行通信时,首先通过 Service Manager 来查询和取得所要交互的服务。而每个服务也要向servicemanager 注册自己能提供的服务。而注册服务实际上是通过在本地创建sm代理BpServiceManager 并调用其 addService()函数实现的。



三. hwservicemanager的启动

  hwservicemanager是hidl服务管理中心,负责管理系统中的所有hidl服务,同样也是有init进程启动的。Hwservicemanager 的主程序实现在 system/hwservicemanager/service.cpp。它同样是一个很关键的 service,如果起不来,系统也会出现问题,看它的 rc 文件定义就知道:

service hwservicemanager /system/bin/hwservicemanager
    user system
    disabled
    group system readproc
    critical
    onrestart setprop hwservicemanager.ready false
    onrestart class_restart hal 
    onrestart class_restart early_hal
    writepid /dev/cpuset/system-background/tasks
    class animation
    shutdown critical

  ServiceManager 要先于所有其他 HIDL service 执行,否则所有其他 HIDL service 都获取不到 servicemanager,需要等待,并打印:

"Waited for hwservicemanager.ready for a second, waiting another..."

  也 就 是 其 它 的 HIDL service 都 要 等 到 hwservicemanager 执 行 并 设 置 prop:”hwservicemanager.ready”为 true 之后才可以执行。来看下这个 prop 何时会修改:

 int main() {
 ServiceManager *manager = new ServiceManager(); // IServiceManager 的子类

 if (!manager->add(serviceName, manager)) {
 ALOGE("Failed to register hwservicemanager with itself.");
 }
 //...
 rc = property_set("hwservicemanager.ready", "true");
 //...


四. zygote的启动

  凡事对Android系统有过一定了解的人,zygote对于Android系统意味着什么。Zygote 是 native 应用程序属于 class main,在 init 执行 nonencrypted action 阶段会被启动。Zygote 是所有 android java 进程的父进程,是 java 世界的入口,如果这些详细的展开来讲的话,那真的是几天几夜估计也将不会其中的知识点。我们只调重点的,它实现以下几个功能其基本流程图如下:
在这里插入图片描述
  zygote启动的rc文件如下所示,这个具体要看启动的是64位机器还是32位,定义在system/core/rootdir/init.zygote64_32.rc中:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    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
    onrestart restart vendor.servicetracker-1-0

  下面让我们对该流程图中的关键步骤,简要分析分析:


4.1 AndroidRuntime::startVm

  startVM该函数中主要是初始化 VM 的参数,然后接着调用JNI_CreateJavaVM创建 VM。需要重点关注其中 dalvik heapsize 的初始化,如果没有配置正确的参数或者使用默认的参数很有可能导致手机无法进入 Launcher。因为目前APP 占用的 heapsize 都比较大,使用默认参数很容易出现 OOM 导致应用不断重启。

    parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
    parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");

    parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
    parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
    parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
    parseRuntimeOption("dalvik.vm.heaptargetutilization",
                       heaptargetutilizationOptsBuf,
                       "-XX:HeapTargetUtilization=");

  这个值应该根据具体的Android终端硬件配置决定,我们的终端相关的值如下:

msm8953_64:/ # getprop | grep dalvik.vm.heap
[dalvik.vm.heapgrowthlimit]: [192m]
[dalvik.vm.heapmaxfree]: [8m]
[dalvik.vm.heapminfree]: [4m]
[dalvik.vm.heapsize]: [512m]
[dalvik.vm.heapstartsize]: [16m]
[dalvik.vm.heaptargetutilization]: [0.75]
msm8953_64:/ #

4.2 AndroidRuntime::startReg

  startReg该函数主要作用是注册 JNI 函数,遍历 gRegJNI 数组中 JNI register 方法注册 JNI method。注册JNI 方法后,会通过 JNI 调用 java class(zygoteInit)的 main 函数进入 java 世界。

int AndroidRuntime::startReg(JNIEnv* env)
{
	......

    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
	......
    return 0;
}


static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
            return -1;
        }
    }
    return 0;
}

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_util_SeempLog),
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
    REG_JNI(register_android_util_MemoryIntArray),
    REG_JNI(register_android_util_PathParser),
    REG_JNI(register_android_util_StatsLog),
    REG_JNI(register_android_app_admin_SecurityLog),
    REG_JNI(register_android_content_AssetManager),
    REG_JNI(register_android_content_StringBlock),
    REG_JNI(register_android_content_XmlBlock),
    REG_JNI(register_android_content_res_ApkAssets),
    REG_JNI(register_android_text_AndroidCharacter),
    REG_JNI(register_android_text_Hyphenator),
    REG_JNI(register_android_text_MeasuredParagraph),
    REG_JNI(register_android_text_StaticLayout),
    REG_JNI(register_android_view_InputDevice),
    REG_JNI(register_android_view_KeyCharacterMap),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_SystemProperties),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_os_Parcel),
    REG_JNI(register_android_os_HidlSupport),
    REG_JNI(register_android_os_HwBinder),
    ......
}


int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeFinishInit", "()V",
            (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
        { "nativeSetExitWithoutCleanup", "(Z)V",
            (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
        methods, NELEM(methods));
}

4.3 ZygoteInit

  在zygote启动阶段ZygoteInit主要完成了如下几件事情:

4.3.1 zygoteServer.registerServerSocketFromEnv

  通过获取环境变量值得到 zygote 文件描述符,根据该文件描述符创建 socket,用来和 ActivityManagerService 通信。AMS 通过 Process.start 来创建新的进程,而Process.start 会先通过 socket 连接到 zygote 进程,并最终由 zygote 完成进程创建。这里传入的-为-socket-name=zygote.

	private static final String SOCKET_NAME_ARG = "--socket-name=";
	public static void main(String argv[]) {
			....
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            zygoteServer.registerServerSocketFromEnv(socketName);
	......
}

  通过获取 ANDROID_SOCKET_ zygote 环境变量值得到 zygote 文件描述符,通过前面可知这里的描述符就是zygote,根据该文件描述符创建 socket 用来和 ActivityManagerService 通信。

    void registerServerSocketFromEnv(String socketName) {
        if (mServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                String env = System.getenv(fullSocketName);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                mServerSocket = new LocalServerSocket(fd);
                mCloseSocketFd = true;
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

ActivityManagerService 通过 Process.start 来创建新的进程,而 Process.start 会先通过socket 连接到 zygote 进程,并最终由 zygote 完成进程创建。如下是App进程创建请求Zygote创建新的进程。

//定义在frameworks/base/core/java/android/os/Process.java
    public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int runtimeFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String invokeWith,
                                  String[] zygoteArgs) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }


	//定义在frameworks/base/core/java/android/os/ZygoteProcess.java
    public final Process.ProcessStartResult start(final String processClass,
                                                  final String niceName,
                                                  int uid, int gid, int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  String seInfo,
                                                  String abi,
                                                  String instructionSet,
                                                  String appDataDir,
                                                  String invokeWith,
                                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
                    zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

    private Process.ProcessStartResult startViaZygote(final String processClass,
                                                      final String niceName,
                                                      final int uid, final int gid,
                                                      final int[] gids,
                                                      int runtimeFlags, int mountExternal,
                                                      int targetSdkVersion,
                                                      String seInfo,
                                                      String abi,
                                                      String instructionSet,
                                                      String appDataDir,
                                                      String invokeWith,
                                                      boolean startChildZygote,
                                                      String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
	......
	        synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
	......
}       


    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");

        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(mSocket);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
            maybeSetApiBlacklistExemptions(primaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
        }
        if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
        }

        // The primary zygote didn't match. Try the secondary.
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            try {
                secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
            }
            maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
        }

        if (secondaryZygoteState.matches(abi)) {
            return secondaryZygoteState;
        }

        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }                                               

4.3.2 preload预加载

  预加载类和资源,android Java 进程都是由 zygote 进程 fork,zygote 通过预加载类和资源可以加快子进程的执行速度和优化内存。因为预加载的类和资源较多,在开机优化过程中也需要重点关注 preload 的耗时。

    static void preload(TimingsTraceLog bootTimingsTraceLog) {
        beginIcuCachePinning();
        preloadClasses();//预加载Class文件
        preloadResources();//预加载Resource文件
        nativePreloadAppProcessHALs();
        preloadOpenGL();
        preloadSharedLibraries();
        preloadTextResources();
        WebViewFactory.prepareWebViewInZygote();
        endIcuCachePinning();
        warmUpJcaProviders();
    }
[Landroid.accounts.Account;
[Landroid.animation.Animator;
[Landroid.animation.Keyframe$FloatKeyframe;
[Landroid.animation.Keyframe$IntKeyframe;
[Landroid.animation.Keyframe$ObjectKeyframe;
[Landroid.animation.Keyframe;
[Landroid.animation.PropertyValuesHolder;
[Landroid.app.LoaderManagerImpl;
[Landroid.content.ContentProviderResult;
[Landroid.content.ContentValues;
[Landroid.content.Intent;
[Landroid.content.UndoOwner;
[Landroid.content.pm.ActivityInfo;
[Landroid.content.pm.ConfigurationInfo;
[Landroid.content.pm.FeatureGroupInfo;
[Landroid.content.pm.FeatureInfo;
[Landroid.content.pm.InstrumentationInfo;
[Landroid.content.pm.PathPermission;

4.3.3 forkSystemServer

  启动 system_server 进程,android java 系统服务都将驻留在该进程
中。是android framework核心。设置systemserver 进程uid和gid,process name,class name。

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_PTRACE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG,
            OsConstants.CAP_WAKE_ALARM,
            OsConstants.CAP_BLOCK_SUSPEND
        );
        /* Containers run without some capabilities, so drop any caps that are not available. */
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data;
        try {
            data = Os.capget(header);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to capget()", ex);
        }
        capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);

        /* Hardcoded command line to start the system server */
        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",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer) {
                parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }


五. SystemServer的启动

  上面介绍了 SystemServer 的实际进程名是 system_server。我们可以在Android终端中通过ps命令进行查看:

msm8953_64:/ # ps | grep system_server
system    1429  794   2375836 137000 SyS_epoll_ 0000000000 S system_server
msm8953_64:/ #

System_server 作为 zygote fork的第一个进程,不言而喻具很重要。如果 system_server 退出也会导致 zygote 进程退出,具体的处理是在 Zygote Sigchldhandler 中。具体看下 com.android.server.SystemServer的入口函数:

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

run 方法中主要是启动 Android 系统服务,即我么App开发中用到的各种服务很多是在这里的。

    private void run() {
       
        	......
         // Start services.
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();//开机相关服务
            startCoreServices();//核心服务
            startOtherServices();//其他服务
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }       	
        	......

Android又将 service 分为三个等级,开机相关服务、核心服务和其他服务,下面让我们分别介绍:


5.1 BootStrap Services

  既然是开机相关服务,重要性就不言而喻了。其服务有如下几个:


5.2 CoreService

  既然是核心服务,也必须是非常重要的服务了。

5.3 OtherService

  这里的服务并不是说不重要,而是可以根据实际情况进行想对应的裁剪。

StartOtherService()最后调用 ActivityManagerService.SystemReady() 启动 Home 进程,发送 ACTION_BOOT_COMPLETED Intent。



总结

  随着Android版本越高,Android的工作量也是越来越大了,分析起来不得不使出吃奶的力气了,本篇只是从整体上讲述了Android核心服务和关键进程启动的流程,至于想要详细的分析那就不是能一天两天能做到的了。需要大家孜孜不倦的苦干了。



写在最后

  Android 9§ 核心服务和关键进程启动的告一段落了,不容易啊分析起来,在接下来的篇章我们将继续讲解Android P启动中非常重要的一个进程zygote启动流程。如果对给位有帮助欢迎点赞一个,如果写得有问题也欢迎多多指正。未完待续,下个篇章再见。

标签:String,service,启动,system,zygote,JNI,进程,Android,android
来源: https://blog.csdn.net/tkwxty/article/details/106496548