Activity启动流程

0 阅读7分钟

Activity启动流程

启动一个 Activity,通常有两种情况,一种是在应用内部启动 Activity,另一种是 Launcher 启动。

一、应用内启动

当我们调用startActivity()时,这个请求会经过多个进程和系统服务,大致流程如下:

  • 应用进程(调用者Activity所在进程)通过Binder调用到ActivityManagerService(AMS)。
  • AMS处理启动请求,检查权限、目标Activity信息等。
  • 如果目标Activity所在进程未启动,AMS会通知Zygote进程fork一个新进程。
  • 新进程启动后,会创建ActivityThread,并调用main()方法,然后进入消息循环。
  • 新进程通过Binder调用AMS的attachApplication(),告诉AMS自己已经启动。
  • AMS通过Binder调用新进程的bindApplication(),传递应用信息,并创建目标Activity。
  • 新进程开始Activity的生命周期调用,最终完成启动。

二、Launcher 启动

从桌面点击图标启动应用,实际上是从Launcher应用启动目标应用的主Activity。整个流程与普通的Activity启动类似,但Launcher本身也是一个应用,所以涉及到两个应用之间的启动过程。 整个流程可以分为以下几个阶段:

  1. Launcher进程向AMS发送启动目标应用主Activity的请求。
  2. AMS处理启动请求,如果目标应用进程不存在,则创建新进程。
  3. 目标应用进程启动,并创建主Activity,然后显示界面。

首先了解一下关键角色:

角色所在进程职责
调用者Activity应用进程发动启动请求
Instrumentation应用进程监控应用程序与系统交互
ActivityManagerService(AMS)system_server进程所有Activity的调度中心
ApplicationThread应用进程AMS与应用进程通信的桥梁
ActivityThread应用进程应用主线程,管理Activity生命周期
Zygotezygote进程孵化新进程

一次startActivity调用,本质上是应用进程请求系统进程(主要是ActivityTaskManagerService) 来调度和管理一个新的Activity。这个过程分为两段:

  1. 进程内调用链:在您的应用进程内传递,终点是发起一个跨进程调用(IPC)。
  2. 跨进程调用:通过Binder进入系统进程,由系统服务处理。

startActivity()开始,

// 1. 从这里开始
public class MainActivity extends Activity {
    public void startNewActivity() {
        startActivity(new Intent(this, SecondActivity.class));
    }
}

// 2. 进入Activity.java
public void startActivity(Intent intent) {
    startActivity(intent, null); // Bundle options为null
}

public void startActivity(Intent intent, @Nullable Bundle options) {
    // 关键调用:Instrumentation.execStartActivity()
    if (options != null) {
        mInstrumentation.execStartActivity(
            this, mMainThread.getApplicationThread(), 
            mToken, this, intent, -1, options);
    } else {
        mInstrumentation.execStartActivity(
            this, mMainThread.getApplicationThread(), 
            mToken, this, intent, -1);
    }
}

