Android 7.0 System Start

Posted by WhiteHawksan on Sat, 08 Jun 2019 23:46:47 +0200

    The Linux kernel is booted by Bootloader loading configuration first, and the Android system is booted only after the Linux kernal is booted.

1. Start the init process

After the Linux kernel starts, the first android user process Init ( system core init init. cpp) will be opened. The key code is as follows:

int main(int argc, char** argv) {
    ......
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();
        // Clear the umask. Sets default permissions when creating files
        umask(0);
        // Get the basic filesystem setup we need put together in the initramdisk
        // on / and then we'll let the rc file figure out the rest.
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);

        ......
    }
    // At this point we're in the second stage of init.
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";
    ...... // Some initialization operations
    ActionManager& am = ActionManager::GetInstance();
    ServiceManager& sm = ServiceManager::GetInstance();
    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am));
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        // Parsing init.rc file
        parser.ParseConfig("/init.rc");
        parser.set_is_system_etc_init_loaded(
                parser.ParseConfig("/system/etc/init"));
        parser.set_is_vendor_etc_init_loaded(
                parser.ParseConfig("/vendor/etc/init"));
        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
    } else {
        parser.ParseConfig(bootscript);
        parser.set_is_system_etc_init_loaded(true);
        parser.set_is_vendor_etc_init_loaded(true);
        parser.set_is_odm_etc_init_loaded(true);
    }
    ......
    return 0;
}

2. Start the Zygo process

In the main method of init.cpp, the init.rc file ( system core rootdir init.rc) is parsed, which is an initialization file defined by AIL (Android Init Language), and the specific grammatical rules are in the system core init README.md file. In the init.rc file, the configuration information of the Zygo process is introduced through the following statement.

import /init.${ro.zygote}.rc

Specific configuration information is init.zygote32.rc ( system core rootdir init.zygote32.rc) file for example: including user, group, priority, and operation information at restart of zygote.

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

From the init.zygote32.rc configuration information, you can know that the source file of zygote is in the / system/bin/app_process directory, app_main.cpp.
(Source file frameworks base cmds app_process app_main. cpp), the following is the annotation of the file, which shows that the file is the entry of the application process.

/*
 * Main entry of app process.
 *
 * Starts the interpreted runtime, then starts up the application.
 *
 */

The main method of this document is as follows:

int main(int argc, char* const argv[])
{
    ......

    // Android Runtime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0], the first parameter is ignored
    argc--;
    argv++;

    // Configure runtime
    ......
    // Parse the parameters of runtime and ignore the first invalid parameter
    bool zygote = false;
    bool startSystemServer = false;

    ......
    if (zygote) {
        // Start zygote if the zygote process is not started
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

After app_main.cpp is executed, it is officially transferred from c/c++ to Java to execute ZygoteInit ( frameworks base core java com android).\
Interna os ZygoteInit. java) process, through the annotation of this file, you can see that the main operations in the process are: preloading some classes, waiting for some commands in the socket.

/**
 * Startup class for the zygote process.
 *
 * Pre-initializes some classes, and then waits for commands on a UNIX domain
 * socket. Based on these commands, forks off child processes that inherit
 * the initial state of the VM.
 *
 */

The main method in ZygoteInit.java is as follows:

public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();
        // Zygote goes into its own process group.
        // Set the process pid to 0
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }
        try {
            // Registered Monitoring
            zygoteServer.registerServerSocket(socketName);
            // Preload some key classes
            preload();

            ......
            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();
            // Set seccomp policy
            Seccomp.setPolicy();
            ZygoteHooks.stopZygoteNoThreadCreation();
            if (startSystemServer) {
                // Open System Server
                startSystemServer(abiList, socketName, zygoteServer);
            }
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

The preload() method is as follows: load the resources and classes necessary for the android system and application operation (preload the class file through preloadClassess())

static void preload() {
        Log.d(TAG, "begin preload");
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
        beginIcuCachePinning();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
        preloadClasses();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
        preloadResources();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
        preloadOpenGL();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        preloadSharedLibraries();
        preloadTextResources();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        WebViewFactory.prepareWebViewInZygote();
        endIcuCachePinning();
        warmUpJcaProviders();
        Log.d(TAG, "end preload");
    }

Preloaded class information configuration, source directory ( frameworks base preloaded-classes)

  /**
    * The path of a file that contains classes to preload.
    */
    private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";

3. Start the System Server process

Start SystemServer () is called in the main method of ZygoteInit.java to open the System Server process:

/**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
.......   
        /* Hardcoded command line to start the system server */
        // Hard-coded command line to open system server
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };

        ......

    }

The source file directory of System Server ( frameworks base services java com android server SystemServer. java), where the main method directly calls its own run method. In the run method, a series of services are opened and Looper.prepareMainLooper() and Looper.loop() methods are called to initialize the message loop of the main thread.

   /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
private void run() {
        try {
            // Mmmmmm... more memory!
            VMRuntime.getRuntime().clearGrowthLimit();
            // The system server has to run all of the time, so it needs to be
            // as efficient as possible with its memory usage.
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
            // Some devices rely on runtime fingerprint generation, so make sure
            // we've defined it before booting further.
            Build.ensureFingerprintProperty();
            // Within the system server, it is an error to access Environment paths without
            // explicitly specifying a user.
            Environment.setUserRequired(true);
            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);
            // Ensure binder calls into the system always run at foreground priority.
            BinderInternal.disableBackgroundScheduling(true);
            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);
            // Prepare the main looper thread (this thread).
            android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            // Here, the Looper.prepareMainLooper() method is called to initialize Looper in the main thread.
            Looper.prepareMainLooper();
            // Initialize native services.
            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.
            createSystemContext();
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
        // Start services.
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            // Turn on ancillary services, including sensors, brightness
            startBootstrapServices();
            // Open Core Services, Battery Service, Usage Stats Service, WebView Update Service
            startCoreServices();
            // Open some other services: Vibrator Service, Network Management Service, Connectivity Service, Network Stats Service...
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
        // Loop forever.
        Looper.loop();

    }

Topics: Android Java socket Linux