Android Framework Learning (3) Syetem Server Process Start Resolution

From the previous blog, we know that the Zygote process started the Syetem Server process. In this blog, we will learn about the Syetem Server process together.

Role of System Server

The android framework process startup process of the whole system is as follows:

init process --> Zygote process --> System Server process --> various application processes

The main function of the System Server process is to start all kinds of system services, such as Activity Manager Service, Package Manager Service, Windows Manager Service and so on. All kinds of system services we usually know are actually started in the System Server process, and when our application needs to use all kinds of system services. In fact, it is also through communication with the System Server process to obtain the handle of various service objects and perform the corresponding operations.

Syetem Server process startup process

As we said before, the Syetem Server process is started in the startSystem Server function of ZygoteInit.Java
frameworks/base/core/java/com/Android/internal/os/ZygoteInit.java

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
     ...
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            handleSystemServerProcess(parsedArgs);
        }
        return true;
    }

Call handleSystem Server Process in the startSystem Server function to start the Syetem Server process.

handleSystemServerProcess

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 processes copy the address space of the Zygote process, so they also get the Socket created by the Zygote process, which is not useful for the SyetemServer process, so you need to comment on the code at 1 to close the Socket. Call the zygoteInit function of RuntimeInit at Note 2

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

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
    }

Note 1 calls the nativeZygoteInit function, so it calls the Native layer code and switches from java code to native code.

Start the Binder thread pool
View JNI files for nativeZygoteInit function pairs
frameworks/base/core/jni/AndroidRuntime.cpp

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

Through the gMethods array of JNI, we can see that the nativeZygoteInit function corresponds to the com_android_internal_os_RuntimeInit_nativeZygoteInit function of the JNI file AndroidRuntime.cpp:

...
static AndroidRuntime* gCurRuntime = NULL;
...
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

Here gCurRuntime is a pointer to the Android Runtime type, and AppRuntime, a subclass of Android Runtime, is defined in app_main.cpp.

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

The code in Note 1 is used to start a Binder thread pool so that Syetem Server processes can use Binder to communicate with other processes. From the above, we can see that the main task of RuntimeInit.java's nativeZygoteInit function is to start the Binder thread pool.

applicationInit
Back to the code in RuntimeInit.java, the application Init function is called at comment 2
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
The invokeStaticMain function is mainly called in the application Init function:

 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
    }

At Note 1, the className is "com.android.server.SystemServer", so the cl returned by reflection is the SystemServer class. Note 2 finds the main function in System Server. At Note 3, pass the main function found into the MethodAndArgsCaller exception and throw it. Code intercepting MethodAndArgsCaller exceptions is in the main function of ZygoteInit.java

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

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

The run function of MethodAndArgsCaller is called at Note 1:

public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
         ...
        }
    }

Here mMethod refers to the main function of System Server, so the main function is called dynamically.

Syetem Server Process Analysis

The entry to the System Server function is also the main function:
frameworks/base/services/java/com/android/server/SystemServer.java

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

It's just a new System Server object that executes its run method. Looking at the definition of the System Server class, we know that it's actually final type, so we can't override or inherit the System Server.

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. Setting up the language environment and other attributes of the system

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. Loading libandroid_servers.so Library
3.createSystemContext()

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

You can see that there are Context objects in the System Server process, and they are created by the ActivityThread.systemMain method. The logic of this part will be introduced later by introducing the start-up process of Activity. There is no extension here. We only know that Context needs to be created in the System Server process. Object.

4. Create System Service Manager
Create System Service Manager, which creates, starts, and manages system services
Then call:

LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

Save the SystemService Manager object in a data structure in the SystemServer process.

Start services
After creating the System Service Manager, the following logic is executed

// Start services.
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

There are three main methods involved:
StartBootstrap Services () is mainly used to boot system Boot-level services.
StartCore Services () is mainly used to start the core services of the system.
StartOther Services () is mainly used to start some non-critical or non-timely services.

5. Start Bootstrap Services Method

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

Note 1 executes the following code

Installer installer = mSystemServiceManager.startService(Installer.class);

MSystemService Manager is the object of system service management. It has been created in main method. Let's take a look at the implementation of its startService method.

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

The service class is created by the reflector constructor method, then added to the service list data of the SystemService Manager, and finally invoked the service.onStart() method, because we are passing Installer.class. Let's take a look at Installer's onStart method here:

@Override
    public void onStart() {
        Slog.i(TAG, "Waiting for installd to be ready.");
        mInstaller.waitForConnection();
    }

The waitForConnection method of mInstaller is executed. Here we briefly introduce the Installer class, which is a service class when the system installs apk. It inherits SystemService (an abstract interface of system services). We need to start and complete the Installer service before we can start other system services.

Then look at the waitForConnection () method:

public void waitForConnection() {
        for (;;) {
            if (execute("ping") >= 0) {
                return;
            }
            Slog.w(TAG, "installd not ready");
            SystemClock.sleep(1000);
        }
    }

By tracing the code, it can be found that it is constantly connected to Zygote process through ping command (System Server and Zygote process communicate through socket, other processes communicate through Binder);

CONCLUSION: Before starting the start-up service, the Zyget process is always tried to connect through socket mode, and then other services are started after successful connection.

Continue back to the startBootstrapServices method, note 2:

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

Start the Activity Manager Service service and set up System Service Manager and Installer for it. Activity Manager Service is a very important service in the system. Activity, service, Broadcast, content Provider all need to interact with other systems.

Look at the definition of the Lifecycle class:

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

You can find that Lifecycle is a static internal class of ActivityManagerService. In its construction method, an ActivityManagerService is created. Through the analysis of Installer service just now, we know that the startService method of SystemServiceManager calls the onStart() method of the service, while in the definition of Lifecycle class, it calls the onStart() method of the service. We can see that its onStart() method directly calls the mService.start() method. mService is a reference to ActivityManagerService in Lifecycle class. So we can see the implementation of the start method of ActivityManagerService:

private void start() {
        Process.removeAllProcessGroups();
        mProcessCpuThread.start();

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

Note 3 to start the PowerManagerService service

mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

Similar to the ActiveyManagerService service above, the startup method calls its construction method and onStart method. PowerManagerService is mainly used for PowerManager-related calculations in computing systems, and then decides how the system should react. At the same time, it coordinates how Power interacts with other modules of the system, such as when there is no user activity, the screen darkens and so on.
Note 4 to start the LightsService service

mSystemServiceManager.startService(LightsService.class);

Mainly about flash, LED and other related services in the mobile phone; it also calls LightsService's construction method and onStart method;
Note 5 to start the DisplayManagerService service

mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

Mainly mobile display services;
Note 6 to start PackageManagerService
Start PackageManager Service, which is also an important service in android system, including installation, parsing, deletion, uninstallation of multi-apk files, and so on.

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

You can see that there are some differences between the way the PackageManagerService service is started and other services are started. The static main method of the PackageManagerService is directly invoked. Here we look at the implementation of its main method.

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

A PackageManagerService object is created directly in the new way, and the related variables are initialized in its construction method. Finally, the Service Manager. addService method is invoked, which mainly interacts with JNI layer through Binder mechanism.

Note 7, Start UserManagerService and SensorService
At this point, the startBootstrapServices method is executed.
6.startCoreServices() method

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

Battery Service, Usage Stats Service, WebView Update Service are launched here.

7. StartOther Services Method
StartOther Services method is mainly used to start other services in the system, such as Camera Service, Alarm Manager Service, VrManager Service, etc. There are many codes. There is no code pasted here. The process of startup is similar to that of ActiveyManager Service, and the construction method of service will be invoked to initialize variables with onStart method. .

Summarize the Startup Process of Syetem Server

1.SystemServer process is an important process in android, which is started by Zygote process.

2. System Server process is mainly used to start the service in the system.

3. The startup function of the system server process startup service is the main function.

4.SystemServer initializes some system variables, loads class libraries, creates Context objects, creates SystemServiceManager objects and so on before starting system services.

5. The System Server process divides system services into three categories: boot services, core services and other services, and starts them step by step.

6.SertemServer process will first try to establish socket communication with Zygote before attempting to start the service. Only after successful communication will it begin to attempt to start the service.

7. System Service Manager object is used to manage the system service, and the related variables of service are initialized by calling the construction method of service object and onStart method.

8. Service objects have their own asynchronous message objects and run in separate threads.

Keywords: Android Java socket Mobile

Added by jynmeyer on Thu, 04 Jul 2019 23:43:43 +0300