美文网首页App启动流程
App启动流程:为目标App启动做准备

App启动流程:为目标App启动做准备

作者: sjandroid | 来源:发表于2019-04-17 14:45 被阅读30次

    目录

    • 概述
    • 详细过程
    • 总结

    概述

    当前源码的分析是基于 Android8.0。

    这部分内容概括来说主要就是做了2件事:

    1. “Launcher进程把待启动App的信息封装到Intent中,然后通过Binder把该信息发送给system_server进程中的AMS服务”
    2. “AMS拿这些信息为启动App做一些前期的准备工作”

    详细过程

    为App启动做准备.png

    1.Launcher.startActivity()
    总结:为待启动Activity添加"FLAG_ACTIVITY_NEW_TASK"标记位。表示待启动app的根Activity需要运行在一个新的TaskRecord中。

    boolean startActivity(View v, Intent intent, Object tag) {
            //为待启动Activity添加"FLAG_ACTIVITY_NEW_TASK"标记位
            //该标记位意思为:待启动Activity需要运行在一个新的TaskRecord中
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
            try {
                ......
                if (useLaunchAnimation) {
                    ......
                    if (user == null || user.equals(android.os.Process.myUserHandle())) {
                        //调用Activity的startActivity()启动目标app的根Activity
                        startActivity(intent, opts.toBundle());
                    } else {
                        ......
                    }
                } else {
                    if (user == null || user.equals(android.os.Process.myUserHandle())) {
                        //调用Activity的startActivity()启动目标app的根Activity
                        startActivity(intent);
                    } else {
                        ......
                    }
                }
                return true;
            } catch (SecurityException e) {
                ......
            }
            return false;
        }
    
    

    2.Activity.startActivityForResult()
    源码

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
            if (mParent == null) {
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(this,  //当前Activity实例,此时就是指向的Launcher实例
            mMainThread.getApplicationThread(), //Launcher进程中的ApplicationThread实例
            mToken, 
            this, //当前Activity实例,此时就是指向的Launcher实例
            intent, 
            requestCode, 
            options);
                ......
            } else {
                ......
            }
        }
    

    3.Instrumentation.execStartActivity()
    参数:
    1:Context who:上下文信息,表示是谁要启动Activity。由于Laucnher继承于Activity所以此处who就是指向的一个Laucnher实例。

    2:IBinder contextThread:
    2.1:IBinder的实例,该类是专门用于Binder这种IPC通信的。
    2.2:此处的contextThread指向的是“Launcher进程的ActivityThread中的mAppThread本地实例”。
    2.3:ApplicationThread继承于IActivityManager.Stub。它代表的是“一个Binder本地代理”,该类专门用来与AMS进行交互的,AMS会通过进程的mAppThead与app进程进行通信,通知app进程执行一些操作(启动/暂停Activity等)。
    2.4: ActivityThread是用于管理app进程中的主线程的,其内部有一个类型为ApplicationThread的mAppThread属性。当app进程通过Zygote fork子进程完毕之后,app进程就会反射并执行ActivityThread的main()。
    在main()内部会初始化ActivityThread实例并执行初始化mApplicationThread。

    3:IBinder token: 表示“当前Activity的mToken属性,也就是调用者(此处是Laucnher这个Activity)中保存的mToken属性”。
    一个IBinder类型实例,它也是用于IPC通信的。
    Activity的mToken属性,该属性的值是在attach()中被赋值的。
    该属性对应的是当前Activity在TaskRecord中对应的ActivityRecord的appToken属性。
    该属性是在ActivityRecord()的构造方法中被初始化的。
    3.1:它代表的是“ActivityRecord的appToken属性”。
    3.2:该属性的实际类型为ActivitiRecord.Token,Token继承于IApplication.Stub。
    3.3:Token内部只是记录了一个“ActiviryRecord的软引用对象”。

    4:Activity target:Activity实例,表示的是“启动目标Activity的源Activity实例”。
    5:Intent intent:具体的启动Intent(待启动的目标Activity信息会封装到Intent中)。
    6:int requestCode:请求码。此值是从Activity中传过来的,值为-1。
    7:Bundle options:往Bundle中添加的数据(待启动目标app的包名等)。

    源码

    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            //把Laucnher进程的ApplicationThread拿到
            IApplicationThread whoThread = (IApplicationThread) contextThread;
            ......
            try {
               ......
                int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
                //检查目标Activity的启动结果是否失败
                checkStartActivityResult(result, intent);
            } catch (RemoteException e) {
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        }
    

    总结:
    1:通过Binder IPC方式与system_server进程的AMS服务通信来启动目标Activity。
    2:通过checkStartActivityResult()来检查Activity启动结果。如果启动结果在[-100,-1]范围的话,则会根据实际的res值抛出相应的异常,用于提示此次启动Activity具体是因为什么问题而导致启动失败了(例如:如果待启动的Activity没有在Manifest文件中注册,就会抛出“ActivityNotFoundException”)。


    4.ActivityManager.getService():
    总结:获取system_server进程在app进程AMS本地代理对象。
    具体app进程是如何获取到sysytem_server提供的系统的服务的,<<请戳这里>>


    5.AMS.startActivity():
    参数:
    1:IApplicationThread caller:表示“调用者app中的ApplicationThread对象”,此值指向的就是“当前app(Launcher进程)中的mAppThread对象”。
    2:String callingPackage:表示“调用者的包名”,调用ContextImpl.getBasePackageName(),获取当前Activity所在包名。此时该值指向的是“Laucnher这个Activity所在的包名”。
    3:Intent intent:具体的启动Intent。
    4:String resolvedType:
    5:IBinder resultTo:调用者所在Activity的mToken属性。
    6:int requestCode:请求码,此值为 -1。
    7:int startFlags:此值为 0。
    8:ProfilerInfo profilerInfo:此值为 null。
    9:Bundle bOptions:附加信息。

    总结:
    1:该操作是一次IPC操作。该方法的执行会从Luncher/其它app进程跳转至SystemServer进程去执行AMS提供的startActivity()。
    2:其中比较重要的参数为:caller:Launcher/其他进程中的ApplicationThread对象(等目标Activity启动完毕后,采用此对象pause掉Luancher这个启动目标Activity的源Activity组件)。


    6.AMS.startActivityAsUser():
    其内部会调用AMS.startActivityAsUser()。


    7.ActivityStarter.startActivityMayWait():
    参数:
    1:IApplicationThread caller:调用者app中的ApplicationThread对象。
    2:int callingUid:-1。
    3:String callingPackage:调用者的包名。
    4:Intent intent:具体的启动Intent。
    5:String resolvedType:
    6:IVoiceInteractionSession voiceSession:此值为 null。
    7:IVoiceInteractor voiceInteractor:此值为null。
    8:IBinder resultTo:调用者所在Activity的mToken属性。
    9:int requestCode:请求码。值为-1。
    10:int startFlags:此值为 0。
    11:ProfilerInfo profilerInfo:此值为 null。
    12:WaitResult outResult:此值为null。
    13:Configuration globalConfig:此值为 null.
    14:Bundle bOptions:附加信息。
    15:boolean ignoreTargetSecurity:此值为 false。
    16:int userId:调用者app所在进程的userId。
    17:IActivityContainer iContainer:此值为 null。

    18:TaskRecord inTask:此值为 null。表示“要启动的Activity所在的TaskRecord为null,新启动的目标Activity所在的TaskRecord还不存在。
    18.1:表示一个“任务记录”,对声明了“相同taskAffinity”的Activity组件进行管理。
    18.2:提供了存储、删除栈中Activity等功能。

    19:String reason:调用原因。此值为“startActivityAsUser”。

    源码

    final int startActivityMayWait(IApplicationThread caller, int callingUid,
                String callingPackage, Intent intent, String resolvedType,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int startFlags,
                ProfilerInfo profilerInfo, WaitResult outResult,
                Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
                IActivityContainer iContainer, TaskRecord inTask, String reason) {
            
            //通过PMS.resolveIntent()解析出待启动Activity的更多有用信息,并封装至ResolveInfo
            ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
            ......
            //从PMS解析出的ResolveInfo获得ActivityInfo
            ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
    
            ActivityOptions options = ActivityOptions.fromBundle(bOptions);
            ActivityStackSupervisor.ActivityContainer container =
                    (ActivityStackSupervisor.ActivityContainer)iContainer;
            synchronized (mService) {
            ......
            //如果在Manifest文件中为<application>中的"android:cantSaveState"属性设 
            //置了true,则表示该
            //应用程序是重量级的,无法参与正常的应用程序生命周期。
            //默认为false。不会走到这里
                if (aInfo != null &&
                        (aInfo.applicationInfo.privateFlags
                                & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                    ......
                }
    
            ......
                int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                        aInfo, rInfo, voiceSession, voiceInteractor,
                        resultTo, resultWho, requestCode, callingPid,
                        callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                        options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                        inTask, reason);
    
                ......
                return res;
            }
        }
    

    总结:
    该方法主要做的事:
    1:通过PMS.resolveIntent():根据Intent中封装的待启动Activity组件的信息,解析出待启动Activity的更多有用信息,并封装至ResolveInfo(用于记录”Manifest文件中注册的组件的全部信息)。
    2:调用ASS. resolveActivity():从PMS解析出的ResolveInfo获得ActivityInfo(ActivityInfo不包括Intent-Filter信息,只是<activity>标签中声明的属性信息)。
    3:调用startActivityLocked()继续后续操作。


    8.ActivityStarter.startActivityLocked()
    总结:
    1:判断Activity的启动原因(reason是在启动时就传过来的,具体值为“startActivityAsUser”)是否为“空”。为空的话则会抛出“非法参数异常(IllegalArgumentException)”。
    2:调用startActivity()继续后续操作。

    源码

    int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
                String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
                String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
                ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
                ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
                TaskRecord inTask, String reason) {
            
            //查看“启动原因是否为空”
            if (TextUtils.isEmpty(reason)) {
                throw new IllegalArgumentException("Need to specify a reason.");
            }
            ......
    
            mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                    callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                    container, inTask);
    
            if (outActivity != null) {
                // mLastStartActivityRecord[0] is set in the call to startActivity above.
                outActivity[0] = mLastStartActivityRecord[0];
            }
            return mLastStartActivityResult;
        }
    

    9.ActivityStarter.startActivity()
    总结:
    1:根据调用者app中的ApplicationThread,通过AMS内的“getRecordForAppLocked()”获取已启动的app的进程信息ProcessRecord(因为caller不为null,且该caller是指向Launcher进程中的ActivityThread中的ApplicatThread)。
    2:获取调用者(此处是Launcher所在的进程)进程的pid、uid。
    3:获取调用者的调用Activity(此处Launcher(Activity))在AMS的Activity栈中保存的ActivityRecord实例。

    4:检查requestCode是否大于0,如果大于0则表示: 调用者需要接收待启动Activity组件的一个回复。次数的requestCode为 -1。
    4.1:此时的resultRecord就会被赋值为源ActivityRecord,该ActivityRecord会被封装到待启动ActivityRecord中,用于在合适的时机回调调用Activity,也就是Laucnher。

    5:检查传递来的参数,如果参数不符合要求,则抛出响应的err信息。这些信息会交给Instrumentation.checkStartActivityResult()来检查Activity启动结果是否出错了。
    5.1:如果,Intent获取的要启动的Activity组件的"ComponentName"信息为null的话(未通过Intent指定要跳转的Activity的确切的类名信息),则不会继续后续操作,并会返回此err。
    5.2:如果,通过PMS找不到待启动Activity的详细信息(ActivityInfo),则不会继续后续操作,并会返回此err。

    6:检查是否已授权。
    7:为待启动Activity组件新创建一个ActivityRecord。
    8:继续调用 startActivity()继续后续操作。

    源码

    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
                                  String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
                                  IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                  IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
                                  String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
                                  ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
                                  ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
                                  TaskRecord inTask) {
            int err = ActivityManager.START_SUCCESS;
            // Pull the optional Ephemeral Installer-only bundle out of the options early.
            final Bundle verificationBundle
                    = options != null ? options.popAppVerificationBundle() : null;
    
            //caller不为null,且caller为调用app的ApplicationThread的实例。
            ProcessRecord callerApp = null;
            if (caller != null) {
                callerApp = mService.getRecordForAppLocked(caller);
                if (callerApp != null) {
                    //保存调用者app的pid、uid
                    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;
                }
            }
        
            ......
    
            ActivityRecord sourceRecord = null;
            ActivityRecord resultRecord = null;
            //resultTo不为null
            if (resultTo != null) {
                //获取调用者app的(此处为Launcher)在Activity栈中记录的ActivityRecord
                sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
                if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                        "Will send result to " + resultTo + " " + sourceRecord);
                if (sourceRecord != null) {
                    //如果通过startActivityForResult()启动的Activity组件,且设置requestCode大于0。
                    //则表示调用者需要接收待启动Activity组件的一个回复。
                    //此时的resultRecord就会被赋值为源ActivityRecord, 该ActivityRecord会被封装到待启动ActivityRecord中,用于在合适的实际回调调用Activity。
                    //requestCode为-1,此条件不满足,resultRecord还是null
                    if (requestCode >= 0 && !sourceRecord.finishing) {
                        resultRecord = sourceRecord;
                    }
                }
            }
         
            ......
    
            //待启动Activity信息不为null,此处不走
            if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
                err = ActivityManager.START_INTENT_NOT_RESOLVED;
            }
    
            //待启动Activity的ActivityInfo信息不为null,此处不走
            //如果待启动的Activity信息不能通过PMS从已安装的app中检索到的话,则会在Instrument.checkStartActivityResult()中捕获到这个错误。
            if (err == ActivityManager.START_SUCCESS && aInfo == null) {
                err = ActivityManager.START_CLASS_NOT_FOUND;
            }
    
            ......
    
            //voiceSession为null,此处不走
            if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
            ......
            }
    
            //resultRecord为null,所以ActivityStack也是null
            final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
    
            ......
    
            //权限检查,如果已授权会返回true,未授权则返回false。
            boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
                    resultRecord, resultStack, options);
            ......
            //未授权会走这里
            if (abort) {
                if (resultRecord != null) {
                    resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                            RESULT_CANCELED, null);
                }
                // We pretend to the caller that it was really started, but
                // they will just get a cancel result.
                ActivityOptions.abort(options);
                return START_SUCCESS;
            }
    
            ......
    
            //为待启动Activity组件新创建一个ActivityRecord
            ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                    callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                    resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                    mSupervisor, container, options, sourceRecord);
            ......
    
            return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                    options, inTask, outActivity);
        }
    

    10.ActivityStarter.startActivity():


    11.ActivityStarter.startActivityUnchecked():
    重要参数:
    1:ActivityRecord r:为待启动Activity创建一个新的ActivityRecord。
    2:ActivityRecord sourceRecord:获取调用者app的(此处为Launcher)在Activity栈中记录的ActivityRecord。
    3:int startFlags:此值为 0。
    4:boolean doResume:此值为 true。是否恢复位于“焦点(ASS.mFocusedStack)”栈中的Activity组件。
    5:TaskRecord inTask:此值为null。表示需要创建一个新的TaskRecord把此ActivityRecord压入其内部的存储ActivityRecord列表中。

    总结:
    1:调用setInitialState():初始化一些操作。
    1.1:保存待启动ActivityRecord、Intent、调用者对应的ActivityRecord。
    1.2:解析待启动Activity的launchMode与launchFlags。
    1.3:调用adjustLaunchFlagsToDocumentMode(),根据待启动Activity中声明"documentLaunchMode"属性,进一步初始化“launchFlas”(注意通过Intent.getFlags()获取的flag只设置了“ FLAG_ACTIVITY_NEW_TASK”)。
    2:调用computeLaunchingTaskFlags():进一步为待启动Activity设置"launchFlags"。
    3:调用getReusableIntentActivity():如果待启动Activity的launchMode是"singleTask/singleInstance"的话,则在整个Activity栈结构中找到这个已存在的Activity。
    4:调用ActivityStack.setTaskFromReuseOrCreateNewTask():创建一个新的ActivityStack(此ActivityStack指向的是“ASS.mFocusedStack”属性表示的“焦点栈”。为什么要把新创建的ActivityStack指向ASS中的mFocusedStack??这是因为在后续会先暂停其他Activity栈中保存的已经处于栈顶的Activity,然后再恢复处于焦点栈中待启动的Activity会用到)、TaskRecord,将新创建的TaskRecord添加至此ActivityStack中,将待启动ActivityRecord添加至此新创建的TaskRecord。。
    5:调用ActivityStack.startActivityLocked():内部调用insertTaskAtTop()把要启动的Activity所在的TaskRecord添加到ActivityStack栈顶(实际是把该TaskRecord插入到“mTaskHistory”这个ArrayList的顶部)。这样做是为了:在接下来将该ActivityRecord激活。

    源码

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
            //初始化设置:
            //1:保存待启动ActivityRecord、Intent、调用者对应的ActivityRecord。
            //2:解析并初始化待启动Activity的launchMode与launchFlags。
            setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                    voiceInteractor);
            computeLaunchingTaskFlags();
            computeSourceStack();
            mIntent.setFlags(mLaunchFlags);
            ......
            //如果待启动Activity对应的ActivityRecord中的包名为null,也会返回"Activity没有找到"的标记位,进而在Instrument.checkStartActivityResult()中抛出这个错误。
            if (mStartActivity.packageName == null) {
                ......
                return START_CLASS_NOT_FOUND;
            }
    
            //“如果正在启动的活动与当前在顶部的活动相同,那么我们需要检查它是否应该只启动一次。”
            //此处判断“处于栈顶的Activity,是否是待启动的Activity”。
            //这种情况的场景为:“待启动的Activity所在的app已经启动(由“top.app != null && top.app.thread != null”条件可得),且 “待启动的Activity是否处于栈顶” 且设置了“FLAG_ACTIVITY_SINGLE_TOP”标记位”
            final ActivityStack topStack = mSupervisor.mFocusedStack;
            final ActivityRecord topFocused = topStack.topActivity();
            final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
            final boolean dontStart = top != null && mStartActivity.resultTo == null
                    && top.realActivity.equals(mStartActivity.realActivity)
                    && top.userId == mStartActivity.userId
                    && top.app != null && top.app.thread != null
                    && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                    || mLaunchSingleTop || mLaunchSingleTask);
            if (dontStart) {
                ......
                if (mDoResume) {
                    //激活此Activity
                    mSupervisor.resumeFocusedStackTopActivityLocked();
                }
                ......
                //调用Activity的onNewIntent()
                top.deliverNewIntentLocked(
                        mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
                ......
                return START_DELIVERED_TO_TOP;
            }
           ......
            //1:创建一个新的TaskRecord,将待启动ActivityRecord添加至此新创建的TaskRecord。
            //2:将TaskRecord添加至ASS.mFocusedStack此ActivityStack中。
            int result = START_SUCCESS;
            if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                    && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
                newTask = true;
                [参看11.1小节]
                result = setTaskFromReuseOrCreateNewTask(
                        taskToAffiliate, preferredLaunchStackId, topStack);
            } 
            ......
            [见小节12]
            mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                    mOptions);
            if (mDoResume) {
                ......
                } else {
                    ......
                    [见小节13]
                    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                            mOptions);
                }
            } else {
                ......
            }
            ......
            return START_SUCCESS;
        }
    

    11.1.ActivityStack.setTaskFromReuseOrCreateNewTask():
    这个方法很重要,基本的关于Activity是如何添加至Activity栈的操作都在这里了。

    总结:
    1:通过computeStackFocus():创建一个新的ActivityStack。
    2:通过 步骤1新创建的ActivityStack 的createTaskRecord()新创建一个TaskRecord并把该TaskRecord添加至该新创建的ActivityStack中。
    3:通过 ActivityStarter.addOrReparentStartingActivity():把待启动ActivityRecord添加至TaskRecord内部维护的一个ActivityRecord栈的顶部。
    4:调用 ActivityStack.moveToFront():把 步骤1新创建的ActivityStack赋值给“ASS.mFocusedStack”。

    源码
    1.ActivityStarter.setTaskFromReuseOrCreateNewTask()

        private int setTaskFromReuseOrCreateNewTask(
                TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
            //创建一个新的ActivityStack,且该ActivityStack的id为1。
            //把新创建的ActivityStack赋值给“mTargetStack ”,表示“待启动Activity所在的那个Activity栈”。
            mTargetStack = computeStackFocus(
                    mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
    
            if (mReuseTask == null) {
                //新创建一个TaskRecord并把该TaskRecord添加到新创建的ActivityStack中。
                //该TaskRecord用于存放待启动Activity对应的ActivityRecord。
                final TaskRecord task = mTargetStack.createTaskRecord(
                        mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                        mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                        mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                        mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
                //等TaskRecord创建完毕后,把待启动ActivityRecord添加至TaskRecord内部维护的一个ActivityRecord栈中。
                //具体的:每个TaskRecord内部都有一个类型为ArrayList<ActivityRecord>“mActivities”,该属性用于存储哪些“添加、销毁”的Activity对应的ActivityRecord实例。
                addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
                ......
            } else {
                ......
            }
            ......
            if (mDoResume) {
                //调用setFocusStackUnchecked(),把computeStackFocus()获得的ActivityStack赋值给“ASS.mFocusedStack”。
                //“mFocusedStack”表示“焦点栈”,这个栈中存储了哪些“”
                //“mFocusedStack”将在后续操作中用来“激活待启动Activity”。
                mTargetStack.moveToFront("reuseOrNewTask");
            }
            return START_SUCCESS;
        }
    

    2.ActivityStarter.computeStackFocus()

        private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
                int launchFlags, ActivityOptions aOptions) {
            //app的根Activity肯定还没加到相应的TaskRecord中,所以task为null
            final TaskRecord task = r.getTask();
            //此方法获取到的stack也是null
            ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
            ......
            if (stack == null) {
                ......
                final int stackId = task != null ? task.getLaunchStackId() :
                        bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
                                FULLSCREEN_WORKSPACE_STACK_ID;
                //此时获得的stackId为FULLSCREEN_WORKSPACE_STACK_ID,也就是 1。
                //该stackId会赋值给新创建的ActivityStack。
                stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
            }
            ......
            return stack;
        }
    
    

    3.ActivityStackSupervisor.getStack():

    protected <T extends ActivityStack> T getStack(int stackId, boolean createStaticStackIfNeeded,
                boolean createOnTop) {
           ......
            return (T) createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);
        }
    

    4.ActivityStackSupervisor.createStackOnDisplay():

    ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
            //获取ActivityDisplay实例
            final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
            if (activityDisplay == null) {
                return null;
            }
            
            //创建一个新的ActivityStack实例
            final ActivityContainer activityContainer =
                    new ActivityContainer(stackId, activityDisplay, onTop);
            return activityContainer.mStack;
        }
    

    5.ActivityStackSupervisor.getActivityDisplayOrCreateLocked()

    private ActivityDisplay getActivityDisplayOrCreateLocked(int displayId) {
            //获取ActivityDisplay实例。
            //一个显示屏幕对应一个ActivityDisplay实例。
            //ActivityDisplay 存储了多个ActivityStack实例。
            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
            if (activityDisplay != null) {
                return activityDisplay;
            }
            ......
            return activityDisplay;
        }
    

    6.ActivityStack.createTaskRecord()

    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                boolean toTop, int type) {
            //创建一个新的TaskRecord
            TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
                    voiceInteractor, type);
            //把这个TaskRecord添加到ActivityStack中的
            addTask(task, toTop, "createTaskRecord");
            final boolean isLockscreenShown =
                    mService.mStackSupervisor.mKeyguardController.isKeyguardShowing();
            if (!layoutTaskInStack(task, info.windowLayout) && mBounds != null && task.isResizeable()
                    && !isLockscreenShown) {
                task.updateOverrideConfiguration(mBounds);
            }
            task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
            return task;
        }
    

    参考:
    https://www.2cto.com/kf/201706/648908.html


    12.ActivityStack.startActivityLocked():
    总结:
    1:ActivityStack.insertTaskAtTop():将待启动ActivityRecord所在的TaskRecord移动至“mTaskHistory列表的顶部”。
    2:ActivityRecord.showStartingWindow():显示theme设置的预览窗口。

    源码

    final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
                boolean newTask, boolean keepCurTransition, ActivityOptions options) {
            TaskRecord rTask = r.getTask();
            final int taskId = rTask.taskId;
            // mLaunchTaskBehind tasks get placed at the back of the task stack.
            if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
                // Last activity in task had been removed or ActivityManagerService is reusing task.
                // Insert or replace.
                // Might not even be in.
                insertTaskAtTop(rTask, r);
            }
            //遍历其中维护的“ActivityRecord栈结构(该栈结构采用ArrayList来实现)”,为第一个ActivityRecord设置"frontOfTask",表示在"mActivities"这个队列中,第一个ActivityRecord是此队列的根Activity,也就是栈底的那个Activity。
            task.setFrontOfTask();
    
            if (!isHomeOrRecentsStack() || numActivities() > 0) {
                ......
                boolean doShow = true;
                
                if (r.mLaunchTaskBehind) {
                    ......
                } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                    ......
                    //显示theme中定义的“预览窗口”
                    r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
                }
            } else {
                ......
            }
        }
    

    1.ActivityStack.insertTaskAtTop()

    private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
            updateTaskReturnToForTopInsertion(task);
            //先从List中移除
            mTaskHistory.remove(task);
            //添加至TaskRecord内部mTaskHistory列表的顶部(实际上是添加到List的尾部,但是在激活阶段则是从尾部获取待启动的Activity)
            final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
            mTaskHistory.add(position, task);
            ......
        }
    

    13.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked():
    参数:
    1:ActivityStack targetStack:为待启动ActivityRecord创建的ActivityStack。
    2:ActivityRecord target:待启动ActivitRecord。

    总结:
    1:调用“ActivityStack.topRunningActivityLocked()”从“ActivityStack中存储的TaskRecord列表”中获取“待启动ActivityRecord”。
    1.1:在 小节[11.1]我们知道,存储待启动ActivityRecord的TaskRecord就被添加至ActivityStack的mTaskHistory的顶部(其实List的尾部)。
    1.2:从后往前遍历ActivityStack.mTaskHistory这个列表。
    2:暂停“所有栈中处于Resume状态的Activity(无论Launcher是否与待启动Activity在一个ActivityStack中)”。
    3:调用ActivityStackSupervisor.startSpecificActivityLocked()去启动app进程的那个根Activity。

    源码

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            //从“ActivityStack中存储的TaskRecord列表”中获取“待启动ActivityRecord”。
            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    
            ......
    
            // 待启动的Activity已经处于栈顶且已经被启动了,则不会进行后续操作
            if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                        mStackSupervisor.allResumedActivitiesComplete()) {
                ......
                return false;
            }
    
           ......
    
            // 如果待启动Activity正在被执行pause操作,则不会进行后续操作
            if (!mStackSupervisor.allPausedActivitiesComplete()) {
               ......
                return false;
            }
    
           ...... 
    
            //1:每个ActivityStack都有一个“mResumedActivity”,此属性类型为ActivityRecord,表示“在这个栈中,目前处于Resume状态的Activity,也就是当前在屏幕中正在显示的那个Activity”。
            //2:“如果Launcher与待启动Activity在一个栈中”中的话,则mResumedActivity不为null。
            //3:无论“Launcher与待启动Activity在不在一个栈中”,都会调用startPausingLocked()暂停处于Resume状态的Activity。
            //[见小节13.1]
            //暂停其他“非焦点栈”中处于Resume状态的Activity。
            boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
            //“如果Launcher与待启动Activity都在“焦点栈”中”,调用startPausingLocked()暂停Launcher。
            if (mResumedActivity != null) {
                pausing |= startPausingLocked(userLeaving, false, next, false);
            }
            
            ......
            
            if (next.app != null && next.app.thread != null) {
                ......
            } else {
                //hasBeenLaunched属性表示待启动Activity是否已经被 启动了。
                //此时该属性为false,会走这里
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else {
                  ......
                }
                //等暂停处于Resume状态的Activity后,就会执行startSpecificActivityLocked()开始真正的激活待启动Activity的时候了。
                mStackSupervisor.startSpecificActivityLocked(next, true, true);
            }
            return true;
        }
    

    13.1:ActivityStackSupervisor.pauseBackStacks()
    总结:
    1:待启动的ActivityRecord所在的Activity栈在创建完毕后,就赋值给了ASS.mFocusedStack。
    2:除了“mFocusedStack”属性指向的“处于焦点栈”的Activity栈外,暂停其他Activity栈中处于栈顶的状态为Resumed的Activity。
    3:通过该方法就会把Launcher所在进程的ApplicationThread 在ASM服务中的Binder代理对象,去执行Activity的暂停操作。

    源码
    1.ASS.pauseBackStacks()

    boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
            boolean someActivityPaused = false;
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                    final ActivityStack stack = stacks.get(stackNdx);
                    //暂停其他Activity栈顶的Activity
                    if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
                        if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                                " mResumedActivity=" + stack.mResumedActivity);
                        someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                                dontWait);
                    }
                }
            }
            return someActivityPaused;
        }
      
        boolean isFocusedStack(ActivityStack stack) {
            if (stack == null) {
                return false;
            }
    
            final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
            if (parent != null) {
                stack = parent.getStack();
            }
            return stack == mFocusedStack;
        }
    

    2.ActivityStack.startPausingLocked()

    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
                ActivityRecord resuming, boolean pauseImmediately) {
            ......
            if (prev.app != null && prev.app.thread != null) {
                ......
                try {
                    ......
                    //暂停Launcher
                    prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                            userLeaving, prev.configChangeFlags, pauseImmediately);
                } catch (Exception e) {
                    ......
                }
            } 
            ......
        }
        
    

    总结

    为App启动做准备这一阶段主要做的事情如下:

    1. Launcher通过AMS在每个进程缓存的AMS本地Binder代理对象,把封装了待启动Activity的Intent信息发送给处于system_server进程的AMS服务。
    2.通过PMS.resolveIntent(),根据Intent中封装的待启动Activity的组件信息,解析出与该Activity对应的ActivityInfo(ActivityInfo封装了在Manifest文件注册此Ativity时的属性信息(不包括Intent-Filter,此信息被封装到了ResolveInfo中))。
    3.检查参数的正确性。如果参数不符合要求,则抛出响应的err信息。这些信息会交给Instrumentation.checkStartActivityResult()来检查Activity启动结果是否出错了(eg:如果通过PMS服务找不到与待启动Activity对应的ActivityInfo信息,也就是说检查当前设备中已安装的app,找不到哪个app的根Activity与之对应,则会抛出ActivityManager.START_CLASS_NOT_FOUND此错误信息)。
    4.缓存待启动ActivityRecord、解析并初始化待启动Activity的launchMode与launchFlags等信息。
    5.为待启动Activity创建一个新的ActivityStack、TaskRecord,并把新创建的待启动ActivityRecord压入TaskRecord的栈顶位置,把新创建的TaskRecord压入ActivityStack专门用来存储所有在ActivityStack中创建过的TaskRecord栈的顶部。把此 ActivityStack 赋值给ASS.mFocusedStack。
    6.显示theme设置的预览窗口。
    7.暂停“所有栈中处于Resume状态的Activity(无论Launcher是否与待启动Activity在一个ActivityStack中)”。其内部就是通过Launcher进程的ApplicationThread在AMS服务中的Binder对象来做到通知Laucnher暂停Activity的。

    相关文章

      网友评论

        本文标题:App启动流程:为目标App启动做准备

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