Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
10 views

【Android Development Advanced Series】Android Multi-Process Topic

The document discusses the process of creating a new process for an Android application. It involves the following key steps: 1. The ActivityManagerService component creates a new process and calls Process.start(), passing in "android.app.ActivityThread" as the entry point class. 2. Process.start() calls Process.startViaZygote() to launch the process via the Zygote process. 3. Process.startViaZygote() builds arguments about the new process and calls Process.zygoteSendAndGetPid() to communicate with Zygote. 4. Process.zygoteSendAndGetPid() writes the arguments to Zygote and

Uploaded by

Siba Ssm
Copyright
© © All Rights Reserved
0% found this document useful (0 votes)
10 views

【Android Development Advanced Series】Android Multi-Process Topic

The document discusses the process of creating a new process for an Android application. It involves the following key steps: 1. The ActivityManagerService component creates a new process and calls Process.start(), passing in "android.app.ActivityThread" as the entry point class. 2. Process.start() calls Process.startViaZygote() to launch the process via the Zygote process. 3. Process.startViaZygote() builds arguments about the new process and calls Process.zygoteSendAndGetPid() to communicate with Zygote. 4. Process.zygoteSendAndGetPid() writes the arguments to Zygote and

Uploaded by

Siba Ssm
Copyright
© © All Rights Reserved
You are on page 1/ 30

【Android Development Advanced Series】Android Multi-Process Topic

Posted On 2023-10-16 09:31:33 110 0 report

1 Process Startup Process

The application process created by the Android application framework layer has two characteristics, one is that the entry function of the process is
ActivityThread.main, and the other is that the process naturally supports the Binder inter-process communication mechanism, both of which are implemented in
the process of process initialization, and this article will analyze in detail how these two characteristics are implemented in the process of creating an Android
application process.

The entry function of the application process created by the Android application framework layer is ActivityThread.main, which is easy to understand, that is,
after the process is created, the Android application framework layer will load the ActivityThread class in this process, and then execute its main function, which
is where the process executes the message loop. How should we understand the fact that the application processes created by the Android application
framework layer naturally support the Binder inter-process communication mechanism? Earlier, when we learned the Binder inter-process communication
mechanism of the Android system, we said that it has four components, namely the driver, the daemon, the Client and the Server, in which the Server
component must enter a loop to continuously interact with the Binder driver during initialization, in order to obtain the request sent by the Client component,
which can be referred to for detailsHowever, when we implement the Server component in the Android application, we do not let the process enter a loop to
wait for the request of the Client component, however, when the Client component gets the remote interface of the Server component, However, it can
smoothly communicate with the server components between processes, which is because the Android application process has already started a thread pool to
support the interaction between the server component and the binder driver when it is created, which greatly facilitates the creation of server components in the
Android application.

In the Android application framework layer, the ActivityManagerService component is responsible for creating a new process for the Android application, which
originally ran in a separate process, but this process was created during the system startup process. Under what circumstances does the
ActivityManagerService component typically create a new process for the application? When the system decides to start an activity or service in a new process,
it will create a new process, and then start the activity or service in this new processThere are three articles: Source Code Analysis of Android Application
Startup Process and Method and Process Analysis of Android Application Starting New Activities in New Process.

Before we dive into the process of starting a new process with the ActivityManagerService member function startProcessLocked, let's take a look at the
sequence diagram of the process creation process and then analyze each step in detail.
Step 1.ActivityManagerService.startProcessLocked

This function is defined in the frameworks/base/services/Java/com/android/server/am/ActivityManagerService .java file:

public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

......

