源码阅读之Activity启动流程

作者: 十蛋stan | 来源:发表于2018-07-29 17:38 被阅读11次

如果在Activity里启动Activity,那启动代码是Activity::startActivity(intent),然后会调用startActivityForResult()

Activity:
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
...
    Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);
...
}

最终会通过mInstrumentation.execStartActivity()来启动Activity.
如果是通过Context来启动Activity(比如在Service里启动Activity),那么会调用ContextWrapper里的mBase这个Context去startActivity()

ContextWrapper:
@Override
public void startActivity(Intent intent) {
    mBase.startActivity(intent);
}

那么mBase是什么时候赋值的呢?
这是Activity生成的时候通过attach()传过去的.

Activity:
final void attach(Context context,...){
  ...
  attachBaseContext(context);
  ...
}

那么attach是什么地方调用呢?
attach是在ActivityThread的performLaunchActivity里调用的

ActivityThread:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  ...
  ContextImpl appContext = createBaseContextForActivity(r);
  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();
    if (r.state != null) {
      r.state.setClassLoader(cl);
    }
  }
  ...
  try {
    activity.attach(appContext, this, ...)
    ...
  }
  ...
  
}

在performLaunchActivity()里首先通过mInstrumentation通过反射生成Activity对象,然后调用attach把ContextImpl类型的appContext赋值给mBase.所以这个mBase就是ContextImpl类型.
那么ContextImpl的startActivity做了什么呢?代码:

ContextImpl:
@Override
public void startActivity(Intent intent, Bundle options) {
  warnIfCallingFromSystemProcess();
  // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
  // generally not allowed, except if the caller specifies the task id the activity should
  // be launched in.
  if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
    throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
  }
  mMainThread.getInstrumentation().execStartActivity(getOuterContext(), mMainThread.getApplicationThread(), null, (Activity) null, intent, -1, options);
}

也是调用Instrumentation去execStartActivity().这个Instrumentation类其实是Activity生命周期的管理类,负责Activity的创建和生命周期的管理.看他的方法:

Instrumentation:
public void callActivityOnStart(Activity activity) 
public void callActivityOnCreate(Activity activity) 
public void callActivityOnResume(Activity activity) 
public void callActivityOnPause(Activity activity) 
public void callActivityOnStop(Activity activity) 
public void callActivityOnDestroy(Activity activity) 
等等等等...

下面Activity要开始启动了.那么现在开始分析Instrumentation::execStartActivity()做了什么.

Instrumentation:
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
  ...
  try {
    //对intent做一些优化,先不管
    intent.migrateExtraStreamToClipData();
    //这个who就是要去启动别的Activity的原有Context
    intent.prepareToLeaveProcess(who);
    int result = ActivityManager.getService().startActivity(...)
    checkStartActivityResult(result, intent);
  }
  ...
}

prepareToLeaveProcess根据字面意思就是准备开启新的app进程之前做一些准备工作,但普通Activity跳转不涉及新进程的生成,可以暂时先不管.
然后ActivityManager.getService()他其实就是获得了AMS的Binder引用.
checkStartActivityResult()则负责处理调用失败的一些错误处理

接下来看AMS的startActivity

ActivityManagerService:
@Override
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());
}

startActivity马上就去调startActivityAsUser()了.startActivityAsUser主要任务是根据调用者userId做一些权限检查.比如enforceNotIsolatedCaller("Activity")检查调用者是否属于被隔离对象,handleIncomingUser是去检查调用者是否有权利执行这一操作.

ActivityManagerService:
public final int startActivityAsUser(){
  ...
  enforceNotIsolatedCaller("startActivity");
  userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null);
  return mActivityStarter.startActivityMayWait(...);
  ...
}

然后就去调用ActivityStarter::startActivityMayWait().ActivityStarter是一个Activity的启动管理类.他会去筛选匹配相应的Activity,并把它加入合适的栈这些操作.

ActivityStarter:
final int startActivityMayWait(...){
  ...
  //判断是否是显示的Intent,componentSpecified为true就是显示的
  boolean componentSpecified = intent.getComponent() != null;
  ...
  //这里就是根据intent查找匹配相应的信息,最后使用PackegeMangerService解析xml去获得的
  ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
  //得到Target Activity 信息
  ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
  ...
  //进行下一步
  int res = startActivityLocked(...){}
}

