Android应用启动

在讲应用启动之前,我们需要了解两个知识点

  • Binder IPC机制
  • Zygote 机制

Binder IPC比较复杂,请移步Binder IPC机制

Zygote?

我们知道,Android 是基于 Linux 内核开发的,而在 Linux 中,所有的进程都是直接或者间接地由 init 进程 fork 出来的。Zygote 进程也不例外,它是在系统启动的过程,由 init 进程创建的。

Zygote 的运行

做过手机系统开发的大佬都知道,init 进程代码在系统启动脚本 system/core/rootdir/init.rc 文件中。 截取一部分代码,可以发现,
是通过运行 service zygote 命令来创建 zygote

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
...

初始化 Zygote

执行命令后,最终会调用 Zygote 相关的 Java 代码。Zygote 进程的初始化在 ZygoteInit 这个类中的 main 方法

public static void main(String argv[]) {
    // zygote 进程的 socketServer 
    ZygoteServer zygoteServer = new ZygoteServer();
    ZygoteHooks.startZygoteNoThreadCreation();

    ...

    final Runnable caller;
    try {

        boolean startSystemServer = false;
        String socketName = "zygote";
        String abiList = null;
        boolean enableLazyPreload = false;

        // 为 zygote 命令连接(ZygoteConnection)注册一个 server socket
        // 内部实现类 LocalServerSocket Os.listen 开始一个阻塞监听 socket 连接
        zygoteServer.registerServerSocket(socketName);
        ...

        if (startSystemServer) {
            // 创建系统进程
            Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
            if (r != null) {
                r.run();
                return;
            }
        }

        // SocketServer 阻塞监听连接
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        throw ex;
    } finally {
        zygoteServer.closeServerSocket();
    }

    // We're in the child process and have exited the select loop. Proceed to execute the
    // command.
    if (caller != null) {
        caller.run();
    }
}

ZygoteServer 轮询连接

runSelectLoop 方法,来看看关键的代码,while(true) 死循环,轮询操作,接收一个新的连接,读取命令

Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);
    // 轮训 FileDescriptor,peers
    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        ...
        try {
            if (i == 0) {
                // 接收一个新的连接,保存到集合
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                // 下一次 while轮训时, 拿到 socket 连接
                ZygoteConnection connection = peers.get(i);
                // 处理命令
                final Runnable command = connection.processOneCommand(this);
                ...
            }
        } catch (Exception e) {
            ...
        }
    }
}

使用过 socket 的大佬应该很熟悉,

  • ZygoteServer 相当于 SocketServer 服务端包装类
  • ZygoteConnection 表示一个远端 Socket 连接

ZygoteConnection 处理命令

我们看看 ZygoteConnection 是怎么处理命令的,

Runnable processOneCommand(ZygoteServer zygoteServer) {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    ...
    // 实际创建进程的地方还是回到了 Zygote 类中
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
            parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
            parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
            parsedArgs.appDataDir);

    // 创建进程后的处理,异常处理,关闭连接等
    ...
}

回到 Zygote forkAndSpecialize 中,

 public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
      int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
      int[] fdsToIgnore, String instructionSet, String appDataDir) {
    // ZygoteHooks
    VM_HOOKS.preFork();
    // Resets nice priority for zygote process.
    resetNicePriority();
    // native 方法创建进程
    int pid = nativeForkAndSpecialize(
              uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
              fdsToIgnore, instructionSet, appDataDir);
    // Enable tracing as soon as possible for the child process.
    ...
    VM_HOOKS.postForkCommon();
    return pid;
}

小结

至此, 我们大致了解了 zygote 是什么以及它的作用

  • Zygote 是由 init 进程,通过执行脚本命令创建的一个进程,由 ZygoteInit main 方法完成初始化
  • 初始化时 启动一个 ZygoteServer,SocketServer 的Java包装类,监听 Socket 连接
  • ZygoteServer 拿到 Socket 连接 ZygoteConnection(连接的包装类),处理命令
  • ZygoteConnection 主要是处理创建进程的命令,最后会回到 Zygote 类 forkAndSpecialize
  • Zygote.forkAndSpecialize 调用 JNI native 方法实现进程的创建

App 的启动

