android source code analysis (2)

Keywords: Android Java socket xml

Android Startup Key Points

When the system bootstrapper starts the Linux kernel, the kernel loads various data structures and drivers.
Once you have the driver, start the Android system and load the first user-level process: init

system/core/init/Init.c:

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

    // Create various folders and mount directories.
    mkdir("/dev", 0755);
    ......

    // Initialize the log.
    log_init();
    
    // Parse the configuration file.
    init_parse_config_file("/init.rc");

    ...

    return 0;
}

Loading the Init.rc file starts a Zygote (incubator) process, which is a parent process for the Android system to start key services.
system/core/rootdir/Init.rc:

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

app_process, a C++ program, corresponds to App_main.cpp, and the initialization of Zyget process is opened in the App_main.cpp file.
frameworks\base\cmds\app_process \App_main.cpp:

int main(int argc, const char* const argv[])
    {
        // Define the Android runtime environment.
        AppRuntime runtime;
        int i = runtime.addVmArguments(argc, argv);
    
        ......
    
        bool startSystemServer = (i < argc) ? 
                strcmp(argv[i], "--start-system-server") == 0 : false;
        setArgv0(argv0, "zygote");
        set_process_name("zygote");

        // Start the initialization class of Zygo using the runtime environment.
        runtime.start("com.android.internal.os.ZygoteInit",
            startSystemServer);
         ......
    }

The ZygoteInit.java initialization class is called, where the value of startSystem Server is generally true and false.

frameworks\base\core\java\com\android\internal\os\ ZygoteInit.java:

public static void main(String argv[]) {
            // Load class classes that the system runs dependent on.
            preloadClasses();

            ...
            
            if (argv[1].equals("true")) {
                // The Zygote incubator process begins to incubate the core services of the system.
                startSystemServer();
            } else if (!argv[1].equals("false")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
            
            ...
        }

        private static boolean startSystemServer()
            throws MethodAndArgsCaller, RuntimeException {
            String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
                "--capabilities=130104352,130104352",
                "--runtime-init",
                "--nice-name=system_server",
                "com.android.server.SystemServer",
            };

            ...

            // The incubator forks open the System Server class and takes the parameters defined above.
            // Delivered to this class. Used to start system critical services.
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids, debugFlags, null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        
            ...
        }

SystemServer.java is called, and in its main method, the init1() method is called.

frameworks\base\services\java\com\android\server\ SystemServer.java:

public static void main(String[] args) {
            ...
            
            // Load the local dynamic link library.
            System.loadLibrary("android_servers");
    
            // Call the c function in the dynamic link library.
            init1(args);
        }
    
   // Here the function of init1 is defined as:
// Under frameworksbaseservicesjnicom_android_server_System Server.cpp
  native public static void init1(String[] args);

Init1() method is a C code implementation method, which is implemented under com_android_server_SystemServer.cpp.

frameworks\base\services\jni\com_android_server_SystemServer.cpp:

