Android 12 Activity 启动流程分析

1,677 阅读8分钟

前言

在Android中Activity是与用户直接交互的组件,提供窗口用于绘制界面,不同Activity之间关联松散,通过startActivity方法完成Activity跳转。本文是以Android-12.0.0_r3源码对Activity启动流程进行分析。

源码地址:aospxref.com/android-12.…

应用端

可以通过调Context或Activity的startActivity方法完成Activity跳转,startActivity是Activity启动流程的起点。

Context和Activity启动Activity主要有两点区别

  1. Context startActivity的intent需要setFlag: Intent.FLAG_ACTIVITY_NEW_TASK, 否则会直接抛出AndroidRuntimeExeption异常。
  2. Context startActivity不支持启动结果回调,不支持类似Activity中startActivityForResult的启动方式。

无论哪种启动方式最终都会走到Instrumentation的execStartActivity方法,在execStartActivity中回调ActivityMonitor的onStartActivity,ActivityMonitor是Instrumentation的一个内部类,可以用于实现监听整个APP中startActivity,可以startActivity拿到传入的intent参数。

Instrumentation的execStartActivity接着会调用 ActivityTaskManager.getService().startActivity,这是一次通过binder方式进行的跨进程调用,客户端是ActivityTaskManager,服务端是ActivityTaskManagerService,getService()获取到的是IActivityTaskManager,IActivityTaskManager的startActivity由服务端是ActivityTaskManagerService实现。

System Server进程

ActivityTaskManagerService

ActivityTaskManagerService是系统进程中管理activities以及activity的容器的组件。 Activity调起流程进入system server进程后,首先获取了一下客户端调用者进程的uid,并且明确需要验证调用者,接着获取到ActivityStarter对象,传入一系列参数,执行ActivityStarter的execute方法。

ActivityStarter

ActivityStarter是启动一个activity的控制器。这个类决定一个intent和flags怎样转化为一个actiivty,并且关联Task和Root Task。ActivityStarter在Activity启动中的起到的作用是参数校验、状态检查。

核心方法

  • execute
  • executeRequest
  • startActivityUnchecked
  • startActivityInner

execute:从提前传入的请求参数中解析重要信息。
executeRequest:中开启了几项检查,包括检查调起APP是否存在、被调起的组件是否存在、intent中指定的类是否存在,语音交互调起是否支持的检查、调起权限检查。然后组装调起参数,调用startActivityUnchecked。
startActivityUnchecked:调用该方法时表示大部分初步的权限检查已经完成,执行 Trace,以及异常处理。
startActivityInner:如果启动的是已经启动过了的的activity,确定会将Activity添加到栈顶,或者把会把新的intent传递过去到已经在栈顶的Activity,还将活动任务操作到请求的或有效的根任务/显示上。任务栈检查,重复启动检查。

  • Task#startActivityLocked
  • RootWindowContainer#resumeFocusedTasksTopActivities-->Task#resumeTopActivityUncheckedLocked

Task

Task将相关的Activity组合到一起,以Activity Stack的方式进行管理。

  • resumeTopActivityUncheckedLocked
  • resumeTopActivityInnerLocked

resumeTopActivityUncheckedLocked确保待启动的Activity进入Resume,如果成功进入resume会返回true,否则什么也不会发生返回false。

      private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
              boolean deferPause) {
// ATMS不在启动中切未启动直接结束返回
// 未找到下一个顶部展示的activity跳转执行 resumeNextFocusableActivityWhenRootTaskIsEmpty
// 下一个顶部展示的activity已经在resume状态了直接返回
// 检查此活动是否能够恢复。对于 pre-Q 应用程序,只有每个应用程序的最顶层活动
// 如果当前正在pausing一个activity,那就直接返回
// 如果进入休眠状态且当前没有resumedActivity结束执行
// 已经存在其他调用将待展示的activity启动且进入started结束执行
// pausing or resume returen true
// prev activity set un visiable
// 动画相关
// ...

if (next.attachedToProcess()) {
// 被调起activity 进程、线程都已启动
if (notUpdated) {
    ActivityRecord nextNext = topRunningActivity();
    ProtoLog.i(WM_DEBUG_STATES, "Activity config changed during resume: "
    + "%s, new next: %s", next, nextNext);
    if (nextNext != next) {
    // Do over!
    mTaskSupervisor.scheduleResumeTopActivities();
}
    if (!next.mVisibleRequested || next.stopped) {
        next.setVisibility(true);
    }
    next.completeResumeLocked();
    return true;
}
// 进行状态更新

    next.notifyAppResumed(next.stopped);  
    EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
          next.getTask().mTaskId, next.shortComponentName);

    mAtmService.getAppWarningsLocked().onResumeActivity(next);
    next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
    next.abortAndClearOptionsAnimation();
    transaction.setLifecycleStateRequest(
          ResumeActivityItem.obtain(next.app.getReportedProcState(),
                  dc.isNextTransitionForward()));
    mAtmService.getLifecycleManager().scheduleTransaction(transaction);

} else {
// 新启动activity
    mTaskSupervisor.startSpecificActivity(next, true, true);
}
      
