preface

We are familiar with the general Android engineers are based on SDK in the application layer development, will not involve system source code, but if you want to go to the bottom of the development, or in-depth plug-in, Framework system layer development work, if you do not understand Android source code but not, So the next I based on their own understanding and learning to record with Android development is closely related to the source analysis, probably from the Android SystemServer start, four components start, AMS, PMS and other dimensions to introduce, the following is my plan, of course, may change in the future.

If you haven’t paid attention to it yet, you can pay attention to it first. The series of articles will be updated continuously.

Android 8.0 source code analysis (a) SystemServer process started

Android 8.0 source code analysis (ii) Launcher

Android 8.0 source code analysis (three) application process creation to the application startup process

Android 8.0 source code analysis (four) Activity start

Android 8.0 source code analysis (5) Service startup

Android 8.0 source code analysis (6) BroadcastReceiver launch

Android 8.0 source code analysis (seven) ContentProvider start

ActivityManagerService

Android 8.0 source code analysis (nine) WindowManager

Android 8.0 source code analysis (ten) WindowManagerService window management

introduce

AMS, WMS, PMS, etc., are used to start the SystemServer process. Therefore, learn how to start the SystemServer process, and what it does when it starts. These are all things we need to learn in this chapter.

Source code analysis

Before analyzing the SystemServer startup source code, let’s take a look at the SystemServer startup sequence diagram

1. Zygote creates a portal to the Java framework layer

Zygote is the entry point to the Java framework. What is Zygote? The Zygote startup process is started by using the script init.rc. We will write a separate article about Zygote startup process later. Here we will jump directly to the entry of Zygote startup JNI layer. This is zygoteinit. Java, and we’ll look directly at the implementation of main.

//com.android.internal.os.ZygoteInit.java
    public static void main(String argv[]) {...try{...// Whether to enable the SystemServer flag
            boolean startSystemServer = false;
          	// Server Socket name
            String socketName = "zygote";

          	// Determine whether to start the system service according to the information passed by the JNI layer
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = 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]); }}/** * 1. Create a server Socket named "zygote" */

            zygoteServer.registerServerSocket(socketName);
           
            if(! enableLazyPreload) { bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
                /** * 2. Use to preload resources */
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else{ Zygote.resetNicePriority(); }...if (startSystemServer) {
                /** * 3. Start the SystemServer process ** /
                startSystemServer(abiList, socketName, zygoteServer);
            }

            Log.i(TAG, "Accepting command socket connections");
            /** * 4. Wait for AMS request */
            zygoteServer.runSelectLoop(abiList);
						// Clear or close the corresponding Socket
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throwex; }}Copy the code

Using the code above we can break down the work zygoteinit.main () does into four big steps

    1. Create a Socket with the Server name “Zygote” and wait for AMS to request Zygote to create a new application process.
    1. Preload classes and resources.
    1. Determine whether to start the SystemServer process based on the information passed by JNI.
    1. Wait for AMS requests to create new application processes.

1. zygoteServer.registerServerSocket(socketName);

So let’s first look at what we did in the first step. What’s the function code

//com.android.internal.os ZygoteServer.java

    void registerServerSocket(String socketName) {
        if (mServerSocket == null) {
            int fileDesc;
            /** * 1. Get the Socket name */
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                /** * 2. Obtain the Socket environment variable value */
                String env = System.getenv(fullSocketName);
                /** * 3. Convert the value of the Socket environment variable to the file descriptor parameter */
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                /** * 4. Create file descriptor */
                FileDescriptor fd = new FileDescriptor();
								// Pass the Socket converted information to the file descriptor, which is used to obtain specific information
                fd.setInt$(fileDesc);
                /** *5. Create a server Socket */
                mServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex); }}}Copy the code

What does the registerServerSocket function do?

    1. ANDROID_SOCKET_zygote = ANDROID_SOCKET_zygote
    1. The funSocketName Socket name is converted to the value of the system environment variable
    1. Converts the value of the Socket’s system environment variable to the parameter of the file descriptor
    1. Create a FileDescriptor with FileDescriptor
    1. Create a server Socket and pass the corresponding file descriptor to the server Socket as an argument

Finally, the server Socket is created and is waiting for AMS to request the Zygote process to create a new application process.

