Android 启动之SystemServer启动步骤

在上一篇文章中我们说到,init进程fork 出了 Zygote 进程,Zygote进程接着会fork 出SystemServer,SystemServer 是Android框架服务进程,负责启动各种java框架服务,现在我们跟一跟它的启动流程,一探究竟。

ZygoteInit.java frameworks\base\core\java\com\android\internal\os

ZygoteServer.java frameworks\base\core\java\com\android\internal\os

    public static void main(String argv[]) {
    …………
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//调用fork 启动进程

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {  //子进程 即systemServer ,运行runable 后就反回了
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);  // 如果是 zygote ,那么进入无线的loop,等待AMS发送socket通信
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();  //zygote fork 出的子进程(systemServer走不到这里),关闭socket
            }
        }
        …………
        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run(); //调用子进程的main函数,进入子进程
        }
    }

    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,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteArguments(args);//解析啥的
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            if (Zygote.nativeSupportsTaggedPointers()) {
                /* Enable pointer tagging in the system server. Hardware support for this is present
                 * in all ARMv8 CPUs. */
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
            }

            /* Enable gwp-asan on the system server with a small probability. This is the same
             * policy as applied to native processes and system apps. */
            parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;

            if (shouldProfileSystemServer()) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process 正式fork 出子进程*/
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {//如果是systemServer 关闭socket,
            if (hasSecondZygote(abiList)) { //判断ABI是否正确
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket(); //关闭 systemServer 的socket 
            return handleSystemServerProcess(parsedArgs);//进入
        }

        return null;
    }




这是一个JNI方法,进入 com_android_internal_os_Zygote.cpp ,基本上是调用C++方法fork 出子进程,然后把pid反回回去。


    static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();

        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities); //可以看到这里调用的是native方法

        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

        ZygoteHooks.postForkCommon();
        return pid;
    }


接着看 ZygoteInit.java —— forkSystemServer 里的 handleSystemServerProcess,它的返回值是一个runable,意思是做一些预处理,然后找到 SystemServer 的main方法反回回去执行。

    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName);
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
            // Capturing profiles is only supported for debug or eng builds since selinux normally
            // prevents it.
            if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                try {
                    Log.d(TAG, "Preparing system server profile");
                    prepareSystemServerProfile(systemServerClasspath);
                } catch (Exception e) {
                    Log.wtf(TAG, "Failed to set up system server profile", e);
                }
            }
        }

        if (parsedArgs.mInvokeWith != null) {
            String[] args = parsedArgs.mRemainingArgs;
            // 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.
            //如果我们有一个非空的系统服务器类路径,我们将不得不复制现有参数并将类路径附加到它。 当我们执行一个新进程时,ART 将正确处理类路径。
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }

            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);

            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);

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

            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }

        /* should never reach here */
    }

可以看出,这里是顺序执行 RuntimeInit.commonInit(),ZygoteInit.nativeZygoteInit(),最后返回 RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);

    public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

RuntimeInit. 没仔细看,应该是做了一些基本的初始化操作。nativeZygoteInit 这个jni 方法找了半天没找到,后来才发现是在 AndroidRuntime.cpp 中注册的,跟踪过去看看源码。


static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntime 又是一个 AndroidRuntime 的对象,我们直接进入 AndroidRuntime 里 找到它

进入 app_main.cpp frameworks\base\cmds\app_process ,找到onZygoteInit

    virtual void onZygoteInit()
    {
        sp proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

原来是初始化Binder,然后将线程注册到Binder 线程池。

接着看
RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv, classLoader);


    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // 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);

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        final Arguments args = new Arguments(argv);

        // 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
        return findStaticMain(args.startClass, args.startArgs, classLoader); //1
    }


    protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        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.
         */
        return new MethodAndArgsCaller(m, argv);
    }


    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                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);
            }
        }
    }

实际上就是根据参数找到main 方法,然后一层一层返回回去,最后在 ZygoteInit 的main方法里里面执行,第一阶段完结撒花~

SystemServer 进入main方法


    public static void main(String[] args) {
        new SystemServer().run();//简单粗暴
    }


//构造方法也列没啥东西

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

        // Record process start information.
        // Note SYSPROP_START_COUNT will increment by *2* on a FDE device when it fully boots;
        // one for the password screen, second for the actual boot.
        mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
        mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
        mRuntimeStartUptime = SystemClock.uptimeMillis();
        Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime);

        // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
        // We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
        // TODO: mRuntimeRestart will *not* be set to true if the proccess crashes before
        // sys.boot_completed is set. Fix it.
        mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
    }



//重点在于run方法,run 方法里主要是进行一些初始化操作,创建Looper什么的,比较值得关注的有几点。
一、createSystemContext 新建系统上下文
二、mSystemServiceManager = new SystemServiceManager(mSystemContext); 根据一 中得到的SystemContext 来初始化 mSystemServiceManager,它负责启动服务,里面有个ArrayList 维护了各个系统服务的实例。

