前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android Framework学习(三)之SyetemServer进程启动解析

Android Framework学习(三)之SyetemServer进程启动解析

作者头像
老马的编程之旅
发布2022-06-22 11:08:55
3960
发布2022-06-22 11:08:55
举报
文章被收录于专栏:深入理解Android

从上篇博客中,我们知道了Zygote进程启动了SyetemServer进程,本篇博客我们就一起来学习SyetemServer进程。

SystemServer的作用

整个系统的android framework进程启动流程如下:

代码语言:javascript
复制
init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程

SystemServer进程主要的作用是启动各种系统服务,比如ActivityManagerService,PackageManagerService,WindowManagerService等服务,我们平时熟知的各种系统性的服务其实都是在SystemServer进程中启动的,而当我们的应用需要使用各种系统服务的时候其实也是通过与SystemServer进程通讯获取各种服务对象的句柄的进而执行相应的操作的。

SyetemServer进程启动流程

之前我们曾经说过,在ZygoteInit.Java的startSystemServer函数中启动了SyetemServer进程 frameworks/base/core/java/com/Android/internal/os/ZygoteInit.java

代码语言:javascript
复制
private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
     ...
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            handleSystemServerProcess(parsedArgs);
        }
        return true;
    }

在startSystemServer函数中调用handleSystemServerProcess来启动SyetemServer进程。

handleSystemServerProcess

代码语言:javascript
复制
private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        closeServerSocket();//1
      ...
        if (parsedArgs.invokeWith != null) {
           ...
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createSystemServerClassLoader(systemServerClasspath,
                                                   parsedArgs.targetSdkVersion);
                Thread.currentThread().setContextClassLoader(cl);
            }
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//2
        }
    }

SyetemServer进程是复制了Zygote进程的地址空间,因此也会得到Zygote进程创建的Socket,这个Socket对于SyetemServer进程没有用处,因此,需要注释1处的代码来关闭该Socket。在注释2处调用RuntimeInit的zygoteInit函数

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

代码语言:javascript
复制
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();
        commonInit();
        nativeZygoteInit();//1
        applicationInit(targetSdkVersion, argv, classLoader);//2
    }

注释1处调用nativeZygoteInit函数,所以又调用了Native层的代码,从java代码又切换进native代码

启动Binder线程池 查看nativeZygoteInit函数对用的JNI文件 frameworks/base/core/jni/AndroidRuntime.cpp

代码语言:javascript
复制
static const JNINativeMethod gMethods[] = {
    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};

通过JNI的gMethods数组,可以看出nativeZygoteInit函数对应的是JNI文件AndroidRuntime.cpp的com_android_internal_os_RuntimeInit_nativeZygoteInit函数:

代码语言:javascript
复制
...
static AndroidRuntime* gCurRuntime = NULL;
...
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

这里gCurRuntime是AndroidRuntime类型的指针,AndroidRuntime的子类AppRuntime在app_main.cpp中定义

代码语言:javascript
复制
 virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();//1
    }

注释1处的代码用来启动一个Binder线程池,这样SyetemServer进程就可以使用Binder来与其他进程进行通信了。综合上述,可以看出RuntimeInit.java的nativeZygoteInit函数主要做的就是启动Binder线程池。

applicationInit 回到RuntimeInit.java的代码,在注释2处调用了applicationInit函数 frameworks/base/core/java/com/android/internal/os/RuntimeInit.java applicationInit函数中主要调用了invokeStaticMain函数:

代码语言:javascript
复制
 private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;
        try {
            cl = Class.forName(className, true, classLoader);//1
        } 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 });//2
        } 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);
        }
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3
    }

注释1处className为“com.android.server.SystemServer”,因此通过反射返回的cl为SystemServer类。注释2处找到SystemServer中的main函数。在注释3处将找到的main函数传入到MethodAndArgsCaller异常中并抛出该异常。截获MethodAndArgsCaller异常的代码在ZygoteInit.java的main函数中

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

代码语言:javascript
复制
public static void main(String argv[]) {
       ...
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();//1
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

在注释1处调用了MethodAndArgsCaller的run函数:

代码语言:javascript
复制
public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
         ...
        }
    }

这里mMethod指的就是SystemServer的main函数,因此main函数被动态调用。

SyetemServer进程分析

SystemServer函数的入口同样是main函数: frameworks/base/services/java/com/android/server/SystemServer.java

代码语言:javascript
复制
public static void main(String[] args) {
        new SystemServer().run();
    }