2. Start the SystemServer process

Next, please go back to the ZygoteInit main function in comment 3 for specific implementation, as follows:

  //com.android.internal.os ZygoteInit.main->startSystemServer

	private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
        longcapabilities = 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 ); ./* Hardcoded command line to start the system server */
        /** * 1. Start SystemServer parameters */
        String args[] = {
                "--setuid=1000"."--setgid=1000"."- setgroups = 1001100 2100 3100 4100 5100 6100 7100 8100 9101 0101 8102 1102 3103 2300 1300 2300 3300 6300 7300 9301 0"."--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server"."--runtime-args"."com.android.server.SystemServer".// Full class name path
        };
        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 */
            /** * Create a child process, namely the SystemServer 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 the current code is running in a child process, i.e. SystemServer process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            // Close the Socket created by Zygote
            zygoteServer.closeServerSocket();
            /** * Process SystemServer */
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }
Copy the code

So let’s take a look at what the current function is doing based on this code. Okay

    1. As a parameter to start the SystemServer process, according to the defined arGS.
    1. ForkSystemServer is created by using the Zygote. ForkSystemServer function (which is also created internally in Native) and returns the pid process
    1. If the pid is 0 then it will have been running in the process of SystemServer, perform handleSystemServerProcess function

HandleSystemServerProcess specific processing SystemServer () logic, the second point is introduced in the article.

3. zygoteServer.runSelectLoop(abiList);

Zygoteinit.main () : zygoteinit.main () : zygoteinit.main () : zygoteinit.main () : zygoteinit.main ();

