前言

一直想写写插件化,才发现自己连Activity的启动过程都不甚了解。插件化说到底考验的是开发者对于Android 源码的深入理解程度。 万丈高楼从地起,从头开始吧

Actiity启动流程

Activity的一次启动大致会经过如下四个阶段,其中涉及与AMS的Binder通讯,与Zygote的通讯。为此,我每个阶段都准备了一张时序图, 能很好的理清调用思路

1.开始启动

Activity 开始启动时序图

Activity的所有的启动Activity的操作都会经过startActivityForResult,然后会交给Instrumentation去实现转发, Instrumentation这个类在调试app时起到了很大的作用,它可以追踪Activity和Application的生命周期,如果需要用于测试 可以继承,然后反射注入,在自动化测试时经常用到。

然后我们看到Instrumentation会通过binder向AMS请求。这里会先请求到ActivityManager注册的服务AMS,然后才调用服务的 startActivity来开始请求。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
//Instrumentation.java
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
        ...
        int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        ...
        return null;
}
//ActivityManager.java
 private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() {
        @Override
        protected IActivityManager create() {
            final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
            final IActivityManager am = IActivityManager.Stub.asInterface(b);
            return am;
        }
};

ActivityManager.getService()获取的其实就是上图ActivityManager中的单例,然后调用startActivity时会将Activity自身所处进程的IApplicationThread传给AMS,这个主要是用于AMS的之后的回调。

层层转发,最后才将任务分发给了ActivityStack(外包既视感!),第一阶段到此结束,对于这个阶段要注意上述的IApplicationThread的传入, IApplicationThread本身就是一个AIDL的接口,具体实现在ActivityThread中,每一个ActivityThread都会生成一个ApplicationThread,用于 在与AMS通讯的回调使用。其实AMS也是一个AIDL的实现,我们在这一步相当于是获取AIDL,然后将自身的AIDL传给别人,实现一个回调注册。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class ActivityThread{
    ...
    private class ApplicationThread extends IApplicationThread.Stub {
        ...
    }
    ...
}

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
            ...
        }

2.栈顶Activity退出

栈顶Activity退出时序图

AMS在收到一个启动新APP的请求之后做的第一件重要的事,就是将当前Activity置于“休眠状态”,告诉它“我知道你的请求了,你可以下班了”。

从图中我们知道,AMS这边会产生一个ClientTransaction,一个ClientTransaction可以携带多个转化操作,不过这里这个ClientTransaction只 携带一个PauseActivityItem,从命名就可以看出,这个是一个让Activity “Pause” 的操作。

然后将ClientTansaction通过上文所说的IAppicationThread(这里也被说成是Client客户端)传回去。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class ClientTransaction implements Parcelable, ObjectPoolItem {
    ...
    private IApplicationThread mClient;
    ...
    public void schedule() throws RemoteException {
        //回调操作
        mClient.scheduleTransaction(this);
    }
    ...
}

经过Binder操作之后,ActivityThread这边的IApplicationThread就收到回调操作,然后继续任务分发,会将任务分发给ActivityThread中的 H,这个H其实就是一个Handler。ActivityThread在创建的同时也为该进程中创建了一个默认Looper,也就是我们常说的mainLooper,这个H就是ActvityThread为mainLooper准备的配套设施。

最后,传送过来的PauseActivityItem会执行具体的Pause操作,经过Instrumentation的转发,执行栈顶的Activity的performPause,最后也会 调用了我们常见的生命周期回调 onPause。

3.启动新进程

应用新进程启动时序图

ActivityStack在完成了pause 栈顶Actvity之后,就开始真正启动新应用的步骤了。通过AMS 将具体的启动任务分发到Process的start方法中, Process调用ZygoteProcess的start方法,然后ZygoteProcess调用startViaZygote进行操作,这一系列转发之后,关键时候来了。ZygoteProcess与 Zygote开始通讯,两者IPC通讯的方式也很直接,使用了Socket完成操作。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//Process.java
public class Process {
    ...
    public static final String ZYGOTE_SOCKET = "zygote";
    public static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary";
    public static final ZygoteProcess zygoteProcess = new ZygoteProcess(ZYGOTE_SOCKET, SECONDARY_ZYGOTE_SOCKET);
    ...
}

//ZygoteProcess.java
public ZygoteProcess(LocalSocketAddress primarySocket, LocalSocketAddress secondarySocket) {
    //socket的句柄 为“zygote”
    mSocket = primarySocket;
    mSecondarySocket = secondarySocket;
}

private Process.ProcessStartResult startViaZygote(...) throws ZygoteStartFailedEx {
    ...
    return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    ...
    primaryZygoteState = ZygoteState.connect(mSocket);
    ...
}

private static Process.ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)throws ZygoteStartFailedEx {
    final BufferedWriter writer = zygoteState.writer;
    final DataInputStream inputStream = zygoteState.inputStream;
    //socket通讯
    writer.write(Integer.toString(args.size()));
    writer.newLine();
    for (int i = 0; i < sz; i++) {
        String arg = args.get(i);
        writer.write(arg);
        writer.newLine();
    }
    writer.flush();
    ...
}

在Zygote进程这边,会收到socket通讯请求,然后处理请求,这里我们先梳理一下Zygote进程的一些东西。按照 android系统启动了流程,Zygote进程初始化会在ZygoteInit.java文件中来完成。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class ZygoteInit {
    public static void main(String argv[]) {
        ...
        ZygoteServer zygoteServer = new ZygoteServer();
        ...
        //循环处理其他进程请求
        caller = zygoteServer.runSelectLoop(abiList);
        //如果是fork子进程,在执行完任务之后就退出       
        if (caller != null) {
            caller.run();
        }
    }
}

