preface

We should have continued to write the other two components of the Activity and Service, but there will be a lot of repetitive content, and basically by analogy, to write in the same way as before would be a bit hydrologic suspect.

Later if I have time to comb it completely, then perhaps there is a reading value.

This article is about the startup of the system

Init process – the beginning of everything

Just like our program starts with init, the first Android process is init, process number 1, which creates Zygote, property service, etc

System startup



Android phones have boot modes such as BootLoader and Recovery. By default, press the power button to start the BootLoader, which will start the system

The startup of Android is also the startup of Linux.

When the kernel is started, steps like setting up the cache, loading the driver, and looking for the init.rc file (the configuration file) start the init process

Start the init process

The entry function to init is main(). Let’s look at its source code implementation

The system/core/init/init. CPP (android 8, 9)

int main(int argc , char** argv) {...bool is_first_stage = (getenv ("INIT_SECOND_STAGE") = =nullptr); 
    if (is_first_stage) { 
        // Create and mount the file directories required for startup
        mount ("tmpfs"."/dev"."tmpfs" , MS NOSUID,"mode=0755"); . }...// Initialize the properties service
    property_init(a); .// Start the properties service
    start_property_service(a); .if (bootscript.empty()) { 
    // Parse the init.rc configuration file
    parser.ParseConfig ("/init.rc"); . }Copy the code

Android 10 starts out with a little bit different code, but the general flow is the same. Android 11 doesn’t change that much

The system/core/init/main CPP (android 10, 11)

int main(int argc, char** argv) { ... if (argc > 1) { if (! strcmp(argv[1], "subcontext")) { android::base::InitLogging(argv, &android::base::KernelLogger); const BuiltinFunctionMap function_map; return SubcontextMain(argc, argv, &function_map); } if (! strcmp(argv[1], "selinux_setup")) { return SetupSelinux(argv); } argc > 1 starts the second stage function if (! strcmp(argv[1], "second_stage")) { return SecondStageMain(argc, argv); Return FirstStageMain(argc, argv); }Copy the code

The system/core/init/first_stage_init. CPP (android 10, 11)

int FirstStageMain(int argc, char** argv) { ... CHECKCALL(mount(" TMPFS ", "/dev", "TMPFS ", MS_NOSUID, "mode=0755")); . return 1; }Copy the code

The system/core/init/init. CPP (android 10, 11)

int SecondStageMain(int argc, char** argv) { ... // Initialize the property service property_init(); . // StartPropertyService StartPropertyService(&epoll); . // parse the init.rc configuration file LoadBootScripts(am, sm); . return 0; } static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) { Parser parser = CreateParser(action_manager, service_list); std::string bootscript = GetProperty("ro.boot.init_rc", ""); if (bootscript.empty()) { parser.ParseConfig("/init.rc"); . }... }Copy the code

The init process does several things:

  • Create and mount the file directories required for startup
  • Initialize the property service
  • Start the Properties service
  • Parse the init.rc configuration file and start Zygote

Property services

Attribute service is used to record some usage information of users and software, such as system Settings, in the form of key-value pairs, which are divided into common attributes and control attributes

  • Common attributes: such as language information, wifi information
  • Control properties: Used to perform commands, such as boot animations

Zygote

Zygote, also known as an incubator, is used to create DVMS (Dalvik Virtual Machines) and ART, application processes, and SystemServer processes that run critical services of the system

The working principle of

The application process and SystemServer process are created in the form of FOCK (replication process). Zygote’s Java framework layer creates a server-side Socket that waits for AMS to request Zygote to create a new application process.

Start the

The Zygote startup is called in the init.rc configuration file, importing the script through the ro.zygote property selection. The main method is the main() method

system/core/rootdir/init.rc

import /init.${ro.zygote}.rc
on nonencrypted
    class_start main
    class_start late_start
Copy the code

The value of the ro.zygote attribute can be:

attribute instructions
init.zygote32.rc Support for pure 32-bit programs,
init.zygote32_64.rc Support for both 32-bit and 64-bit programs
init.zygote64.rc Support for pure 64-bit programs,
init.zygote64_32.rc Support for both 32-bit and 64-bit programs

Init Starts Zygote process (process simplified)

The Zygote process is started

Starting the Zygote process does the following:

  • Create AppRuntime and call its start hang to start the Zygote process.
  • Create a Java virtual machine and register JNI methods for the Java Virtual machine.
  • Enter Zygote’s Java framework layer by calling ZygoteInit’s main function from JNI.
  • The server-side Socket is created through the registerZygoteSocket method, and the new application process is created by waiting for AMS’s request through the runSelectLoop method.
  • Start the SystemServer process.

Analyze the Zygote process startup process

Zygote start is more important, here wordy, from the point of view of the source code

AndroidRuntime start the Zygote

frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... /* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; If (startVm(&mjavavm, &env, zygote, primary_zygote)! = 0) { return; } onVmCreated(env); If (startReg(env) < 0) {ALOGE("Unable to Register all Android natives\n"); return; }... /* * Start VM. This thread becomes the main thread of the VM, and will not return until the VM exits. * className:com.android.internal.os.ZygoteInit */ char* slashClassName = toSlashClassName(className ! = NULL ? className : ""); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", Env ->CallStaticVoidMethod(startClass, startMeth,); /* keep going */} else { strArray); ... }Copy the code

After calling the CallStaticVoidMethod method, you enter the main method of ZygoteInit. This step begins to enter the Java framework layer, which is different after Android 10

ZygoteInit initialization

This step is different from android 10. Before Android 10, registerServerSocket was used to create sockets. Android 10 starts with ZygoteServer construction to create sockets, but the general process remains the same

Android 8,9 source code

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

public static void main(String argv[]) { ... / / create a Socket Server end, socketName: "zygote" zygoteServer. RegisterServerSocket (socketName); if (! enableLazyPreload) { ... // Preload classes and resources preload(bootTimingsTraceLog); . } else { Zygote.resetNicePriority(); }... If (startSystemServer) {// Start the SystemServer process (8.0 for startSystemServer) Runnable r = forkSystemServer(abiList, socketName, zygoteServer); if (r ! = null) { r.run(); return; } } Log.i(TAG, "Accepting command socket connections"); / / wait for AMS request caller = zygoteServer runSelectLoop (abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { zygoteServer.closeServerSocket(); } if (caller ! = null) { caller.run(); }}Copy the code

Android 10,11 source

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

public static void main(String argv[]) { ... if (! enableLazyPreload) { ... // Preload classes and resources preload(bootTimingsTraceLog); . } else { Zygote.resetNicePriority(); } // Create Server Socket zygoteServer = new zygoteServer (isPrimaryZygote); . If (startSystemServer) {// Start the SystemServer process (8.0 for startSystemServer) Runnable r = forkSystemServer(abiList, socketName, zygoteServer); if (r ! = null) { r.run(); return; } } Log.i(TAG, "Accepting command socket connections"); / / wait for AMS request caller = zygoteServer runSelectLoop (abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { zygoteServer.closeServerSocket(); } if (caller ! = null) { caller.run(); }}Copy the code

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

ZygoteServer(boolean isPrimaryZygote) {
    mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

    if (isPrimaryZygote) {
        mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
        mUsapPoolSocket =
                Zygote.createManagedSocketFromInitSocket(
                        Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
    } else {
        mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
        mUsapPoolSocket =
                Zygote.createManagedSocketFromInitSocket(
                        Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
    }

    mUsapPoolSupported = true;
    fetchUsapPoolPolicyProps();
}
Copy the code

SystemServer

SystemServer is a process started by Zygote to create system services such as AMS, WMS, PMS, etc

After the SystemServer process is created, it does the following:

  • Start a Binder thread pool so that you can communicate with other processes.
  • Create SystemServiceManager, which creates, starts, and manages the life cycle of system services.
  • Start various system services.

Launcher

Launcher is the desktop we usually see, which is started by AMS. The next article will introduce the startup process of Launcher

reference

[1] LIU Wangshu. Advanced Decryption for Android [M]: Publishing House of Electronics Industry,2018-10