Android Framework——zygote starts SystemServer

overview

In the Android system, all application processes and system service processes SystemServer are conceived (fork) by the Zygote process, which may be why it is called Zygote (fertilized egg). Since the Zygote process has such an important position in the Android system, this article will analyze its startup process in detail

overall timing

Let’s first outline the overall operation process. When the power button is pressed, the system boot program BootLoader is first loaded, then the linux kernel is started, and then the init process is started, and finally the Zygote process is started. In theory, all applications in the Android system are theoretically launched by Zygote. Zygote starts the startup service in the early stage, and the main fork program in the later stage.

init start process

  • The first process in user space, the process number is 1 (it is written as 0 in page 257 of "In-depth Understanding of Android Kernel Thoughts", record it here)
  • responsibility
  • Create a Zygote
  • Initialize property service
  • The init file is located in the source directory system/core/init

The three stages of starting the init process

  • Start the power supply and start the system, and load the bootloader BootLoader.
  • Start the Linux kernel
  • Start the init process.
  • Start the Zygote process
  • Initialize the startup properties service.

Zygote process

  • The parent process of all Apps, ZygoteInit.main
  • The Zygote process is generated by fork after parsing the init.rc file by the init process. The Zygote process mainly includes
  • Load the Zygoteinit class and register the Zygote Socket server socket
  • load virtual machine
  • Loading classes in advance PreloadClasses
  • Load resources in advance PreLoadResouces
  • The system_server process is from Zygote fork. System Server is the first process hatched by Zygote. System Server is responsible for starting and managing the entire Java FrameWork, including ActivityManagerService, WorkManagerService, PagerManagerService, PowerManagerService and other services

system_server process

The carrier of the major services of the system, the SystemServer.main system_server process can be divided into boot services, core services and other services from the perspective of source code

  • 引导服务(7个):ActivityManagerService、PowerManagerService、LightsService、DisplayManagerService、PackageManagerService、UserManagerService、SensorService;
  • Core services (3): BatteryService, UsageStatsService, WebViewUpdateService;
  • Other services (70+): AlarmManagerService, VibratorService, etc.

Service Manager process

The butler of bInder service

ServiceManager is a daemon process in the Binder IPC communication process. It is also a Binder itself, but it does not use a multi-threaded model to communicate with Binder. Instead, it writes binder.c to communicate directly with the Binder driver, and there is only one binder_loop to read And processing transactions, the advantage of this is that it is simple and efficient. The ServiceManager itself is relatively simple, and its work can query and register services

flow chart

ServiceManager centrally manages all services in the system. It can control whether the process has the right to register the service through the authority, and find out whether there is a corresponding Service through the string. Since the ServiceManager process has registered the death notification of the Service, after the process where the service is located dies, Just tell the ServiceManager that each Client can obtain the Service by querying the ServiceManager

The start-up mainly includes the following stages

  • Open the Binder driver and call the mmap() method to allocate 128k of memory mapping space, binder_open
  • Register to become the big steward of Binder service binder_become_context_manager
  • Verify selinux permissions, determine whether the process has the right to register to view the specified service
  • Enter an infinite loop, process the request binder_loop sent by the Client
  • Register the service according to the name of the service. Repeated registration will remove the previous registration information
  • Death notification, when the process dies, call the binder_release method, and then call binder_node_release, this process sends a death notification callback

App process

  • App process ActivityThread.main started by Process.start
  • The first app process hatched by Zygote is Launcher, which is the desktop app that users see
  • Zygote will also create App processes such as Browser, Phone, Email, etc. Each App runs on at least one process
  • All App processes are forked by Zygote

3) Start the Zygote process

Zygote process, a process that plays an important role in the Android system. We know that the two important services PackageManagerService and ActivityManagerService in the Android system are started by the SystemServer process, and the SystemServer process itself is the fork of the Zygote process during startup In this way, we must know the important position of the Zygote process in the Android system.

It can be seen from the figure that the order of each process in the Android system is:

init process –-> Zygote process –> SystemServer process –> application process

