Android應用程序框架層創建的應用程序進程具有兩個特點,一是進程的入口函數是ActivityThread.main,二是進程天然支持Binder進程間通信機制;這兩個特點都是在進程的初始化過程中實現的,本文將詳細分析Android應用程序進程創建過程中是如何實現這兩個特點的。
Android應用程序框架層創建的應用程序進程的入口函數是ActivityThread.main比較好理解,即進程創建完成之后,Android應用程序框架層就會在這個進程中將ActivityThread類加載進來,然后執行它的main函數,這個main函數就是進程執行消息循環的地方了。Android應用程序框架層創建的應用程序進程天然支持Binder進程間通信機制這個特點應該怎么樣理解呢?前面我們在學習Android系統的Binder進程間通信機制時說到,它具有四個組件,分別是驅動程序、守護進程、Client以及Server,其中Server組件在初始化時必須進入一個循環中不斷地與Binder驅動程序進行到交互,以便獲得Client組件發送的請求,具體可參考Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文,但是,當我們在Android應用程序中實現Server組件的時候,我們并沒有讓進程進入一個循環中去等待Client組件的請求,然而,當Client組件得到這個Server組件的遠程接口時,卻可以順利地和Server組件進行進程間通信,這就是因為Android應用程序進程在創建的時候就已經啟動了一個線程池來支持Server組件和Binder驅動程序之間的交互了,這樣,極大地方便了在Android應用程序中創建Server組件。
在Android應用程序框架層中,是由ActivityManagerService組件負責為Android應用程序創建新的進程的,它本來也是運行在一個獨立的進程之中,不過這個進程是在系統啟動的過程中創建的。ActivityManagerService組件一般會在什么情況下會為應用程序創建一個新的進程呢?當系統決定要在一個新的進程中啟動一個Activity或者Service時,它就會創建一個新的進程了,然后在這個新的進程中啟動這個Activity或者Service,具體可以參考Android系統在新進程中啟動自定義服務過程(startService)的原理分析、Android應用程序啟動過程源代碼分析和Android應用程序在新的進程中啟動新的Activity的方法和過程分析這三篇文章。
ActivityManagerService啟動新的進程是從其成員函數startProcessLocked開始的,在深入分析這個過程之前,我們先來看一下進程創建過程的序列圖,然后再詳細分析每一個步驟。
Step 1. ActivityManagerService.startProcessLocked
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
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[] gids = null; try { gids = mContext.getPackageManager().getPackageGids( 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) { ...... } } ...... }它調用了Process.start函數開始為應用程序創建新的進程,注意,它傳入一個第一個參數為"android.app.ActivityThread",這就是進程初始化時要加載的Java類了,把這個類加載到進程之后,就會把它里面的靜態成員函數main作為進程的入口點,后面我們會看到。
Step 2. Process.start
這個函數定義在frameworks/base/core/java/android/os/Process.java文件中:
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; } } ...... }這里的supportsProcesses函數返回值為true,它是一個Native函數,實現在frameworks/base/core/jni/android_util_Process.cpp文件中:
jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz) { return ProcessState::self()->supportsProcesses(); }
ProcessState::supportsProcesses函數定義在frameworks/base/libs/binder/ProcessState.cpp文件中:
bool ProcessState::supportsProcesses() const { return mDriverFD >= 0; }這里的mDriverFD是設備文件/dev/binder的打開描述符,如果成功打開了這個設備文件,那么它的值就會大于等于0,因此,它的返回值為true。
回到Process.start函數中,它調用startViaZygote函數進一步操作。
Step 3. Process.startViaZygote
這個函數定義在frameworks/base/core/java/android/os/Process.java文件中:
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) throws ZygoteStartFailedEx { int pid; synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); // --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 (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); int sz = gids.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); } } ...... }這個函數將創建進程的參數放到argsForZygote列表中去,如參數"--runtime-init"表示要為新創建的進程初始化運行時庫,然后調用zygoteSendAndGetPid函數進一步操作。
Step 4. Process.zygoteSendAndGetPid
這個函數定義在frameworks/base/core/java/android/os/Process.java文件中:
public class Process { ...... private static int zygoteSendArgsAndGetPid(ArrayList<String> 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; } ...... }這里的sZygoteWriter是一個Socket寫入流,是由openZygoteSocketIfNeeded函數打開的:
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) { ...... } } ...... } ...... }這個Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit類在runSelectLoopMode函數偵聽的。
Step 5. ZygoteInit.runSelectLoopMode
這個函數定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
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<FileDescriptor> fds = new ArrayList(); ArrayList<ZygoteConnection> 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); } } } } ...... }當Step 4將數據通過Socket接口發送出去后,就會下面這個語句:
done = peers.get(index).runOnce();這里從peers.get(index)得到的是一個ZygoteConnection對象,表示一個Socket連接,因此,接下來就是調用ZygoteConnection.runOnce函數進一步處理了。
Step 6. ZygoteConnection.runOnce
這個函數定義在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:
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); } } ...... }真正創建進程的地方就是在這里了:
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);有Linux開發經驗的讀者很容易看懂這個函數調用,這個函數會創建一個進程,而且有兩個返回值,一個是在當前進程中返回的,一個是在新創建的進程中返回,即在當前進程的子進程中返回,在當前進程中的返回值就是新創建的子進程的pid值,而在子進程中的返回值是0。因為我們只關心創建的新進程的情況,因此,我們沿著子進程的執行路徑繼續看下去:
if (pid == 0) { // in child handleChildProc(parsedArgs, descriptors, newStderr); // should never happen return true; } else { /* pid != 0 */ ...... }這里就是調用handleChildProc函數了。
Step 7. ZygoteConnection.handleChildProc
這個函數定義在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:
class ZygoteConnection { ...... private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { ...... if (parsedArgs.runtimeInit) { RuntimeInit.zygoteInit(parsedArgs.remainingArgs); } else { ...... } } ...... }由于在前面的Step 3中,指定了"--runtime-init"參數,表示要為新創建的進程初始化運行時庫,因此,這里的parseArgs.runtimeInit值為true,于是就繼續執行RuntimeInit.zygoteInit進一步處理了。
Step 8. RuntimeInit.zygoteInit
這個函數定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
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); } ...... }這里有兩個關鍵的函數調用,一個是zygoteInitNative函數調用,一個是invokeStaticMain函數調用,前者就是執行Binder驅動程序初始化的相關工作了,正是由于執行了這個工作,才使得進程中的Binder對象能夠順利地進行Binder進程間通信,而后一個函數調用,就是執行進程的入口函數,這里就是執行startClass類的main函數了,而這個startClass即是我們在Step 1中傳進來的"android.app.ActivityThread"值,表示要執行android.app.ActivityThread類的main函數。
我們先來看一下zygoteInitNative函數的調用過程,然后再回到RuntimeInit.zygoteInit函數中來,看看它是如何調用android.app.ActivityThread類的main函數的。
step 9. RuntimeInit.zygoteInitNative
這個函數定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
public class RuntimeInit { ...... public static final native void zygoteInitNative(); ...... }這里可以看出,函數zygoteInitNative是一個Native函數,實現在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); }
這里它調用了全局變量gCurRuntime的onZygoteInit函數,這個全局變量的定義在frameworks/base/core/jni/AndroidRuntime.cpp文件開頭的地方:
static AndroidRuntime* gCurRuntime = NULL;這里可以看出,它的類型為AndroidRuntime,它是在AndroidRuntime類的構造函數中初始化的,AndroidRuntime類的構造函數也是定義在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
AndroidRuntime::AndroidRuntime() { ...... assert(gCurRuntime == NULL); // one per process gCurRuntime = this; }那么這個AndroidRuntime類的構造函數又是什么時候被調用的呢?AndroidRuntime類的聲明在frameworks/base/include/android_runtime/AndroidRuntime.h文件中,如果我們打開這個文件會看到,它是一個虛擬類,也就是我們不能直接創建一個AndroidRuntime對象,只能用一個AndroidRuntime類的指針來指向它的某一個子類,這個子類就是AppRuntime了,它定義在frameworks/base/cmds/app_process/app_main.cpp文件中:
int main(int argc, const char* const argv[]) { ...... AppRuntime runtime; ...... }而AppRuntime類繼續了AndroidRuntime類,它也是定義在frameworks/base/cmds/app_process/app_main.cpp文件中:
class AppRuntime : public AndroidRuntime { ...... };因此,在前面的com_android_internal_os_RuntimeInit_zygoteInit函數,實際是執行了AppRuntime類的onZygoteInit函數。
Step 10. AppRuntime.onZygoteInit
這個函數定義在frameworks/base/cmds/app_process/app_main.cpp文件中:
class AppRuntime : public AndroidRuntime { ...... virtual void onZygoteInit() { sp<ProcessState> 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<Thread> 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遠程接口過程源代碼分析這三篇文章。
Step 14. 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);最后,線程退出時,也會告訴Binder驅動程序,它退出了,這樣Binder驅動程序就不會再在Client端的進程間調用分發給它了:
mOut.writeInt32(BC_EXIT_LOOPER); talkWithDriver(false);我們再來看看talkWithDriver函數的實現。
Step 15. talkWithDriver
這個函數定義在frameworks/base/libs/binder/IPCThreadState.cpp文件中:
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_t outAvail = (!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; do { ...... #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接口源代碼分析一文。
回到Step 8中的RuntimeInit.zygoteInit函數中,在初始化完成Binder進程間通信機制的基礎設施后,它接著就要進入進程的入口函數了。
Step 16. RuntimeInit.invokeStaticMain
這個函數定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
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); } ...... }前面我們說過,這里傳進來的參數className字符串值為"android.app.ActivityThread",這里就通ClassLoader.loadClass函數將它加載到進程中:
cl = loader.loadClass(className);然后獲得它的靜態成員函數main:
m = cl.getMethod("main", new Class[] { String[].class });函數最后并沒有直接調用這個靜態成員函數main,而是通過拋出一個異常ZygoteInit.MethodAndArgsCaller,然后讓ZygoteInit.main函數在捕獲這個異常的時候再調用android.app.ActivityThread類的main函數。為什么要這樣做呢?注釋里面已經講得很清楚了,它是為了清理堆棧的,這樣就會讓android.app.ActivityThread類的main函數覺得自己是進程的入口函數,而事實上,在執行android.app.ActivityThread類的main函數之前,已經做了大量的工作了。
我們看看ZygoteInit.main函數在捕獲到這個異常的時候做了什么事:
public class ZygoteInit { ...... public static void main(String argv[]) { try { ...... } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { ...... } } ...... }它執行MethodAndArgsCaller的run函數:
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("<pre-initialized>"); 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() : "<unknown>"; 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簡要介紹和學習計劃一文。