天天看點

Android Framework學習(五)之應用程序啟動流程

在之前的部落格中我們學習了Launcher的啟動流程,在SystemServer程序執行完成,各種系統服務啟動完成之後,會調用ActivityManagerService中的systemReady()方法,在systemReady()方法中會執行Launcher啟動的相關邏輯,本篇部落格,我們将一起學習應用程式程序的啟動流程,注意:這裡是“應用程式程序啟動過程”,而不是應用程式啟動過程

應用程序概述

關于Android的應用程序在android guide中有這樣的一段描述:

By default, every application runs in its own Linux process. Android starts the process when any of the application’s components need to be executed, then shuts down the process when it’s no longer needed or when the system must recover memory for other applications.           

複制

每一個android應用預設都是在他自己的linux程序中運作。android作業系統會在這個android應用中的元件需要被執行的時候啟動這個應用程序,并且會在這個應用程序沒有任何元件執行或者是系統需要為其他應用申請更多記憶體的時候殺死這個應用程序。是以當我們需要啟動這個應用的四大元件之一的時候如果這個應用的程序還沒有啟動,那麼就會先啟動這個應用程式程序。

Launcher應用程式在啟動過程中會通過PackageManagerService服務請求查詢系統所有的已安裝應用的包名,圖示和應用名稱等資訊,然後填充到Launcher中的Adapter中,這樣點選某一項應用圖示的時候就可以根據該圖示的包名和啟動Activity的類名初始化Intent對象,然後調用startActivity(Intent)啟動相關的應用程式了。

ActivityManagerService在啟動應用程式時會檢查這個應用程式需要的應用程式程序是否存在,不存在就會請求Zygote程序将需要的應用程式程序啟動。Zygote的Java架構層中,會建立一個Server端的Socket,這個Socket用來等待ActivityManagerService來請求Zygote來建立新的應用程式程序的。我們知道Zygote程序通過fock自身建立的應用程式程序,這樣應用程式程式程序就會獲得Zygote程序在啟動時建立的虛拟機執行個體。當然,在應用程式建立過程中除了擷取虛拟機執行個體,還可以獲得Binder線程池和消息循環,這樣運作在應用程序中應用程式就可以友善的使用Binder進行程序間通信以及消息處理機制了。

應用程式程序建立

發送建立應用程式程序請求

ActivityManagerService會通過調用startProcessLocked函數來向Zygote程序發送請求

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        ...
        try {
            try {
                final int userId = UserHandle.getUserId(app.uid);
                AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            int uid = app.uid;//1
            int[] gids = null;
            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
            if (!app.isolated) {
              ...
              /**
              * 2 對gids進行建立和指派
              */
                if (ArrayUtils.isEmpty(permGids)) {
                    gids = new int[2];
                } else {
                    gids = new int[permGids.length + 2];
                    System.arraycopy(permGids, 0, gids, 2, permGids.length);
                }
                gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
                gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
            }

           ...
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";//3
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            /**
            * 4
            */
            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);
           ...
        } catch (RuntimeException e) {
          ...
        }
    }
   ...
    }           

複制

在注釋1處的達到建立應用程式程序的使用者ID,在注釋2處對使用者組ID:gids進行建立和指派。注釋3處如果entryPoint 為null則指派為”android.app.ActivityThread”。在注釋4處調用Process的start函數,将此前得到的應用程式程序使用者ID和使用者組ID傳進去,第一個參數entryPoint我們得知是”android.app.ActivityThread”,接下來我們來檢視Process的start函數。

public static final ProcessStartResult 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) {
      ...
    }
}           

複制

調用了startViaZygote函數

frameworks/base/core/java/android/os/Process.java

private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
        /**
        * 1
        */
            ArrayList<String> argsForZygote = new ArrayList<String>();
            argsForZygote.add("--runtime-args");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
          ...
            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());
            }
         ...
            argsForZygote.add(processClass);
            if (extraArgs != null) {
                for (String arg : extraArgs) {
                    argsForZygote.add(arg);
                }
            }
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }           

複制

在注釋1處建立了字元串清單argsForZygote ,并将啟動應用程序的啟動參數儲存在argsForZygote中,函數的最後會調用zygoteSendArgsAndGetResult函數,需要注意的是,zygoteSendArgsAndGetResult函數中第一個參數中調用了openZygoteSocketIfNeeded函數,而第二個參數是儲存應用程序的啟動參數的argsForZygote。

frameworks/base/core/java/android/os/Process.java

private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;
            writer.write(Integer.toString(args.size()));
            writer.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");
                }
                writer.write(arg);
                writer.newLine();
            }
            writer.flush();
            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }           