// ...

ActivityTaskSupervisor

  • startSpecificActivity
  • realStartActivityLocked
  • mService.getLifecycleManager().scheduleTransaction(clientTransaction);
  • ActivityTaskManagerService#startProcessAsync

如下代码是Activity启动流程的关键点,区分了不启动进程和需要启动进程两种情况的启动Ativity。

void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
          // Is this activity's application already running?
          final WindowProcessController wpc =
                  mService.getProcessController(r.processName, r.info.applicationInfo.uid);
  
          boolean knownToBeDead = false;
          if (wpc != null && wpc.hasThread()) {
              try {
                  realStartActivityLocked(r, wpc, andResume, checkConfig);
                  return;
              } catch (RemoteException e) {
                  Slog.w(TAG, "Exception when starting activity "
                          + r.intent.getComponent().flattenToShortString(), e);
              }
  
              // If a dead object exception was thrown -- fall through to
              // restart the application.
              knownToBeDead = true;
          }
  
          r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
  
          final boolean isTop = andResume && r.isTopRunningActivity();
          mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
      }

startSpecificActivity中通过判断进程如果正在运行会调用realStartActivityLocked并结束返回,如果没有正在运行的进程则调用 ActivityTaskManagerService的startProcessAsync先启动进程。

直接启动目标Activity

realStartActivityLocked中主要是进程信息、配置信息参数初始化并封装到clientTransaction中,最终通过调用scheduleTransaction方法使用binder跨进程通信完成从system 进程切到APP进程的调用,又通过ActivityThread中的内部类H使用handler切换到当前APP主线程。


  • scheduleTransaction
  • transaction.schedule();
  • mClient.scheduleTransaction(this);
  • IApplicationThread
  • ActivityThread.this.scheduleTransaction(transaction);
  • ClientTransactionHandler
  • sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
  • handleMessage mTransactionExecutor.execute(transaction);
  • executeCallbacks(transaction);
  • cycleToPath
  • performLifecycleSequence
  • mTransactionHandler.handleLaunchActivity
  • ActivityThread performLaunchActivity

Activity activity = null;
          try {
              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(isProtectedComponent(r.activityInfo),
                      appContext.getAttributionSource());
              if (r.state != null) {
                  r.state.setClassLoader(cl);
              }
          } catch (Exception e) {
              if (!mInstrumentation.onException(activity, e)) {
                  throw new RuntimeException(
                      "Unable to instantiate activity " + component
                      + ": " + e.toString(), e);
              }
          }
          ...
          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,
                  r.assistToken, r.shareableActivityToken);
                  
         ...       
        if (r.isPersistable()) {
              mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
          } else {
              mInstrumentation.callActivityOnCreate(activity, r.state);
          }


因为ActiivtyThread是属于famework.jar, 无法直接引用APP中的代码,所以直接通过ClassLoader方式创建activity实例。接着检查Application有无,若 无则类似创建activity一样创建实例。然后顺序调用activity attach初始化activity中一些参数,activity setTheme,最终调用到了callActivityOnCreate,里边调用activity performCreate,在performCreate才完成Activity oncreate的回调。

至此调起已启动APP的Activity流程结束。

启动新进程

Android中启动APP进程主要有以下几个步骤

  1. 等待创建请求:Zygote 进程会在启动后等待新的应用程序进程的创建请求。
  2. 接收创建请求:当有新的应用程序进程的创建请求到达时,Zygote 进程会接收该请求,并根据该请求创建一个新的进程。
  3. 复制进程:为了快速创建新的进程,Zygote 进程会通过复制自身进程并清除一些状态来创建一个新的应用程序进程。这个过程是通过使用类似于 Unix 的 fork 系统调用实现的。
  4. 初始化应用程序进程:新的应用程序进程会继承 Zygote 进程的一些特性,例如 Java 虚拟机实例、类和资源等。Zygote 进程会对新进程进行一些初始化工作,例如为新进程设置一些系统属性、启动主线程等。
  5. 加载应用程序代码:新的应用程序进程会在启动时加载应用程序的代码,并开始执行应用程序的入口函数。

ActivityTaskSupervisor的另一个分叉点,调用的是ActivityTaskManagerService的startProcessAsync,再通过H分发到AMS内部类LocalService启动新进程。在AMS中后又分发到ProcessList的startProcess处理启动进程。

  • ActivityManagerService startProcess
  • startProcessLocked
  • startProcess

ProcessList

ProcessList是系统管理进程相关的类,ProcessList的startProcess 中关键代码:

if (hostingRecord.usesWebviewZygote()) {
                  startResult = startWebView(entryPoint, ...
              } else if (hostingRecord.usesAppZygote()) {
                  final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
                  
                  // We can't isolate app data and storage data as parent zygote already did that.
                  startResult = appZygote.getProcess().start(entryPoint, ...
              } else {
                  regularZygote = true;
                  startResult = Process.start(entryPoint, ...
              }
 
  • WebviewZygote:辅助 zygote 进程,用于创建 isolated_app 进程来渲染不可信的 web 内容,具有最为严格的安全限制;
  • appZygote:应用 zygote 进程,与常规 zygote 创建的应用相比受到更多限制;
  • regularZygote:常规的 zygote32/zygote64 进程,是所有 Android应用的父进程

ZygoteProcess

检查并创建socket连接

  • Process.ZYGOTE_PROCESS.startChildZygote
  • startChildZygote
  • startViaZygote
  • openZygoteSocketIfNeeded
  • attemptConnectionToPrimaryZygote
  • ZygoteState.connect
  • LocalSocket # connect

发送参数

  • ZygoteProcess start
  • startViaZygote 参数封装
  • zygoteSendArgsAndGetResult 参数toString
  • attemptUsapSendArgsAndGetResult 参数写入文件
  • usapWriter.write(msgStr);
  • new Process.ProcessStartResult();
      zygoteSessionSocket.connect(zygoteSocketAddress);
      zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
      zygoteOutputWriter = new BufferedWriter(
                      new OutputStreamWriter(zygoteSessionSocket.getOutputStream()), Zygote.SOCKET_BUFFER_SIZE);
          
      usapWriter.write(msgStr);
      usapWriter.flush();

      Process.ProcessStartResult result = new Process.ProcessStartResult();
      result.pid = usapReader.readInt();
      // USAPs can't be used to spawn processes that need wrappers.
      result.usingWrapper = false;
  

zygoteServer

zygoteServer在runSelectLoop中会循环执行获取消息,获取到消息后会交给ZygoteConnection处理,在ZygoteConnection的processCommand方法中下边这段代码包含了forkAndSpecialize fork进程、handleChildProc 处理子进程的事件。

pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
      parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
      parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,                              fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
      parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
      parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
      parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
      parsedArgs.mBindMountAppStorageDirs);

try {
      if (pid == 0) {
          // in child
          zygoteServer.setForkChild();

          zygoteServer.closeServerSocket();
          IoUtils.closeQuietly(serverPipeFd);
          serverPipeFd = null;

          return handleChildProc(parsedArgs, childPipeFd,
                  parsedArgs.mStartChildZygote);
      } 

在进程fork完成后,会先后有两次返回,返回的pid == 0表示在子进程,继续执行handleChildProc,在findStaticMain中最终通过classLoader直接加载ActivityThread的Main方法。

  • handleChildProc
  • ZygoteInit.zygoteInit
  • RuntimeInit.applicationInit
  • findStaticMain

ActivityThread

main是一个静态函数,在main中new了一个ActivityThread并且执行了Loper prepare和loop方法,在这两个方法中间执行了attach方法,在acctach中通过AMS的代理对象调用attachApplication,在AMS中又调回了ActivityThread

  • main
  • thread.attach
  • attachApplicationLocked
  • attachApplication
  • bindApplication
  • handleBindApplication
  • callApplicationOnCreate
final IActivityManager mgr = ActivityManager.getService();
      try {
          mgr.attachApplication(mAppThread, startSeq);
      } catch (RemoteException ex) {
          throw ex.rethrowFromSystemServer();
      }

bindApplication中通过内部类H发送BIND_APPLICATION消息,将处理逻辑转到主线程,最后在callApplicationOnCreate里边调用Instrumentation的callApplicationOnCreate,callApplicationOnCreate里是调用application的onCreate方法,至此完成了应用的初始化。

启动新的Activity

在完成Application 初始化完成后,在AMS的bindApplication方法里会接着执行启动新的Activity,最终调用到了TaskSupervisor的realStartActivityLocked,回到上文的ActivityTaskSupervisor启动逻辑里,不再复述。

  • mAtmInternal.attachApplication
  • mRootWindowContainer.attachApplication
  • startActivityForAttachedApplicationIfNeeded
  • mTaskSupervisor.realStartActivityLocked
 // See if the top visible activity is waiting to run in this process...
      if (normalMode) {
          try {
              didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
          } catch (Exception e) {
              Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
              badApp = true;
          }
      }

有一张来源于Activity的启动过程详解启动流程的图总结的非常好,借用一下 image.png

总结

Activity启动流程长且复杂,本文主要对Activity启动流程中启动方式区别、 ActivityStarter与Task启动逻辑校验、目标Activity调起、进程调起等关键点进行了分析。