启动ZygoteInit之后,zygoteServer就会一直处于循环等待和处理消息的状态。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//ZygoteServer.java
Runnable runSelectLoop(String abiList) {
    while (true) {
        ...
        //等待接受请求
        ZygoteConnection newPeer = acceptCommandPeer(abiList);
        peers.add(newPeer);
        fds.add(newPeer.getFileDesciptor());
        ...
        ZygoteConnection connection = peers.get(i);
        //处理请求
        final Runnable command = connection.processOneCommand(this);
        if (mIsForkChild) {
            if (command == null) {
                throw new IllegalStateException("command == null");
            }
            return command;
            }
        }    
    }
}

private ZygoteConnection acceptCommandPeer(String abiList) {
    //等待
    return createNewConnection(mServerSocket.accept(), abiList);
}

获得消息之后就交给ZygoteConnection来处理具体事务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//ZygoteConnection.java
 Runnable processOneCommand(ZygoteServer zygoteServer) {
    //孵化操作
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
                parsedArgs.instructionSet, parsedArgs.appDataDir);
    if (pid == 0) {
        // in child
        ...
        return handleChildProc(parsedArgs, descriptors, childPipeFd,parsedArgs.startChildZygote);
    }
}

handleChildProc会调用ZygoteInit的静态方法childZygoteInit,childZygoteInit又会调用RuntimeInit的findStaticMain 来真正创建新应用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//RuntimeInit.java
protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } 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);
        }
        return new MethodAndArgsCaller(m, argv);
}

findStaticMain方法实际就是执行了反射操作,调用的传入类的main方法,而传入的类就是ActivityThread.java 到此才真正启动了应用

这里需要注意的是Zygote的孵化操作,这一部分其实完全需要新开一篇来讲,但是为了完全理解,我就再多嘴一下。 孵化新进程之后,建立应用就不用再重新加载资源,直接使用之前的,这项技术称为COW,如果当前进程是用于孵化新应用的 子进程的话,在新建应用成功之后,当前孵化的Zygote就会退出。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class ZygoteInit {
    public static void main(String argv[]) {
        String socketName = "zygote";
        ...
        ZygoteServer zygoteServer = new ZygoteServer();
        ...
        //循环处理其他进程请求
        caller = zygoteServer.runSelectLoop(abiList);
        //如果是fork子进程,在执行完任务之后就退出       
        if (caller != null) {
            caller.run();
        }
    }
}

还有一个地方就是上述Socket实际是由android本地生成的一个通讯管道,这块,目前笔者还不是很清楚,暂时只能记录下来 待后续补上。

Zygote socket通讯

4.ActivityThread 初始化

新Activity启动时序图

终于走到了最后一步,我们的应用的初始化这这里开始,上一阶段最后,系统反射了ActivityThread.java的main方法 main方法中会生成一个ActivityThread实例,同时准备该进程的mainLooper,和Handler。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public final class ActivityThread extends ClientTransactionHandler {
    public static void main(String[] args) {
        ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
}

当前的ActivityThread会调用attach来关联到AMS。AMS 会获取当前的ActivityThread的启动资料记录 具体是根据当前进程的pid。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
private final boolean attachApplicationLocked(IApplicationThread thread,int pid, int callingUid, long startSeq) {
    ProcessRecord app;
    long startTime = SystemClock.uptimeMillis();
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            //获取启动资料
            app = mPidsSelfLocked.get(pid);
        }
    } else {
        app = null;
    }
    ...
}

上图中的mPidsSelfLocked的存储操作发生在向Zygote请求fork新进程之后,将请求到的pid和新进程的信息都保存在mPidsSelfLocked中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//ActivityManagerService.java

 private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        ...
        if (mConstants.FLAG_PROCESS_START_ASYNC) {
            ...
            //建立新进程
             final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
                            app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
                            requiredAbi, instructionSet, invokeWith, app.startTime);
            //存储新进程信息
            handleProcessStartedLocked(app, startResult, startSeq);
            ...
            return true;
        } else {
            ...
            //建立新进程
             final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
                            app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
                            requiredAbi, instructionSet, invokeWith, app.startTime);
            //存储新进程信息
            handleProcessStartedLocked(app, startResult, startSeq);
            ...
            return app.pid > 0;
        }
    }

private boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,long expectedStartSeq, boolean procAttached) {
     ...
    synchronized (mPidsSelfLocked) {
        this.mPidsSelfLocked.put(pid, app);
        ...
        return true;
    }
}

获取到的ProcessRecord app会在后续的用于查找需要启动的Activity的信息,最后在ActivityStackSupervisor的realStartActivityLocked 发起启动Activity的事务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {

    ...
    //准备了Launch和Resume的事务,向ActivityThread发送执行
    final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);
    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
        System.identityHashCode(r), r.info,
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
        profilerInfo));
    final ActivityLifecycleItem lifecycleItem;
    if (andResume) {
        lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
    clientTransaction.setLifecycleStateRequest(lifecycleItem);
    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}

之后的过程跟第二步分析的Pause过程大致相同,不再多言

总结

本篇文章着重大致分析Activity的启动的完整流程,其实一个Activity的启动情况很多,不同的生命周期有着不同的 调用流程,这里也就不一一描述了。同时,笔者深感对于Zygote的启动过程和其特有的Socket通讯还有很多迷惑之处,后续会继续 深入分析,继续耕耘。本篇文章调用时序跳转过多,特此留下一张简图,以供参考。

Activity启动简图