Android Source-Start Source Analysis of Android System

Keywords: Android Java socket Google

Analysis of Startup Source Code for Android System

Understanding Android's source code can help us learn better about the excellent source code of the system, and how a program is implemented by google engineers. Source analysis can also strengthen our programming ideas.

guide

Android system startup process source code analysis, based on Android 5.1 (I prefer this version of the source code, because the changes are large)

Android system is based on the linux kernel, so when Android starts, it loads the linux kernel first, and when the kernel starts, it loads various drivers and data structures. However, the first process of Android is the init process.

The process is implemented by C code, i.e. init.c; so we start reading from init.c. Because there are many init.c files in Android source code, we need to read the init file of kernel core, and pay attention to the package name.

1. The main function of init.c:


In C language, main method is the entry of function, we start with main function, because it is the analysis code, so I will delete the unnecessary part of the code, leaving only part as an example.

int main(int argc, char **argv)
{

    //Step 1 creates the necessary folders, with permission allocation 7 for readable, writable, executable 5 for readable, executable, and unwritable mountable disks
    mkdir("/dev", 0755);
    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");

        //Step 2 initialization code includes log initialization configuration file initialization and hardware layer initialization
    klog_init();
    property_init();


        //One initialization that needs to be noticed in setp3 is initialization of init.rc configuration file. Insert init.rc interpretation here. Please skip 2.init.rc interpretation.
    init_parse_config_file("/init.rc");

        //setp4 is followed by a lot of queues waiting for initialization to complete, as well as some operation code that failed to initialize.
    action_for_each_trigger("early-init", action_add_queue_tail);
    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");


    return 0;
}

2.init.rc Interpretation init.rc is a boot configuration file under linux system. The main work in android is as follows.


Initialization and writing of setp1 file system, change of permissions, etc.

    mkdir /sys/fs/cgroup/memory 0750 root system
    mount cgroup none /sys/fs/cgroup/memory memory
    write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1
    chown system system /sys/kernel/ipv4/tcp_rmem_max

setp2 service startup, the following example is a familiar service, network module service startup, this initialization socket network communication

 Daemon processes to be run by init.
    service netd /system/bin/netd
    class main
    socket netd stream 0660 root system
    socket dnsproxyd stream 0660 root inet
    socket mdns stream 0660 root system
    socket fwmarkd stream 0660 root inet

setp3 Key Services Explanation, Incubator Services

 service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote  //Focus on code
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm

Server service zygote, the emergence of the process is completed by an incubator, that is to say, the incubator process is the parent process.

But what's odd is that there is no service in this file that directly starts the server process? This is more troublesome.

Think about it, since the file mentions that onrestart restart zygote, starting from the idea of java, must have imported the package of the server process in this file, so let's see what the file's associated files are.

 import /init.environ.rc
 import /init.usb.rc
 import /init.${ro.hardware}.rc
 import /init.${ro.zygote}.rc
 import /init.trace.rc

At the top of the file you will find an import /init.${ro.zygote}.rc file association. Find this file. Search for this file will find several, because the operating system is divided into four digits, but the content is the same. The subtle difference is that the path folder name of app_process will be different. But they all point to the same path.

As follows:

    //service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

** setp4 in this service, you can see that the path is app_process. Look at the file in this path, there is only one file ** App_main.cpp, this C++ file is the incubator process.
This time it's a C++ file. Like C++ and C, the entry functions are main functions.

3. Interpretation of App_main.cpp Incubator:


int main(int argc, char* const argv[])
{
// Step 1 ignores some parameter initialization methods

        //step2 AppRuntime is the runtime object of Android. The following code initializes an Android runtime environment
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));


        //Step 3 initializes some important parameters, and then judges the parameters. When the parameters are initialized, the first parameter and the parent path will be skipped.
        bool zygote = false;
        bool startSystemServer = false;
        bool application = false;
        String8 niceName;
        String8 className;

        //Step 4 now starts the Android code, com.android.internal.os.ZygoteInit
        //Are you familiar with this kind of incubator process for android?
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args);
        } else if (className) {
            runtime.start("com.android.internal.os.RuntimeInit", args);
        } else {
            fprintf(stderr, "Error: no class name or --zygote supplied.\n");
            app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
        }
    }