理解了 Zygote 的作用后,我们以 Android O 源码为基础,分析 Android App 启动的流程,这有助于后续学习 Android framework ,
hook技术, dex等知识的学习

Launcher 里启动 App

在 Launcher 源码里启动 App,调用的也是我们常用的 startActivity 方法。Activity 里的最后调用的是,

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    // mParent 指当前的 Activity 是否是嵌套在其他的 Activity 中,我们通常很少嵌套 Activity
    if (mParent == null) {
        // options 参数处理
        options = transferSpringboardActivityOptions(options);
        // 通过 Instrumentation 启动Activity
        // mMainThread.getApplicationThread()返回的是 ApplicationThread,继承自 IApplicationThread.Stub
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            // 发送启动结果
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        ...
    }
    ...
}

Instrumentation 里 execStartActivity,关键的代码在 ActivityManager.getService().startActivity(…) 启动 Activity

public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, String target,
    Intent intent, int requestCode, Bundle options) {
    ...
    // ActivityManager.getService 拿到 IActivityManager 调用 startActivity
    int result = ActivityManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target, requestCode, 0, null, options);
    checkStartActivityResult(result, intent);
    ...
}

ActivityManager.getService 返回的是 IActivityManager,命名方式可以看出是一个接口

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

IActivityManagerSingleton 的初始化,

private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() {
        @Override
        protected IActivityManager create() {
            // 通过 ServiceManager 拿到 ActivityManagerService(AMS) 的 Service IBinder对象
            final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
            // IActivityManager.Stub.asInterface 
            final IActivityManager am = IActivityManager.Stub.asInterface(b);
            return am;
        }
    };

看到 IActivityManager.Stub.asInterface 是不是有点似曾相似的感觉,是的,这里使用到的就是 AIDL 跨进程通信的机制, IActivityManager 是定义好的 AIDL 接口。Application 层的源码到这里就结束了,再往下,我们就要找 ServiceManager 了

framework 里启动

Binder 调用AMS

ServiceManager 在 android.os 包下,看看相关方法

public final class ServiceManager {
    private static final String TAG = "ServiceManager";
    private static IServiceManager sServiceManager;
    // 定义 HashMap 缓存各种 IBinder 实例,我们的 AMS 实例也是存储在该 hashmap 中
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

    private static IServiceManager getIServiceManager() {
        ...
        // ServiceManagerNative 将 Binder 转换为 IServiceManager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

    public static IBinder getService(String name) {
        ...
        // 调用 IServiceManager 的 getService 方法
        return Binder.allowBlocking(getIServiceManager().getService(name));
        ...
    }
}

其中 BinderInternal.getContextObject() 是一个 native 方法,返回一个系统全局的 “context” 对象 IBinder,通常是 IServiceManager 的实现。
因为是 native 方法,我们可以猜到这个 IServiceManager 实现是由 C++ 来完成的。 这部分就复杂了,感觉越讲内容越多了,不是我们应用启动的内容暂时就到
这里。

回到 ServiceManager.getService(“activity”), 拿到的是 IActivityManager 的实现,AMS 在 com.android.server.am 包下。 调用的是
startActivityAsUser() ,这里又使用了 ActivityStarter 来启动

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

    @Override
    public final int startActivityAsUser(...) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // 调用 ActivityStarter 方法启动
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
    }
}

这里面就不一层层介绍了,实在太绕了,归纳如下流程

ActivityStarter.java:
-->startActivityMayWait
    -->startActivityLocked
        -->startActivity
            -->startActivity
                -->startActivityUnchecked(来自ActivityStackSupervisor的方法) 

ActivityStackSupervisor.java:
    -->resumeFocusedStackTopActivityLocked(来自ActivityStack的方法)  
ActivityStack.java:
    -->resumeTopActivityUncheckedLocked
        -->resumeTopActivityInnerLocked
            -->startSpecificActivityLocked(来自ActivityStackSupervisor)
                -->startProcessLocked(来自AMS,启动新进程)

