源码分析Android SystemServer进程的启动过程

最近复习了柯元旦老师的《Android内核剖析》,获益良多。所以想从自己的钻研出发,走一遍柯老师走过的路。我看的《Android内核剖析》版本是基于Android2.3系统来写的,因为我尝试从Android5.1系统再钻研一遍书籍中所钻研过的知识点。

本文将尝试从源码分析SystemServer进程的启动过程,Ams,Wms及其他常用到的服务的创建,以及打开第三方应用的启动过程。

一、SystemServer进程的启动
SystemServer听名字就知道是个非常重要的进程,它是Android Framework启动后fork的第一个进程,可见其重要性。那么该进程在跑什么东西呢?主要是一些系统服务,例如我们常听说的Ams(ActivityManagerService)和Wms(WindowManagerService)。

SystemServer的启动入口在ZygoteInit.java的main函数中。ZygoteInit是Zygote进程加载的第一个类,Zygote进程则是所有Apk应用进程的父进程,所有应用进程都是由Zygote进程fork出来。

从源码开始着手,我们只关心SystemServer相关的部分,ZygoteInit.java:

public static void main(String argv[]) {
        try {
            // 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());
                } 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 (startSystemServer) {
                startSystemServer(abiList, socketName);           ②
            }

            ...
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

先看看main函数的参数,它的参数来自启动Zygote的命令,该命令在于系统根目录下的init.rc文件中,其中有一行是:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote -- start-system-server

该行的意思是调用/system/bin/下的app_process命令(或工具),并且后面一串就是其主要参数。

该命令的源码在/frameworks/base/cmds/app_process/app_main.cpp里,我们跟进去看看主要部分:

int main(int argc, char* const argv[])
{
    ...

    // Parse runtime arguments. Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++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;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));        ②
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args);        ③
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

看上面标注①的地方:如果有参数是”–start-system-server”,那么变量startSystemServer被置为true,从我们调用的命令来看,这么为true;

标注②:如果startSystemServer为true,那么变量args将添加”start-system-server”这个字符串。我们从变量名args可以猜测到这个变量是保存一些启动参数的。

标注③:毫无疑问这里会启动”com.android.internal.os.ZygoteInit”这个类并且带有参数args,如果一来就会辗转到ZygoteInit的main函数里,并且带有args的参数。

OK,终于明白ZygoteInit的main函数的参数有什么东东,接下来回到该类的main方法里:

public static void main(String argv[]) {
        try {
            // 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());
                } 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 (startSystemServer) {
                startSystemServer(abiList, socketName);           ②
            }

            ...
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

标注①:正如刚才分析的,这里的参数是含有”start-system-server”这个字符串,所以此处startSystemServer变量被置为true;

标注②:调用接口startSystemServer();

终于看到启动SystemServer的地方了:

    /** * Prepare the arguments and fork for the system server process. */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        ...
        /* 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,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            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);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);        ③
        }

        return true;
    }

标注①:为SystemServer创建一些启动参数,注意这个参数,后面启动会用到。并且从参数可以知道,SystemServer的uid是1000,gid是1000还有一些相关信息都被硬编码的方式编写在此。(一般情况每一个apk应用都有唯一一个uid,用于区分,系统服务如Ams也会根据uid来判断应用的权限,一般uid=1000及其他一些系统的uid程序拥有很多系统权限,uid=0代表root用户)

标注②:重头戏来了!调用Zygote.forkSystemServer()接口fork一个SystemServer进程。fork是linux系统创建子进程的重要方法,其作用是复制当前进程,创建一个新的进程,但是其进程id不相同。当该方法返回值等于0时,代表是创建的新进程。
跟踪进去Zygote.forkSystemServer()接口,发现其调用了JNI的native方法,所以不跟进去,大概流程就是创建了一个新的进程。

标注③:正如上面所说,返回值等于0代表是创建了新的进程,也就是子进程,此时将会调用handleSystemServerProcess()方法去完成SystemServer的创建。

再跟进去该方法:

/** * Finish remaining work for the newly forked system server process. */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
...
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
        }

        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,
                    null, args);
        } else {
          ...
        }

        /* should never reach here */
    }

标注①:此处会调用WrapperInit.execApplication()方法,不断跟踪进去,会发现其最终调用的代码在于RuntimeInit类中:

RuntimeInit.java:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        /* * 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方法。还记得上面创建SystemServer时有创建一堆参数,其最后一个参数是”com.android.server.SystemServer”。没错这个参数辗转最后会作为RuntimeInit.invokeStaticMain()方法的参数,所以这里会反射”com.android.server.SystemServer”该类,并执行其main函数,也就是创建了SystemServer进程后,执行其SystemServer类的main函数。

至此,SystemServer进程的启动过程已大致分析完成。

二、创建Ams、Wms等主要系统服务
这部分源码相对比较简单,主要就是SystemServer中调用的接口。

继续上部分的代码,这里会进入SystemServer的main函数:

/** * The main entry point from zygote. */
    public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }

    private void run() {
        // If a device's clock is before 1970 (before 0), a lot of
        // APIs crash dealing with negative numbers, notably
        // java.io.File#setLastModified, so instead we fake it and
        // hope that time from cell towers or NTP fixes it shortly.
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());

        // In case the runtime switched since last boot (such as when
        // the old runtime was removed in an OTA), set the system
        // property so that it is in sync. We can't do this in
        // libnativehelper's JniInvocation::Init code where we already
        // had to fallback to a different runtime because it is
        // running as root and we need to be the system user to set
        // the property. http://b/11463182
        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 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.
        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");
        nativeInit();        ②

        // 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.
        try {
            startBootstrapServices();         ⑤
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {
            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }

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

标注①:准备主线程(也就是正在运行的线程)的Looper;
标注②:native调用,该方法的注释是Called to initialize native system services.

标注③:创建SystemServer的Context,后面继续分析;
标注④:创建SystemServiceManager,其作用就是创建并管理系统服务的生命周期;
标注⑤:
startBootstrapServices();
startCoreServices();
startOtherServices();
连续调用了三个接口,这三个接口正是创建了我们常见的各种系统服务,后面继续分析;
标注⑥:Looper开始循环,等待消息执行。

我们看看SystemServer的Context创建过程:

private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

调用了ActivityThread.systemMain():

    public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(true);
        } else {
            HardwareRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }

从这里可以看出SystemServer与普通Apk程序的创建还是很不相同,SystemServer的ActivityThread 是通过ActivityThread 的静态方法systemMain()创建,做了一些简单处理如设置无硬件加速等。不过同样的,其最终还是会调用attach方法,不同的是,普通apk程序调用的是attch(false),那么创建过程肯定也会大不一样。这里就不分析了,继续代码。

mSystemContext = activityThread.getSystemContext()会调用getSystemContext方法,然后里面又会调用ContextImpl.createSystemContext的方法:

    static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread,
                packageInfo, null, null, false, null, null);
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
        return context;
    }

对比创建Activity的Context,发现会有一些不同:

    static ContextImpl createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, IBinder activityToken) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        if (activityToken == null) throw new IllegalArgumentException("activityInfo");
        return new ContextImpl(null, mainThread,
                packageInfo, activityToken, null, false, null, null);
    }

其不同性,这里不分析,至此SystemServer的Context已经创建好。

回到SystemServer.main()最重要的部分,创建系统服务,跟踪分析其三连调用
startBootstrapServices();
startCoreServices();
startOtherServices();:

    /** * 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. */
    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
        // permissions. We need this to complete before we initialize other services.
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

        // Power manager needs to be started early because other services need it.
        // Native daemons may be watching for it to be registered so it must be ready
        // to handle incoming binder calls immediately (including being able to verify
        // the permissions for those calls).
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // Now that the power manager has been started, let the activity manager
        // initialize power management features.
        mActivityManagerService.initPowerManagement();

        // 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);

        // Only run "core" apps if we're encrypting the device.
        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;
        }

        // Start the package manager.
        Slog.i(TAG, "Package Manager");
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();

        Slog.i(TAG, "User Service");
        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();
    }

    /** * Starts some essential services that are not tangled up in the bootstrap process. */
    private void startCoreServices() {
        // Manages LEDs and display backlight.
        mSystemServiceManager.startService(LightsService.class);

        // Tracks the battery level. Requires LightService.
        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);
    }

    /** * Starts a miscellaneous grab bag of stuff that has yet to be refactored * and organized. */
    private void startOtherServices() {
        final Context context = mSystemContext;
        AccountManagerService accountManager = null;
        ContentService contentService = null;
        VibratorService vibrator = null;
        IAlarmManager alarm = null;
        MountService mountService = null;
        NetworkManagementService networkManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        ConnectivityService connectivity = null;
        NetworkScoreService networkScore = null;
        NsdService serviceDiscovery= null;
        WindowManagerService wm = null;
        BluetoothManagerService bluetooth = null;
        UsbService usb = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        CommonTimeManagementService commonTimeMgmtService = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        AudioService audioService = null;
        MmsServiceBroker mmsService = null;
        ...
}

其实就是创建并用SystemServiceManager或者ServiceManager管理着这些服务。注意,以前是没有SystemServiceManager,全部服务都是由ServiceManager进行管理的,官方这样修改的意图是什么还需要后续去研究。

上面的代码可以看到我们经常通过Context.getSystemService常用的一些Manager都这里创建了。

至此该部分的研究暂一段落。

三、普通Apk应用程序的启动过程
请看下一篇《源码分析Android 应用进程的启动过程》

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/scnuxisan225/article/details/49515183
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