Link

  1. When init starts Zygote, it mainly calls the AppRuntime.start() method in the main function of app_main.cpp to start the Zygote process;
  2. Then go to the start function of AndroidRuntime: use JNI to call the main function of ZygoteInit. The reason why JNI is used here is because ZygoteInit is java code. In the end, Zygote entered the Java FrameWork layer from the Native layer. Before that, no code entered the Java FrameWork layer, so it can be considered that Zygote created the java FrameWork layer.
  3. /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    @UnsupportedAppUsagepublic static void main(String argv[]) {
    ZygoteServer zygoteServer = null;
    // Mark zygote start. This ensures that thread creation will throw
    // an error.ZygoteHooks.startZygoteNoThreadCreation();
    // Zygote goes into its own process group.try {Os.setpgid(0, 0);} 
    catch (ErrnoException ex) {
    throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }Runnable caller;try {
    // Report Zygote start time to tron unless it is a runtime restartif (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
    MetricsLogger.histogram(null, "boot_zygote_init",(int) SystemClock.elapsedRealtime());}
    String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
    TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,Trace.TRACE_TAG_DALVIK);
    bootTimingsTraceLog.traceBegin("ZygoteInit");
    RuntimeInit.enableDdms();
    boolean startSystemServer = false;
    String zygoteSocketName = "zygote";
    String abiList = null;
    boolean enableLazyPreload = false;
    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)) {zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
    } 
    else {throw new RuntimeException("Unknown command line argument: " + argv[i]);
    }
    }
    final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
    if (abiList == null) 
   {
   throw new RuntimeException("No ABI list supplied.");
   }
   // In some configurations, we avoid preloading resources and classes eagerly.
   // In such cases, we will preload things prior to our first fork.if (!enableLazyPreload) {bootTimingsTraceLog.traceBegin("ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());preload(bootTimingsTraceLog);EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());bootTimingsTraceLog.traceEnd(); 
   // ZygotePreload} else {Zygote.resetNicePriority();}
   // Do an initial gc to clean up after startupbootTimingsTraceLog.traceBegin("PostZygoteInitGC");gcAndFinalize();bootTimingsTraceLog.traceEnd(); 
   // PostZygoteInitGCbootTimingsTraceLog.traceEnd(); 
   // ZygoteInit// Disable tracing so that forked processes do not inherit stale tracing tags from
   // Zygote.Trace.setTracingEnabled(false, 0);Zygote.initNativeState(isPrimaryZygote);
   ZygoteHooks.stopZygoteNoThreadCreation();
   zygoteServer = new ZygoteServer(isPrimaryZygote);
   if (startSystemServer) {
// 使用了forkSystemServer()方法去创建SystemServer进程Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.if (r != null) {r.run();return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// 这里调用了ZygoteServer的runSelectLoop方法来等等ActivityManagerService来请求创建新的应用程序进程            
// loops forever in the zygote.caller = zygoteServer.runSelectLoop(abiList);} 
catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;} 
finally 
{
if (zygoteServer != null) {zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.if (caller != null) {caller.run();
}
}

Among them, the SystemServer process is started in the forkSystemServer() method of ZygoteInit, the core code of the forkSystemServer() method:

private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) 
{
// 一系统创建SystemServer进程所需参数的准备工作try {...
/* Request to fork the system server process 
*/// 3.1pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids,parsedArgs.runtimeFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);
} 
catch (IllegalArgumentException ex) 
{throw new RuntimeException(ex);}
/* For child process 
*/if (pid == 0) {
if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}
zygoteServer.closeServerSocket();
// 3.2return handleSystemServerProcess(parsedArgs);
}return null;
}

It can be seen that in the forkSystemServer() method, Note 3.1 calls Zygote's forkSystemServer() method to create a SystemServer process, which internally executes the native method nativeForkSystemServer, which will eventually use the fork function to create a SystemServer process in the current process. If the pid is equal to 0, that is, it is currently in the newly created subprocess ServerServer process, then use the handleSystemServerProcess() method at Note 3.2 to handle some processing work of the SystemServer process.