startSpecificActivityLocked 这个方法,检查应用进程记录是否已经运行,

  • 如果App 进程记录已经存在,则执行 realStartActivityLocked
  • 如果不存在则运行 mService.startProcessLocked

    void startSpecificActivityLocked(ActivityRecord r,

        boolean andResume, boolean checkConfig) {
    // 当前 Activity 的 application 是否在运行?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    
    r.getStack().setLaunchTime(r);
    //app 正在运行,
    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            // 1. 执行 realStartActivityLocked
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
    }
    // 2. app 未启动, 执行 startProcessLocked,启动新进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
    

    }

zygote fork进程启动app

由上面的分析,我们知道,在 app 尚未启动时,会执行 mService.startProcessLocked 这个方法

final ProcessRecord startProcessLocked(...) {
    return startProcessLocked(...);
}

final ProcessRecord startProcessLocked(...) {
    long startTime = SystemClock.elapsedRealtime();
    ProcessRecord app;
    // 一系列检查操作
    ...

    // 开始创建进程,同时记录耗时时间
    checkTime(startTime, "startProcess: stepping in to startProcess");
    startProcessLocked(
            app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    checkTime(startTime, "startProcess: done starting proc!");
    return (app.pid != 0) ? app : null;
}

startProcessLocked 里, 这里稍微留一下,entryPoint 被赋值为 android.app.ActivityThread

private final void startProcessLocked(ProcessRecord app, String hostingType,
    String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    ...
    // Start the process.  It will either succeed and return a result containing
    // the PID of the new process, or else throw a RuntimeException.
    boolean isActivityProcess = (entryPoint == null);
    if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    ...
    if (hostingType.equals("webview_service")) {
        ...
    } else {
        // 这里就是开始创建进程的地方了
        startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                app.info.dataDir, invokeWith, entryPointArgs);
    }
    ...

来看看 Process 类里是怎么做的,方法也是一堆参数,先忽略了。 可以看到用到了 zygoteProcess 这个类

public static final ZygoteProcess zygoteProcess =
        new ZygoteProcess("zygote", "zygote_secondary");

 public static final ProcessStartResult start(...) {
    return zygoteProcess.start(...);
}

简单看看 ZygoteProcess 的构造,可以发现跟 Socket 貌似有点关联,前面了解过 Zygote,我们大概能知道,
这里准备要涉及 Socket 来实现进程间的通讯

public class ZygoteProcess {
    /**
    * socket的名称,用于跟主zygote的交流
    */
    private final String mSocket;
    /**
    * 另外一个 zogote socket名称(适配不同 ABI)
    */
    private final String mSecondarySocket;

    public ZygoteProcess(String primarySocket, String secondarySocket) {
        mSocket = primarySocket;
        mSecondarySocket = secondarySocket;
    }

    public final Process.ProcessStartResult start(...) {
        // 通过 Zygote 来启动
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }
    ...
}

startViaZygote,

/**
* 启动一个新的进程,通过 zygote 机制. 
*/
private Process.ProcessStartResult startViaZygote(...)
                                                  throws ZygoteStartFailedEx {
    // zygote 参数集合                                                          
    ArrayList<String> argsForZygote = new ArrayList<String>();

    // --runtime-args, --setuid=, --setgid=,
    // and --setgroups= must go first
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
        argsForZygote.add("--enable-jni-logging");
    }
    // 省略的这部分都是往参数集合里加配置参数
    ...
    // 这里 processClass 是 AMS 里的 entryPoint
    argsForZygote.add(processClass);

    synchronized(mLock) {
        // 将参数集合传递
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

主要做了如下操作

  1. 添加配置参数
  2. openZygoteSocketIfNeeded socket连接操作
  3. zygoteSendArgsAndGetResult 通过 socket 连接发送数据

简单看看 zygoteSendArgsAndGetResult,

private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> args)
        throws ZygoteStartFailedEx {
    ...
    // IO 写操作
    final BufferedWriter writer = zygoteState.writer;
    final DataInputStream inputStream = zygoteState.inputStream;

    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();
    }
    // 通过 ZygoteState.writer 写数据
    writer.flush();

    // 到这里,进程已经创建完成了,后续就是读取进程 pid 了
    Process.ProcessStartResult result = new Process.ProcessStartResult();

    result.pid = inputStream.readInt();
    result.usingWrapper = inputStream.readBoolean();

    if (result.pid < 0) {
        throw new ZygoteStartFailedEx("fork() failed");
    }
    return result;
}