匹配相应Activity信息的操作在mSupervisor.resolveIntent()里,mSupervisor是一个ActivityStackSupervisor.看名字就知道他的主要功能是管理ActivityStack.他的成员比如:

ArrayList<ActivityRecord> mActivitiesWaitingForVisibleActivity
ArrayList<WaitInfo> mWaitingForActivityVisible
ArrayList<ActivityRecord> mStoppingActivities
ArrayList<WaitResult> mWaitingActivityLaunched
ArrayList<ActivityRecord> mFinishingActivities
ArrayList<ActivityRecord> mGoingToSleepActivities
等等

对Activity的各个状态进行维护.成员如下:

//包含launcher app 的stack
ActivityStack mHomeStack;
//正在操作的stack
ActivityStack mFocusedStack;
//上一次操作的stack,如果stack在变换位置,他就持有old stack,等待mFocusedStack处理完毕就变成mFocusedStack
ActivityStack mLastFocusedStack;

他对栈的状态进行维护.
最终匹配intent的操作在PackageManagerService里

PackageManagerService:
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType, int flags, int userId, boolean resolveForStart) {
  try{
    ...
    //进行显示和隐式Intent的匹配后的结果
    final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags, callingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
    //根据一些优先级继续筛选
    final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId);
    return bestChoice;
    ...
  }
}

匹配完之后就进入到startActivityLocked(题外话,名字后面跟Locked的一般是提醒我们注意线程安全,这里涉及不可重入资源的处理).这个方法会调用startActivity().startActivity里会做一些启动Activity的权限判断

ActivityStarter:
int startActivityLocked(...){
  ...
  mLastStartActivityResult = startActivity(...);
  ...
}

private int startActivity(参数较多的那个){
  ...
  //判断调用者本身进程是否存在,否则返回START_PERMISSION_DENIED,因为调用者有可能被系统杀死
  ProcessRecord callerApp = null;
  if (caller != null) {
    callerApp = mService.getRecordForAppLocked(caller);
    if (callerApp != null) {
      callingPid = callerApp.pid;
      callingUid = callerApp.info.uid;
    } else {
                Slog.w(TAG, "Unable to find app for caller " + caller
                        + " (pid=" + callingPid + ") when starting: "
                        + intent.toString());
      err = ActivityManager.START_PERMISSION_DENIED;
    }
  }
  ...
  //权限判断
  boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
                resultRecord, resultStack, options);
  abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo);
  ...
  //生成ActivityRecord准备下一步操作了
  ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,...)
  return startActivity(参数较少的那个);
}

private int startActivity(参数较少的那个){
  ...
  startActivityUnchecked(...);
  ...
}

ActivityStarter:
private int startActivityUnchecked(...){
  //主要是判断flag是否是FLAG_ACTIVITY_NEW_TASK或LAUNCH_SINGLE_INSTANCE
  computeLaunchingTaskFlags();
  //万一原来的栈被回收后所做一些操作,比如重新设置FLAG_ACTIVITY_NEW_TASK
  computeSourceStack();
  mIntent.setFlags(mLaunchFlags);
  //判断是否要把Activity放入新的Task里,比如我们设置了singleTask或singleInstance就有可能生成新的Task
  ActivityRecord reusedActivity = getReusableIntentActivity();
  ...
  if (reusedActivity != null) {
    ...
    if (!mAddingToTask && mReuseTask == null) {
      resumeTargetStackIfNeeded();
      if (outActivity != null && outActivity.length > 0) {
        outActivity[0] = reusedActivity;
      }
      //这里return了START_TASK_TO_FRONT,那么生成新的Activity就应该走resumeTargetStackIfNeeded()这个流程
      return START_TASK_TO_FRONT;
    }
    ...
  }
  ...
  //  如果即将打开的Activity就是当前前端的Activity,就检查是否只能启动一次
  final ActivityStack topStack = mSupervisor.mFocusedStack;
  final ActivityRecord topFocused = topStack.topActivity();
  final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
  if (dontStart) {
    ...
    return START_DELIVERED_TO_TOP
  }
  ...
  
  //判断是否是newTask
  int result = START_SUCCESS;
  if (mStartActivity.resultTo == null && mInTask == null &&!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
    newTask = true;
    result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack);
  }
  ...
  //在target stack里启动mStartActivity
  mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mOptions);
  ...
  mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions);
  ...
  
}

由于篇幅有限,我打算只搞清楚一个新的Activity启动的流程.其他分支逻辑就一笔带过.这里直接进入resumeFocusedStackTopActivityLocked();
进入ActivityStackSupervisor里