private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr){

......

try{

int uid = app.info.uid;

int[] guide = null;

try{

guide = mContext.getPackageManager().getPackageGuide(app.info.packageName);

} catch(PackageManager.NameNotFoundException e) {

......

......
int debugFlags = 0;

......

int pid = Process.start("android.app.ActivityThread", mSimpleProcessManagement ? app.processName : null, uid, uid, gids, debugFlags, null);

......

} catch(RuntimeException e) {

......

......

It calls the Process.start function to start creating a new process for the application, note that it passes in a first parameter "android.app.ActivityThread", which
is the Java class to be loaded when the process is initialized, and after loading this class into the process, it will use the static member function main as the
entry point of the process, as we will see later.

Step 2. Process.start

This function is defined in the frameworks/base/core/java/android/os/Process .java file:

public class Process {

......

public static final int start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, String[] zygoteArgs)

if(supportsProcesses()) {

try{

return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, zygoteArgs);

} catch(ZygoteStartFailedEx ex) {

......

} else{

......

return 0;

......

The supportsProcesses function here returns a value of true, which is a native function implemented in the frameworks/base/core/jni/android_util_Process.cpp
file:

jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)

return ProcessState::self()->supportsProcesses();

The ProcessState::supportsProcesses function is defined in the frameworks/base/libs/binder/ProcessState .cpp file:

bool ProcessState::supportsProcesses() const

return mDriverFD >= 0;

The mDriverFD is the opening descriptor of the device file /dev/binder, and if the device file is successfully opened, its value will be greater than or equal to 0,
so its return value is true.

Back in the Process.start function, it calls the startViaZygote function to do things further.
Step3. Process.startViaZygote

This function is defined in the frameworks/base/core/java/android/os/Process .java file:

public class Process {

......

private static int startViaZygote(final String processClass, final String niceName, final int uid,

final int gid, final int[] gids, int debugFlags, String[] extraArgs) throwsZygoteStartFailedEx

int pid;

synchronized(Process.class) {

ArrayList argsForZygote = new ArrayList();

// --runtime-init, --setuid=, --setgid=,

// and --setgroups= must go first

argsForZygote.add("--runtime-init");

argsForZygote.add("--setuid="+ uid);

argsForZygote.add("--setgid="+ gid);

if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {

argsForZygote.add("--enable-safemode");

if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {

argsForZygote.add("--enable-debugger");

if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {

argsForZygote.add("--enable-checkjni");

if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {

argsForZygote.add("--enable-assert");

//TODO optionally enable debuger

//argsForZygote.add("--enable-debugger");

// --setgroups is a comma-separated list

if(guide != null & guide.length > 0) {

StringBuilder sb = new StringBuilder();

sb.append("--setgroups=");

int sz = guide.length;

for (int i = 0; i < sz; i++) {

if (i != 0) {

sb.append(',');

sb.append(gids[i]);

argsForZygote.add(sb.toString());

if (niceName != null) {

argsForZygote.add("--nice-name="+ niceName);

}
argsForZygote.add(processClass);

if (extraArgs != null) {

for(String arg : extraArgs) {

argsForZygote.add(arg);

pid = zygoteSendArgsAndGetPid(argsForZygote);

......

This function puts the parameters of the created process into the argsForZygote list, for example, the parameter "--runtime-init" indicates that the runtime
library is to be initialized for the newly created process, and then calls the zygoteSendAndGetPid function for further operations.

Step 4. Process.zygoteSendAndGetPid

This function is defined in the frameworks/base/core/java/android/os/Process .java file:

public class Process {

......

private static int zygoteSendArgsAndGetPid(ArrayList args) throws ZygoteStartFailedEx

int pid;

openZygoteSocketIfNeeded();

try{

/**

* See com.android.internal.os.ZygoteInit.readArgumentList()

* Presently the wire format to the zygote process is:

* a) a count of arguments (argc, in essence)

* b) a number of newline-separated argument strings equal to count

* After the zygote process reads these it will write the pid of

* the child or -1 on failure.

*/

sZygoteWriter.write(Integer.toString(args.size()));

sZygoteWriter.newLine();

int sz = args.size();

for (int i = 0; i < sz; i++) {

String arg = args.get(i);

if (arg.indexOf('\n') >= 0) {

throw new ZygoteStartFailedEx("embedded newlines not allowed");

sZygoteWriter.write(arg);

sZygoteWriter.newLine();

sZygoteWriter.flush();

// Should there be a timeout on this?

pid = sZygoteInputStream.readInt();

if (pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");

} catch(IOException ex) {

......

return pid;

......

Here sZygoteWriter is a Socket write stream that is opened by the openZygoteSocketIfNeeded function:

public class Process {

......

/**

* Tries to open socket to Zygote process if not already open. If

* already open, does nothing. May block and retry.

*/

private static void openZygoteSocketIfNeeded() throws ZygoteStartFailedEx

int retryCount;

if(sPreviousZygoteOpenFailed) {

/*

* If we've failed before, expect that we'll fail again and

* don't pause for retries.

*/

retryCount = 0;

} else{

retryCount = 10;

/*

* See bug #811181: Sometimes runtime can make it up before zygote.

* Really, we'd like to do something better to avoid this condition,

* but for now just wait a bit...

*/

for (int retry = 0; (sZygoteSocket == null) && (retry < (retryCount + 1)); retry++ )

if (retry > 0) {

try{

Log.i("Zygote", "Zygote not up yet, sleeping...");

Thread.sleep(ZYGOTE_RETRY_MILLIS);

} catch(InterruptedException ex) {

// should never happen

try{

sZygoteSocket = new LocalSocket();


sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED));

sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream());

sZygoteWriter = new BufferedWriter(new OutputStreamWriter(sZygoteSocket.getOutputStream()), 256);

Log.i("Zygote", "Process: zygote socket opened");

sPreviousZygoteOpenFailed = false;

break;

} catch(IOException ex) {

......

......

......

This socket is listened to by the ZygoteInit class in the frameworks/base/core/java/com/android/internal/os/ZygoteInit .java file in the runSelectLoopMode
function.

Step 5. ZygoteInit.runSelectLoopMode

This function is defined in the frameworks/base/core/java/com/android/internal/os/ZygoteInit .java file:

public class ZygoteInit {

......

/**

* Runs the zygote process's select loop. Accepts new connections as

* they happen, and reads commands from connections one spawn-request's

* worth at a time.

* @throws MethodAndArgsCaller in a child process when a main() should

* be executed.

*/

private static void runSelectLoopMode() throws MethodAndArgsCaller {

ArrayList fds = new ArrayList();

ArrayList peers = new ArrayList();

FileDescriptor[] fdArray = new FileDescriptor[4];

fds.add(sServerSocket.getFileDescriptor());

peers.add(null);

int loopCount = GC_LOOP_COUNT;

while (true) {

int index;

/*

* Call gc() before we block in select().

* It's work that has to be done anyway, and it's better

* to avoid making every child do it. It will also

* madvise() any free memory as a side-effect.

* Don't call it every time, because walking the entire

* heap is a lot of overhead to free a few hundred bytes.

*/
if (loopCount <= 0) {

gc();

loopCount = GC_LOOP_COUNT;

} else{

loopCount--;

try{

fdArray = fds.toArray(fdArray);

index = selectReadable(fdArray);

} catch(IOException ex) {

throw new RuntimeException("Error in select()", ex);

if (index < 0) {

throw new RuntimeException("Error in select()");

} else if (index == 0) {

ZygoteConnection newPeer = acceptCommandPeer();

peers.add(newPeer);

fds.add(newPeer.getFileDesciptor());

} else{

boolean done;

done = peers.get(index).runOnce();

if(done) {

peers.remove(index);

fds.remove(index);

......

When Step 4 sends the data through the socket interface, the following statement will be filed:

done = peers.get(index).runOnce();

What we get here from peers.get(index) is a ZygoteConnection object, which represents a Socket connection, so the next step is to call the
ZygoteConnection.runOnce function for further processing.

Step 6. ZygoteConnection.runOnce

This function is defined in the frameworks/base/core/java/com/android/internal/os/ZygoteConnection .java file:

class ZygoteConnection

......

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller

String args[];

Arguments parsedArgs = null;

FileDescriptor[] descriptors;

try{

args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();

} catch(IOException ex) {

......

return true;

......

/** the stderr of the most recent request, if avail */

PrintStream newStderr = null;

if (descriptors != null && descriptors.length >= 3) {

newStderr = new PrintStream(new FileOutputStream(descriptors[2]));

int pid;

try{

parsedArgs = new Arguments(args);

applyUidSecurityPolicy(parsedArgs, peer);

applyDebuggerSecurityPolicy(parsedArgs);

applyRlimitSecurityPolicy(parsedArgs, peer);

applyCapabilitiesSecurityPolicy(parsedArgs, peer);

int[][] rlimits = null;

if (parsedArgs.rlimits != null) {

rlimits = parsedArgs.rlimits.toArray(intArray2d);

pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);

} catch(IllegalArgumentException ex) {

......

} catch(ZygoteSecurityException ex) {

......

if (pid == 0) {

// in child

handleChildProc(parsedArgs, descriptors, newStderr);

// should never happen

return true;

} else { /* pid != 0 */

// in parent... pid of < 0 means failure

return handleParentProc(pid, descriptors, parsedArgs);

......

This is where the process is actually created:

pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);

Readers with Linux development experience can easily understand this function call, this function will create a process, and there are two return values, one is
returned in the current process, and the other is returned in the newly created process, that is, it is returned in the child process of the current process, and the
return value in the current process is the pid value of the newly created child process, and the return value in the child process is 0. Since we only care about
the new process we create, let's continue along the execution path of the child process:
if (pid == 0) {

// in child

handleChildProc(parsedArgs, descriptors, newStderr);

// should never happen

return true;

} else {

/* pid != 0 */

......

This is where the handleChildProc function is called.

Step7. ZygoteConnection.handleChildProc

This function is defined in the frameworks/base/core/java/com/android/internal/os/ZygoteConnection .java file:

class ZygoteConnection {

......

private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller

......

if(parsedArgs.runtimeInit) {

RuntimeInit.zygoteInit(parsedArgs.remainingArgs);

} else{

......

......

Since in Step 3, the "--runtime-init" parameter is specified, which means that the runtime library is to be initialized for the newly created process, so the
parseArgs.runtimeInit value here is true, so we continue to run RuntimeInit.zygoteInit for further processing.

Step 8. RuntimeInit.zygoteInit

This function is defined in the frameworks/base/core/java/com/android/internal/os/RuntimeInit .java file:

public class RuntimeInit {

......

public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller

// TODO: Doing this here works, but it seems kind of arbitrary. Find

// a better place. The goal is to set it up for applications, but not

// tools like am.

System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));

System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));

commonInit();

zygoteInitNative();

int curArg = 0;

for ( /* curArg */; curArg < argv.length; curArg++) {

String arg = argv[curArg];

if (arg.equals("--")) {

curArg++;

break;
} else if (!arg.startsWith("--")) {

break;

} else if (arg.startsWith("--nice-name=")) {

String niceName = arg.substring(arg.indexOf('=') + 1);

Process.setArgV0(niceName);

if(curArg == argv.length) {

Slog.e(TAG, "Missing classname argument to RuntimeInit!");

// let the process exit

return;

// Remaining arguments are passed to the start class's static main

String startClass = argv[curArg++];

String[] startArgs = new String[argv.length - curArg];

System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);

invokeStaticMain(startClass, startArgs);

......

There are two key function calls here, one is the zygoteInitNative function call, and the other is the invokeStaticMain function call, the former is to perform the
related work of Binder driver initialization, it is because of this work that the Binder object in the process can smoothly communicate between Binder processes,
and the latter function call is the entry function of the execution process. This is the main function of the startClass class, and this startClass is the
"android.app.ActivityThread" value we passed in Step 1, which means that the main function of the android.app.ActivityThread class is to be executed.

Let's take a look at the call process of the zygoteInitNative function, and then go back to the RuntimeInit.zygoteInit function to see how it calls the main
function of the android.app.ActivityThread class.

step 9. RuntimeInit.zygoteInitNative

This function is defined in the frameworks/base/core/java/com/android/internal/os/RuntimeInit .java file:

public class RuntimeInit {

......

public static final native void zygoteInitNative();

......

As you can see here, the function zygoteInitNative is a native function implemented in the frameworks/base/core/jni/AndroidRuntime.cpp file:

static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)

gCurRuntime->onZygoteInit();

Here it calls the onZygoteInit function of the global variable gCurRuntime, which is defined at the beginning of the frameworks/base/core/jni/AndroidRuntime
.cpp file:

static AndroidRuntime* gCurRuntime = NULL;

As you can see here, its type is AndroidRuntime, which is initialized in the constructor of the AndroidRuntime class, which is also defined in the
frameworks/base/core/jni/AndroidRuntime .cpp file:

AndroidRuntime::AndroidRuntime()

......

assert(gCurRuntime == NULL); // one per process


gCurRuntime = this;

So when was the constructor of this AndroidRuntime class called? The declaration of the AndroidRuntime class is in
frameworks/base/include/android_runtime/ AndroidRuntime.h file, if we open this file, we will see that it is a virtual class, that is, we can't directly create an
AndroidRuntime object, we can only use a pointer of an AndroidRuntime class to point to a subclass of it, this subclass is AppRuntime, which is defined in
frameworks/base/cmds/app_process/app_ main.cpp file:

int main(int argc, const char* constargv[])

......

AppRuntime runtime;

......

The AppRuntime class continues with the AndroidRuntime class, which is also defined in the frameworks/base/cmds/app_process/app_main.cpp file:

class AppRuntime : public AndroidRuntime

......

};

Therefore, in the previous com_android_internal_os_RuntimeInit_zygoteInit function, the onZygoteInit function of the AppRuntime class is actually executed.

Step 10. AppRuntime.onZygoteInit

This function is defined in the frameworks/base/cmds/app_process/app_main.cpp file:

class AppRuntime : public AndroidRuntime

......

virtual void onZygoteInit()

sp proc = ProcessState::self();

if(proc->supportsProcesses()) {

LOGV("App process: starting thread pool.\n");

proc->startThreadPool();

......

};

这里它就是调用ProcessState::startThreadPool启动线程池了,这个线程池中的线程就是用来和Binder驱动程序进行交互的了。

Step 11. ProcessState.startThreadPool

这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

void ProcessState::startThreadPool()

AutoMutex _l(mLock);

if(!mThreadPoolStarted) {

mThreadPoolStarted = true;

spawnPooledThread(true);

ProcessState类是Binder进程间通信机制的一个基础组件,它的作用可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service
Manager接口之路、Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析和Android系统进程间通信(IPC)机制Binder中的Client获得Server远
程接口过程源代码分析这三篇文章。这里它调用spawnPooledThread函数进一步处理。
Step 12. ProcessState.spawnPooledThread

这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

void ProcessState::spawnPooledThread(bool isMain)

if(mThreadPoolStarted) {

int32_t s = android_atomic_add(1, &mThreadPoolSeq);

char buf[32];

sprintf(buf, "Binder Thread #%d", s);

LOGV("Spawning new pooled thread, name=%s\n", buf);

sp t = new PoolThread(isMain);

t->run(buf);

这里它会创建一个PoolThread线程类,然后执行它的run函数,最终就会执行PoolThread类的threadLoop函数了。

Step 13. PoolThread.threadLoop

这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

class PoolThread : public Thread

public:

PoolThread(bool isMain) : mIsMain(isMain)

protected:

virtual bool threadLoop()

IPCThreadState::self()->joinThreadPool(mIsMain);

return false;

const bool mIsMain;

};

这里它执行了IPCThreadState::joinThreadPool函数进一步处理。IPCThreadState也是Binder进程间通信机制的一个基础组件,它的作用可以参考浅谈
Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路、Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码
分析和Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析这三篇文章。

Step14. IPCThreadState.joinThreadPool

这个函数定义在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

void IPCThreadState::joinThreadPool(bool isMain)

......

mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

......

status_t result;

do{

int32_t cmd;

......

// now get the next command to be processed, waiting if necessary

result = talkWithDriver();
if(result >= NO_ERROR) {

size_t IN = mIn.dataAvail();

if (IN < sizeof(int32_t)) continue;

cmd = mIn.readInt32();

......

result = executeCommand(cmd);

......

} while(result != -ECONNREFUSED && result != -EBADF);

......

mOut.writeInt32(BC_EXIT_LOOPER);

talkWithDriver(false);

这个函数首先告诉Binder驱动程序,这条线程要进入循环了:

mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

然后在中间的while循环中通过talkWithDriver不断与Binder驱动程序进行交互,以便获得Client端的进程间调用:

result = talkWithDriver();

获得了Client端的进程间调用后,就调用excuteCommand函数来处理这个请求:

result = executeCommand(cmd);

Finally, when the thread exits, it also tells the binder driver that it has exited, so that the binder driver can no longer be called and distributed to it between
processes on the client side:

mOut.writeInt32(BC_EXIT_LOOPER);

talkWithDriver(false);

Let's take a look at the implementation of the talkWithDriver function.

Step 15. talkWithDriver

This function is defined in the frameworks/base/libs/binder/IPCThreadState .cpp file:

status_t IPCThreadState::talkWithDriver(bool doReceive)

......

binder_write_read bwr;

// Is the read buffer empty?

const bool needRead = mIn.dataPosition() >= mIn.dataSize();

// We don't want to write anything if we are still reading

// from data left in the input buffer and the caller

// has requested to read the next data.

const size_toutAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

bwr.write_size = outAvail;

bwr.write_buffer = (long unsigned int)mOut.data();

// This is what we'll read.

if(doReceive && needRead) {

bwr.read_size = mIn.dataCapacity();

bwr.read_buffer = (long unsigned int)mIn.data();

} else{

bwr.read_size = 0;

......
// Return immediately if there is nothing to do.

if ((bwr.write_size == 0) && (bwr.read_size == 0))

return NO_ERROR;

bwr.write_consumed = 0;

bwr.read_consumed = 0;

status_t err;

of the{

......

#if defined(HAVE_ANDROID_OS)

if(ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)

err = NO_ERROR;

else

err = -errno;

#else

err = INVALID_OPERATION;

#endif

......

} while(err == -EINTR);

....

if(err >= NO_ERROR) {

if(bwr.. write_consumed > 0) {

if(bwr.write_consumed < (ssize_t)mOut.dataSize())

mOut.remove(0, bwr.write_consumed);

else

mOut.setDataSize(0);

if(bwr.read_consumed > 0) {

mIn.setDataSize(bwr.read_consumed);

mIn.setDataPosition(0);

......

return NO_ERROR;

return err;

这个函数的具体作用可以参考Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文,它只要就是通过ioctl文件操作函数来和Binder
驱动程序交互的了:

ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)

有了这个线程池之后,我们在开发Android应用程序的时候,当我们要和其它进程中进行通信时,只要定义自己的Binder对象,然后把这个Binder对象的远程
接口通过其它途径传给其它进程后,其它进程就可以通过这个Binder对象的远程接口来调用我们的应用程序进程的函数了,它不像我们在C++层实现Binder进程
间通信机制的Server时,必须要手动调用IPCThreadState.joinThreadPool函数来进入一个无限循环中与Binder驱动程序交互以便获得Client端的请求,这样就实
现了我们在文章开头处说的Android应用程序进程天然地支持Binder进程间通信机制。

细心的读者可能会发现,从Step 1到Step 9,都是在Android应用程序框架层运行的,而从Step 10到Step 15,都是在Android系统运行时库层运行的,这两


个层次中的Binder进程间通信机制的接口一个是用Java来实现的,而另一个是用C++来实现的,这两者是如何协作的呢?这就是通过JNI层来实现的了,具体可以
参考Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析一文。
Going back to the RuntimeInit.zygoteInit function in Step 8, after initializing the infrastructure for the Binder's inter-process communication mechanism, it will
then enter the process's entry function.

Step 16. RuntimeInit.invokeStaticMain

This function is defined in the frameworks/base/core/java/com/android/internal/os/RuntimeInit .java file:

public class ZygoteInit {

......

static void invokeStaticMain(ClassLoader loader, String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller

Class cl;

try{

cl = loader.loadClass(className);

} catch(ClassNotFoundException ex) {

......

Method m;

try{

m = cl.getMethod("main", new Class[] { String[].class});

} catch(NoSuchMethodException ex) {

......

} catch(SecurityException ex) {

......

int modifiers = m.getModifiers();

......

/*

* This throw gets caught in ZygoteInit.main(), which responds

* by invoking the exception's run() method. This arrangement

* clears up all the stack frames that were required in setting

* up the process.

*/

throw new ZygoteInit.MethodAndArgsCaller(m, argv);

......

As we said earlier, the value of the className string of the parameter passed here is "android.app.ActivityThread", and here it is loaded into the process
through the ClassLoader.loadClass function:

cl = loader.loadClass(className);

Then get its static member function main:

m = cl.getMethod("main", new Class[] { String[].class});

The function finally does not call the static member function main directly, but by throwing an exception ZygoteInit.MethodAndArgsCaller, and then letting the
ZygoteInit.main function call the main function of the android.app.ActivityThread class when the exception is caught. Why? The comment has made it clear that
it is meant to clean up the stack, so that the main function of the android .app.ActivityThread class thinks that it is the entry function of the process, when in
fact, a lot of work has been done before the main function of the android.app.ActivityThread class is executed.

Let's take a look at what the ZygoteInit.main function does when it catches this exception:

public class ZygoteInit {

......

public static void main(String argv[]) {


try{

......

} catch(MethodAndArgsCaller caller) {

caller.run();

} catch(RuntimeException ex) {

......

......

It executes the run function of MethodAndArgsCaller:

public class ZygoteInit {

......

public static class MethodAndArgsCaller extends Exception implements Runnable

/** method to call */

private final Method mMethod;

/** argument array */

private final String[] mArgs;

public MethodAndArgsCaller(Method method, String[] args) {

mMethod = method;

mArgs = args;

public void run() {

try{

mMethod.invoke(null, new Object[] { mArgs });

} catch(IllegalAccessException ex) {

......

} catch(InvocationTargetException ex) {

......

......

这里的成员变量mMethod和mArgs都是在前面构造异常对象时传进来的,这里的mMethod就对应android.app.ActivityThread类的main函数了,于是最后就
通过下面语句执行这个函数:

mMethod.invoke(null, new Object[] { mArgs });

这样,android.app.ActivityThread类的main函数就被执行了。

Step 17. ActivityThread.main

这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:

public final class ActivityThread {

......

public static final void main(String[] args)

SamplingProfilerIntegration.start();
Process.setArgV0("");

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();

if(Process.supportsProcesses()) {

throw new RuntimeException("Main thread loop unexpectedly exited");

thread.detach();

String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName()

: "";

Slog.i(TAG, "Main thread of " + name + " is now exiting");

......

从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象:

ActivityThread thread = new ActivityThread();

然后进入消息循环中:

Looper.loop();

这样,我们以后就可以在这个进程中启动Activity或者Service了。

至此,Android应用程序进程启动过程的源代码就分析完成了,它除了指定新的进程的入口函数是ActivityThread的main函数之外,还为进程内的Binder对象提
供了Binder进程间通信机制的基础设施,由此可见,Binder进程间通信机制在Android系统中是何等的重要,而且是无处不在,想进一步学习Android系统的
Binder进程间通信机制,请参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。

2 进程创建

Android系统中的进程管理:进程的创建

http://mobile.51cto.com/android-520139.htm

2.1 概述

Android系统以Linux内核为基础,所以对于进程的管理自然离不开Linux本身提供的机制。例如:

· 通过fork来创建进行

· 通过信号量来管理进程

· 通过proc文件系统来查询和调整进程状态等

对于Android来说,进程管理的主要内容包括以下几个部分内容:

· 进程的创建

· 进程的优先级管理

· 进程的内存管理

· 进程的回收和死亡处理

本文会专门讲解进程的创建,其余部分将在后面的文章中讲解。

2.2 主要模块
为了便于下文的讲解,这里先介绍一下Android系统中牵涉到进程创建的几个主要模块。同时为了便于读者更详细的了解这些模块,这里也同时提供了这些
模块的代码路径。

这里提到的代码路径是指AOSP的源码数中的路径。

关于如何获取AOSP源码请参见这里:Downloading the Source。

本文以Android N版本的代码为示例,所用到的Source Code Tags是:android-7.0.0_r1。

相关模块:

· app_process

代码路径:frameworks/base/cmds/app_process

说明:app_process是一个可执行程序,该程序的主要作用是启动zygote和system_server进程。

· Zygote

代码路径:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

说明:zygote进程是所有应用进程的父进程,这是系统中一个非常重要的进程,下文我们会详细讲解。

[if !supportLists]· [endif]ActivityManager

代码路径:frameworks/base/services/core/java/com/android/server/am/

说明:am是ActivityManager的缩写。

这个目录下的代码负责了Android全部四大组件(Activity,Service,ContentProvider,BroadcastReceiver)的管理,并且还掌控了所有应用程序进程的创建
和进程的优先级管理。

因此,这个部分的内容将是本系列文章讲解的重点。

2.3 关于进程

在Android系统中,进程可以大致分为系统进程和应用进程两大类。

系统进程是系统内置的(例如:init,zygote,system_server进程),属于操作系统必不可少的一部分。系统进程的作用在于:

· 管理硬件设备

· 提供访问设备的基本能力

· 管理应用进程

应用进程是指应用程序运行的进程。这些应用程序可能是系统出厂自带的(例如Launcher,电话,短信等应用),也可能是用户自己安装的(例如:微信,支付
宝等)。

系统进程的数量通常是固定的(出厂或者系统升级之后就确定了),并且系统进程通常是一直存活,常驻内存的。系统进程的异常退出将可能导致设备无法正
常使用。

而应用程序和应用进程在每个人使用的设备上通常是各不一样的。如何管理好这些不确定的应用进程,就是操作系统本身要仔细考虑的内容。也是衡量一个
操作系统好坏的标准之一。

在本文中,我们会介绍init,zygote和system_server三个系统进程。

除此之外,本系列文章将会把主要精力集中在讲解Android系统如何管理应用进程上。

2.4 init进程(核心)

init进程是一切的开始,在Android系统中,所有进程的进程号都是不确定的,唯独init进程的进程号一定是1。因为这个进程一定是系统起来的第一个进程。
并且,init进程掌控了整个系统的启动逻辑。

我们知道,Android可能运行在各种不同的平台,不同的设备上。因此,启动的逻辑是不尽相同的。为了适应各种平台和设备的需求,init进程的初始化工作
通过init.rc配置文件来管理。你可以在AOSP源码的system/core/rootdir/路径找到这些配置文件。配置文件的主入口文件是init.rc,这个文件会通过import引入其他
几个文件。

在本文中,我们统称这些文件为init.rc。init.rc通过Android Init Language来进行配置。

建议读者大致阅读一下其语法说明 。

init.rc中配置了系统启动的时候该做哪些事情,以及启动哪些系统进程。

这其中有两个特别重要的进程就是:zygote和system_server进程。

· zygote的中文意思是“受精卵“。这是一个很有寓意的名称:所有的应用进程都是由zygote fork出来的子进程,因此zygote进程是所有应用进程的父进程。

· system_server 这个进程正如其名称一样,这是一个系统 服务器 。Framework层的几乎所有服务都位于这个进程中。这其中就包括管理四大组件的


ActivityManagerService。

2.5 Zygote进程

init.rc文件会根据平台不一样,选择下面几个文件中的一个来启动zygote进程:
· init.zygote32.rc

· init.zygote32_64.rc

· init.zygote64.rc

· init.zygote64_32.rc

这几个文件的内容是大致一致的,仅仅是为了不同平台服务的。这里我们以init.zygote32.rc的文件为例,来看看其中的内容:

service zygote/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

class main

socket zygote stream 660root system

onrestart write/sys/android_power/request_state wake

onrestart write/sys/power/state on

onrestart restartaudioserver

onrestart restartcameraserver

onrestart restart media

onrestart restart netd

writepid/dev/cpuset/foreground/tasks /dev/stune/foreground/tasks

在这段配置文件中(如果你不明白这段配置的含义,请阅读一下文档:Android Init Language),启动了一个名称叫做zygote的服务进程。这个进程是通


过/system/bin/app_process这个可执行程序创建的。

并且在启动这个可执行程序的时候,传递了`-Xzygote/system/bin --zygote --start-system-server

class main`这些参数。

要知道这里到底做了什么,我们需要看一下app_process的源码。app_process的源码在这个路径:
frameworks/base/cmds/app_process/app_main.cpp。

这个文件的main函数的有如下代码:

int main(int argc, char*const argv[])

...

while (i < argc) {

const char* arg = argv[i++];

if (strcmp(arg, "--zygote")== 0) {

zygote = true;

niceName = ZYGOTE_NICE_NAME;

} else if (strcmp(arg,"--start-system-server") == 0) {

startSystemServer = true;

...

...

if (!className.isEmpty()) {

...

} else {

...

if (startSystemServer) {

args.add(String8("start-system-server"));

...

if (zygote) {

runtime.start("com.android.internal.os.ZygoteInit", args,zygote);
} else if (className) {

runtime.start("com.android.internal.os.RuntimeInit",args, zygote);

} else {

fprintf(stderr, "Error: no classname or --zygote supplied.\n");

app_usage();

LOG_ALWAYS_FATAL("app_process: noclass name or --zygote supplied.");

return 10;

这里会判断,

· 如果执行这个命令时带了--zygote参数,就会通过runtime.start启动com.android.internal.os.ZygoteInit。

· 如果参数中带有--start-system-server参数,就会将start-system-server添加到args中。

这段代码是C++实现的。在执行这段代码的时候还没有任何Java的环境。而runtime.start就是启动Java虚拟机,并在虚拟机中启动指定的类。于是接下来的
逻辑就在ZygoteInit.java中了。

这个文件的main函数主要代码如下:

public static voidmain(String argv[]) {

...

try {

...

boolean startSystemServer = false;

String socketName = "zygote";

String abiList = null;

for (int i = 1; i < argv.length; i++){

if("start-system-server".equals(argv[i])) {

startSystemServer = true;

} else if(argv[i].startsWith(ABI_LIST_ARG)) {

...

...

registerZygoteSocket(socketName);

...

preload();

...

Zygote.nativeUnmountStorageOnInit();

ZygoteHooks.stopZygoteNoThreadCreation();

if (startSystemServer) {

startSystemServer(abiList,socketName);

Log.i(TAG, "Accepting commandsocket connections");

runSelectLoop(abiList);

closeServerSocket();

} catch (MethodAndArgsCaller caller) {

caller.run();

} catch (RuntimeException ex) {

Log.e(TAG, "Zygote died withexception", ex);


closeServerSocket();

throw ex;

在这段代码中,我们主要关注如下几行:

1. 通过 registerZygoteSocket(socketName); 注册Zygote Socket

2. 通过 preload(); 预先加载所有应用都需要的公共资源

3. 通过 startSystemServer(abiList, socketName); 启动system_server

4. 通过 runSelectLoop(abiList); 在Looper上等待连接

这里需要说明的是:zygote进程启动之后,会启动一个socket套接字,并通过Looper一直在这个套接字上等待连接。

所有应用进程都是通过发送数据到这个套接字上,然后由zygote进程创建的。

这里还有一点说明的是:

在Zygote进程中,会通过preload函数加载需要应用程序都需要的公共资源。

预先加载这些公共资源有如下两个好处:

· 加快应用的启动速度 因为这些资源已经在zygote进程启动的时候加载好了

· 通过共享的方式节省内存 这是Linux本身提供的机制:父进程已经加载的内容可以在子进程中进行共享,而不用多份数据拷贝(除非子进程对这些数据进行了
修改。)

preload的资源主要是Framework相关的一些基础类和Resource资源,而这些资源正是所有应用都需要的:

开发者通过Android SDK开发应用所调用的API实现都在Framework中。

static void preload() {

Log.d(TAG,"begin preload");

Trace.traceBegin(Trace.TRACE_TAG_DALVIK,"BeginIcuCachePinning");

beginIcuCachePinning();

Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

Trace.traceBegin(Trace.TRACE_TAG_DALVIK,"PreloadClasses");

preloadClasses();

Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");

preloadResources();

Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");

preloadOpenGL();

Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

preloadSharedLibraries();

preloadTextResources();

WebViewFactory.prepareWebViewInZygote();

endIcuCachePinning();

warmUpJcaProviders();

Log.d(TAG,"end preload");

2.6 system_server Process

As mentioned above, the zygote process will start the system_server process as needed after it is up. system_server process contains a large number of
system services. For example:

· NetworkManagementService, which is responsible for network management;

· WindowManagerService, which is responsible for window management;

· VibratorService, which is responsible for vibration management;


· InputManagerService, which is responsible for input management;

Wait a minute. We will explain system_server in other articles in the future, so I won't go into too much detail here.

In this article, we will focus only on the ActivityManagerService system service in the system_server.

2.7 ActivityManagerService

As mentioned above, the zygote process starts a socket after starting, and then waits for a connection at that socket. The one that will connect to it is the
ActivityManagerService. This is because ActivityManagerService controls the creation of all application processes. All application processes are sent by the
ActivityManagerService via a socket to the Zygote process, which is then created by the zygote fork.

ActivityManagerService uses the Process.start method to request zygote to create a process:

public static finalProcessStartResult start(final String processClass, final String niceName, int uid, int gid,int[] gids, int debugFlags, int mountExternal, int
targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[]zygoteArgs)

try {

return startViaZygote(processClass,niceName, uid, gid, gids,

debugFlags, mountExternal, targetSdkVersion, seInfo,

abi, instructionSet, appDataDir,zygoteArgs);

} catch (ZygoteStartFailedEx ex) {

Log.e(LOG_TAG, "Starting VM processthrough Zygote failed");

throw newRuntimeException("Starting VM process through Zygote failed", ex);

This function assembles the parameters needed to start the process and sends it to the zygote process via the socket. The zygote process then forks the
process based on the parameters sent.

In the ActivityManagerService, the place to call Process.start is the following method:

private final void startProcessLocked(ProcessRecord app, String hostingType,

String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs)

...

Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion,
app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs);

...

As we will see below, all four component processes are created by calling the startProcessLocked method here.

For each application process, there is a ProcessRecord in the ActivityManagerService. This object records all the detailed state of the application process.

PS: For the internal structure of ProcessRecord, we will explain it in the next article.

For ease of searching, each ProcessRecord will be stored in the following two collections.

· Collections organized by name and UID:

/**

* All of the applications we currently have running organized by name.

* The keys are strings of the application package name (as

* returned by the package manager), and the keys are ApplicationRecord

* objects.

*/

final ProcessMap mProcessNames = new ProcessMap();

· Collections organized by PID:

/**

* All of the processes we currently have running organized by pid.


* The keys are the pid running the application.

* NOTE: This object is protected by its own lock, NOT the global

* activity manager lock!

*/

final SparseArray mPidsSelfLocked = new SparseArray();

The following diagram is a subsection of the above:

2.8 关于应用组件

Processes and Threads 提到:

"When an app component starts and the app isn't running anything else, the Android system starts a new Linux process for the app using a single thread of
execution."

Therefore, any of the four components coming first will result in the creation of an application process. Let's take a closer look at how each of them leads to the
creation of the application process when it starts.

PS: The management of the four components itself is a relatively large topic, limited to space, here will not be a very in-depth explanation, here is mainly to
explain the relationship between the four components and the creation of the process.

In the app, the developer does this by:

· startActivity(Intent intent) to start the Activity

· startService(Intent service) to start the Service

· sendBroadcast(Intent intent) to send the broadcast

· ContentResolver
There are some overloaded methods for startActivity, startService, and sendBroadcast.

In fact, all of these methods mentioned here are ultimately called into the ActivityManagerService through the binder, which handles them.

To make it clear, the application process and the process where the ActivityManagerService resides (i.e., the system_server process) are independent of each
other, and the methods between the two processes usually cannot be directly called to each other.

In Android, the Binder framework is provided to provide inter-process communication and method invocation capabilities.

The invocation relationship is shown in the following figure:

2.9 Activity and Process Creation

In the ActivityManagerService, each running activity has an ActivityRecord object that records the detailed state of the activity.

The startActivity method in the ActivityManagerService accepts a request for Context.startActivity, which is coded as follows:

@Override

public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestC
ode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions)

return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());

Launching an activity is a very complex process. Here is a brief background on the background:

• ActivityManagerService uses stacks and tasks to manage activities

• Each activity belongs to a task, and a task may contain multiple activities. A stack contains multiple tasks

• The ActivityStackSupervisor class is responsible for managing all stacks

• The process of starting an activity involves:

o Intent parsing

o Stack, Task query or creation

o Creation of an activity process


o Creation of the Activity window

o Lifecycle scheduling of an activity

The following figure shows the management structure of an activity:

At the end of the activity start, the previous activity will be paused, and the newly started activity resume will be visible to the user.

At this point, if it is found that the newly started Activity process has not been started, it will be started via startSpecificActivityLocked. The entire invocation
process is as follows:

· ActivityManagerService.activityPaused =>

· ActivityStack.activityPausedLocked =>

· ActivityStack.completePauseLocked =>

· ActivityStackSupervisor.ensureActivitiesVisibleLocked=>

· ActivityStack.makeVisibleAndRestartIfNeeded =>

· ActivityStackSupervisor.startSpecificActivityLocked =>

· ActivityManagerService.startProcessLocked

· ActivityStackSupervisor.startSpecificActivityLocked

The key codes are as follows:

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig)

// Is this activity's application already running?

ProcessRecordapp = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);

r.task.stack.setLaunchTime(r);

if (app != null&& app.thread != null) {

...

mService.startProcessLocked(r.processName, r.info.applicationInfo, true,0, "activity", r.intent.getComponent(), false, false, true);

}
The ProcessRecord app here describes the process in which the Activity is located.

2.10 Service and Process Creation

Starting a Service is a bit simpler than an Activity. In the ActivityManagerService, there is a ServiceRecord object for each running Service, which records the
detailed state of the Service.

The startService method in ActivityManagerService handles requests from the Context.startService API, the relevant code:

@Override

public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId)
throwsTransactionTooLargeException

...

synchronized(this) {

final intcallingPid = Binder.getCallingPid();

final intcallingUid = Binder.getCallingUid();

final longorigId = Binder.clearCallingIdentity();

ComponentNameres = mServices.startServiceLocked(caller, service, resolvedType, callingPid,callingUid, callingPackage, userId);

Binder.restoreCallingIdentity(origId);

return res;

The mServices object in this code is of type ActiveServices, which is responsible for managing active Services.

The process of invoking a Service is as follows:

· ActivityManagerService.startService =>

· ActiveServices.startServiceLocked =>

· ActiveServices.startServiceInnerLocked =>

· ActiveServices.bringUpServiceLocked =>

· ActivityManagerService.startProcessLocked

ActiveServices.bringUpServiceLocked determines that if the process in which the Service is located has not been started, it will start it through
ActivityManagerService.startProcessLocked. The relevant code is as follows:

// Not running -- get it started, and enqueue this servicerecord

// to be executed when the app comes up.

if (app == null && !permissionsReviewRequired) {

if((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, "service", r.name, false, isolated, false)) == null) {

String msg ="Unable to launch app " + r.appInfo.packageName + "/" + r.appInfo.uid + " for service" + r.intent.getIntent() + ": process is bad";

Slog.w(TAG,msg);

bringDownServiceLocked(r);

return msg;

if (isolated) {

r.isolatedProc= app;

The mAm here is the ActivityManagerService.

2.11 Provider and Process Creation

In the ActivityManagerService, each running ContentProvider has a ContentProviderRecord object that records the detailed state of the ContentProvider.

Developers use the insert, delete, update, and query APIs in the ContentResolver to use the ContentProvider. In the ContentResolver implementation, no
matter which interface is used, the ContentResolver will first obtain a remote interface of type IContentProvider through the acquireProvider method. This
remote interface interfaces with the implementation provider of the ContentProvider.

The same ContentProvider may be used by multiple modules at the same time, and the process that calls the ContentResolver interface is only a client of the
ContentProvider. As shown in the figure below:

ContentResolver.acquireProvider will eventually be called to ActivityManagerService.getContentProvider, which is coded as follows:

@Override

public final ContentProviderHolder getContentProvider(IApplicationThread caller, String name, int userId, boolean stable)

enforceNotIsolatedCaller("getContentProvider");

if (caller == null) {

String msg ="null IApplicationThread when getting content provider " + name;

Slog.w(TAG, msg);

throw new SecurityException(msg);

// The incoming user check is now handled in checkContentProviderPermissionLocked() to deal with cross-user grant.

return getContentProviderImpl(caller, name, null, stable, userId);

In the getContentProviderImpl method, it will determine whether the corresponding ContentProvider process has been started, and if not, it will be started by
the startProcessLocked method.

2.12 Receiver and Process Creation

Developers use the Context.sendBroadcast API to send broadcasts. The ActivityManagerService.broadcastIntent method handles the corresponding
broadcast send.

Broadcasting is a one-to-many form of messaging, and the number of recipients of the broadcast is indefinite. As a result, sending broadcasts can be a time-
consuming process in itself (as notifications are made on a case-by-case basis).

Inside the ActivityManagerService, broadcasts are managed in the form of queues:


· BroadcastQueue describes a broadcast queue

· BroadcastRecord describes a broadcast event

In the ActivityManagerService, if a request is received to send a broadcast, a BroadcastRecord is created and then placed in the BroadcastQueue.

The queue is then notified to process the broadcast itself. The ActivityManagerService itself can then proceed to process the other requests.

The broadcast queue itself handles the transmission of broadcasts on a different thread, so that the load on the main thread of the ActivityManagerService is
not too heavy.

The logic of notifying the broadcast event to the receiver is actually implemented in the BroadcastQueue.processNextBroadcast(boolean fromMsg) method. In
this method, if the recipient (i.e. BrodcastReceiver) is found to have not started, it will be started via the ActivityManagerService.startProcessLocked method.
The relevance is as follows:

final void processNextBroadcast(boolean fromMsg)

...

// Hard case: need to instantiate the receiver, possibly starting its application process to host it.

ResolveInfo info = (ResolveInfo)nextReceiver;

ComponentName component = new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name);

...

// Not running -- get it started, to be executed when the app comes up.

if (DEBUG_BROADCAST)

Slog.v(TAG_BROADCAST,"Need to start app [" + mQueueName + "] " + targetProcess + " for broadcast " + r);

if ((r.curApp=mService.startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, "b


roadcast", r.curComponent, (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false)) == null)

// Ah, this recipient is unavailable. Finish it if necessary,

//and mark the broadcast record as ready for the next.


Slog.w(TAG,"Unable to launch app " + info.activityInfo.applicationInfo.packageName + "/" + info.activityInfo.applicationInfo.uid +
" for broadcast " + r.intent + ": process is bad");

logBroadcastReceiverDiscardLocked(r);

finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false);

scheduleBroadcastsLocked();

r.state = BroadcastRecord.IDLE;

return;

mPendingBroadcast = r;

mPendingBroadcastRecvIndex = recIdx;

At this point, the launch of the four major components has been analyzed.

3 Reference Links

A detailed explanation of the many processes of Android development

http://blog.csdn.net/feiyang877647044/article/details/51673466

Android In-App Multi-Process Implementation A single APK app multi-process

http://blog.csdn.net/a78270528/article/details/51143740

ONE PLACE TO BE AWARE OF ANDROID MULTI-PROCESS

http://www.cnblogs.com/John-Chen/p/4364275.html

The eighth pitfall in Android development: the multi-process problem

https://my.oschina.net/u/1393188/blog/491568

A summary of the multi-process application in Android


http://www.jb51.net/article/104173.htm

Evolution of the multi-process architecture of Android background task-based apps

http://www.jianshu.com/p/4ac1f373e8cd

Android in-app multi-process analysis and research

http://blog.csdn.net/goodlixueyong/article/details/49853079

Android enables multi-process

http://www.2cto.com/kf/201512/455410.html

Android single APK app multi-process

http://blog.csdn.net/hudashi/article/details/7858125

Android single-app multi-process and single-process multi-app

http://blog.csdn.net/Ragnaro/article/details/51569096

Source code analysis of the Android application process startup process

http://blog.csdn.net/luoshengyang/article/details/6747696

Analysis of the method and process of starting a new activity in a new process for an Android application

http://shangxun.iteye.com/blog/2124498

(Good) In-depth understanding of the Dalvik Virtual Machine - Android Application Process Startup Process Analysis

http://blog.csdn.net/threepigs/article/details/50779056

Android Basics Android in-app multi-process analysis and research

http://blog.csdn.net/qq_33326449/article/details/52748710

Summary of Android background keep-alive practice: the "stubborn disease" that instant messaging apps can't cure

http://www.52im.net/thread-429-1-1.html

Process management in Android: process creation

http://mobile.51cto.com/android-520139.htm

Understand the Android process creation process

http://gityuan.com/2016/03/26/app-process-create/

Android implements the daemon via JNI

https://blog.csdn.net/yyh352091626/article/details/50542554

Exploration of the method of creating sub-processes in Android applications

https://blog.csdn.net/a332324956/article/details/9114919

Advanced Programming in UNIX Environments (3rd Edition)

IN-DEPTH UNDERSTANDING OF THE LINUX KERNEL (VERSION 3)

Processes and Threads

Android Booting

You might also like