了解过 zygote 机制的我们知道,IO 操作,数据会传递给 ZygoteServer 服务端轮询处理,而数据的处理在 ZygoteConnection.processOneCommand,最终通过 Zygote 调用 native 方法 fork 出新的进程

App 进程已存在

在App 的 Application已经在运行的情况下,会执行 ActivityStackSupervisor 的 realStartActivityLocked 方法

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
    boolean andResume, boolean checkConfig) throws RemoteException {
        ...
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);
        ...
}

scheduleLaunchActivity 是来自 ActivityThread, 最终会使用 Handler 机制,发送 Message 消息去启动Activity

public final void scheduleLaunchActivity(...) {

        updateProcessState(procState, false);

        ActivityClientRecord r = new ActivityClientRecord();
        ...

        sendMessage(H.LAUNCH_ACTIVITY, r);
}

handleMessage 处理 LAUNCH_ACTIVITY 消息,

public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } 
            break;
        }
}

handlerLaunchActivity 里的调用 performLaunchActivity 完成最终的启动

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 构建 component
    ...

    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        // 通过 ClassLoader 加载 Activity 类,启动
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        ...
    }

    try {
        // 构建 Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (activity != null) {
            ...
            // 调用 Activity attach 到 window
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);
            ...
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {

    }
    return activity;
}

至此,Activity 的启动页就大致结束了,其他的细节我们就不关注了。
此外,这里 ActivityThread 也是我们着重关注的对象.

ActivityThread

ActivityThread 在 Android 中它就代表了 Android 的主线程,但是并不是一个 Thread 类。

严格来说,UI主线程不是 ActivityThread。ActivityThread 类是 Android APP 进程的初始类,它的 main 函数是这个 APP 进程的入口。
APP 进程中 UI 事件的执行代码段都是由 ActivityThread 提供的。也就是说,MainThread 实例是存在的,可以理解为 ActivityThread main方法所运行的线程。

public final class ActivityThread {
    ...
    private static ActivityThread sCurrentActivityThread;
    final H mH = new H();

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        ...
    }

    public static void main(String[] args) {
        ...

        // 创建 Looper 和 MessageQueue 对象,用于处理主线程的消息
        Looper.prepareMainLooper();

        // 创建ActivityThread对象
        ActivityThread thread = new ActivityThread(); 

        // 建立Binder通道 (创建新线程)
        thread.attach(false);

        if (sMainThreadHandler == null) {
            // sMainThreadHandler 即 mH
            sMainThreadHandler = thread.getHandler();
        }
        // 消息循环运行
        Looper.loop(); 
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

    private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        public static final int PAUSE_ACTIVITY_FINISHING= 102;
        public static final int STOP_ACTIVITY_SHOW      = 103;
        public static final int STOP_ACTIVITY_HIDE      = 104;
        public static final int SHOW_WINDOW             = 105;
        public static final int HIDE_WINDOW             = 106;
        public static final int RESUME_ACTIVITY         = 107;
        public static final int SEND_RESULT             = 108;
        public static final int DESTROY_ACTIVITY        = 109;
        public static final int BIND_APPLICATION        = 110;
        public static final int EXIT_APPLICATION        = 111;
        public static final int NEW_INTENT              = 112;
        public static final int RECEIVER                = 113;
        public static final int CREATE_SERVICE          = 114;
        public static final int SERVICE_ARGS            = 115;
        public static final int STOP_SERVICE            = 116;
        ...
    }
}

mH Handler 里处理了四大组件的各种消息,如启动 Activity LAUNCH_ACTIVITY,创建Servie CREATE_SERVICE 等等。 可以说 ActivityThread 是 Activity 生命周期中一个至关重要的管理类, 也可以理解为是主线程操作的管理类。

总结

大致的流程图如下

App启动

  1. 点击桌面App图标,Launcher进程采用Binder IPC 向 system_server 进程发起startActivity请求
  2. system_server进程接收到请求后,向zygote进程发送创建进程的请求
  3. Zygote进程fork出新的子进程,即App进程
  4. App进程,通过Binder IPC向sytem_server进程发起attachApplication请求
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求
  6. App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息
    主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法
  7. App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面