小夜曲:晓说ActivityThread

该篇是Android启动系列的最后一篇,本文从应用进程的创建启动角度出发,分析ActivityThread是如何创建的。相对于上篇,本文内容较少,阅读无压力~

从接触Android的那一刻开始,看到最多的是:耗时任务不能在主线程执行,UI操作要在主线程执行……当时人傻无知,从来没有想过什么是主线程,为啥不能在主线程做耗时任务等等。
大家都说ActivityThread是主线程,那它是线程吗?它为什么被称为主线程?它做啥了?

回顾

在上文《沉思曲:Activity启动》一文中,分析了Activity的启动过程。并在调用startSpecificActivityLocked方法时,提到这里会判断目的Activity进程是否存在,如果不存在,就会创建新进程,本文就从这个创建新进程的分支开始。

创建应用进程


先回顾下startSpecificActivityLocked方法

该方法在ActivityStackSupervisor.java中

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        //获取待启动Activity的进程信息
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        //待启动Activity所在进程存在
        if (app != null && app.thread != null) {
            try {
                app.addPackage(r.info.packageName, mService.mProcessStats);
                //接着往下执行
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
        }

        //待启动Activity所在进程不存在,为其创建新进程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
  • 上方法中,如果目的Activity所在进程不存在,调用AMS的startProcessLocked方法创建目的应用进程。

1.1、startProcessLocked

startProcessLocked定义在ActivityManagerService.java中,该方法会调用Process的start方法。

// Start the process.  It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, null);
  • 该方法调用Process的start方法,注意传入参数:"android.app.ActivityThread"

1.2、 start | Process.java

/**
 * Start a new process.
 * 
 * 

If processes are enabled, a new process is created and the * static main() function of a processClass is executed there. * The process will continue running after this function returns. * *

If processes are not enabled, a new thread in the caller's * process is created and main() of processClass called there. * *

The niceName parameter, if not an empty string, is a custom name to * give to the process instead of using processClass. This allows you to * make easily identifyable processes even if you are using the same base * processClass to start them. * * @param processClass The class to use as the process's main entry * point. * @param niceName A more readable name to use for the process. * @param uid The user-id under which the process will run. * @param gid The group-id under which the process will run. * @param gids Additional group-ids associated with the process. * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param seInfo null-ok SE Android information for the new process. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure * * {@hide} */ 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[] zygoteArgs) { try { //通过Zygote启动新进程 return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); throw new RuntimeException( "Starting VM process through Zygote failed", ex); } }

从注释可知,该方法用来启动一个新进程:

  • 如果进程启动,则processClass(此处入参为“android.app.ActivityThread”)会运行在该新进程中,并且在该方法调用完成后,新进程会继续运行。
  • 如果进程未启动,则调用该start方法所在的进程会创建一个新的线程,然后processClass运行在该新线程中。

方法调用startViaZygote方法,从方法名看出,进程创建似乎是要交给zygote。

1.3、startViaZygote | 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[] extraArgs)
                              throws ZygoteStartFailedEx {
    synchronized(Process.class) {
        //启动新进程的参数
        ArrayList argsForZygote = new ArrayList();

        //添加各种参数到argsForZygote
        argsForZygote.add("--runtime-init");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        ...

        if (niceName != null) {
            argsForZygote.add("--nice-name=" + niceName);
        }

        if (seInfo != null) {
            argsForZygote.add("--seinfo=" + seInfo);
        }
        argsForZygote.add(processClass);
        
        ...

        //调用该方法,由zygote创建进程,并获取新进程信息
        return zygoteSendArgsAndGetResult(argsForZygote);
    }
}

这个方法设置启动新进程所需参数,并往下调用zygoteSendArgsAndGetResult方法。

1.4、zygoteSendArgsAndGetResult | Process.java

private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList args)
        throws ZygoteStartFailedEx {
    //进程通信,连接到Zygote的Server Socket,交由Zygote创建
    openZygoteSocketIfNeeded();

    try {
        //sZygoteWriter将参数发送到Server Socket
        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();

        //sZygoteInputStream从Server Socket读取结果
        ProcessStartResult result = new ProcessStartResult();
        result.pid = sZygoteInputStream.readInt();
        ...
        result.usingWrapper = sZygoteInputStream.readBoolean();
        return result;
    ...
}

从方法名可以猜出该方法大致干啥了:发送启动参数给Zygote进程,交由Zygote进程启动,并获得启动结果。看下是否如此:
1、调用openZygoteSocketIfNeeded方法。
2、调用sZygoteWriter往ServerSocket写创建进程所需要的参数,ServerSocket是啥?
3、创建ProcessStartResult,并写入从ServerSocket读取的数据,作为结果返回。
看来重点在openZygoteSocketIfNeeded方法!

1.5、openZygoteSocketIfNeeded | Process.java

private static void openZygoteSocketIfNeeded() 
        throws ZygoteStartFailedEx {

    //重连次数
    int retryCount;

    if (sPreviousZygoteOpenFailed) {
        retryCount = 0;
    } else {
        retryCount = 10;            
    }

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

        try {
            //client socket
            sZygoteSocket = new LocalSocket();
            //连接到Zygote的server socket
            sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, 
                    LocalSocketAddress.Namespace.RESERVED));
            //sZygoteInputStream负责读取server socket信息
            sZygoteInputStream
                    = new DataInputStream(sZygoteSocket.getInputStream());
            //sZygoteWriter发送信息到server socket
            sZygoteWriter =
                new BufferedWriter(
                        new OutputStreamWriter(
                                sZygoteSocket.getOutputStream()),
                        256);
            sPreviousZygoteOpenFailed = false;
            break;
        ...
}