其中只是new出一个SystemServer对象并执行其run方法,查看SystemServer类的定义我们知道其实final类型的,所以我们不能重写或者继承SystemServer。

代码语言:javascript
复制
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);
        }

        ...
        if (!SystemProperties.get("persist.sys.language").isEmpty()) {//1
            final String languageTag = Locale.getDefault().toLanguageTag();

            SystemProperties.set("persist.sys.locale", languageTag);
            SystemProperties.set("persist.sys.language", "");
            SystemProperties.set("persist.sys.country", "");
            SystemProperties.set("persist.sys.localevar", "");
        }

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

        ...
        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");//2

        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();

        // Initialize the system context.
        createSystemContext();//3

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

        // Start services.
        try {
            startBootstrapServices();//5
            startCoreServices();//6
            startOtherServices();//7
        } 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");
    }

1.设置系统的语言环境等属性

代码语言:javascript
复制
if (!SystemProperties.get("persist.sys.language").isEmpty()) {
            final String languageTag = Locale.getDefault().toLanguageTag();

            SystemProperties.set("persist.sys.locale", languageTag);
            SystemProperties.set("persist.sys.language", "");
            SystemProperties.set("persist.sys.country", "");
            SystemProperties.set("persist.sys.localevar", "");
        }

2.加载libandroid_servers.so库 3.createSystemContext()

代码语言:javascript
复制
private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

可以看到在SystemServer进程中也存在着Context对象,并且是通过ActivityThread.systemMain方法创建context的,这一部分的逻辑以后会通过介绍Activity的启动流程来介绍,这里就不在扩展,这里我们只知道在SystemServer进程中也需要创建Context对象。

4.创建SystemServiceManager 创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理 然后调用:

代码语言:javascript
复制
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

将SystemServiceManager对象保存SystemServer进程中的一个数据结构中。

Start services 创建SystemServiceManager后,会执行以下逻辑

代码语言:javascript
复制
// Start services.
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

里面主要涉及了是三个方法: startBootstrapServices() 主要用于启动系统Boot级服务 startCoreServices() 主要用于启动系统核心的服务 startOtherServices() 主要用于启动一些非紧要或者是非需要及时启动的服务

5.startBootstrapServices方法

代码语言:javascript
复制
private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);//1

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

        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);//3

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

        // Manages LEDs and display backlight so we need it to bring up the display.
        mSystemServiceManager.startService(LightsService.class);//4

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

        // 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);//6
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();

        Slog.i(TAG, "User Service");
        ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());//7

        // 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.
        startSensorService();
    }

注释1处执行了如下代码

代码语言:javascript
复制
Installer installer = mSystemServiceManager.startService(Installer.class);

mSystemServiceManager是系统服务管理对象,在main方法中已经创建完成,这里我们看一下其startService方法的具体实现:

代码语言:javascript
复制
public <T extends SystemService> T startService(Class<T> serviceClass) {
        final String name = serviceClass.getName();
        Slog.i(TAG, "Starting " + name);

        // Create the service.
        if (!SystemService.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Failed to create " + name
                    + ": service must extend " + SystemService.class.getName());
        }
        final T service;
        try {
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);
        } catch (InstantiationException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service could not be instantiated", ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service must have a public constructor with a Context argument", ex);
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service must have a public constructor with a Context argument", ex);
        } catch (InvocationTargetException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service constructor threw an exception", ex);
        }

        // Register it.
        mServices.add(service);

        // Start it.
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + name
                    + ": onStart threw an exception", ex);
        }
        return service;
    }

通过反射器构造方法创建出服务类,然后添加到SystemServiceManager的服务列表数据中,最后调用了service.onStart()方法,因为我们传递的是Installer.class,我们这里我们查看一下Installer的onStart方法:

代码语言:javascript
复制
@Override
    public void onStart() {
        Slog.i(TAG, "Waiting for installd to be ready.");
        mInstaller.waitForConnection();
    }

执行了mInstaller的waitForConnection方法,这里简单介绍一下Installer类,该类是系统安装apk时的一个服务类,继承SystemService(系统服务的一个抽象接口),我们需要在启动完成Installer服务之后才能启动其他的系统服务。

然后查看waitForConnection()方法:

代码语言:javascript
复制
public void waitForConnection() {
        for (;;) {
            if (execute("ping") >= 0) {
                return;
            }
            Slog.w(TAG, "installd not ready");
            SystemClock.sleep(1000);
        }
    }

通过追踪代码可以发现,其在不断的通过ping命令连接Zygote进程(SystemServer和Zygote进程通过socket方式通讯,其他进程通过Binder方式通讯);