static JNINativeMethod gMethods[] = {
             // Map the native method init1 to android_server_SystemServer_init1
            { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
        };

        static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
        {
                  system_init();
        }

        // This method has no method body.
        extern "C" int system_init();

The method body of the system_init() method is in the System_init.cpp class.

frameworks\base\cmds\system_server\library\ System_init.cpp

extern "C" status_t system_init()
        {
            ......
        
            // Open some hardware-related services.
            SensorService::instantiate();
            
if (!proc->supportsProcesses()) {
        // Start the AudioFlinger
        AudioFlinger::instantiate();
        // Start the media playback service
        MediaPlayerService::instantiate();
        // Start the camera service
        CameraService::instantiate();
        // Start the audio policy service
        AudioPolicyService::instantiate();
    }
            ......
            
            // Get the Android runtime environment
            AndroidRuntime* runtime = AndroidRuntime::getRuntime();
        
            LOGI("System server: starting Android services.\n");
            // Call the static method init2 in the System Server class. Transfer from the native layer to the java layer.
            runtime->callStatic("com/android/server/SystemServer", "init2");
             ......
        }

At this point, the service at the native level is started, and System_init() returns to invoke the init2() method of System Server after opening the service at the native level.

frameworks\base\services\java\com\android\server\SystemServer.java:

public static final void init2() {
            Slog.i(TAG, "Entered the Android system server!");

            // Initialization of access to Android system services.
            Thread thr = new ServerThread();
            thr.setName("android.server.ServerThread");
            thr.start();
 }

In the init2() method, a ServerThread is opened. In the run method of ServerThread, various Framework-level services are opened. PackageManagerService and ActivityManagerService are also started at this time.

frameworks\base\services\java\com\android\server\SystemServer.java:

class ServerThread extends Thread {
    ……
    @Override
    public void run() {
        ……
 
        LightsService lights = null;
        PowerManagerService power = null;
        BatteryService battery = null;
        ConnectivityService connectivity = null;
        IPackageManager pm = null;
        Context context = null;
        WindowManagerService wm = null;
        BluetoothService bluetooth = null;
        BluetoothA2dpService bluetoothA2dp = null;
        HeadsetObserver headset = null;
        DockObserver dock = null;
        UsbObserver usb = null;
        UiModeManagerService uiMode = null;
        RecognitionManagerService recognition = null;
        ThrottleService throttle = null;
        
        // Initialize the service of the system and add the service to Service Manager to facilitate the unified management of the system in the future
        // Critical services...
        try {
            Slog.i(TAG, "Entropy Service");
            ServiceManager.addService("entropy", new EntropyService());
 
            Slog.i(TAG, "Power Manager");
            power = new PowerManagerService();
            ServiceManager.addService(Context.POWER_SERVICE, power);
 
            ………
}
}

Framework-level services are started.

Android Startup Details

  • Create folders and mount devices

  • Redirecting input and output, such as error message output

  • Setting Log Output

  • Resolve configuration information related to the current device (/ init.%s.rc)

  • Processing Action Execution: This stage Zygote will be started

     The execution of each action has its own priority:
    
       early-init
       Init
       early-boot
       boot
    
  • The infinite cycle, waiting for something to happen

int main(int argc, char **argv)
{
……
// Create folders and mount devices

    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);
 
    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);
 
……
// Input and output of initialization log
    open_devnull_stdio();
    log_init();
    
    // Load init.rc configuration file
    init_parse_config_file("/init.rc");
 
   ……
    // Resolve configuration information related to the current device
    get_hardware_name(hardware, &revision);
    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
    init_parse_config_file(tmp);
 
//Processing Action Execution: This stage Zygote will be started (executing actions according to priority)
    action_for_each_trigger("early-init", action_add_queue_tail);
……
    action_for_each_trigger("init", action_add_queue_tail);
    ……
    action_for_each_trigger("early-boot", action_add_queue_tail);
    action_for_each_trigger("boot", action_add_queue_tail);
……
// The infinite cycle, waiting for something to happen

    for(;;) {
        ……
    }
}

Init.rc Startup Details

  • Opening up various Daemons

  • Start app_process

……
// Launch daemons
service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
onrestart restart media
……
// Start app_process
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
onrestart restart netd
……

App_main implementation details

  • startVM - Turn on the virtual machine (for heap memory settings)

  • Register JNI functions

  • Start the main method of "com.android.internal.os.ZygoteInit"

void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
    ……
// Turn on the virtual machine and call it in stratVm:
// Property_get ("dalvik.vm.heapsize", "heapsizeOptsBuf+4", "16m"); to set heap memory
    /* start the virtual machine */
    if (startVm(&mJavaVM, &env) != 0)
        goto bail;
 
//Register JNI functions

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        LOGE("Unable to register all android natives\n");
        goto bail;
    }
……
// Start "com.android.internal.os.ZygoteInit"
env->CallStaticVoidMethod(startClass, startMeth, strArray);
……
}

