Zygote is actually a process reproduction tool that uses the socket select model for reproduction. Fork is executed in a command-like manner.
The flowchart is shown below.
You can see:
1. the Zygote service is actually a Select service model.
2. To start java code, an androidRuntime is enabled and disabled.
3. started SystemServer process. This process starts a thread to register many services, starts the HOME (desktop) of the mobile phone, and starts the service loop. (Note: this service is a Binder service, and the Binder service starts with two threads. It may be because there are two CPUs.
The Code is as follows:
4. Zygote enters the select loop system and starts the service.
5. This service is simple and common service code. (That is, data retrieval and data transmission are similar to SOCKET ). The upper layer must write the corresponding code based on the service prototype.
Java code
ProcessState: self ()-> startThreadPool (); // start one.
IPCThreadState: self ()-> joinThreadPool (); // Add this thread.
Cpp Code
Case BR_TRANSACTION:
{
Binder_transaction_data tr;
Result = mIn. read (& tr, sizeof (tr ));
LOG_ASSERT (result = NO_ERROR,
"Not enough command data for brTRANSACTION ");
If (result! = NO_ERROR) break;
Parcel buffer;
Buffer. ipcSetDataReference (
Reinterpret_cast <const uint8_t *> (tr. data. ptr. buffer ),
Tr. data_size,
Reinterpret_cast <const size_t *> (tr. data. ptr. offsets ),
Tr. offsets_size/sizeof (size_t), freeBuffer, this );
Const pid_t origPid = mCallingPid;
Const uid_t origUid = mCallingUid;
MCallingPid = tr. sender_pid;
MCallingUid = tr. sender_euid;
Int curPrio = getpriority (PRIO_PROCESS, mMyThreadId );
If (gDisableBackgroundScheduling ){
If (curPrio> ANDROID_PRIORITY_NORMAL ){
// We have inherited a specified CED priority from the caller, but do not
// Want to run in that state in this process. The driver set our
// Priority already (though not our scheduling class), so bounce
// It back to the default before invoking the transaction.
Setpriority (PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL );
}
} Else {
If (curPrio> = ANDROID_PRIORITY_BACKGROUND ){
// We want to use the inherited priority from the caller.
// Ensure this thread is in the background scheduling class,
// Since the driver won't modify scheduling classes for us.
// The scheduling group is reset to default by the caller
// Once this method returns after the transaction is complete.
AndroidSetThreadSchedulingGroup (mMyThreadId,
ANDROID_TGROUP_BG_NONINTERACT );
}
}
// LOGI (">>>> TRANSACT from pid % d uid % d \ n", mCallingPid, mCallingUid );
Parcel reply;
IF_LOG_TRANSACTIONS (){
TextOutput: Bundle _ B (alog );
Alog <"BR_TRANSACTION thr" <(void *) pthread_self ()
<"/Obj" <tr.tar get. ptr <"/code"
<TypeCode (tr. code) <":" <indent <buffer
<Dedent <endl
<"Data addr ="
<Reinterpret_cast <const uint8_t *> (tr. data. ptr. buffer)
<", Offsets addr ="
<Reinterpret_cast <const size_t *> (tr. data. ptr. offsets) <endl;
}
If (tr.tar get. ptr ){
Sp <BBinder> B (BBinder *) tr. cookie );
Const status_t error = B-> transact (tr. code, buffer, & reply, 0 );
If (error <NO_ERROR) reply. setError (error );
} Else {
Const status_t error = the_context_object-> transact (tr. code, buffer, & reply, 0 );
If (error <NO_ERROR) reply. setError (error );
}
// LOGI ("<TRANSACT from pid % d restore pid % d uid % d \ n ",
// MCallingPid, origPid, origUid );
If (tr. flags & TF_ONE_WAY) = 0 ){
LOG_ONEWAY ("Sending reply to % d! ", MCallingPid );
SendReply (reply, 0 );
} Else {
LOG_ONEWAY ("NOT sending reply to % d! ", MCallingPid );
}
MCallingPid = origPid;
MCallingUid = origUid;
IF_LOG_TRANSACTIONS (){
TextOutput: Bundle _ B (alog );
Alog <"BC_REPLY thr" <(void *) pthread_self () <"/obj"
<Tr.tar get. ptr <":" <indent <reply <dedent <endl;
}
}
Break;