4. Interpretation of the Java incubator class ZygoteInit.java:


step1 package com.android.internal.os; where this class resides

Step 2 has no main function for java code, so let's start with the construction method.

/**
 * Class not instantiable.
 * More embarrassing not to call
 */
private ZygoteInit() {
}

Incubator classes are private constructors that do not allow us to directly instance classes, so according to the conventional java code routine, there is usually a static method to create or directly obtain an instance.
But after looking for it, I didn't, haha! But I was surprised to find a main method:

Interpretation of step 3 main method

    public static void main(String argv[]) {

            //In the 2.3 android source code, there is a runtime heap memory size setting, but it seems to have been cancelled.

        try {
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

           /*
           *It's worth noting that google engineers have a lot of logical judgments when they write code.
           *System-level code is rigorous
           */

           //Incubator socket registration
            registerZygoteSocket(socketName);

           /**
           *static void preload()
           *As you can see from the naming, this method is used as a preload
           *Pre-loading is more important than pre-loading, which will be described in detail below.
           *Jump 5. Preload preload();
           */
            preload();

            // Do an initial gc to clean up after startup
            //One thing to emphasize is that java's recycling mechanism will come if you don't care about him.
            //But we can see that the system will call gc actively before and after doing a lot of IO operations, which can be used for reference as a habit.
            gc();


                    //Focus on Startup Services
            if (startSystemServer) {
                //Jump 6. Introduction to Starting Android System Services
                startSystemServer(abiList, socketName);
            }

        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {

        }
    }

5. Preloading preload();

Step 1 method content

    static void preload() {
            Log.d(TAG, "begin preload");
            preloadClasses();
            preloadResources();
            preloadOpenGL();
            preloadSharedLibraries();
            // Ask the WebViewFactory to do any initialization that must run in the zygote process,
            // for memory sharing purposes.
            WebViewFactory.prepareWebViewInZygote();
            Log.d(TAG, "end preload");
        }

Step 2 preloadClasses () preload class description

/**
* Read the classes to be loaded from the configuration file PRELOADED_CLASSES="/system/etc/preloaded-classes"
* Standard JAVA IO Read Operations
* Read one line at a time, and then load the reflective class
* Delete most of the code. Leave the core
* In Android 5.1, this configuration file has 3010 lines
*/

private static void preloadClasses() {

        is = new FileInputStream(PRELOADED_CLASSES);

        try {
            BufferedReader br
                = new BufferedReader(new InputStreamReader(is), 256);
            while ((line = br.readLine()) != null) {

                try {

                    Class.forName(line);

                } catch (ClassNotFoundException e) {

                } catch (UnsatisfiedLinkError e) {

                } catch (Throwable t) {

                }
            }

        } catch (IOException e) {

        } finally {
                //Load
           runtime.preloadDexCaches();
        }
    }

Step 3 preloadResources () loads resources. This method is relatively simple and has nothing to say.

 private static void preloadResources() {
    final VMRuntime runtime = VMRuntime.getRuntime();

    Debug.startAllocCounting();
    try {
        System.gc();
        runtime.runFinalizationSync();
        mResources = Resources.getSystem();
        mResources.startPreloading();
       //load resource data
        mResources.finishPreloading();
    } catch (RuntimeException e) {
        Log.w(TAG, "Failure preloading resources", e);
    } finally {
        Debug.stopAllocCounting();
    }
}

Step 4 preload opengl () method, loading opengl is related, opengl is an open source organization maintenance, loading is really as simple as java dependency libraries, there is nothing to explain.

private static void preloadOpenGL() {
    if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
        EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
    }
}

