Android 10 system process SystemServer

Keywords: Android

        In the previous section The Android 10 system process Zygote starts The Zygote process is started. It is said that the Zygote process will create the SystemServer process and execute the main () function. The SystemServer process hosts the core services of the entire Android framework layer. Let's take a look at the main() function of / frameworks/base/services/java/com/android/server/SystemServer.java:

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

Create a SystemServer object and execute its run () method:

private void run() {
    try {
        traceBeginAndSlog("InitBeforeStartServices");
        // Record the process start information in sys props.
        //When creating this object, the following properties will be initialized, and these properties will be set to the system here
        SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));//Set the number of boot times
        SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));
        SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));
        EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,
                mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);
        //If the clock of a device is before 1970 (before 0 years),
        //Then many APIs will crash because they handle negative numbers, especially java.io.File#setLastModified
        //I set the time to 1970
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }
        //If the time zone does not exist, set the time zone to GMT
        String timezoneProperty = SystemProperties.get("persist.sys.timezone");
        if (timezoneProperty == null || timezoneProperty.isEmpty()) {
            Slog.w(TAG, "Timezone not set; setting to GMT.");
            SystemProperties.set("persist.sys.timezone", "GMT");
        }
        //Change the library file of the virtual machine. For Android 10.0, libart.so is used by default
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
        // Mmmmmm... more memory!
        //Clear the upper limit of vm memory growth, because the startup process requires more virtual machine memory space
        VMRuntime.getRuntime().clearGrowthLimit();
    ...
        //The system server must be running all the time, so it needs to use memory as efficiently as possible
        //Set the possible effective memory usage to 0.8
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
        //Some devices rely on runtime fingerprint generation, so please make sure we have defined it before starting further.
        Build.ensureFingerprintProperty();
        //Before accessing environment variables, you need to specify users explicitly
        //In system_ In the server, any incoming package should be released to avoid throwing BadParcelableException.
        BaseBundle.setShouldDefuse(true);
        //In system_ In server, when packaging exceptions, the information needs to include stack traces
        Parcel.setStackTraceParceling(true);
        //Ensure that the binder call of the current system process always runs in the foreground priority
        BinderInternal.disableBackgroundScheduling(true);
        //Set system_ The maximum number of binder threads in the server. The maximum value is 31
        BinderInternal.setMaxThreads(sMaxBinderThreads);
        //Prepare the main thread looper, that is, run on the current thread
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();
        Looper.getMainLooper().setSlowLogThresholdMs(
                SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
        //Load Android_ The servers.so library initializes the native service
        System.loadLibrary("android_servers");
        // Debug builds - allow heap profiling.
        //In case of Debug version, heap memory analysis is allowed
        if (Build.IS_DEBUGGABLE) {
            initZygoteChildHeapProfiling();
        }
        //Check whether the last shutdown process failed. This call may not return
        performPendingShutdown();
        //Initialize system context
        createSystemContext();
        //Create system service management -- System Service Manager
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setStartInfo(mRuntimeRestart,
                mRuntimeStartElapsedTime, mRuntimeStartUptime);
        //Add mSystemServiceManager to the local service's member sLocalServiceObjects
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Prepare the thread pool for init tasks that can be parallelized
        //Prepare a thread pool for init tasks that can be parallelized
        SystemServerInitThreadPool.get();
    } finally {
        traceEnd();  // InitBeforeStartServices
    }
    // Start services.
    //Start service
    try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices();   // Start boot service
        startCoreServices();        // Start core services
        startOtherServices();       // Start other services
        SystemServerInitThreadPool.shutdown(); //Stop thread pool
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        traceEnd();
    }
    //Initialize VmPolicy for the current virtual machine
    StrictMode.initVmDefaults(null);
  ...
    // Loop forever.
    //Dead loop execution
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

Here, we mainly initialize some system variables, create the system context, create the system service management object SystemServiceManager, and finally start the system service. Here, the system service can be divided into three types: boot service, core service and other services. Let's go inside and have a look:

Create system context:

private void createSystemContext() {
    //Create context information for the systemserver process
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    //set up themes
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
    //Get the systemui context information and set the theme
    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

  This process will create objects such as ActivityThread, Instrumentation, ContextImpl, LoadedApk and Application. One thing to note is that ActivityThread is created through its systemMain () method, while the normal Application process is created through ActivityThread through its main () method.

To create a system service management object SystemServiceManager:

         The SystemServiceManager object is mainly used to create managed system services. This class is simplified as follows:

public class SystemServiceManager {
    private static final String TAG = "SystemServiceManager";

    private final Context mContext;

    // Services that should receive lifecycle events.
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();


    SystemServiceManager(Context context) {
        mContext = context;
    }


    /*
     * Loads and initializes a class from the given classLoader. Returns the class.
     */
    @SuppressWarnings("unchecked")
    private static Class<SystemService> loadClassFromLoader(String className,
                                                            ClassLoader classLoader) {
        try {
            return (Class<SystemService>) Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException("Failed to create service " + className
                    + " from class loader " + classLoader.toString() + ": service class not "
                    + "found, usually indicates that the caller should "
                    + "have called PackageManager.hasSystemFeature() to check whether the "
                    + "feature is available on this device before trying to start the "
                    + "services that implement it. Also ensure that the correct path for the "
                    + "classloader is supplied, if applicable.", ex);
        }
    }

    /**
     * Creates and starts a system service. The class must be a subclass of
     * {@link com.android.server.SystemService}.
     *
     * @param serviceClass A Java class that implements the SystemService interface.
     * @return The service instance, never null.
     * @throws RuntimeException if the service fails to start.
     */
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();
            Slog.i(TAG, "Starting " + name);
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + 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);
            }

            startService(service);
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

    public void startService(@NonNull final SystemService service) {
        // Register it.
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

}