複制

zygoteSendArgsAndGetResult函數主要做的就是将傳入的應用程序的啟動參數argsForZygote,寫入到ZygoteState中,ZygoteState是由openZygoteSocketIfNeeded函數傳回的

frameworks/base/core/java/android/os/Process.java

private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);//1
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
        }
    }
    if (primaryZygoteState.matches(abi)) {//2
        return primaryZygoteState;
    }
    // The primary zygote didn't match. Try the secondary.
    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        try {
        secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);//3
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
        }
    }

    if (secondaryZygoteState.matches(abi)) {
        return secondaryZygoteState;
    }

    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);           

複制

之前分析Zygote程序啟動過程時,曾說過在Zygote的main函數中會建立name為“zygote”的Server端Socket。在注釋1處會調用ZygoteState的connect函數與名稱為ZYGOTE_SOCKET的Socket建立連接配接,這裡ZYGOTE_SOCKET的值為“zygote”。注釋2處如果連接配接name為“zygote”的Socket傳回的primaryZygoteState與目前的abi不比對,則會在注釋3處連接配接name為“zygote_secondary”的Socket。這兩個Socket差別就是:name為”zygote”的Socket是運作在64位Zygote程序中的,而name為“zygote_secondary”的Socket則運作在32位Zygote程序中。既然應用程式程序是通過Zygote程序fock産生的,當要連接配接Zygote中的Socket時,也需要保證位數的一緻。

接收請求并建立應用程式程序

Socket進行連接配接成功并比對abi後會傳回ZygoteState類型對象,我們在分析zygoteSendArgsAndGetResult函數中講過,會将應用程序的啟動參數argsForZygote寫入到ZygoteState中,這樣Zygote程序就會收到一個建立新的應用程式程序的請求,我們回到ZygoteInit的main函數

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
       ...
        try {
         ...       
            //注冊Zygote用的Socket
            registerZygoteSocket(socketName);//1
           ...
           //預加載類和資源
           preload();//2
           ...
            if (startSystemServer) {
            //啟動SystemServer程序
                startSystemServer(abiList, socketName);//3
            }
            Log.i(TAG, "Accepting command socket connections");
            //等待用戶端請求
            runSelectLoop(abiList);//4
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }           

複制

再次回顧一下main方法中的内容,注釋1處通過registerZygoteSocket函數來建立一個Server端的Socket,這個name為”zygote”的Socket用來等待ActivityManagerService來請求Zygote來建立新的應用程式程序。注釋2處用來預加載類和資源。注釋3處用來啟動SystemServer程序,這樣系統的關鍵服務也會由SystemServer程序啟動起來。注釋4處調用runSelectLoop函數來等待ActivityManagerService的請求。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();//2
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);
        while (true) {
        ...
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce();//1
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }           

複制

當有ActivityManagerService的請求資料到來時會調用注釋1處的代碼,結合注釋2處的代碼,我們得知注釋1處的代碼其實是調用ZygoteConnection的runOnce函數來處理請求的資料:

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;
        try {
            args = readArgumentList();//1
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            Log.w(TAG, "IOException on command socket " + ex.getMessage());
            closeSocket();
            return true;
        }
...
        try {
            parsedArgs = new Arguments(args);//2
        ...
        /**
        * 3 
        */
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
        } catch (ErrnoException ex) {
          ....
        }
       try {
            if (pid == 0) {
                // in child
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                return true;
            } else {
                // in parent...pid of < 0 means failure
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }           

複制

在注釋1處調用readArgumentList函數來擷取應用程式程序的啟動參數,并在注釋2處将readArgumentList函數傳回的字元串封裝到Arguments對象parsedArgs中。注釋3處調用Zygote的forkAndSpecialize函數來建立應用程式程序,參數為parsedArgs中存儲的應用程序啟動參數,傳回值為pid。forkAndSpecialize函數主要是通過fork目前程序來建立一個子程序的,如果pid等于0,則說明是在新建立的子程序中執行的,就會調用handleChildProc函數來啟動這個子程序也就是應用程式程序

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
      ...
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs, null /* classLoader */);
        }
    }           

複制

handleChildProc函數中調用了RuntimeInit的zygoteInit函數

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();
        commonInit();
        nativeZygoteInit();//1
        applicationInit(targetSdkVersion, argv, classLoader);//2
    }           

複制

注釋1處會在新建立的應用程式程序中建立Binder線程池,本文最後進行解釋,在注釋2處調用了applicationInit函數:

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
 ...
        final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());       
            return;
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        invokeStaticMain(args.startClass, args.startArgs, classLoader);//1
    }           