Step 5 preloadShared Libraries () loads dependency Libraries

 private static void preloadSharedLibraries() {
    Log.i(TAG, "Preloading shared libraries...");
    System.loadLibrary("android");
    System.loadLibrary("compiler_rt");
    System.loadLibrary("jnigraphics");
}

step6 WebViewFactory.prepareWebViewInZygote() browser is a special application in APP. This is not detailed here.

 public static void prepareWebViewInZygote() {
    try {
            //Loading Browser Kernel
        System.loadLibrary("webviewchromium_loader");
        long addressSpaceToReserve =
                SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
                CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
        sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
    } catch (Throwable t) {

    }
}

6. Introduction to Starting Android System Services

Step 1 method declaration

 private static boolean startSystemServer(String abiList, String socketName)
                    throws MethodAndArgsCaller, RuntimeException {
               //Code for initializing parameters (too much, no code)
               /**
               * "com.android.server.SystemServer"
               *There is an eye-catching parameter SystemServer for parameter initialization
               */
                try {
                /**
                *args The parameter "com. android. server. System Server" is encapsulated in the parameter.
                */
                    parsedArgs = new ZygoteConnection.Arguments(args);
                    /* Request to fork the system server process */

                    //In this method, you can see that fork\\\ has a system 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 (pid == 0) {
                    if (hasSecondZygote(abiList)) {
                        waitForSecondaryZygote(socketName);
                    }
                    //Processing the remaining sub-processes after the system process has been completed
                    handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

7. System Server Analysis

step1 class declaration and construction description

public final class SystemServer//This class is declared as a final class, unchangeable, open access

public SystemServer() {
    // Check for factory test mode. // Just do pattern checking
    mFactoryTestMode = FactoryTest.getMode();
}

In Android 2.3 source code, the SystemServer class also contains two internal classes, but in version 5.1, the two internal classes have been merged (SensorService.cpp). Interestingly, you can trace the source code of 2.3.

Analysis of step 2 main method

public static void main(String[] args) {
    new SystemServer().run();
    //In the main method, only the constructor and run methods are invoked.
}

Step3 run method analysis

private void run() {
    //Time Initialization
    if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
        Slog.w(TAG, "System clock is before 1970; setting to 1970.");
        SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
    }
    //Initialization of looper, handler processing does not need to initialize a looper itself because the system has prepared looper for the main thread
    Looper.prepareMainLooper();

    // Initialize native services
    /**
    *Loading a so library file and calling init's jni method
    *libandroid_servers.so
    *You can find the so Library of this file in the directory to read the init method
    */
    System.loadLibrary("android_servers");
    nativeInit();

    // Start services. Focus on point 9
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    }

    // Loop forever.
    //Here's how to start the rotation training to complete the message processing.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

8.android_servers library source code

Step 1 source code lookup
Path: F: Android 5 Android 5.1 frameworks base services core JNI

step2 nativeInit Method

static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }
}

This method mainly calls SensorService::instantiate(), and exemplifies the SensorService object.

Step 3 Sensor Service Reading

The path is as follows: F: Android 5 Android 5.1 frameworks native services sensorservice
Because the onFirstRef method is executed after SensorService starts up, let's look directly at this method.

void SensorService::onFirstRef()
{
//Initialization of Hardware
SensorDevice& dev(SensorDevice::getInstance());

        //Initialization of looper
        mLooper = new Looper(false);
        //Running SensorService
        run("SensorService", PRIORITY_URGENT_DISPLAY);

}

9 Follow-up Startup

step1 Hardware Completed

startBootstrapServices();
startCoreServices();
startOtherServices();

step2 startBootstrapServices()

 private void startBootstrapServices() {

    Installer installer = mSystemServiceManager.startService(Installer.class);

    // Activity manager runs the show.Activity related startup
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);

    //Power-related startup
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    mActivityManagerService.initPowerManagement();

   //Display related startup
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

  //Application Manager
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();

    //Service Manager
    ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());

    // Initialize attribute cache used to cache resources from packages.
    AttributeCache.init(mSystemContext);

    // Set up the Application instance for the system process and get started.
    mActivityManagerService.setSystemProcess();
}

