源码探索系列32---万物初生System Servers

不知你是否也和我一样,会好奇整个系统给的启动过程是怎样的?
今天我们先来看下整个过程重要的一个环节SystemServer的内容
enter image description here

如图所示,在系统启动好,到了第4步的时候
首先,Zygote进程由init进程解析init.rc文件后fork生成。(Zygote进程主要为加载ZygoteInit类、注册Zygote Socket服务端套接字、加载虚拟机、preloadClasses、preloadResouces等),
然后Zygote进程forkSystem Server进程。System Server进程很重要,负责启动和管理整个Framework内容,包括ActivityManagerPowerManager等服务。
接着, 在孵化出上面的SystemServer 后,孵化出的第一个App进程是Launcher,就是我们的桌面; 除此之外,它还会创建各种系统App,例如电话phone,信息Message等程序。


上面作为整个流程的大致介绍,现在我们就来看下SystemServer的内容吧!

前进

API:23

让我们先从他的启动开始说起吧,在ZygoteInit里面

public static void main(String argv[]) {

  RuntimeInit.enableDdms();//启动DDMS,这个名字熟悉吧?
  boolean startSystemServer = false;
   String socketName = "zygote";

    String abiList = null;
    for (int i = 1; i < argv.length; i++) {
        if ("start-system-server".equals(argv[i])) {
            startSystemServer = true;
        } 
        ...
    }  
    ...
    if (startSystemServer) {
        startSystemServer(abiList, socketName);
    }  
}

这是启动SystemServer的起点

 private static boolean startSystemServer(String abiList, String socketName)
        throws MethodAndArgsCaller, RuntimeException {

    long capabilities = posixCapabilitiesAsBits(
        OsConstants.CAP_BLOCK_SUSPEND,
        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_RESOURCE,
        OsConstants.CAP_SYS_TIME,
        OsConstants.CAP_SYS_TTY_CONFIG
    );

    /* 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,1032,3001,3002,3003,3006,3007",        
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer", //<--重要参数
        //非常的显示的说到这个类是要被用到的。
    };

    ZygoteConnection.Arguments parsedArgs = null;


    int pid;  
    parsedArgs = new ZygoteConnection.Arguments(args);
    ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
    ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

    /* Request to fork the system server process */
    pid = Zygote.forkSystemServer(
            parsedArgs.uid, parsedArgs.gid,
            parsedArgs.gids,
            parsedArgs.debugFlags,
            null,
            parsedArgs.permittedCapabilities,
            parsedArgs.effectiveCapabilities);                
    //孵出子进程system_server

    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        //Finish remaining work for the newly forked system 
        //server process.//我们的主线2
        handleSystemServerProcess(parsedArgs);
    }
    return true;

}

我们看下叫Zygote类的内容

 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;

}

通过native层去fork我们的SystemServer。那么他的native最后跑到哪里去呢?
frameworks/base/core/jni/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) {

  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                          debug_flags, rlimits,
                                          permittedCapabilities, 
                                          effectiveCapabilities,
                                          MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, 
                                          NULL,NULL, NULL);
        ...
      return pid;
}

嗯,跳去另外一个

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();
      //fork子进程
      pid_t pid = fork();

    if (pid == 0) {

      ...

      env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
                              is_system_server ? NULL : instructionSet);
      ...                       
    } else if (pid > 0) {
        // the parent process
    }

    return pid;
}

int register_com_android_internal_os_Zygote(JNIEnv* env) {

  gZygoteClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteClassName));
  gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, 
  "callPostForkChildHooks","(ILjava/lang/String;)V");

  return RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, 
                              NELEM(gMethods));
}                                

主要是创建工作,我们回头看下主线2handleSystemServerProcess()的内容

/**
 * Finish remaining work for the newly forked system server process.
 */
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs){

       ...

        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            // If we have a non-null system server class path,  we'll have to 
            //duplicate the existing arguments and append the classpath to it. 
            //ART will handle the classpath correctly when we exec a new process.

            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 {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = new PathClassLoader(systemServerClasspath, 
                ClassLoader.getSystemClassLoader());

                Thread.currentThread().setContextClassLoader(cl);
            } 

             // Pass the remaining arguments to SystemServer.                  
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, 
                                            parsedArgs.remainingArgs, cl);

        }     

    }

没什么好说的,继续看下RuntimeInit.zygoteInit()的内容

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader){ 

      ...
    commonInit();//一些初始化工作
    nativeZygoteInit(); //跳来跳去...看得好累..zygote初始化
    applicationInit(targetSdkVersion, argv, classLoader);       
}