Implementation details of ZygoteInit

  • Preload the corresponding class preloadClasses() (this process takes about 20 seconds, and pre-load about 2000 classes by reflection)

  • preloadResources() preload resource file

  • Start System Server

public static void main(String argv[]) {
        try {
            ……
            // Preload corresponding classes
            preloadClasses();
            //Preload resource files
            preloadResources();
            ……
            // Start System Server
            if (argv[1].equals("true")) {
                startSystemServer();
            } else if (!argv[1].equals("false")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
        ……
    }

After continuous optimization, the pre-loaded classes and resources have taken less than 20 seconds. In fact, most of our boot time is still spent on scanning apk.


image.png

System Server implementation details

  • Open the native World through init1()

  • Open the Java world of the Framework layer through init2()

  • When Init2() opens the Framework layer, when PackageMangerService is opened, it starts scanning and monitoring:

          system/framework, system/app, data/app, data/app, data/app-private folders under all the apk information, scan all the apk permissions and four components information, and finally find the following:  
    
        <category android:name="android.intent.category.HOME" />
    
      Launcher of this filter information starts and completes the start-up of the whole system.
    

Application Startup Details

The main role of Package Manager Service

  1. Build the socket connection between the installer of java layer and the installd of c layer, so that the functions of install,remove,dexopt in the upper layer are finally realized by installd in the lower layer.

  2. Create a PackageHandler message loop to handle external apk installation request messages, such as adbinstall, which will be sent when the package installer installs the apk

  3. Loading, parsing and managing the permission information required by each apk

  4. Start AppDirObserver thread monitoring / system/framework,/system/app,/data/app,/data/app-private directory events, mainly listening for add and remove events.

  5. Analyse all apks one by one (Android Manifest. xml, assert, res, etc.) To establish the configuration structure of each APK and add the information of each APK to the global list

  6. Save the information of each apk parsed to: data/system/packages.xml, packages.list.

     Packetages. list records the following data: pkgName, userId, debugFlag, dataPath 
    
How PackageManagerService Identify Launcher Applications

PackageManagerService finds the Intent-Filter inclusion when parsing the Android Manifest. XML of the apk:

<category android:name="android.intent.category.HOME" />

Application and start-up

How to Generate Desktop Icon of Package Manager Service

PackageManagerService finds the Intent-Filter inclusion when parsing the Android Manifest. XML of the apk:

<intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>

Activeness, this Activity is the Activeness that is opened when you click on the icon on the desktop.

Which entry class does the application start?

ActivityThread is mainly used to start the main thread of the application, and manage the activities dealing with users on the application side, and manage the life cycle of each component.
frameworks\base\core\java\android\app\ ActivityThread.java

public static final void main(String[] args) {
        ……
        // Actually, ActivityThread is what we often call UI thread, which is the main thread.
// The main thread can use Handler for asynchronous communication because Looper has been created in the main thread, and this Looper was created here. If other threads need to communicate with Handler, they need to create Looper themselves.
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }
 
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
 
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
 
        Looper.loop();
 
        ……
}
 
/** Work will be done to start activity */
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ……
        Activity a = performLaunchActivity(r, customIntent);
 
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward);
            ……
         }
}
 
/** After some initialization and assignment operations, the activity is created and its onCreate method is invoked.*/
private final Activity performLaunchActivity(ActivityClientRecord r, 
Intent customIntent) {
        ……
        Activity activity = null;
        ……
        activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        ……
            if (activity != null) {
                ……
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstance,
                        r.lastNonConfigurationChildInstances, config);
 
                // Start calling acitivity's onCreate method
mInstrumentation.callActivityOnCreate(activity, r.state);
                ……
}
……
        return activity;
    }
 
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
       ……
        ActivityClientRecord r = performResumeActivity(token, clearHide);
}
 
/** H Responsible for processing messages sent by Application Thread to message queues */
private final class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        ……
        
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
 
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo);
                    handleLaunchActivity(r, null);
                } break;
              ……
        }
      ……
}
 

Posted by tHud on Sat, 02 Feb 2019 00:36:15 -0800