複制

在applicationInit中會在注釋1處調用invokeStaticMain函數,需要注意的是第一個參數args.startClass,這裡是指android.app.ActivityThread。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;
    try {
        cl = Class.forName(className, true, classLoader);//1
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }
    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });//2
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
                "Missing static main on " + className, ex);
    }
    ...
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3
}           

複制

可以看到注釋1處通過反射來獲得android.app.ActivityThread類,接下來在注釋2處來獲得ActivityThread的main函數,并将main函數傳入到注釋3處的ZygoteInit中的MethodAndArgsCaller類的構造函數中,MethodAndArgsCaller類内部會通過反射調用ActivityThread的main函數,這樣應用程式程序就建立完成了。

Binder線程池啟動過程

回到注釋1處的RuntimeInit類的zygoteInit函數

frameworks/base/core/Java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();
        commonInit();
        nativeZygoteInit();//1
        applicationInit(targetSdkVersion, argv, classLoader);
    }           

複制

注釋1處會在新建立的應用程式程序中建立Binder線程池,來檢視nativeZygoteInit函數:

private static final native void nativeZygoteInit();           

複制

很明顯nativeZygoteInit是一個jni方法,它對應的函數是什麼呢。在 AndroidRuntime.cpp的JNINativeMethod數組中我們得知它對應的函數是com_android_internal_os_RuntimeInit_nativeZygoteInit

frameworks/base/core/jni/AndroidRuntime.cpp

static const JNINativeMethod gMethods[] = {
    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};           

複制

檢視 com_android_internal_os_RuntimeInit_nativeZygoteInit函數:

frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}           

複制

gCurRuntime是在AndroidRuntime初始化就建立的

frameworks/base/core/jni/AndroidRuntime.cpp

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength)
{
   ...
    gCurRuntime = this;
}           

複制

AppRuntime繼承AndroidRuntime,AppRuntime建立時就會調用AndroidRuntime的構造函數,gCurRuntime就會被初始化,它指向的是AppRuntime,是以我們來檢視AppRuntime的onZygoteInit函數,AppRuntime的實作在app_main.cpp中

frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }           

複制

最後一行會調用ProcessState的startThreadPool函數:

frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }           

複制

支援Binder通信的程序中都有一個ProcessState類,它裡面有一個mThreadPoolStarted 變量,來表示Binder線程池是否已經被啟動過,預設值為false。在每次調用這個函數時都會先去檢查這個标記,進而確定Binder線程池隻會被啟動一次。如果Binder線程池未被啟動則設定mThreadPoolStarted為true,最後調用spawnPooledThread函數來建立線程池中的第一個線程,也就是線程池的main線程

frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());//1
    }
}           

複制

可以看到Binder線程為一個PoolThread。注釋1調用PoolThread的run函數來啟動一個啟動一個新的線程。

frameworks/native/libs/binder/ProcessState.cpp

class PoolThread : public Thread
{
..
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);//1
        return false;
    }
    const bool mIsMain;
};           

複制

PoolThread類繼承了Thread類。注釋1處會将調用IPCThreadState的joinThreadPool函數,将目前線程注冊到Binder驅動程式中,這樣我們建立的線程就加入了Binder線程池中,這樣新建立的應用程式程序就支援Binder程序間通信了

消息循環建立過程

回到RuntimeInit的invokeStaticMain函數

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;
  ...
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}           

複制

會抛出一個MethodAndArgsCaller異常,這個異常會被ZygoteInit的main函數捕獲

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
     ...
        try {
           ...
        } catch (MethodAndArgsCaller caller) {
            caller.run();//1
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }           

複制

注釋1處捕獲到MethodAndArgsCaller 時會執行caller的run函數

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        private final Method mMethod;
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }
        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });//1
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            }
            ...
                throw new RuntimeException(ex);
            }
        }
    }           

複制

在這裡,mMethod指的就是ActivityThread的main函數,mArgs 指的是應用程式程序的啟動參數。在注釋1處調用ActivityThread的main函數

frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
...
        Looper.prepareMainLooper();//1
        ActivityThread thread = new ActivityThread();//2
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();//3
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }           

複制

注釋1處在目前應用程式程序中建立消息循環,注釋2處建立ActivityThread,注釋3處調用Looper的loop,使得Looper開始工作,開始處理消息。可以看出,系統在應用程式程序啟動完成後,就會建立一個消息循環,用來友善的使用Android的消息處理機制。