ActivityStackSupervisor:
  boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
      return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
  }

进入resumeTopActivityUncheckedLocked():

ActivityStack:
  //注释说这个方法不安全,会导致一个non-focus stack里的Activity to be resumed.使用ActivityStackSupervisor#resumeFocusedStackTopActivityLocked去resume
  boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    try {
      // Protect against recursion.
      mStackSupervisor.inResumeTopActivity = true;
      result = resumeTopActivityInnerLocked(prev, options);
    } finally {
      mStackSupervisor.inResumeTopActivity = false;
    }
  }

  调用TargetStack的resumeTopActivityInnerLocked():
  private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    //如果前端Activity就是我们要启动的Activity,什么也不做
    if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) {
    return;
    ...
    //暂停当前resume的Activity
    if (mResumedActivity != null) {
      pausing |= startPausingLocked(userLeaving, false, next, false);
    }
    ...
    //如果要启动新的Activity会调用startSpecificActivityLocked()
    mStackSupervisor.startSpecificActivityLocked(next, true, true);
    ...  
  }

又回到ActivityStackSupervisor

ActivityStackSuperVisor:
  void startSpecificActivityLocked(...) {
    ...
    realStartActivityLocked(r, app, andResume, checkConfig);
    ...
  }

  final boolean realStartActivityLocked(...) {
    //如果还有没暂停好的Activity,return掉
    if (!allPausedActivitiesComplete()) {
      return;
    }
    ...
    //继续启动Activity会进入这
    app.thread.scheduleLaunchActivity(...) 
    ...
  }

这时就进入ActivityThread里了:
app.thread是ActivityThread的内部类ApplicationThread,可以看成是ActivityThread的管理类.一般就是通过Handler发送Message等操作

ActivityThread.ApplicationThread:
  public final void scheduleLaunchActivity(...) {
    ...
    sendMessage(H.LAUNCH_ACTIVITY, r);
  }
//最终会调用ActivityThread的handleLaunchActivity();
ActivityThread:
  private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    Activity a = performLaunchActivity(r, customIntent);
    ...
  }

  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    //创建ContextImpl
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
      ...
      //生成Activity
      activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
      ...
      activity.attach(appContext,...);
      ...
    }
    ...
  }

到这里为止启动一个新的Activity的逻辑就结束了.

总结下Activity的启动:
启动的第一次IPC入口为Instrumentation.execStartActivity(),这里会去请求AMS.然后AMS去调用ActivityStarter.ActivityStarter在ActivityStackSupervisor的辅助下进一步去判断,比如让PackageManagerService解析所有app符合条件的Intent信息,接着就根据Flag(singleInstance,singleTop,singleTask)这些标签去判断要在哪个Task里面启动Activity.然后去判断是否加载新的Activity或调用已经存在的Activity的onNewIntent().所有信息都搞清楚后如果需要启动Activity就去调用ActivityThread去生成新的Activity了.

一些类的总结:
Instrumentation:
负责Activity的创建和生命周期的管理

ResolveInfo:
Intent被filter过滤后得到的部分信息

ActivityInfo:
activity或receiver的信息封装,是ResolveInfo的成员之一

ActivityStarter:
负责Activity如何以及何时创建,然后根据Intent和Flag去处理生成的Activity和对应的Activity栈.

ActivityStack:
管理当前系统中所有Activity的一个数据结构.我一开始以为整个系统只有一个ActivityStack,因为是管理类嘛.可是后来发现ActivityStackSupervisor里不止一个ActivityStack,所以不要理解成简单的一个Activity管理类.

ActivityStackSupervisor:
ActivityStack的管理者.其中mHomeStack管理的是Launcher相关的任务,包括Launcher、RecentTask,Keyguad,除了上述以外的任务都归mFocusedStack管理

参考源码android-27

写完这篇博客的思考:
Activity的启动流程是一个非常复杂的逻辑,如果去追求所有的细枝末节会耗费大量的精力并且不容易记忆,当然跟我的水平有关.所以我只是列出了一部分复合这篇主题的逻辑.
以后我也会从一个小问题出发去探索源码,这样才能更深刻的去理解源码.有错误欢迎大家指出.

相关文章

网友评论

    本文标题:源码阅读之Activity启动流程

    本文链接:https://www.haomeiwen.com/subject/urzlmftx.html