// com.android.internal.os ZygoteInit.main->runSelectLoop

    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        /** * 1. Add the value of the fd field of the Socket */
        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);

        /** * wait for AMS request */ in an infinite loop
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            /** * 2. Dump FDS information into the pollFds array. * /
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

            /** * 3. Iterate over the pollFds information */
            for (int i = pollFds.length - 1; i >= 0; --i) {

                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                // If I == 0, the server Socket is connected to the client
                if (i == 0) {
                    4 / * * * * /
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    // Add ZygoteConnection to the Socket connection list
                    peers.add(newPeer);
                    // Add ZygoteConnection's file descriptor to the FDS list
                    fds.add(newPeer.getFileDesciptor());
                } else {// If not, AMS sent Zygote a request to create an application process
                    Call ZygoteConnection's runOnce function to create a new application process and close the connection from the list of Socket connections */
                    boolean done = peers.get(i).runOnce(this);
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }
Copy the code

What does this function mainly do

    1. MServerSocket is our registerZygoteSocket functions created in the server Socket, call mServerSocket. GetFileDescriptor () function is used to obtain the Socket fd Field value and add to the FDS list. An infinite loop is then used to wait for AMS to request the Zygote process to create a new application process.
    1. Dump the FDS information into the pollFds array.
    1. PollFds information traversal, if I == 0, then it is considered that the server Socket is connected to the client, that is, the connection is established with AMS. Otherwise, AMS sends Zygote a request to create an application process and closes the connection from the list of peers, fd, and Socket connections.

summary

A small summary is made through the implementation of ZygoteInit main

    1. Enter the Java framework layer of Zygote by calling the main function of ZygoteInit via JNI.
    1. The server Socket is created through the registerZygoteSocket function, and the new application process is created by waiting for AMS’s request through the runSelectLoop function.
    1. Start the SystemServer process

This section sets the stage for SystemServer startup, knowing where to call startup, and then analyzing it in detail.

2. Process the SystemServer process

Through a section of the second point we know in ZygoteInit. Finally into processing SystemServer is the main () – > startSystemServer handleSystemServerProcess () function, So let’s just look at the implementation of this function

//com.android.internal.os ZygoteInit.main

    private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller {...if(parsedArgs.invokeWith ! =null) {... }else {
            ClassLoader cl = null;
            if(systemServerClasspath ! =null) {
                /** * 1. Create PathClassLoader */
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

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

            /** * 2. Call your zygoteInit function */
            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

Copy the code

ZygoteInit = ZygoteInit = ZygoteInit = ZygoteInit = ZygoteInit = ZygoteInit

// com.android.internal.os ZygoteInit

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

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

        RuntimeInit.commonInit();
        /** * 1. Start the Binder thread pool */
        ZygoteInit.nativeZygoteInit();
        /** * 2. Enter the SystemServer main method */
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
Copy the code

The nativeZygoteInit() function called in Note 1 calls native code that starts the Binder thread pool so that SystemServer can communicate with other processes through Binder. The effect of comment 2 is to call SystemServer main by reflection.

1. Binder thread pool starts

Binder source code can refer to androidRuntime.cpp, app_main.cpp.

After a successful startup, you can use Binder to communicate with other processes.

2. Go to systemServer.java main()

We continue to go back to ZygoteInit. In Java ZygoteInit RuntimeInit. ApplicationInit call, the code is as follows

  //com.android.internal.os RuntimeInit.java

	protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {... invokeStaticMain(args.startClass, args.startArgs, classLoader); }Copy the code
    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller 
    { Class<? > cl;try {
            / * * * 1. Through the className (com) android) server. SystemServer) reflection get SystemServer class * className passed through the AMS and other places, is not the only * /
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            /** * 2. Get SystemServer main */
            m = cl.getMethod("main".new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            ...
        } catch (SecurityException ex) {
            ...
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
           ...
        }

        /** * 3. Pass m and argv to MethodAndArgsCaller, throw an exception, and catch the exception in zygoteinit. main */
        throw new Zygote.MethodAndArgsCaller(m, argv);
    }
Copy the code

By the above code we know first by com. Android. Server SystemServer reflection to the Class, then through the current access to the Class to get its main method, Threw a Zygote. MethodAndArgsCaller (m, argv) anomalies.

//com.android.internal.os Zygote.java
    public static class MethodAndArgsCaller extends Exception
            implements Runnable {... }Copy the code

As you can see from the above code, it is the Exception class that inherits the Java Exception parent and then implements the Runnable function. It’s actually interesting to write it here. The exception here is caught in the zygoteinit.java main function, and we will see the code implementation

//com.android.internal.os ZygoteInit.java


    public static void main(String argv[]) {...if (startSystemServer) {
                /** * 1. Start the SystemServer processstartSystemServer(abiList, socketName, zygoteServer); }...//2. Catch exceptions
        } catch (Zygote.MethodAndArgsCaller caller) {
      		//3. Run the run function
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throwex; }}Copy the code

With the above code finally executed in comment 3, we look at the internal code implementation

////com.android.internal.os Zygote.java

    public static class MethodAndArgsCaller extends Exception
            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(a) {
            try {
                /** * 1. The SystemServer main method is executed */
                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 newRuntimeException(ex); }}}Copy the code

From comment 1, we know that the systemServer.java main() function is called directly by reflection, so let’s go straight to its main implementation.

//com.android.server SystemServer.java
    /** * The main function here is mainly called by zygote via reflection */
    public static void main(String[] args) {
 				// Call the internal run function
        new SystemServer().run();
    }
Copy the code
//com.android.server SystemServer.java

    private void run(a) {
        try{.../** * Create a message for the main thread Looper */

            Looper.prepareMainLooper();

            // Initialize native services.
            /** * 1. Load libandroid_servers. so */
            System.loadLibrary("android_servers");

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

            // Initialize the system context.
            /** * Create system-level Context */
            createSystemContext();

            // Create the system service manager.
            /** * 2. Create SystemServiceManager. It creates, starts, and manages the lifecycle of system services */
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            /** * 3. SystemServiceManager starts AMS, PowerMS, and PackageMS services */
            startBootstrapServices();
            /** * 4. Start DropBoxManagerService, BatteryService, UsageStatsService, and WebViewUpdateService */
            startCoreServices();
            /** * 5. CameraService, AlarmManagerService, and VrManagerService are enabled. * /
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System"."* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
            Slog.e("System"."************ Failure starting system services", ex);
            throw ex;
        } finally{ traceEnd(); }...// Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
Copy the code

See below for a summary of the main things done with the above code

    1. Create a message Looper
    1. Load the dynamic library libandroid_Servers.so
    1. Create system-level Context
    1. Create SystemServiceManager. It creates, starts, and manages the life cycle of system services
    1. Start AMS, PowerMS, and PackageMS services using SystemServiceManager
    1. Start DropBoxManagerService, BatteryService, UsageStatsService, and WebViewUpdateService. Their parent classes are SystemServer
    1. Start CameraService, AlarmManagerService, and VrManagerService

As can be seen from the functions in comments 3, 4 and 5 in the above code, the system is officially divided into three types, namely boot services, core services and other services, among which the other services are some non-critical services that do not need to be started immediately. There are more than 100 of these three types of services. Some of the system services and their functions are listed below.

Guide services role
Installer A service class of APK is installed. The Installer service can be started only after the Installer service is started
ActivityManagerService Responsible for starting, switching and scheduling of four components
PowerManagerService Calculate the system’s calculations relative to Power, and then decide how the system should react
LightsService Manage and display backlit leds
DisplayManagerService Used to manage all display devices
UserManagerService Multi-user mode management
SensorService Provide various sensor services for the system
PackageManagerService It is used to install, parse, delete, and uninstall the APK
. .
Core services role
DropBoxManagerService Used to generate and manage some log files while the system is running
BatteryService Manage battery-related services
UsageStatsService How often and how long mobile phone users use each APP
WebViewUpdateService WebView update service
Other services role
CameraService Camera-related services
AlarmManagerService Global timer management service
InputManagerService Managing Input Events
WindowManagerService Window management service
VrManagerService Manage services in VR mode
BluetoothService Bluetooth Management Service
NotificationManagerService Notification Management Service
DeviceStorageMonitorService Storage management services
LocationManagerService Location management Service
AudioService Audio related management services
. .

3. Provide an example for starting ActivityManagerService

Because the service startup logic is similar, start ActivityManagerService as an example

//com.android.server SystemServer.java
 private void startBootstrapServices(a) {...//1. Invoke startService of SystemServiceManager
    mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
   //2. AMS is bound to the system service management class
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
   //3. AMS is bound to the APK installation servicemActivityManagerService.setInstaller(installer); . }Copy the code

We see first SystemServiceManager. StartService implementation

   //com.android.server SystemServiceManager.java
		public <T extends SystemService> T startService(Class<T> serviceClass) {
        try{...try {
            		//1. Reflection instantiates objects
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } catch (InstantiationException ex) {
              
            ....
         		/ / 2.
            startService(service);
            return service;
        } finally{ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); }}Copy the code
    public void startService(@NonNull final SystemService service) {
        / / 1.
        mServices.add(service);
        // Start it.
        long time = System.currentTimeMillis();
        try {
          	/ / 2.
            service.onStart();
        } catch(RuntimeException ex) { ... }... }Copy the code

We know serviceClass through code is with the parameter passed in ActivityManagerService. Lifecycle. The class to the class and then reflect instantiation object Lifecycle, Finally Lifecycle’s onStart function is called. The following code

//com.android.server.am ActivityManagerService.java

    public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;

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

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

        public ActivityManagerService getService(a) {
          / / 3.
            returnmService; }}Copy the code

Lifecycle is a static inner class in AMS that inherits SystemService. Lifecycle is a static inner class that inherits SystemService. Lifecycle is a static inner class that inherits SystemService. This corresponds to the onStart function of service subclass Lifecycle, Finally getService is mSystemServiceManager. StartService (ActivityManagerService. Lifecycle. The class). The getService () function call.

At this point ActivityManagerService is instantiated by SystemServiceManager.

summary

The SystemServer startup logic is similar, so the last AMS to illustrate the startup process. Finally, the SystemServer process startup and other service startup are also explained, and finally we conclude the link.

conclusion

Java framework entry zygoteinit.main () function to start the SystemServer process and handle the service startup logic execution process summary description below:

    1. Create a Socket with the Server name “Zygote” and wait for AMS to request Zygote to create a new application process.
    1. Preload classes and resources.
    1. Determine whether to create a SystemServer process based on the information passed by JNI.
    1. Start a Binder thread pool to communicate with other processes.
    1. Enter the systemServer.java main() function and create the SystemServiceManager, which is used to create, start, and manage the life cycle of various services.
    1. Start various system services.
    1. Wait for AMS requests to create new application processes.

AMS and how the four components work will be updated in the future

reference

  • Android Advanced Decryption