三、启动各种服务

        // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);//开机引导服务  AMS PMS
            startCoreServices(t);//核心服务  GpuService BugreportManagerService BatteryService
            startOtherServices(t);//其他服务  ALMS WMS 等阿猫阿狗~
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }

等上述都干完后,就调用 Looper.loop(); 进入了无限的循环中~

我们看看第一点,新建系统上下文

//新建系统上下文
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }

    @UnsupportedAppUsage
    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()) {//判断是不是低内存设备,能否使用硬件加速,这会消耗更多内存
            ThreadedRenderer.disable(true);
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();//创建 ActivityThread,可以理解为主线程
        thread.attach(true, 0);
        return thread;
    }

    //构造函数只是创建了一个ResourcesManager实例对象并赋值给自己的成员变量mResourcesManager
    @UnsupportedAppUsage
    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
    }


然后调用看ActivityThread的成员方法attach()。



    @UnsupportedAppUsage
    private void attach(boolean system, long startSeq) {//参数为 true , 0
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {//进不去
               } 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 {
                mInstrumentation = new Instrumentation();//创建并实例化了一个Instrumentation对象
                mInstrumentation.basicInit(this);//只是把 ActivityThread 作为参数传了进去,mInstrumentation 内部增加了一个对外部 ActivityThread 的引用
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);//根据LoadAPK 和 ActivityThread 创造 context,目前内容相同,是两个对象
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);//初始化 SystemServer 的 Applicatrion对象
                mInitialApplication.onCreate();//调用其onCreate
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> {
            synchronized (mResourcesManager) {
                // TODO (b/135719017): Temporary log for debugging IME service.
                if (Build.IS_DEBUGGABLE && mHasImeComponent) {
                    Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
                            + "config=" + globalConfig);
                }

                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                //我们需要立即将此更改应用于资源,因为在返回视图层次结构时将被告知它。
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);//发送消息处理
                    }
                }
            }
        };
        ViewRootImpl.addConfigCallback(configChangedCallback);
    }




    final void basicInit(ActivityThread thread) {
        mThread = thread;
    }

接下来是重头戏,创建context

ContextImpl.createAppContext(this, getSystemContext().mPackageInfo) ——> mActivityThread.getSystemContext() ——> ContextImpl.createSystemContext(mActivityThread);


    @UnsupportedAppUsage
    static ContextImpl createSystemContext(ActivityThread mainThread) {//大意就是,根据ActivityThread 创建 LoadApk,Resource,填充创建好的context然后返回
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
                0, null, null);//根据 传进来的 ActivityThread 和 根据 ActivityThread  创建的 PkgInfo  , 创建了一个 Context
        context.setResources(packageInfo.getResources());//设置context 的 Resourrces 对象,这里是新建的
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
        context.mIsSystemOrSystemUiContext = true;
        return context;
    }

LoadedAPK的这个构造方法只有系统进程创建的时候可以调用。它代表一个系统进程的apk,它里面存储着资源文件的位置,jni包的位置等信息,包名为android。其实代表的就是就是framework-res.apk。该apk仅供systemServer使用。

mSystemContext 的初始化 已经分析完了

然后根据这个 mSystemContext 创建 AppContext

ContextImpl.createAppContext(this, getSystemContext().mPackageInfo)

    @UnsupportedAppUsage
    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        return createAppContext(mainThread, packageInfo, null);
    }

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
            String opPackageName) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
                0, null, opPackageName);//比上面的只多了一个 opPackageName???关键是 这个 opPackageName 还是个null,日了狗?得出结论,这俩是一毛一样的!
        context.setResources(packageInfo.getResources());
        context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context);
        return context;
    }

让我们回到 createSystemContext 方法

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();// (1)
        mSystemContext = activityThread.getSystemContext();// 在 1 中已经创建好了 mSystemContext,这里能直接拿到
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }

接下来分析 final Context systemUiContext = activityThread.getSystemUiContext();
可以看到几乎一模一样的流程,只是多了一个 displayId,创建完成~撒花

    public ContextImpl getSystemUiContext() {
        synchronized (this) {
            if (mSystemUiContext == null) {
                mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
            }
            return mSystemUiContext;
        }
    }

    static ContextImpl createSystemUiContext(ContextImpl systemContext) {
        return createSystemUiContext(systemContext, Display.DEFAULT_DISPLAY);
    }
    static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
        final LoadedApk packageInfo = systemContext.mPackageInfo;
        ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
                null, null, null, 0, null, null);
        context.setResources(createResources(null, packageInfo, null, displayId, null,
                packageInfo.getCompatibilityInfo(), null));
        context.updateDisplay(displayId);
        context.mIsSystemOrSystemUiContext = true;
        return context;
    }

ActivityThread 和 Context 就构成了Android程序的运行环境。apk的代码最终在ActivityThread线程上运行,通过Context应用程序的大管家,可以调用进程所用到的资源和方法。
SystemServer构建 APK运行环境是为了供 framewrok-res.apk 使用。

你可能感兴趣的:(Android 启动之SystemServer启动步骤)