详细大家都能一眼看懂,这不是Java中的Socket的连接吗,这不过这里是用来进程连接。
1、创建Client Socket:sZygoteSocket
2、ClientSocket连接到服务端,ServerSocket:ZYGOTE_SOCKET
3、创建输入流负责从ServerSocket读数据,创建输出流向ServerSocket写数据。

即:

  • openZygoteSocketIfNeeded方法负责连接到Zygote的Server Socket,并发送/读取Server Socket的信息。
  • ServerSocket即ZYGOTE_SOCKET,它有Zygote进程创建。

既然client socket连接到Zygote的创建的ServerSocket了,那接下来看下Zygote是如何处理连接的。

Zygote处理客户端连接


Zygote进程由init进程启动,Zygote的实现在ZygoteInit.java中,其main方法调用标志着Zygote的启动。

2.1、main | ZygoteInit.java

public static void main(String argv[]) {
   try {
        //注册server socket
        //其它进程的创建,通过连接到该Socket后,由zygote孵化出来
        registerZygoteSocket();
        
        ...
        //预加载android framework类和资源
        preload();
        
        ...
        if (argv[1].equals("start-system-server")) {
            //启动SystemServer
            startSystemServer();
        } else if (!argv[1].equals("")) {
            throw new RuntimeException(argv[0] + USAGE_STRING);
        }

        //死循环接收client socket连接,由此创建新进程
        runSelectLoop();

        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {  //标注加红,这个异常捕获是重点!!!
        caller.run();
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}
  • Zygote进程启动时,注册了ServerSocket,即上面提到的ZYGOTE_SOCKET,就是它来处理client socket的连接。
  • Zygote进程启动时还启动了SystemServer,这在第一篇文章中已经分析过了。
  • 最后调用runSelectLoop方法,死循环处理client socket连接。

最后需要注意的是:
main方法采用了try-catch的方式,其中捕获了异常MethodAndArgsCaller。由后面代码可知,通过这种抛异常的方式,使进程跳出死循环,并执行caller.run方法。

2.2、runSelectLoop | ZygoteInit.java

上面方法调用runSelectLoop,死循环处理client连接,看下其内容。

private static void runSelectLoop() throws MethodAndArgsCaller {
    ArrayList fds = new ArrayList();
    //client socket连接列表
    ArrayList peers = new ArrayList();
    
    FileDescriptor[] fdArray = new FileDescriptor[4];
    //将server socket添加到fds中
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);
    int loopCount = GC_LOOP_COUNT;
    
    while (true) {
        int index;
        ...

        try {
            //将fds转换成数组
            fdArray = fds.toArray(fdArray);
            //在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) {
            //第一个为Server socket,此时等待client socket连接
            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);
            }
        }
    }
}