step3 startCoreServices();
This section of the google Engineer's Notes is very detailed, but not much explanation.
private void startCoreServices() {
// Manages LEDs and display backlight.
mSystemServiceManager.startService(LightsService.class);

    // Tracks the battery level.  Requires LightService.
    mSystemServiceManager.startService(BatteryService.class);

    // Tracks application usage stats.
    mSystemServiceManager.startService(UsageStatsService.class);
    mActivityManagerService.setUsageStatsManager(
            LocalServices.getService(UsageStatsManagerInternal.class));
    // Update after UsageStatsService is available, needed before performBootDexOpt.
    mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

    // Tracks whether the updatable WebView is in a ready state and watches for update installs.
    mSystemServiceManager.startService(WebViewUpdateService.class);
}

step4 startOtherServices();
There's a lot of code here, so take it seriously and slowly.

private void startOtherServices() {
   //The previous variable initialization is deleted, and so is the following code, leaving an important part.
    try {
            //Functional service initialization
         //Telephone functions are mostly similar in this try, and it's worth noting that Bluetooth services are missing in this part.
        telephonyRegistry = new TelephonyRegistry(context);
        ServiceManager.addService("telephony.registry", telephonyRegistry);
    } catch (RuntimeException e) {

    }

     //Basically, this is where mobile phones start up services for visible parts of us, such as UI.

    try {
        wm.displayReady();
    } catch (Throwable e) {
        reportWtf("making display ready", e);
    }


      //System settings service initialization, such as wifi, notification, etc.
            mSystemServiceManager.startService("com.android.server.wifi.RttService");

        //launcher service
        mSystemServiceManager.startService(LauncherAppsService.class);
    }

      //Necessary system configuration
    Configuration config = wm.computeNewConfiguration();


   //Authorizable third party APP is started, notably the system Ready () method of Activity Manager Service
    mActivityManagerService.systemReady(new Runnable() {
        @Override
        public void run() {
            Slog.i(TAG, "Making services ready");
            mSystemServiceManager.startBootPhase(
                    SystemService.PHASE_ACTIVITY_MANAGER_READY);

            try {
                mActivityManagerService.startObservingNativeCrashes();
            } catch (Throwable e) {
                reportWtf("observing native crashes", e);
            }

            Slog.i(TAG, "WebViewFactory preparation");
            WebViewFactory.prepareWebViewInSystemServer();

             //Various judgment captures are ignored here
        }
    });
}

10.ActivityManagerService.java


The path is still under the framework
Step1 system Ready () method

public void systemReady(final Runnable goingCallback) {
    //In this method, you will find that many codes are decorated with synchronized
    synchronized(this) {
        if (mSystemReady) {
            // If we're done calling all the receivers, run the next "boot phase" passed in
            // by the SystemServer
            if (goingCallback != null) {
                goingCallback.run();
            }
            return;
        }

       //Security check is to lock screen and input password
        updateCurrentProfileIdsLocked();

        if (!mDidUpdate) {
            if (mWaitingUpdate) {
                return;
            }
            final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
            mWaitingUpdate = deliverPreBootCompleted(new Runnable() {
                public void run() {
                   //Record various components
                    systemReady(goingCallback);
                }
            }, doneReceivers, UserHandle.USER_OWNER);

        }

        mAppOpsService.systemReady();
        mSystemReady = true;
    }



    //By the time we got here, the system was ready.
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
        SystemClock.uptimeMillis());

         //Lock the activity on the top of the stack. So far, it's time to unlock the mobile phone.
        mStackSupervisor.resumeTopActivitiesLocked();
        sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
    }
}

summary

For Android startup source code, it involves a lot of things, in all aspects, I may not say very well, or you slowly absorb understanding. More support.

Posted by Mr P!nk on Thu, 11 Jul 2019 13:55:43 -0700