// 3. Instrumentation.execStartActivity()
public ActivityResult execStartActivity(
        Context who, // 调用者上下文,即当前Activity (this)
        IBinder contextThread, // 核心!应用进程的Binder句柄
        IBinder token,       // 核心!当前Activity的标识令牌
        Activity target,     // 当前Activity (this)
        Intent intent,       // 要启动新Activity的Intent
        int requestCode, 
        Bundle options
    ) {
    
    // contextThread 实际是 ApplicationThread 的 Binder 代理
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    
    try {
        // 4. 关键调用:通过Binder跨进程调用AMS
        int result = ActivityManager.getService()
            .startActivity(whoThread, // ApplicationThread代理
                          who.getBasePackageName(), // 包名
                          intent, 
                          intent.resolveTypeIfNeeded(who.getContentResolver()),
                          token, // 当前Activity的token
                          target != null ? target.mEmbeddedID : null,
                          requestCode, 0, null, options);
        
        // 检查启动结果
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

以上是进程内调用链的最后几步。它的核心使命是:收集好所有必要参数,然后通过Binder IPC将启动请求“扔”给系统。

  • 首先Activity.startActivity()最终会调用重载方法,并准备一个关键的 mInstrumentation对象。

  • 每个应用进程有且仅有一个Instrumentation实例。它由系统在启动进程时创建,并关联到主线程(ActivityThread)。它才是应用进程中真正“执行”Activity、Application生命周期方法(如onCreateonStart)的组件。系统进程通过Binder调用通知ApplicationThreadApplicationThread会转交给Instrumentation来实际调用。在当前startActivity的场景下,它负责将调用打包,并通过Binder转发给系统。

  • ActivityManager.getService()返回的是AMS的Binder代理对象。调用从这里离开应用进程,进入system_server进程,是进程内调用链的终点和跨进程调用的起点。

现在进入到system_server进程,ActivityTaskManagerService(ATMS) 开始工作

这里解释一下,在Android 10之前,AMS(ActivityManagerService)负责所有Activity管理。Android 10引入ATMS,将Activity和任务栈管理从AMS中分离出来,实现关注点分离。其职责包括Activity生命周期的管理,任务栈和返回栈管理,Activity启动模式处理,Activity转场动画管理,多窗口模式支持。

// 5. ActivityManagerService.startActivity()
public final int startActivity(IApplicationThread caller, 
                              String callingPackage, Intent intent, 
                              String resolvedType, IBinder resultTo, 
                              String resultWho, int requestCode, 
                              int startFlags, ProfilerInfo profilerInfo, 
                              Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, 
                              resolvedType, resultTo, resultWho, 
                              requestCode, startFlags, profilerInfo, 
                              bOptions, UserHandle.getCallingUserId());
}

// ATMS不直接处理启动逻辑,而是委托给专门的控制器
private int startActivityAsUser(...) {
    // 关键:获取Activity启动控制器
    return getActivityStartController().obtainStarter(intent, "startActivity")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setIntent(intent)
            // ... 设置所有参数
            .execute();
}

int execute() {
    try {
        // 解析Intent,找到目标Activity
        int res = startActivityMayWait(...);
        return res;
    } finally {
        onExecutionComplete();
    }
}

// 6. 经过多个调用,最终到ActivityStarter
// ActivityStarter是真正的启动引擎,它处理所有复杂的启动逻辑
class ActivityStarter {
    int startActivityMayWait(...) {
        // 7. 这里进行复杂的检查和处理:
        //    - 权限检查
        //    - Activity是否存在
        //    - 启动模式处理
        //    - 任务栈管理
        
        // 8. 获取目标Activity信息
        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo);
        
        // 9. 处理启动模式(重点!)
        //    如果是singleTask,会查找现有任务栈
        //    如果是singleInstance,会创建新任务栈
        
        // 10. 检查目标进程是否存在
        ProcessRecord app = mService.getProcessRecordLocked(
            targetProcessName, info.applicationInfo.uid);
        
        if (app != null && app.thread != null) {
            // 进程已存在,直接启动Activity
            realStartActivityLocked(r, app, andResume, checkConfig);
        } else {
            // 11. 需要创建新进程!
            mService.startProcessLocked(targetProcessName, 
                                       info.applicationInfo, 
                                       knownToBeDead, false, 
                                       intent.getFlags());
        }
    }
}

ATMS在这里做了大量决策,特别是处理启动模式(Launch Mode),后续整理。

如果目标Activity的进程不存在,AMS会通过Zygote创建新进程。

是否需要创建新进程取决于目标Activity所在的应用程序进程是否已经存在。

场景结果
启动同一个应用内的Activity复用现有进程,在同一个进程中创建新Activity
启动其他应用,但该应用已在运行复用目标应用的已有进程
多任务栈,但进程相同创建新的任务栈,但复用进程
首次启动应用应用从未启动过,或应用进程已被系统回收,创建新进程
应用配置了多进程为独立进程创建新进程,常见后台播放器, Webview隔离进程等
// 12. ATMS请求Zygote创建进程
final ProcessRecord startProcessLocked(String processName,
                                      ApplicationInfo info,
                                      boolean knownToBeDead,
                                      int intentFlags,
                                      String hostingType) {
    
    // 通过Socket通知Zygote fork新进程
    Process.ProcessStartResult startResult = Process.start(
        "android.app.ActivityThread", // 入口类,新进程的主类
        app.processName, uid, uid, gids,
        debugFlags, mountExternal, 
        app.info.targetSdkVersion, 
        app.info.seinfo, 
        app.info.abi, 
        app.info.dataDir, 
        null);
    
    // 保存进程记录
    app.setPid(startResult.pid);
    app.thread = null; // 还未连接
}