代码逻辑还是比较清楚:

  • Zygote死循环处理已连接的client socket,client的连接封装成ZygoteConnection 表示,并调用其的runOnce()方法。
  • 如果已连接的client socket都处理完成,那就等待新的client连接。

2.3、runOnce | ZygoteConnection.java

看下连接的处理方法runOnce():

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        //读取client socket传入的参数列表
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } 
    ...

    try {
        //转换参数
        parsedArgs = new Arguments(args);
        ...
        
        //Zygote创建 新进程并负责虚拟机实例到该进程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName);
    }
    ...

    try {
        //新进程
        if (pid == 0) {
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            //新进程中调用
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        }
        ...
}

要划重点了:
1、该方法读取client socket连接时传入的参数,并封装。
2、调用Zygote的forkAndSpecialize创建指定进程。
3、pid=0时即子进程,在子进程中调用handleChildProc方法。

这里涉及到以下几点:

  • 应用进程的确是有Zygote进程创建的,包括前文提到的SystemServer进程
  • 新进程时如何与虚拟机关联的?
    在forkAndSpecialize方法中,Zygote会将创建的Dalvik虚拟机实例复制到新的应用程序进程里面去,从而使得每一个应用程序进程都有一个独立的Dalvik虚拟机实例。

好了,新进程已经创建好了,但似乎还没解决问题,ActivityThread是如何运行在新进程中的呢?接着往下看handleChildProc方法。

2.4、handleChildProc | ZygoteConnection.java

private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        throws ZygoteInit.MethodAndArgsCaller {
  
    //子进程中关闭client/server socket
    closeSocket();
    ZygoteInit.closeServerSocket();
    ...
    if (parsedArgs.niceName != null) {
        //设置进程名
        Process.setArgV0(parsedArgs.niceName);
    }

    //是否设置了runtimeInit参数
    if (parsedArgs.runtimeInit) {
        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    pipeFd, parsedArgs.remainingArgs);
        } else {
            //zygoteInit最后仍会创建ActivityThread实例,并调用其main方法
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs);
        }
    } else {
        String className;
        try {
            //传入的类全限定名,此处为:“android.app.ActivityThread”
            className = parsedArgs.remainingArgs[0];
        } 
        ...
                
        if (parsedArgs.invokeWith != null) {
            WrapperInit.execStandalone(parsedArgs.invokeWith,
                    parsedArgs.classpath, className, mainArgs);
        } else {
            ClassLoader cloader;
            if (parsedArgs.classpath != null) {
                //ClassLoader
                cloader = new PathClassLoader(parsedArgs.classpath,
                        ClassLoader.getSystemClassLoader());
            } else {
                cloader = ClassLoader.getSystemClassLoader();
            }

            try {
                //反射创建className(此处为ActivityThread)实例,并调用其main方法
                ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
            } 
            ...
        }
    }
}

注意哦,现在已经是在新创建的子进程了哦:
1、子进程关闭client/server socket连接,为什么呢?
2、解析参数,根据前面传入的参数“android.app.ActivityThread”,调用ZygoteInit.invokeStaticMain方法,反射创建ActivityThread实例,并调用该实例main方法。

回答两个问题:
1、子进程为什么要关闭client/server socket连接,关闭client还好理解,server socket不是在Zygote进程吗?
了解Linux的都知道,通过fork创建的子进程会继承父进程的代码、数据,也就是:子进程除了自己的堆栈地址跟父进程不同外,其它数据都是直接从父进程拷贝过来的。那新创建的子进程,肯定也是有一份ServerSocket实例拷贝,子进程在创建完成后当然需要关闭。

2、为什么ActivityThread被称为主线程?
首先,ActivityThread不是线程,被称为主线程是因为:它运行在新进程的主线程中(当然了,主线程就是进程中的第一个线程了,此处没有额外再创建新线程,那肯定是主线程了)。