private static final void commonInit() {
    if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

    /* set default handler; this applies to all threads in the VM */
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

    /*
     * Install a TimezoneGetter subclass for ZoneInfo.db
     */
    TimezoneGetter.setInstance(new TimezoneGetter() {
        @Override
        public String getId() {
           //哈,获取时区居然是硬编码在这里
            return SystemProperties.get("persist.sys.timezone");
        }
    });
    TimeZone.setDefault(null);

    /*
     * Sets handler for java.util.logging to use Android log facilities.
     * The odd "new instance-and-then-throw-away" is a mirror of how
     * the "java.util.logging.config.class" system property works. We
     * can't use the system property here since the logger has almost
     * certainly already been initialized.
     */
    LogManager.getLogManager().reset();
    new AndroidConfig();

    /*
     * Sets the default HTTP User-Agent used by HttpURLConnection.
     * 
     * getDefaultUserAgent() Returns an HTTP user agent of the form
     * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MASTER)". 
     */         
    String userAgent = getDefaultUserAgent();
    System.setProperty("http.agent", userAgent);

    /*
     * Wire socket tagging to traffic stats.
     */
    NetworkManagementSocketTagger.install();

    /*
     * If we're running in an emulator launched with "-trace", put the
     * VM into emulator trace profiling mode so that the user can hit
     * F9/F10 at any time to capture traces.  This has performance
     * consequences, so it's not something you want to do always.
     */
    String trace = SystemProperties.get("ro.kernel.android.tracing");
    if (trace.equals("1")) {
        Slog.i(TAG, "NOTE: emulator trace profiling enabled");
        Debug.enableEmulatorTraceOutput();
    }

    initialized = true;
}

我们的曙光终于来了

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {

    // If the application calls System.exit(), terminate the process
    // immediately without running any shutdown hooks.  It is not possible to
    // shutdown an Android application gracefully.  Among other things, the
    // Android runtime shutdown hooks close the Binder driver, which can cause
    // leftover running threads to crash before the process actually exits.
    nativeSetExitWithoutCleanup(true);

    // We want to be fairly aggressive about heap utilization, to avoid
    // holding on to a lot of memory that isn't needed.
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

    final Arguments args;
    try {
        args = new Arguments(argv);
    } catch (IllegalArgumentException ex) {
        Slog.e(TAG, ex.getMessage());
        // let the process exit
        return;
    }

    // The end of of the RuntimeInit event (see #zygoteInit).
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    // Remaining arguments are passed to the start class's static main
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
    //最后这句是线索. 
}

invokeStaticMain()

private static void invokeStaticMain(String className, String[] argv,
                                     ClassLoader classLoader){

     //在startSystemServer()的硬编码初始化参数列表中,我有提到过一次总要参数
    //显然此处args.startClass就是"com.android.server.SystemServer"啦!

    Class<?> cl= Class.forName(className, true, classLoader);
    Method m= cl.getMethod("main", new Class[] { String[].class });
    ...

    /*
     * This throw gets caught in ZygoteInit.main(), which responds
     * by invoking the exception's run() method. This arrangement
     * clears up all the stack frames that were required in setting
     * up the process.
     * 这原因可以!以抛异常来搞,不看注释我也奇怪为了结尾怎么是这样
     */
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

这样我们来看下main函数的内容

public static void main(String argv[]) {

     try{
            RuntimeInit.enableDdms();
              // Start profiling the zygote initialization.
              SamplingProfilerIntegration.start();
            ...

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } 
                ...
            }
            ...


            //终于!!!!!!!!!!!
            if (startSystemServer) {
               startSystemServer(abiList, socketName);
             }

    } catch (MethodAndArgsCaller caller) {
            caller.run(); //重要的一句!!!!
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
     ...

}

我们去看下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.Main()

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