新进程被创建后,来到该应用进程,执行入口ActivityThread.main()

// 13. 新进程的入口点
public static void main(String[] args) {
    // 1. 准备主线程Looper
    Looper.prepareMainLooper();
    
    // 2. 创建ActivityThread实例
    ActivityThread thread = new ActivityThread();
    
    // 3. 关键:attach到AMS
    thread.attach(false, startSeq);
    
    // 4. 开始消息循环
    Looper.loop();
}

// 14. attach到ATMS
private void attach(boolean system, long startSeq) {
    // 获取ATMS的Binder代理
    final IActivityManager mgr = ActivityManager.getService();
    
    try {
        // 告诉ATMS:我准备好了,这是我的ApplicationThread
        mgr.attachApplication(mAppThread, startSeq);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

每个应用进程都有一个ApplicationThread对象,它是AMS回调应用进程的"电话线",而后回到ATMS进程,处理新进程的attach。

// 15. AMS.attachApplication()
public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        // 找到对应的进程记录
        ProcessRecord app = getProcessRecordLocked(thread);
        
        if (app != null) {
            // 绑定进程
            bindApplication(thread, ...);
            
            // 16. 现在可以启动Activity了!
            if (mStackSupervisor.attachApplicationLocked(app)) {
                // 这里会找到等待启动的Activity
                realStartActivityLocked(activity, app, true, true);
            }
        }
    }
}

// 17. 真正启动Activity,之前不需要创建新进程的话直接来到这里
final boolean realStartActivityLocked(ActivityRecord r, 
                                     ProcessRecord app, 
                                     boolean andResume, 
                                     boolean checkConfig) {
    
    // 通过Binder回调到应用进程
    app.thread.scheduleLaunchActivity(
        new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info,
        mergedConfiguration, r.compat, r.launchedFromPackage,
        task.voiceInteractor, app.repProcState, r.icicle, 
        r.persistentState, results, newIntents, 
        !andResume, mService.isNextTransitionForward(),
        profilerInfo);
    
    return true;
}

接下来到新进程,应用进程,来创建Activity实例

// 18. ApplicationThread.scheduleLaunchActivity()
// ApplicationThread是ActivityThread的内部类
private class ApplicationThread extends IApplicationThread.Stub {
    public final void scheduleLaunchActivity(...) {
        // 发送消息到主线程Handler
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
}

// 19. ActivityThread.H处理消息
class H extends Handler {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case LAUNCH_ACTIVITY:
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                break;
        }
    }
}

// 20. 创建Activity实例
private void handleLaunchActivity(ActivityClientRecord r, 
                                  Intent customIntent, String reason) {
    
    // 1. 创建Activity实例(反射)
    Activity activity = mInstrumentation.newActivity(
        cl, component.getClassName(), r.intent);
    
    // 2. 创建Application(如果不存在)
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
    // 3. 关联Context
    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);
    
    // 4. 调用onCreate()
    mInstrumentation.callActivityOnCreate(activity, r.state);
    
    // 5. 调用onStart()和onResume()
    if (!r.activity.mFinished) {
        activity.performStart();
        r.activity.mResumed = true;
    }
}

简述:

"具体来说,当我们调用startActivity()时,首先通过Instrumentation跨进程调用AMS的startActivity方法。AMS会进行一系列检查,包括权限验证、Activity是否存在、启动模式处理等。如果目标进程不存在,AMS会通过Zygote fork新进程。新进程启动后执行ActivityThread.main(),并通过attachApplication()告诉AMS自己已就绪。AMS接着通过ApplicationThread这个Binder代理回调到应用进程,最终在主线程中通过反射创建Activity实例,并依次调用onCreate、onStart、onResume。整个过程涉及到至少两次Binder跨进程调用,以及复杂的任务栈管理逻辑。"

完整流程时序图如下:

image.png