There is an mServices collection in this object. This collection mainly stores system services. You can see that all system services need to inherit com.android.server.SystemService, instantiate the system service object through reflection, and finally call the onStart() method of the system service. About the instantiated system service object, You can view the printed system service log by filtering the system service manager.

Start system service:

        Starting system services can be divided into three categories, mainly through three methods:

startBootstrapServices();   // Start boot service
startCoreServices();        // Start core services
startOtherServices();       // Start other services

Here we mainly look at the other two implementation methods of startBootStrapServices():

 private void startBootstrapServices() {
        traceBeginAndSlog("StartWatchdog");
        //Start watchdog
        //Start watchdog as early as possible. If a deadlock occurs when starting up early, we can let the system_server crashes for detailed analysis
        final Watchdog watchdog = Watchdog.getInstance();
        watchdog.start();
        traceEnd();
    ...

        //Block and wait for installd to complete startup, so as to have the opportunity to create a key directory with appropriate permissions, such as / data/user.
        //We need to complete this task before initializing other services.
        traceBeginAndSlog("StartInstaller");
        Installer installer = mSystemServiceManager.startService(Installer.class);
        traceEnd();
    ...
        //Start the service ActivityManagerService and set mSystemServiceManager and installer for it
        traceBeginAndSlog("StartActivityManager");
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();
        traceEnd();
        //Start service PowerManagerService
        //Power manager needs to be started early because other services need it.
        //The native daemon may be monitoring its registration,
        //Therefore, it must be ready to process incoming binder calls immediately (including permissions that can verify these calls).
        traceBeginAndSlog("StartPowerManager");
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        traceEnd();
    ...
        //Initialize power management
        traceBeginAndSlog("InitPowerManagement");
        mActivityManagerService.initPowerManagement();
        traceEnd();
        //Start the recovery system in case a reboot is required
        traceBeginAndSlog("StartRecoverySystemService");
        mSystemServiceManager.startService(RecoverySystemService.class);
        traceEnd();
    ...
        //Start LightsService
        //Manage the led and display backlight, so we need it to turn on the display
        traceBeginAndSlog("StartLightsService");
        mSystemServiceManager.startService(LightsService.class);
        traceEnd();
    ...
        //Start service DisplayManagerService
        //The display manager needs to provide display indicators before the package manager
        traceBeginAndSlog("StartDisplayManager");
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
        traceEnd();
        //The default display is required before initializing package manager
        traceBeginAndSlog("WaitForDisplay");
        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
        traceEnd();
        //When the device is being encrypted, only the core is running
        String cryptState = VoldProperties.decrypt().orElse("");
        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 service PackageManagerService
        traceBeginAndSlog("StartPackageManagerService");
        try {
            Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        } finally {
            Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
        }
    ...
        //Start the service UserManagerService and create a new directory / data/user/
        traceBeginAndSlog("StartUserManagerService");
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
        traceEnd();
        // Set up the Application instance for the system process and get started.
        //Set up an application instance for the system process and start.
        //Set AMS
        traceBeginAndSlog("SetSystemProcess");
        mActivityManagerService.setSystemProcess();
        traceEnd();
        //Use an ActivityManager instance to set watchdog and listen for restart,
    //This can only be done if the ActivityManagerService is started correctly as a system process
        traceBeginAndSlog("InitWatchdog");
        watchdog.init(mSystemContext, mActivityManagerService);
        traceEnd();
         //The sensor service needs to access package manager service, app ops service and permission service,
        //So we start it after them.
        //Start the sensor service in a separate thread. You should check the completion before using it.
        mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
            TimingsTraceLog traceLog = new TimingsTraceLog(
                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            traceLog.traceBegin(START_SENSOR_SERVICE);
            startSensorService(); //Start sensor service
            traceLog.traceEnd();
        }, START_SENSOR_SERVICE);
    }

It can be seen from here that services are basically created through startService () of SystemServiceManager, with the exception of PackageManagerService, which directly calls its main () method. About the creation of specific services, I will talk about specific services later.

Posted by Jpauls104 on Fri, 24 Sep 2021 01:34:06 -0700