From the above analysis, we can know that the main responsibilities of Zygote process startup are as follows:

  • 1. Create AppRuntime, execute its start method, and start the Zygote process. .
  • 2. Create a JVM and register the JNI method for the JVM.
  • 3. Use JNI to call the main function of ZygoteInit to enter the Java FrameWork layer of Zygote.
  • 4. Use the registerZygoteSocket method to create a server-side Socket, and create a new application process through the runSelectLoop method and other AMS requests.
  • 5. Start the SystemServer process.
  1. The handleSystemServerprocess() method is called to start the SystemServer process. The handleSystemServerProcess() method looks like this:
/*** Finish remaining work for the newly forked system server process.
*/
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {...
if (parsedArgs.invokeWith != null) {...} 
else {ClassLoader cl = null;
if (systemServerClasspath != null) {
// 1cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);}
/** Pass the remaining arguments to SystemServer.
*/// 2return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}

At Note 1, a PathClassLoader is created using systemServerClassPath and targetSdkVersion. Then, at Note 2, the zygoteInit() method of ZygoteInit is executed, which is as follows:

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) 
{
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
// 1ZygoteInit.nativeZygoteInit();
// 2return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
  1. In the comment 2 of the zygoteInit() method, the applicationInit() method of RuntimeInit is called here, and the code is as follows:

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

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {...
// Remaining arguments are passed to the start class's static mainreturn findStaticMain(args.startClass, args.startArgs, classLoader);
}

The findStaticMain() method is finally called in the applicationInit() method:

protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {
Class<?> cl;
try {
// 1cl = Class.forName(className, true, classLoader);
} 
catch (ClassNotFoundException ex) {
throw new RuntimeException("Missing class when invoking static main " + className,ex);
}
Method m;try {
// 2m = cl.getMethod("main", new Class[] { String[].class });
} 
catch (NoSuchMethodException ex) {
throw new RuntimeException("Missing static main on " + className, ex);} 
catch (SecurityException ex) {throw new RuntimeException("Problem getting static main on " + className, ex);}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);}
/** This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/// 3return new MethodAndArgsCaller(m, argv);
}

First, at Note 1, the SystemServer class is obtained by emission. Next, at Note 2, the main() method in SystemServer is found. Finally, at Note 3, the main() method will be passed into the MethodAndArgsCaller() method, where the MethodAndArgsCaller() method is a Runnable instance, which will eventually return until it is used in the main() method of ZygoteInit ,As follows:

if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} 
in the parent (zygote) process, and {
@code r != null} 
in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}

As you can see, the run() method of this Runnable instance is finally called directly, and the code is as follows:

/*** Helper class which holds a method and arguments and can call them. This is used as part of
* a trampoline to get rid of the initial process setup stack frames.
*/
static class MethodAndArgsCaller implements Runnable {
/** method to call 
*/private final Method mMethod;
/** argument array 
*/private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;mArgs = args;}
public void run() {try {
// 1mMethod.invoke(null, new Object[] { 
mArgs });} 
catch (IllegalAccessException ex) {throw new RuntimeException(ex);} 
catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} 
else if (cause instanceof Error) {
throw (Error) cause;}
throw new RuntimeException(ex);
}
}
}

In Note 1, this mMethod refers to the main() method of SystemServer, where the main() method of SystemServer is dynamically called, and finally, the SystemServer process enters the main() method of SystemServer. There is still a remaining problem here, why not directly call the main() method of SystemServer directly in the findStaticMain() method? The reason is that this way of recursively returning and then executing the entry method will make SystemServer's main() method look like SystemServer's entry method, and this will also clear all the stack frames required in the previous SystemServer related setup process.

--------Go to the SystemService process

  1. /frameworks/base/services/java/com/android/server/SystemServer.java

Next, let's look at the main() method of SystemServer:

/**
* The main entry point from zygote.
*/
public static void main(String[] args) 
{
new SystemServer().run();
}

The run() method of SystemServer is called in the main() method, as shown below:

private void run() {try {...
// 1Looper.prepareMainLooper();...
// Initialize native services.
// 2System.loadLibrary("android_servers");
// Check whether we failed to shut down last time we tried.
// This call may not return.performPendingShutdown();
// Initialize the system context.createSystemContext();
// Create the system service manager.
// 3mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool.get();} 
finally {traceEnd();  
// InitBeforeStartServices}
// Start services.try {
traceBeginAndSlog("StartServices");
// 4startBootstrapServices();
// 5startCoreServices();
//6startOtherServices();
SystemServerInitThreadPool.shutdown();} 
catch (Throwable ex) {Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;} 
finally {
traceEnd();
}...
// Loop forever.
// 7Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

At Note 1, a message Looper is created.

At Note 2, the dynamic library libandroid_servers.so is loaded.

At Note 3, SystemServerManager is created, its role is to create, start and manage the lifecycle of system services.

In the startBootstarpServices() method at Note 4, SystemServiceManager is used to start boot services such as ActivityManagerService, PackageManagerService, and PowerManagerService.

In the startCoreServices() method at Note 5, four core services, BatteryService, WebViewUpdateService, DropBoxManagerService, and UsageStatsService are started.

WindowManagerService, InputManagerService, CameraService and other services are started in the startOtherServices() method at Note 6. The parent class of these services is SystemService.

It can be seen that the above system services are divided into three types: boot services, core services, and other services. There are more than 100 of these system services, among which the key ones for us are:

  • Boot service: ActivityManagerService, responsible for the startup, switching, and scheduling of the four major components.
  • Boot service: PackageManagerService, responsible for installing, parsing, deleting, uninstalling and other operations on APK.
  • Boot service: PowerManagerService, responsible for calculating Power-related calculations in the system, and then deciding how the system should respond.
  • Core service: BatteryService, which manages battery-related services.
  • Other services: WindowManagerService, window management service.
  • Other services: InputManagerService, manage input events.

The startup logic of many system services is similar. Here I will start the ActivityManagerService service as an example. The code is as follows:

mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();

The startService() method of SystemServiceManager starts the ActivityManagerService, which looks like this:

@SuppressWarnings("unchecked")
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {final String name = serviceClass.getName();
...try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);
// 1service = constructor.newInstance(mContext);
} 
catch (InstantiationException ex) {...
// 2startService(service);return service;
} 
finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}

An instance of ActivityManagerService is created using reflection at Note 1, and another overloaded method of startService() is called at Note 2, as follows:

public void startService(@NonNull final SystemService service) {
// Register it.
// 1mServices.add(service);
// Start it.long time = SystemClock.elapsedRealtime();
try {
// 2service.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");
}

At Note 1, the ActivityManagerService will first be added to mServices, which is an ArrayList that stores the SystemService type, thus completing the registration of the ActivityManagerService.

At Note 2, the onStart() method of ActivityManagerService is called to start the ActivityManagerService service.

In addition to using the startService() method of SystemServiceManager to start the system service, you can also directly call the main() method of the service to start the system service, such as PackageManagerService:

mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

Here the main() method of PackageManagerService is called directly:

public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.PackageManagerServiceCompilerMapping.checkProperties();
// 1PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);
m.enableSystemUserPackages();
// 2ServiceManager.addService("package", m);
// 3final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}

At Note 1, a new instance of PackageManagerService is created directly.

In Note 2, the PackageManagerService is registered in the service manager ServiceManager. ServiceManager is used to manage various services in the system and is used for communication between Binder processes in the system C/S architecture. That is, if the client needs to use a certain Servcie, it should first Go to the ServiceManager to query the relevant information of the Service, and then use this information to establish a communication channel with the Server process where the Service is located, so that the Client can communicate with the Service of the server process.

7. Summary of SystemService process

The analysis of the startup process of SystemService has been completed so far. After the above analysis, we can see that after the SystemService process is created, the main processing is as follows:

  • 1. Start the Binder thread pool so that Binder cross-process communication can be performed with other processes.
  • 2. Create SystemServiceManager, which is used to create, start and manage the lifecycle of system services.
  • 3. Start various system services: more than 100 kinds of boot services, core services, and other services. Application development mainly focuses on the boot service ActivityManagerService, PackageManagerService and other services WindowManagerService, InputManagerService.

Guess you like

Origin blog.csdn.net/m0_71524094/article/details/129445643