1. The zygote process.

Fork from the init process.

Zygote has two main functions, starting the SystemServer process and forking child processes. WMS, AMS, PMS, etc. all run in systemServer processes. Our normal app process is fork by Zygote.

Why does Zygote need a single thread when forking child threads?

Fork is based on copy-on-write. The ZYgote process has started the JVM, class preloaded resources, and so on. Resources can be inherited from the parent process at fork time. However, fork supports only single threads, not multiple threads. Zygote creates child processes with only one thread, which can cause problems such as deadlocks or resource missyncing. There are many threads in the parent process. When zygote forks a child process, it stops all threads outside the parent’s main thread and waits for the fork process to complete. It is important to note, however, that the Zygote process is not single-threaded, as it has daemon threads to run.

Why not just use SystemServer for incubation

1. From the perspective of architectural design principles, try to achieve the principle of single class or module.

2. From the perspective of function realization. When forked, the child inherits some of the parent’s resources. We need the most preparation when we start a new inheritance. For example, create VMS and load resources. These, if loaded ahead of time, can greatly optimize the process creation process. The systemServer process is mainly used to incubate various sample services and cannot be inherited from child processes. When we start the process, it’s best to be clean, except for the necessary resources. So the system creates a Zygote process. It not only meets the purpose of efficient fork process, but also achieves the single and decoupled module function.

Zygote’s IPC uses sockets, not binders

To avoid deadlocks when forking child threads, a single-threaded environment is required. Binders, on the other hand, are individual threads and are prone to deadlocks when child threads are forked.

2. Binder is cumbersome to call. If Zygote uses Binder to communicate, you need to open the Binder driver, get file descriptors, mMAP memory maps, and create binder objects to the serviceManager. Binder objects are also queried from the serviceManager when invoked. A few back and forth is more troublesome. Zygote and systemServer processes are the parent and child relationship, for this simple message, socket is more convenient.

Zygote uses binder to fork systemServer processes, which inherit zygote’s descriptors and memory maps. The two processes share a common set of data results at the Binder driver layer. Copy-on-write of the child causes the address space to be remapped. However, the child process still accesses the mmap address of the previous parent process, resulting in SIGSEGV and SEGV_MAPERR errors

2. Start the Android system

The overall startup of Android system is quite complicated. The main nodes can be briefly described as. 1. The init process forks out the Zygote process. Zygote forks the SystemServer process and other child processes using the runOnce method. Systemserver starts with the startSystemServer() method. Binder is started with the nativeZygoteInit() method. Then call systemServer’s main function. The main function has the following functions.

private void run(){
   Looper.prepareMainLooper();
   System.loadLibrary("system_service");
   createSystemContext();

   startBootStrapService();
   startCoreService();
   startOtherService();

   Looper.loop();
}
Copy the code
How system services are published:

PublishBinderService (String name,IBinder Service) registers the service with the serviceManager

What thread does the system service run on:

DisplayThead, fgThread IoThread, UIThread (here the UIThread child thread), binder threads

How the interdependencies between services are resolved:

Batch startup: For example, AMS, PMS startup in phases: Different services are started in different phases

Start the desktop

Finally, call the systemReady() method to start the launcher with startHomeActivityLocked

3. Differences between system services and BIND services

The specific type System services The bind service
Start the way StartBootStrapService () in the ststemService process; startCoreService(); startOtherService(); In the start StartService (Intent Intent),classLoader loads the class, and then creates the context
Registration way Public static void addService(String name,IBInder Service){getServiceManager().addService(name,service,false)} Binder service to AMS
Registered location Registered to serviceManager Registered with the AMS
Registration time (1) systemService (Java) (2) SurfaceFlinger (jNI Manually register
use context.getSystemService(Context.POWER_SERVICE) binderService(serviceIntent,ServiceConnection)

4. Process & Binder start

The diagram shows the app’s cold startup process. The startup core of the app is still Zygote. Binder communication is an inescapable point in the startup process.

The application notifies AMS that it has passed when it has startedbinderNotify by correspondence. Binder starts at ZygoteStart the processFrom time to time. Zygote calls the runOnce function when it receives an AMS startup request

boolean runOnce(){
  Stringargs=readArgumentList(); int pid=Zygote.forkAndSpecialize(...) ;if(pid==0){
   handleChildProc();
   return true;
  }else {
   // deal parentProc }}Copy the code

Binder is started in nativeZygoteInit() in handleChildProc(). Binder startup is divided into four main steps

  1. Open binder drive
  2. Map memory and allocate buffers
  3. Register binder threads
  4. Enter the binder loop

5.Application

Generally used:

  1. Save global application variables
  2. Initialization operation
  3. Provide context

Initialization: Follow up from main

public static void main(String[] args){
    Looper.prepareMainLooper();
    ActivityThread thread=new ActivityThread();// Just a normal Java class, not thread
    thread.attach(false);
    
    Looper.loop();
}
Copy the code

Called in the attach function

private void attach(){
  final IActivityManager mgr=ActivityManagerNative.getDefault();//AMS is the binder proxy object for the application process
  mgr.attachApplication(mAppthread);//mAppthread is a binder object for application processes that is passed into AMS
}
Copy the code

The function is then called in ASM

boolean attachApplicationLocked(IApplicationThread thread){
 thread.bindApplication();//IPC communicates to the application process
}
Copy the code

The bindApplication function of the application process is

public  final voidBindApplication () {AppBindData data=new AppBindData();
 
 sendMessage(H.BIND_APPLICATION,data);// Throw it to the main application thread
}
Copy the code

In the main thread to create the Application object and call the mInstrumentatio. CallApplicationOnCreate (app);