2019 Unicorn Enterprise Heavy Gold Recruitment Python Engineer Standard >>> 
Part III: Android Launch
The Android startup process starts with the process init, so it is the ancestor process of all subsequent processes.
One,Init process
The source code is located in the system/core/init directory. Mainly done the following things:
1. Reset the processing function of the signal SIGCHLD when the child process terminates.
Act.sa_handler = sigchld_handler; // Call the wait function to wait for the child process to exit.
act.sa_flags = SA_NOCLDSTOP;
act.sa_mask = 0;
act.sa_restorer = NULL;
sigaction(SIGCHLD, &act, 0);
2. Mount the file system framework created during the kernel boot process to the appropriate directory.
mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
…
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
3. open_devnull_stdio() sets the standard input, output, and error device of the init process to the newly created device node /dev/__null__.
4. log_init(), create and open the device node /dev/__kmsg__.
5. Read and parse the rc configuration file.
5.1 Read the boot mode from the file /sys/class/BOOT/BOOT/boot/boot_mode: Factory Mode, '4'; ATE Factory Mode, '6'. See if it is a facatory mode.
5.2 If so, you need to read and parse two files: init.factory.rc and init.rc.
5.3 If it is a normal startup, read init.rc temporarily.
Here, when reading the parsing file, it is parsed in the smallest executable unit. The rules for writing the init.rc file's initialization script language can be found online. After parsing, it will not be executed immediately, but will be executed according to the conditions of its command itself before init enters the service loop.
6. Import the kernel cmdline, which is the parameter u-boot passes to the kernel, check whether it has androidboot.xxx (androidboot.mode, androidboot.hardware, etc.) parameters, if any, save it in the same name xxx (mode , hardware) in the global variable. Here is the hardware parameter. After exporting a part from the kernel, you need to export a part from /proc/cpuinfo to combine it into a complete hardware parameter, because the rc file for a specific platform will be read and parsed later.
7. Read the platform-specific initrc file, such as: init.mt6516.rc.
Need to pay attention to: For the service, here will create a struct service structure for each service, all linked into the list service_list, and will be started at the end of init.
8. Check if any of the parsed command lines belong to early-init. If so, add it to the action_queue of the linked list and execute it immediately.
9. The device_init() function will open the uevent netlink socket, traverse the /sys/class, /sys/block, /sys/devices directories, check the uevent files of all levels of the directory, and the processing will be sent by the kernel before the vold service is up. Device add, remove and other events.
10. property_init(), as its name implies, is property initialization. First create an anonymous shared memory area named system_properties, make a map read and write mapping to the init process, and the rest of the processes that share it have only read permissions. This prop_area structure is then passed to the property service via the global variable __system_property_area__.
Then call the function load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT) to load the compile-time generated attributes from the /default.prop file.
11. If there is an initlogo.rle file in the root directory, this is a blank image of two android words, which is read into fb and displayed on the LCD. Also output "A N D R O I D " to the serial port. If the image does not exist, there is no output for both.
12. Set the appropriate properties:
property_set("ro.factorytest", "0")
property_set("ro.serialno", serialno[0] ? serialno : "");
property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
property_set("ro.baseband", baseband[0] ? baseband : "unknown");
property_set("ro.carrier", carrier[0] ? carrier : "unknown");
property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
property_set("ro.hardware", hardware);
snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
property_set("ro.revision", tmp);
13. Start executing the command line with init as the trigger:
action_for_each_trigger("init", action_add_queue_tail);
drain_action_queue();
There have been executed eraly-init in front.
14. Start the property service: property_set_fd = start_property_service();
First read the attributes in the remaining three files: /system/build.prop, /system/default.prop, /system/default.prop, and then load the properties starting with persist. with the function load_persistent_properties(). Saved in the directory /data/property under the name of the file name.
Next create a socket interface called property_service (SOCK_STREAM), then enter the listening state, waiting for the property event to arrive.
15. Create a pair of sockets for signal processing.
socketpair(AF_UNIX, SOCK_STREAM, 0, s),signal_fd = s[0],signal_recv_fd = s[1]。
16. Execute the command of eraly-boot and boot as trigger
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
drain_action_queue();
17. Execute the property setting statement in the init.rc starting with property: and enable the property triggering mode.
queue_all_property_triggers();
drain_action_queue();
Property_triggers_enabled = 1; // You can execute init statements that are conditional on properties.
1. The next step is to use the poll mechanism to listen to the dynamics of several fd created earlier.
struct pollfd ufds[4];
…
ufds[0].fd = device_fd;
ufds[0].events = POLLIN;
ufds[1].fd = property_set_fd;
ufds[1].events = POLLIN;
ufds[2].fd = signal_recv_fd;
ufds[2].events = POLLIN;
for(;;) {
int nr, i, timeout = -1;
for (i = 0; i < fd_count; i++)
ufds[i].revents = 0;
Drain_action_queue(); //Execute the command that appears later in the action_queue list.
Restart_processes(); // Start all services for the first time, including later restarting these
service. Restart_service_if_needed() à service_start(svc, NULL) à fork()
…
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
if (ufds[2].revents == POLLIN) {
/* we got a SIGCHLD - reap and restart as needed */
read(signal_recv_fd, tmp, sizeof(tmp));
while (!wait_for_one_process(0))
;
continue;
}
if (ufds[0].revents == POLLIN)
Handle_device_fd(device_fd); // Vold's netlink type socket
if (ufds[1].revents == POLLIN)
Handle_property_set_fd(property_set_fd);//Attribute service socket
if (ufds[3].revents == POLLIN)
handle_keychord(keychord_fd);
}
Here init enters the dead loop and has been listening to the movement of the four file descriptors in ufds. If there is a POLLIN event, it will be processed accordingly, so init does not exit or enter the idle, but is treated as a service. Running. The fourth file descriptor is keychord_fd. It is not clear how to use this, but you can also start the service through it. You can refer to the source code.
The following is an example of init.rc, see the attachment init.rc
two,Various services started in init
The services started in init are in the order of init.rc, which are roughly:
Console: start a shell, code path: system/bin/sh, the source code contains commonly used shell commands, such as ls, cd, etc.
Adbd: start adb daemon, usually with a disabled option, indicating that it needs to be started by name, code path:system/bin/adb.
Servicemanager: This service manages all the binder services in the system. Code path: frameworks/base/cmds/servicemanager.
Vold: android udev, code path: system/vold.
Netd: start ntd daemon, code path: system/netd。
Debuggerd: start debug system, code path: system/core/debuggerd。
zygote: ['zaigəut] This is a very important service, which will be explained later. Start Android Java Runtime and start systemserver. Code path: frameworks/base/cmds/app_process.
media: add AudioFlinger, AudioPolicyService, MediaPlayerService and CameraService to servicemanager, at the same time start the management of the binder communication mechanism, relying on these two classes to complete the functions of the binder mechanism in the android middle layer: ProcessState and IPCThreadState. Code path: frameworks/base/media/mediaserver.
Bootanim: boot animation and ringtone, code path: frameworks/base/cmds/bootanimation.
Next is the modem service, such as: ccci_fsd, ccci_mdinit, pppd_gprs, pppd, gsm0710muxd, muxtestapp, sockcli, socksrv, muxreport, ril-daemon, etc., except for the first two, the following have disabled parameters, need to be by name start up.
Installd: start install package daemon, code path:
frameworks/base/cmds/installd。
There are many other services related to other hardware, such as BT, WIFI, etc.
2.1 servicemanager
This service process code is relatively simple, the function is also simple, c is implemented, used to manage all the binder services in the system, whether it is the local c++ implementation or the java language implementation, this process is required to be unified management, the most important management is , register to add services, get services.
These binder services must register their own binder entities in SMgr before they are exposed to the public. Other processes that need to use the binder service function must first obtain the corresponding reference number of the binder entity in the binder service in SMgr through SMgr. (The reference number of the binder is similar to the concept of the file descriptor in the process, and the valid range is limited to this process).
#define BINDER_SERVICE_MANAGER ((void*) 0)
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
// Open the binder device, mmap maps the binder receive buffer of the current process, and returns a binder_state structure.
if (binder_become_context_manager(bs)) {
/ / This function is used to set the current process to the service management process MSgr, the whole system is this one.
…
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
/*svcmgr_handler As a processing function, the operations that can be completed are: get the service, check if the service exists, add the service, and list the service list. The most used ones are acquisition and addition. */
return 0;
}
2.2 zygote
The zygote service process is also called the incubation process. In the linux user space, the process app_process will do
Some zygote process startup pre-work, such as starting the runtime runtime environment (instance), parameter decomposition, setting the startSystemServer flag, and then using runtime.start () to execute the zygote service code, in fact, simple point is that zygote grabbed app_process The body of this process, changed the name, replaced the latter code with the main function of zygote, which smoothly passed the zygote service process. So we use ps to see all the processes in the console, we will not see app_process, instead it is zygote.
The previous runtime.start() function is actually the class function AndroidRuntime::start(), in
In this function, a virtual machine instance is created and started to execute the main function of the com.android.internal.os.ZygoteInit package. This main function will fork a child process to start systemserver, the parent process exists as a real incubation process, whenever the system requires an Android application, Zygote will receive the socket message FORK out a child process to execute the application. program. Because the Zygote process is generated at system startup, it will complete the initialization of the virtual machine, the loading of the library, the loading and initialization of the preset class library, and can be quickly created when the system needs a new virtual machine instance. A virtual machine comes out.
Each Android application runs in a Dalvik virtual machine instance, and each virtual machine instance is a separate process space. Virtual machine threading mechanism, memory allocation and management, Mutex and so on are all dependent on the underlying linux implementation. So the android application creates a thread that will actually call the linux thread creation interface, and the virtual machine's process share a virtual machine instance to execute the java code.
2.2.1 app_process
The following focuses on the zygote service, the source code is located in frameworks/base/cmds/app_process.
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
Parameters: /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
int main(int argc, const char* const argv[])
{
…
AppRuntime runtime; // This starts the runtime runtime environment (instance). AppRuntime is a subclass of AndroidRuntime. When the object is created, the constructors of the base and subclasses are called in turn.
const char *arg;
const char *argv0;
…
argv0 = argv[0];
// ignore argv[0]
argc--;
argv++;
/*
argc = 4;
argv[0] = “-Xzygote”;
argv[1] = “/system/bin”;
argv[2] = “--zygote”;
argv[3] = “–start-system-server”;
*/
Int i = runtime.addVmArguments(argc, argv); // Find the first parameter in the argument that is not a single-start argument, here is obviously the second argument: /system/bin
if (i < argc) {
runtime.mParentDir = argv[i++]; // Save the command directory in mParentDir, then i = 2.
}
if (i < argc) {
arg = argv[i++];
If (0 == strcmp("--zygote", arg)) { // Usually this branch is true
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
// startSystemServer = true , this bool variable determines whether systemserver is started when runtime.start is executed.
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
} else {
... // only start AndroidRuntime
}
}else{
... // error handling
}
} // main()
2.2.2 AndroidRuntime
Further analysis below
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
Located in the file frameworks/base/core/jni/AndroidRuntime.cpp, the class is defined in:
frameworks/base/include/android_runtime/AndroidRuntime.h
void AndroidRuntime::start(const char* className,
const bool startSystemServer){
LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
…
JNIEnv* env;
…
/* start the virtual machine , mJavaVM is a private variable of class AndroidRuntime, env local variable in the function */
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/* Register android functions. Register the JNI local interface with the newly created virtual machine. Frameworks/base/core/jni/ All jni interfaces in this directory. */
if (startReg(env) < 0) {
…
goto bail;
}
/ / Before starting the virtual machine, you need to construct a parameter array of java form, as follows:
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
stringClass = env->FindClass("java/lang/String");
strArray = env->NewObjectArray(2, stringClass, NULL);
classNameStr = env->NewStringUTF(className);
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ?
"true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/* strArray[0] = “com.android.internal.os.ZygoteInit”
strArry[1] = “true”*/
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
slashClassName = strdup(className);
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/'; // Replace the package name with a path
startClass = env->FindClass(slashClassName); // find this package according to the path
// com.android.internal.os.ZygoteInit, this class is in the file
// com/ndroid/nternal/os/ZygoteInit.java
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
/* This parameter determines the main function we are executing next to zygoteInit.java. */
startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
LOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
// The virtual machine starts and will call the main function of the com.android.internal.os.ZygoteInit package.
…
}
}
LOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly\n");
bail:
free(slashClassName);
}
} // start()
2.2.3 ZygoteInit
Enter the main function of the com.android.internal.os.ZygoteInit package below:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
try {
…
registerZygoteSocket(); // Registers a server socket for zygote command
// load classs and resources
preloadClasses();
preloadResources();
…
// Do an initial gc to clean up after startup
Gc();/*Initialize GC garbage collection mechanism*/
/* Start systemserver by the second parameter startsystemserver=”true” passed from the front. In startSystemServer(), a new process will be named system_server, and the SystemServer.java file in the com.android.server package will be executed. The main function, source location: frameworks/base/services/java/com/android/server/SystemServer.java. */
if (argv[1].equals("true")) {
startSystemServer(); ///*************
} else if(…)
…
if (ZYGOTE_FORK_MODE) {
runForkMode(); /* ZYGOTE_FORK_MODE is always flase */
} else {
runSelectLoopMode();/* The Zygote process enters an infinite loop and is no longer returned. The next zygote will run as an incubation service process. */
}
closeServerSocket();
}
…
} // end main()
From here on, the android startup is divided into two lines, which are:
startSystemServer(); ---------- Zygote's child process
runSelectLoopMode(); /* The Zygote process enters an infinite loop, no longer returns, and performs the incubation. */
2.2.4 systemserver
In the above startSystemServer() function, the following call is made:
startSystemServer()
à Zygote.forkSystemServer()
à The parent process returns true directly, and the child process executes handleSystemServerProcess()
à RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
/*
* Pass the remaining arguments to SystemServer.
* "--nice-name=system_server com.android.server.SystemServer"
*/
/* The above RuntimeInit package is set in the file frameworks\base\core\java\com\android\internal\os\RuntimeInit.java */
à invokeStaticMain(startClass, startArgs)
/* This function is called to execute the main function of the startClass class with the argument system_server . */
à ZygoteInit.MethodAndArgsCaller(m, argv)
/* Get the main() function of the package com.android.server.SystemServer. Then execute. */
The following starts to call the main function of the com.android.server.SystemServer class, the source code is located at:
frameworks/base/services/java/com/android/server/SystemServer.java
This method is called from Zygote to initialize the system. This will cause the nativeservices (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call backup into init2() to start the Android services.
// main--->init1(system_init)--->init2(systemThread)
native public static void init1(String[] args);
public static void main(String[] args) {
...
System.loadLibrary("android_servers");// libandroid_servers.so is compiled from the source code under the directory frameworks/base/services/jni
Init1(args); // init1 is actually a jni local interface, located in the file frameworks\base\services\jni\com_android_server_SystemServer.cpp file system_init() function
}
The init1 interface is located in com_android_server_SystemServer.cpp:
extern "C" int system_init();
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz){
system_init();
}
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{"init1","([Ljava/lang/String;)V",(void*)
android_server_SystemServer_init1 },
};
The function system_init() is located in the file.
frameworks\base\cmds\system_server\library\System_init.cpp
extern "C" status_t system_init()
{
…
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::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();
//start appc service
APPCService::instantiate();
}
…
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
runtime->callStatic("com/android/server/SystemServer", "init2");
/ / Execute the init2 function of the com.android.server.SystemServer class
…
}
The init2 function of the com.android.server.SystemServer package opens a ServerThread thread:
public static final void init2() {
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
The run function of the ServerThread thread will start most of the android service in the system, and finally enter Loop.loop(),,,,(SystemServer.java)
public void run() {
…
// Critical services...
try {
…
Slog.i(TAG, "Power Manager");
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);
…
Slog.i(TAG, "Package Manager");
pm = PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF);
…
Slog.i(TAG, "Content Manager");
ContentService.main(context,
factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);
…
Slog.i(TAG, "Battery Service");
battery = new BatteryService(context);
ServiceManager.addService("battery", battery);
…
The rest of the addservice process is similar, just start the different services, and started a lot later.
Services such as: Lights, Vibrator, Alarm, Sensor, Bluetooth, Input Method, NetStat, NetworkManagement, Connectivity, Mount, Notification, Audio, etc. After these services are all started.
…
…
... // the second half of the run() function
// It is now time to start up the app processes...
Use xxx.systemReady() to notify each service that the system is ready.
…
((ActivityManagerService)ActivityManagerNative.getDefault())
.systemReady(new Runnable() {
public void run() {
…
if (batteryF != null) batteryF.systemReady();
if (connectivityF != null) connectivityF.systemReady();
if (dockF != null) dockF.systemReady();
if (uiModeF != null) uiModeF.systemReady();
if (recognitionF != null) recognitionF.systemReady();
Watchdog.getInstance().start();
…
}
});
…
Looper.loop(); // Run the message queue in this thread。
…
}
2.2.5 home interface startup
Home at
((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady(.)
The function call is started, and the parameter of systemReady() is a callback code, as shown in the gray above.
The implementation of this function is in the file: ActivityManagerService.java.
public void systemReady(final Runnable goingCallback) {
…
if (mSystemReady) {
if (goingCallback != null) goingCallback.run();
Return; // perform a callback
}
…
resumeTopActivityLocked(null);
}
private final boolean resumeTopActivityLocked(HistoryRecord prev) {
…
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
return startHomeActivityLocked();
}
…
}
private boolean startHomeActivityLocked() {
…
if (aInfo != null) {
…
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityLocked(null, intent, null, null, 0, aInfo,
Null, null, 0, 0, 0, false, false); // start home here
}
}
…
}
three,Android start icon

Reference URL:
1.
2.
3. http://www.docin.com/p-191202348.html
4.