源码阅读之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