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.
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
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.
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
Loading, parsing and managing the permission information required by each apk
Start AppDirObserver thread monitoring / system/framework,/system/app,/data/app,/data/app-private directory events, mainly listening for add and remove events.
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
-
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; …… } …… }