private void run() {

    if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
        Slog.w(TAG, "System clock is before 1970; setting to 1970.");
        SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        //初始最小时间为1970年!
    }

    // Here we go! 是的,俺老孙来也
    Slog.i(TAG, "Entered the Android system server!");
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());

       //6.0用libart.so
     SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

    // Enable the sampling profiler.
    if (SamplingProfilerIntegration.isEnabled()) {
        SamplingProfilerIntegration.start();
        mProfilerSnapshotTimer = new Timer();
        //一小时采集一次的分析器。
        mProfilerSnapshotTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                SamplingProfilerIntegration.writeSnapshot("system_server", null);
            }
        }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
    }

    // Mmmmmm... more Mmmmmmmm...memory!
    VMRuntime.getRuntime().clearGrowthLimit();

    // The system server has to run all of the time, so it needs to be
    // as efficient as possible with its memory usage.
    //设置内存的使用率是0.8,尴尬的内存,以后6G内存普及就会好点了
    VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

    // Some devices rely on runtime fingerprint generation, so make sure
    // we've defined it before booting further.
    Build.ensureFingerprintProperty();

    // Within the system server, it is an error to access Environment paths without
    // explicitly specifying a user.
    Environment.setUserRequired(true);

    // Ensure binder calls into the system always run at foreground priority.
    BinderInternal.disableBackgroundScheduling(true);

    // Prepare the main looper thread (this thread).
    android.os.Process.setThreadPriority(
            android.os.Process.THREAD_PRIORITY_FOREGROUND);
    android.os.Process.setCanSelfBackground(false);
    Looper.prepareMainLooper();

    // Initialize native services.
    System.loadLibrary("android_servers");

    // Check whether we failed to shut down last time we tried.
    // This call may not return.
    //检测上次关机过程是否失败
    performPendingShutdown();

    // Initialize the system context. 
    createSystemContext();

    // Create the system service manager.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

    // Start services.
    //重要的内容,启动引导,核心等服务
    startBootstrapServices();
    startCoreServices();
    startOtherServices();       

    ...
    // Loop forever.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

想说的是最后面的start service 的三个函数内容

 /**
 * Starts the small tangle of critical services that are needed to get
 * the system off the ground.  These services have complex mutual dependencies
 * which is why we initialize them all in one place here.  Unless your service
 * is also entwined in these dependencies, it should be initialized in one of
 * the other functions.
 * 注释说明了为什么一次性的在这里初始这么多service的原因
 * 打头阵都是有点原因哈,需要给别人提供服务
 */
private void startBootstrapServices() {

    // Wait for installd to finish starting up so that it has a chance to
    // create critical directories such as /data/user with the appropriate
    //就是等和installd建立socket通道
    Installer installer = mSystemServiceManager.startService(Installer.class);

   //启动AMS,对他熟悉了
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);



    //电源管理部分,这个我还没看过,他需要早点启动因为别的服务需要它
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

  //嗯,为何不是PMS自己初始自己呢?稍后细看
    mActivityManagerService.initPowerManagement();

    // 负责LEDs 、背光灯部分的服务
    mSystemServiceManager.startService(LightsService.class);

    // Display manager is needed to provide display metrics before package manager
    // starts up.
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    // We need the default display before we can initialize the package manager.
    mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

    // 加密设备是只运行核心的内容,嗯,没加密过
    String cryptState = SystemProperties.get("vold.decrypt");
    if (ENCRYPTING_STATE.equals(cryptState)) {
        Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        Slog.w(TAG, "Device encrypted - only parsing core apps");
        mOnlyCore = true;
    }

    // PMS,最近也经常遇到他
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();

 //UMS内容,目录:/data/user
    ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());

    // Initialize attribute cache used to cache resources from packages.
    AttributeCache.init(mSystemContext);

    // Set up the Application instance for the system process and get started.
    mActivityManagerService.setSystemProcess();

    // The sensor service needs access to package manager service, app ops
    // service, and permissions service, therefore we start it after them.
    //因为SensorService需要PMS的服务等,所以被安排到最后面
    startSensorService();
}

我们看完这个,核心就是一堆的AMS,PMS,LS,DMS,PMS,UMS和Sensor的初始化。具体的启动过程代码即不贴了,很长,也很复杂。

然后我们继续看另外两个函数的内容

    /**
 * Starts some essential services that are not tangled up in the bootstrap process.
 */
private void startCoreServices() {

    // Tracks the battery level.  Requires LightService.
    //计算电池容量的,需要LS,所以前面先启动了
    mSystemServiceManager.startService(BatteryService.class);

    // Tracks application usage stats.
    mSystemServiceManager.startService(UsageStatsService.class);
    mActivityManagerService.setUsageStatsManager(
            LocalServices.getService(UsageStatsManagerInternal.class));
    // Update after UsageStatsService is available, needed before performBootDexOpt.
    mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

    // Tracks whether the updatable WebView is in a ready state and watches for update installs.
    mSystemServiceManager.startService(WebViewUpdateService.class);
}

然后那个启动别的服务的函数800行的代码,呵呵,不敢贴上来
主要也是启动服务,包括:CameraService,AudioAservice,VibratorService等等

小结

好吧,总算大致的看了下这个启动过程的一个节点SystemServer的内容
赫,感觉和看那些内核解析/情景源码解析书类似。贴一堆的代码。呵呵

Surreal Numbers
看这部分代码,让我想起了一本书,高德纳的Surreal Numbers

热评文章