2.5、invokeStaticMain | ZygoteInit.java


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

        try {
            cl = loader.loadClass(className);
        } 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 });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        /*
         * 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);
    }

这个方法不写注释也能一眼看懂:
1、反射获得入参对应的Class,此处入参为:“android.app.ActivityThread”
2、反射获取main方法对应的Method
3、新建MethodAndArgsCaller,并以异常形式抛出

  • 前面都好理解,关键是为什么要将main方法封装成异常的形式抛出呢?
    前面提到:子进程实际是从父进程将代码数据拷贝而来,父进程Zygote在死循环中创建了子进程,那子进程当然也存在这份死循环的代码。子进程通过异常抛出的形式,然后异常被捕获,跳出死循环,并在调用异常的run方法,在该run方法中调用被封装的方法main。

ActivityThread


至此,应用进程已经创建好了,并通过反射方式创建了ActivityThread的实例,然后调用该实例的main方法。那看下其main方法都做了啥:

3.1、main | ActivityThread.java

public static void main(String[] args) {
    SamplingProfilerIntegration.start();
    // CloseGuard defaults to true and can be quite spammy.  We
    // disable it here, but selectively enable it later (via
    // StrictMode) on debug builds, but using DropBox, not logs.
    CloseGuard.setEnabled(false);

    Environment.initForCurrentUser();

    // Set the reporter for event logging in libcore
    EventLogger.setReporter(new EventLoggingReporter());

    Security.addProvider(new AndroidKeyStoreProvider());

    Process.setArgV0("");
    
    //为当前线程创建Looper,并未改Looper创建关联的MessageQueue
    Looper.prepareMainLooper();
    
    //创建实例
    ActivityThread thread = new ActivityThread();
    //入口
    thread.attach(false);
    
    //创建Handler,即:H
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    AsyncTask.init();

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    
    //mainLooper循环从消息队列中取消息,并交给H处理
    Looper.loop();

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

有代码知,main方法创建了主线程关联的Looper已经H handler,这些相信大家都很熟了,但还是废话几句吧:

  • main方法在当前进程的主线程中运行,即主线程创建了Looper,并为Looper创建了关联的消息队列,以及handler H。创建完成后,调用Looper的loop方法,循环从消息队列中取出消息交给Looper处理。

    • 关于Looper、MessageQueue、Handler以及Message的关系,大致如下:
      • Looper与线程相关联,在Looper类中采用线程局部变量保存每个线程关联的Looper。主线程默认关联一个Looper,即MainLooper;当然也可以为子线程手动创建关联的Looper,即调用Looper.prepare()方法。
      • 每个Looper实例中,存在一个关联的MessageQueue实例,调用Looper的prepare方法时,会创建Looper实例,以及Looper关联的MessageQueue实例。调用Looper.loop()方法,Looper会循环去关联的MessageQueue中取出消息处理。
      • Handler,当构造Handler的实例时,会获取当前线程关联的Looper对象和MessageQueue对象引用。调用handler发送消息时,实际是将消息放入到MessageQueue中。
      • Message,每个Message对象都关联了一个target,该target就是发送该消息的Handler实例。当Looper从MessageQueue中取出消息时,会将消息发送给其关联的target进行处理。(why:因为一个MessageQueue可能被多个handler引用。)

方法中另外创建了一个ActivityThread的实例,并调用其attach方法,开始应用的启动。

3.2、attach | ActivityThread.java

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    //普通App进这里
    if (!system) {
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("",
                                                UserHandle.myUserId());
                                                
        //VM中保存该应用标志,用于上报错误
        //mAppThread是Binder对象,AMS通过该对象实现与该应用进程通信,ActivityThread初始化时会创建该实例
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        //AMS代理
        IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            //AMS保存该应用进程信息,通过该Binder实现与该应用进程通信
            mgr.attachApplication(mAppThread);  //入口
        } catch (RemoteException ex) {
            // Ignore
        }
    } else {
        ......
    }
    ......
}
  • 该方法入参为false,即普通应用app。
  • 将应用进程Binder关联到VM,用于上报错误信息;
  • 将应用进程Binder关联到AMS,用于AMS与该应用进程通信;
  • 最后,通过AIDL调用AMS的attachApplication方法,所以此时又交由AMS来处理了。

什么是应用进程Binder?
在上文《沉思曲:Acitivity启动》中提到,AMS通过持有应用进程的Binder实现与应用进程的通信。该Binder实现了IApplicationThread接口,实现是ApplicaitonThread。

3.3、attachApplication | ActivityManagerService.java

public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        //应用进程pid
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        //入口
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}
  • 该方法继续调用attachApplicationLocked方法。
  • attachApplicationLocked方法主要是应用进程进行校验,并调用thread的bindApplication方法。thread就是上一方法中的入参:应用进程Binder,实现为ApplicaitonThread,是Binder对象。
  • 由于thread是Binder对象,即应用进程在AMS中的Binder对象,所以此处又由AMS进程切换到应用进程中!!!

3.4、bindApplication | ActivityThread.java

note:ApplicaitonThread是ActivityThread的内部类。

public final void bindApplication(String processName,
            ApplicationInfo appInfo, List providers,
            ComponentName instrumentationName, String profileFile,
            ParcelFileDescriptor profileFd, boolean autoStopProfiler,
            Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
            IUiAutomationConnection instrumentationUiConnection, int debugMode,
            boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
            Configuration config, CompatibilityInfo compatInfo, Map services,
            Bundle coreSettings) {

        if (services != null) {
            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }

        setCoreSettings(coreSettings);

        AppBindData data = new AppBindData();
        data.processName = processName;
        data.appInfo = appInfo;
        data.providers = providers;
        data.instrumentationName = instrumentationName;
        data.instrumentationArgs = instrumentationArgs;
        data.instrumentationWatcher = instrumentationWatcher;
        data.instrumentationUiAutomationConnection = instrumentationUiConnection;
        data.debugMode = debugMode;
        data.enableOpenGlTrace = enableOpenGlTrace;
        data.restrictedBackupMode = isRestrictedBackupMode;
        data.persistent = persistent;
        data.config = config;
        data.compatInfo = compatInfo;
        data.initProfileFile = profileFile;
        data.initProfileFd = profileFd;
        data.initAutoStopProfiler = false;
        
        //发送消息到H,消息类型为H.BIND_APPLICATION
        queueOrSendMessage(H.BIND_APPLICATION, data);
    }

该方法在应用进程中,调用H handler发送消息H.BIND_APPLICATION,看下H handler是如何处理该消息的。

3.5、 H处理H.BIND_APPLICATION消息 | ActivityThread.java

case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData)msg.obj;
                //入口
                handleBindApplication(data);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
  • 该方法接着调用 handleBindApplication

3.6、 handleBindApplication | ActivityThread.java

    private void handleBindApplication(AppBindData data) {
        mBoundApplication = data;
        mConfiguration = new Configuration(data.config);
        mCompatConfiguration = new Configuration(data.config);

        mProfiler = new Profiler();
        mProfiler.profileFile = data.initProfileFile;
        mProfiler.profileFd = data.initProfileFd;
        mProfiler.autoStopProfiler = data.initAutoStopProfiler;

        //设置进程名
        Process.setArgV0(data.processName);
        android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                UserHandle.myUserId());
        //是否开启硬件加速
        if (data.persistent) {
            if (!ActivityManager.isHighEndGfx()) {
                HardwareRenderer.disable(false);
            }
        }
        
        if (mProfiler.profileFd != null) {
            mProfiler.startProfiling();
        }

        //Honeycomb MR1版本前,设置AsyncTask的底层由线程池实现
        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

        //设置TimeZone、Locale
        TimeZone.setDefault(null);
        Locale.setDefault(data.config.locale);

        //更新系统设置,AppBindData中配置默认是最新的
        mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
        mCurDefaultDisplayDpi = data.config.densityDpi;
        applyCompatConfiguration(mCurDefaultDisplayDpi);
        
        //获取Package信息,返回LoadedApk对象。先从缓存读,没有则创建。
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

        //设置分辨率信息
        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
                == 0) {
            mDensityCompatMode = true;
            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
        }
        updateDefaultDensity();
        
        //创建ContextImpl实例
        final ContextImpl appContext = new ContextImpl();
        appContext.init(data.info, null, this);
      
        if (!Process.isIsolated()) {
            final File cacheDir = appContext.getCacheDir();
            if (cacheDir != null) {
                // Provide a usable directory for temporary files
                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
                setupGraphicsSupport(data.info, cacheDir);
            } else {
                Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
            }
        }

        //系统应用,开启debug log
        if ((data.appInfo.flags &
             (ApplicationInfo.FLAG_SYSTEM |
              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
            StrictMode.conditionallyEnableDebugLogging();
        }

        //Honeycomb版本以后,不允许在主线程进行网络操作
        if (data.appInfo.targetSdkVersion > 9) {
            StrictMode.enableDeathOnNetwork();
        }

        //设置debug
        ......

        // 是否启动GL
        if (data.enableOpenGlTrace) {
            GLUtils.setTracingLevel(1);
        }

        // Allow application-generated systrace messages if we're debuggable.
        boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        Trace.setAppTracingAllowed(appTracingAllowed);

        //设置time zone时,走http代理;通过ConnectivityManager设置
        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
        if (b != null) {
            IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
            try {
                ProxyProperties proxyProperties = service.getProxy();
                Proxy.setHttpProxySystemProperty(proxyProperties);
            } catch (RemoteException e) {}
        }
        
        //是否指定trumentation类名,难道可以指定?!
        if (data.instrumentationName != null) {
            InstrumentationInfo ii = null;
            try {
                //获取Instrumentation信息
                ii = appContext.getPackageManager().
                    getInstrumentationInfo(data.instrumentationName, 0);
            }
            ......

            mInstrumentationAppDir = ii.sourceDir;
            mInstrumentationAppLibraryDir = ii.nativeLibraryDir;
            mInstrumentationAppPackage = ii.packageName;
            mInstrumentedAppDir = data.info.getAppDir();
            mInstrumentedAppLibraryDir = data.info.getLibDir();
            
            //创建ApplicationInfo,用来保存应用信息
            ApplicationInfo instrApp = new ApplicationInfo();
            instrApp.packageName = ii.packageName;
            instrApp.sourceDir = ii.sourceDir;
            instrApp.publicSourceDir = ii.publicSourceDir;
            instrApp.dataDir = ii.dataDir;
            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
            
            //创建LoadedApk实例,保存应用APK信息
            LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true);
            //创建应用关联的CotextImpl
            ContextImpl instrContext = new ContextImpl();
            instrContext.init(pi, null, this);

            try {
                java.lang.ClassLoader cl = instrContext.getClassLoader();
                //为应用创建指定的Instrumentation实例
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            }
            ......
            //init,保存应用信息到Instrumentation
            mInstrumentation.init(this, instrContext, appContext,
                   new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
                   data.instrumentationUiAutomationConnection);
            ......
        } else {
            //未指定Instrmentation名称,创建默认Instrumentation
            mInstrumentation = new Instrumentation();
        }

        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
        }

        //允许application和provider启动时访问disk
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        try {
            //创建Application实例
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

            //restricted模式下,c处理provider
            if (!data.restrictedBackupMode) {
                List providers = data.providers;
                if (providers != null) {
                    installContentProviders(app, providers);
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            try {
                //调用Instrumentation的onCreate方法,用于Applicaiton启动onCreate()启动前的操作
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            ......  
          
            try {
                //Instrumentation回调应用Applicaiton的onCreate,启动应用
                mInstrumentation.callApplicationOnCreate(app);
            }
            ......
    }

该方法负责启动应用:

  • 设置进程名、是否开启硬件加速
  • 设置AsyncTask的底层实现方式
  • 设置TimeZone、Locale
  • 设置分辨率、不允许主线程网络操作等
  • 为应用进程设置Instrumentation,用于管理应用进程
  • 通过Instrumentation调用应用Applicationde 的onCreate方法,实现应用的启动等
    • 设置timezone、openGl等信息后,创建Instrumentation用于管理该应用进程,最后并回调该应用的Application的onCreate方法启动应用。

至此,本文内容就差不多结束了,后面应用的启动就不讲了,感兴趣的可以看源码,大同小异。

总结


三篇文章到此结束了,三文粗略的分析了Android系统启动、Activity启动、ActivityThread创建三部分内容。内容都是整理之前资料得到的,网上关于这部分内容的资料也很多,但都比较零散。这里把这部分内容整理出来,一来备忘,二来抛砖引玉。本人才疏学浅,大部分内容都是自己理解加注释,有不当错误之处,恳请指正~

你可能感兴趣的:(小夜曲:晓说ActivityThread)