Android应用程序进程启动过程的源代码分析
来源:互联网 发布:广电网络最新消息 编辑:程序博客网 时间:2024/05/14 12:49
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) {
- ......
- }
- }
- ......
- }
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;
- }
- }
- ......
- }
- 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;
- }
回到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);
- }
- }
- ......
- }
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;
- }
- ......
- }
- 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) {
- ......
- }
- }
- ......
- }
- ......
- }
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);
- }
- }
- }
- }
- ......
- }
- done = peers.get(index).runOnce();
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);
- if (pid == 0) {
- // in child
- handleChildProc(parsedArgs, descriptors, newStderr);
- // should never happen
- return true;
- } else { /* pid != 0 */
- ......
- }
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 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函数的调用过程,然后再回到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();
- ......
- }
- 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()
- {
- ......
- assert(gCurRuntime == NULL); // one per process
- gCurRuntime = this;
- }
- int main(int argc, const char* const argv[])
- {
- ......
- AppRuntime runtime;
- ......
- }
- class AppRuntime : public AndroidRuntime
- {
- ......
- };
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();
- }
- }
- ......
- };
Step 11. ProcessState.startThreadPool
这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:
- void ProcessState::startThreadPool()
- {
- AutoMutex _l(mLock);
- if (!mThreadPoolStarted) {
- mThreadPoolStarted = true;
- spawnPooledThread(true);
- }
- }
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);
- }
- }
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;
- };
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);
- }
- mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
- result = talkWithDriver();
- result = executeCommand(cmd);
- mOut.writeInt32(BC_EXIT_LOOPER);
- talkWithDriver(false);
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;
- }
- ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
细心的读者可能会发现,从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);
- }
- ......
- }
- cl = loader.loadClass(className);
- m = cl.getMethod("main", new Class[] { String[].class });
我们看看ZygoteInit.main函数在捕获到这个异常的时候做了什么事:
- public class ZygoteInit {
- ......
- public static void main(String argv[]) {
- try {
- ......
- } catch (MethodAndArgsCaller caller) {
- caller.run();
- } catch (RuntimeException ex) {
- ......
- }
- }
- ......
- }
- 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.invoke(null, new Object[] { mArgs });
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 thread = new ActivityThread();
- Looper.loop();
至此,Android应用程序进程启动过程的源代码就分析完成了,它除了指定新的进程的入口函数是ActivityThread的main函数之外,还为进程内的Binder对象提供了Binder进程间通信机制的基础设施,由此可见,Binder进程间通信机制在Android系统中是何等的重要,而且是无处不在,想进一步学习Android系统的Binder进程间通信机制,请参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。
原文链接:http://blog.csdn.net/luoshengyang/article/details/6747696- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析 .
- Android应用程序进程启动过程的源代码分析
- Android应用程序(app)进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- Android应用程序进程启动过程的源代码分析
- 读书:《Android系统源代码情景分析》- 简述Android应用程序进程的启动过程
- Android应用程序启动过程源代码分析
- Android应用程序启动过程源代码分析
- Android应用程序启动过程源代码分析
- Android应用程序启动过程源代码分析
- Android应用程序启动过程源代码分析
- Apache VFS:基本介绍
- Windows7下使用Dev-CPP 编译 JNI
- 摄像头工作原理
- 如何在cocos2d-x实现高效的mask(遮罩)
- Linux命令——cut命令学习
- Android应用程序进程启动过程的源代码分析
- 软件中心闪退,Ubuntu12.04 更新时出现W:GPG错误的解决方法
- 黑马程序员--asp.net点击按钮不提交
- iOS应用开发攻略(助你iOS开发中攻城拔寨)
- ubuntu12.04禁用客人会话
- StringBuffer与StringBuilder的区别
- UVa 846 - Steps
- Android OpenGL ES 1.x 教程的Native实现
- 6个常见的 PHP 安全性攻击