结论:在开始执行启动服务之前总是会先尝试通过socket方式连接Zygote进程,在成功连接之后才会开始启动其他服务。

继续回到startBootstrapServices方法,注释2:

代码语言:javascript
复制
// Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

启动ActivityManagerService服务,并为其设置SystemServiceManager和Installer。ActivityManagerService是系统中一个非常重要的服务,Activity,service,Broadcast,contentProvider都需要通过其余系统交互。

查看Lifecycle类的定义:

代码语言:javascript
复制
public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }

        @Override
        public void onStart() {
            mService.start();
        }

        public ActivityManagerService getService() {
            return mService;
        }
    }

可以发现Lifecycle是ActivityManagerService是的一个静态内部类,在其构造方法中会创建一个ActivityManagerService,通过刚刚对Installer服务的分析我们知道,SystemServiceManager的startService方法会调用服务的onStart()方法,而在Lifecycle类的定义中我们看到其onStart()方法直接调用了mService.start()方法,mService是Lifecycle类中对ActivityManagerService的引用,所以我们可以看一下ActivityManagerService的start方法的实现:

代码语言:javascript
复制
private void start() {
        Process.removeAllProcessGroups();
        mProcessCpuThread.start();

        mBatteryStatsService.publish(mContext);
        mAppOpsService.publish(mContext);
        Slog.d("AppOps", "AppOpsService published");
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
    }

注释3处,启动PowerManagerService服务

代码语言:javascript
复制
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

启动方式跟上面的ActivityManagerService服务相似都会调用其构造方法和onStart方法,PowerManagerService主要用于计算系统中和Power相关的计算,然后决策系统应该如何反应。同时协调Power如何与系统其它模块的交互,比如没有用户活动时,屏幕变暗等等。 注释4处,启动LightsService服务

代码语言:javascript
复制
mSystemServiceManager.startService(LightsService.class);

主要是手机中关于闪光灯,LED等相关的服务;也是会调用LightsService的构造方法和onStart方法; 注释5处,启动DisplayManagerService服务

代码语言:javascript
复制
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

主要是手机显示方面的服务; 注释6处,启动PackageManagerService 启动PackageManagerService,该服务也是android系统中一个比较重要的服务,包括多apk文件的安装,解析,删除,卸载等等操作

代码语言:javascript
复制
Slog.i(TAG, "Package Manager");
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();

可以看到PackageManagerService服务的启动方式与其他服务的启动方式有一些区别,直接调用了PackageManagerService的静态main方法,这里我们看一下其main方法的具体实现:

代码语言:javascript
复制
public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        ServiceManager.addService("package", m);
        return m;
    }

直接使用new的方式创建了一个PackageManagerService对象,并在其构造方法中初始化相关变量,最后调用了ServiceManager.addService方法,主要是通过Binder机制与JNI层交互

注释7处,启动UserManagerService和SensorService 至此startBootstrapServices方法执行完成。 6.startCoreServices() 方法

代码语言:javascript
复制
private void startCoreServices() {
        // 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);
    }

这里启动了BatteryService(电池相关服务),UsageStatsService,WebViewUpdateService服务等。

7.startOtherServices方法 startOtherServices方法,主要用于启动系统中其他的服务,CameraService、AlarmManagerService、VrManagerService等服务,代码很多,这里就不贴代码了,启动的流程和ActivityManagerService的流程类似,会调用服务的构造方法与onStart方法初始化变量。

总结SyetemServer启动流程

1.SystemServer进程是android中一个很重要的进程由Zygote进程启动;

2.SystemServer进程主要用于启动系统中的服务;

3.SystemServer进程启动服务的启动函数为main函数;

4.SystemServer在执行过程中首先会初始化一些系统变量,加载类库,创建Context对象,创建SystemServiceManager对象等之后才开始启动系统服务;

5.SystemServer进程将系统服务分为三类:boot服务,core服务和other服务,并逐步启动

6.SertemServer进程在尝试启动服务之前会首先尝试与Zygote建立socket通讯,只有通讯成功之后才会开始尝试启动服务;

7.创建的系统服务过程中主要通过SystemServiceManager对象来管理,通过调用服务对象的构造方法和onStart方法初始化服务的相关变量;

8.服务对象都有自己的异步消息对象,并运行在单独的线程中;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-05-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SystemServer的作用
  • SyetemServer进程启动流程
  • SyetemServer进程分析
  • 总结SyetemServer启动流程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档