Proceso de inicio de actividad (en actualización)

Breve descripción del proceso.

clase clave

Actividad: una entrada de actividad de la aplicación
ActivityManagerService: coordina y administra los cuatro componentes principales de Android; programa uniformemente cada proceso de aplicación
ActivityTaskManagerService: recientemente introducido en Android R, especialmente utilizado para administrar el inicio de la actividad, la programación y otras funciones
ActivityStarter: especialmente utilizado para manejar actividad nueva Inicio
ActivityStartController: basado en el patrón de diseño de fábrica, iniciador de aplicaciones de ActivityStarter
Tarea: una colección de actividades relacionadas, pero las actividades no necesariamente tienen que estar relacionadas.
RootWindowContainer: el contenedor raíz del contenedor de ventanas, administra directamente DisplayContent
TaskDisplayArea: el nodo principal de todas las tareas de la aplicación en el sistema, utilizado para administrar Task
ActivityTaskSupervisor: la mayor parte de la lógica de control durante el proceso de inicio de la tarea se completa en esta clase
LaunchActivityItem: basado en ClientLifecycleManager, usado para proxy Pasado a la aplicación onCreate, onStart
ResumeActivityItem: basado en ClientLifecycleManager, usado para proxy pasado a la aplicación onResumed
ActivityThread: administra la ejecución del hilo principal del proceso de la aplicación, ejecutándose en el proceso del lado de la aplicación
Ubicación del código
sys /frameworks/base/services/core/java/com /android/server/am/
sys/frameworks/base/services/core/java/com/android/server/wm/

Proceso general

Insertar descripción de la imagen aquí

flujo de código

1.Lanzador haga clic en el icono de la aplicación

A partir del método startActivitySafely() del iniciador, se llamarán varias llamadas startActivity() en la Actividad y, finalmente, llegarán a la ruta del código
en el método startActivityForResult()

    @Override
    public void startActivity(Intent intent) {
    
    
        this.startActivity(intent, null);
    }

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
    
    
        getAutofillClientController().onStartActivity(intent, mIntent);
        if (options != null) {
    
    
            startActivityForResult(intent, -1, options);
        } else {
    
    
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

Finalmente, se llama al método startActivityForResult, pasar -1 indica que no es necesario obtener el resultado de startActivity.

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
    
    
        startActivityForResult(intent, requestCode, null);
    }

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
    
    
        if (mParent == null) {
    
    
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
    
    
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
    
    
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
    
    
            if (options != null) {
    
    
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
    
    
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

El mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);método de llamada es manejado por Instrumentación.
1. La clase Instrumentación se utiliza principalmente para monitorear la interacción entre la aplicación y el sistema
. 2. mMainThread, mInstrumentation y mToken están todos asignados en adjuntar ().
3. El mMainThread en el código es ActivityThread y puede entenderse como un proceso, este es el proceso principal del Lanzador.
4. mToken es un objeto IBinder, un agente Binder y una parte importante
de IPC en Android. 5. Obtenga una referencia a ApplicationThread a través de mMainThread. Esta referencia se utiliza para implementar la comunicación entre procesos. Específicamente, el proceso del sistema donde se encuentra ATMS. localizado notifica el proceso de solicitud Una serie de operaciones realizadas.
Ruta del código: frameworks/base/core/java/android/app/Instrumentation.java

    @UnsupportedAppUsage
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
    
    
        ......
        try {
    
    
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), 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;
    }

1. ActivityTaskManager.getService()Devuelve IActivityTaskManager
2. La declaración de ActivityTaskManagerService es ActivityTaskManagerService extiende IActivityTaskManager.Stub
3. Entonces, al ActivityTaskManager.getService()obtener el agente de servicio ActivityTaskManagerService Context.ACTIVITY_TASK_SERVICE, use Binder para llamar al método startActivity() de ActivityTaskManagerService. El siguiente paso es manejado por el método startActivityAsUser() dentro Servicio ActivityTaskManager.

2. Ingrese a ActivityTaskManagerService

A través del mecanismo de carpeta, el proceso del lanzador ingresa a los cajeros automáticos. Llame a la ruta del código startActivity() en ActivityTaskManagerService
: frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
    
    
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    
    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions, int userId) {
    
    
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }
    
    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    
    
        //检查包名与CallingUid是否一致
        assertPackageMatchesCallingUid(callingPackage);
        enforceNotIsolatedCaller("startActivityAsUser");
        if (Process.isSdkSandboxUid(Binder.getCallingUid())) {
    
    
            SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
                    SdkSandboxManagerLocal.class);
            if (sdkSandboxManagerLocal == null) {
    
    
                throw new IllegalStateException("SdkSandboxManagerLocal not found when starting"
                        + " an activity from an SDK sandbox uid.");
            }
            sdkSandboxManagerLocal.enforceAllowedToStartActivity(intent);
        }

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();

    }

Aquí nos fijamos principalmente en el retorno de la última oración
1.ActivityStartController lo obtiene a través del método getActivityStartController()
2.ActivityStartController.obtainStarter() devuelve el objeto ActivityStarter
3. Luego configura los datos. Lo que realmente se llama es el método de establecer datos en ActivityStarter, y los datos se almacenarán en el objeto mRequest de su clase interna Request, finalmente se llama al método ejecutar () de ActivityStarter
Ruta del código: frameworks/base/services/core/java/com/android/server/wm/ActivityStarter. Java

    /**
     * Resolve necessary information according the request parameters provided earlier, and execute
     * the request which begin the journey of starting an activity.
     * @return The starter result.
     */
    int execute() {
    
    
        try {
    
    
        	......

            // Add checkpoint for this shutdown or reboot attempt, so we can record the original
            // intent action and package name.
            if (mRequest.intent != null) {
    
    
                String intentAction = mRequest.intent.getAction();
                String callingPackage = mRequest.callingPackage;
                if (intentAction != null && callingPackage != null
                        && (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)
                                || Intent.ACTION_SHUTDOWN.equals(intentAction)
                                || Intent.ACTION_REBOOT.equals(intentAction))) {
    
    
                    ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);
                }
            }

            int res;
            synchronized (mService.mGlobalLock) {
    
    
                final boolean globalConfigWillChange = mRequest.globalConfig != null
                        && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
                final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
            	......

                res = resolveToHeavyWeightSwitcherIfNeeded();
                if (res != START_SUCCESS) {
    
    
                    return res;
                }
                res = executeRequest(mRequest);
                ......

        } finally {
    
    
            onExecutionComplete();
        }
    }

res = executeRequest(mRequest);Cree el objeto ActivityRecord de la primera actividad de la aplicación, llame a startActivityUnchecked() y luego vaya a startActivityInner()

   /**
     * Executing activity start request and starts the journey of starting an activity. Here
     * begins with performing several preliminary checks. The normally activity launch flow will
     * go through {@link #startActivityUnchecked} to {@link #startActivityInner}.
     */
    private int executeRequest(Request request) {
    
    
        if (TextUtils.isEmpty(request.reason)) {
    
    
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = request.reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord = null;

        final IApplicationThread caller = request.caller;
        Intent intent = request.intent;
        NeededUriGrants intentGrants = request.intentGrants;
        String resolvedType = request.resolvedType;
        ActivityInfo aInfo = request.activityInfo;
        ResolveInfo rInfo = request.resolveInfo;
        final IVoiceInteractionSession voiceSession = request.voiceSession;
        final IBinder resultTo = request.resultTo;
        String resultWho = request.resultWho;
        int requestCode = request.requestCode;
        int callingPid = request.callingPid;
        int callingUid = request.callingUid;
        String callingPackage = request.callingPackage;
        String callingFeatureId = request.callingFeatureId;
        final int realCallingPid = request.realCallingPid;
        final int realCallingUid = request.realCallingUid;
        final int startFlags = request.startFlags;
        final SafeActivityOptions options = request.activityOptions;
        Task inTask = request.inTask;
        TaskFragment inTaskFragment = request.inTaskFragment;

        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;
        ......
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();

        mLastStartActivityRecord = r;
        ......
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
                inTask, inTaskFragment, restrictedBgActivity, intentGrants);

        if (request.outActivity != null) {
    
    
            request.outActivity[0] = mLastStartActivityRecord;
        }

        return mLastStartActivityResult;
    }

mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,inTask, inTaskFragment, restrictedBgActivity, intentGrants);
Llamar al método startActivityUnchecked()

    /**
     * Start an activity while most of preliminary checks has been done and caller has been
     * confirmed that holds necessary permissions to do so.
     * Here also ensures that the starting activity is removed if the start wasn't successful.
     */
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, boolean restrictedBgActivity,
            NeededUriGrants intentGrants) {
    
    
        int result = START_CANCELED;
        final Task startedActivityRootTask;

        // Create a transition now to record the original intent of actions taken within
        // startActivityInner. Otherwise, logic in startActivityInner could start a different
        // transition based on a sub-action.
        // Only do the create here (and defer requestStart) since startActivityInner might abort.
        final TransitionController transitionController = r.mTransitionController;
        Transition newTransition = (!transitionController.isCollecting()
                && transitionController.getTransitionPlayer() != null)
                ? transitionController.createTransition(TRANSIT_OPEN) : null;
        RemoteTransition remoteTransition = r.takeRemoteTransition();
        if (newTransition != null && remoteTransition != null) {
    
    
            newTransition.setRemoteTransition(remoteTransition);
        }
        transitionController.collect(r);
        try {
    
    
            mService.deferWindowLayout();
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,
                    intentGrants);
        } finally {
    
    
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            startedActivityRootTask = handleStartResult(r, options, result, newTransition,
                    remoteTransition);
            mService.continueWindowLayout();
        }
        postStartActivityProcessing(r, result, startedActivityRootTask);

        return result;
    }

result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask,inTaskFragment, restrictedBgActivity,intentGrants);Llamar al método startActivityInner()

    /**
     * Start an activity and determine if the activity should be adding to the top of an existing
     * task or delivered new intent to an existing activity. Also manipulating the activity task
     * onto requested or valid root-task/display.
     *
     * Note: This method should only be called from {@link #startActivityUnchecked}.
     */
    // TODO(b/152429287): Make it easier to exercise code paths through startActivityInner
    @VisibleForTesting
    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, boolean restrictedBgActivity,
            NeededUriGrants intentGrants) {
    
    
        setInitialState(r, options, inTask, inTaskFragment, doResume, startFlags, sourceRecord,
                voiceSession, voiceInteractor, restrictedBgActivity);

        computeLaunchingTaskFlags();

        computeSourceRootTask();
        ......
        if (mTargetRootTask == null) {
    
    
        	//找到目标Task
            mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,
                    mOptions);
        }   
        ......
        final Task startedTask = mStartActivity.getTask();
        if (newTask) {
    
    
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId);
        }
        //此处打印wm_create_activity日志
        mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);

        mStartActivity.getTaskFragment().clearLastPausedActivity();

        mRootWindowContainer.startPowerModeLaunchIfNeeded(
                false /* forceSend */, mStartActivity);

        final boolean isTaskSwitch = startedTask != prevTopTask && !startedTask.isEmbedded();
        //处理Task和Activity进栈操作
        mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,
                mOptions, sourceRecord);
        if (mDoResume) {
    
    
            final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();
            if (!mTargetRootTask.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) {
    
    
                // If the activity is not focusable, we can't resume it, but still would like to
                // make sure it becomes visible as it starts (this will also trigger entry
                // animation). An example of this are PIP activities.
                // Also, we don't want to resume activities in a task that currently has an overlay
                // as the starting activity just needs to be in the visible paused state until the
                // over is removed.
                // Passing {@code null} as the start parameter ensures all activities are made
                // visible.
                mTargetRootTask.ensureActivitiesVisible(null /* starting */,
                        0 /* configChanges */, !PRESERVE_WINDOWS);
                // Go ahead and tell window manager to execute app transition for this activity
                // since the app transition will not be triggered through the resume channel.
                mTargetRootTask.mDisplayContent.executeAppTransition();
            } else {
    
    
                // If the target root-task was not previously focusable (previous top running
                // activity on that root-task was not visible) then any prior calls to move the
                // root-task to the will not update the focused root-task.  If starting the new
                // activity now allows the task root-task to be focusable, then ensure that we
                // now update the focused root-task accordingly.
                if (mTargetRootTask.isTopActivityFocusable()
                        && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
    
    
                    mTargetRootTask.moveToFront("startActivityInner");
                }
                //启动栈顶的Activity
                mRootWindowContainer.resumeFocusedTasksTopActivities(
                        mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
            }
        }
        mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);

       ......

        return START_SUCCESS;
    }

Este método hace principalmente las siguientes cosas:
1. computeLaunchingTaskFlags();
El método computeLaunchingTaskFlags() calcula el valor del indicador de la actividad inicial
2. mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,mOptions, sourceRecord);
startActivityLocked() maneja las operaciones de inserción de tareas y actividades
3. mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
resumeFocusedTasksTopActivities() obtiene la actividad superior de la pila y la reanuda, lo que Estar configurado para reanudar el estado.

2.1 Calcular el valor de la bandera de la actividad inicial

computeLaunchingTaskFlags();
Ruta del código: frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

   private void computeLaunchingTaskFlags() {
    
    
        ......

		//mInTask是Task类型,此处为null,代表Activity要加入的栈不存在,因此需要判断是否需要新Task
        if (mInTask == null) {
    
    
        //mSourceRecord是ActivityRecord类型,它是用来描述“初始Activity”
        //“初始Activity”:比如,ActivityA启动到了ActivityB,ActivityA就是初始Activity
        //当我们使用Context或者Application启动Activity时,此时mSourceRecord为null
            if (mSourceRecord == null) {
    
    
                // This activity is not being started from another...  in this
                // case we -always- start a new task.
                if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
    
    
                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
                    mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
                }
            //初始Activity 如果是在singleInstance栈(LAUNCH_SINGLE_INSTANCE)中的Activity,就需要添加FLAG_ACTIVITY_NEW_TASK的标识
            //因为singleInstance只允许保存一个Activity
            } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
    
    
                // The original activity who is starting us is running as a single
                // instance...  this new activity it is starting must go on its
                // own task.
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            //如果Launch Mode 设置了singleInstance(LAUNCH_SINGLE_INSTANCE) 和singleTask (LAUNCH_SINGLE_TASK)
            //则也要创建一个新栈
            } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
    
    
                // The activity being started is a single instance...  it always
                // gets launched into its own task.
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            }
        }
    }

2.2 Procesamiento de operaciones push de tareas y actividades

mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,mOptions, sourceRecord);
El método startActivityLocked() llamará al método positionChildAtTop() para intentar colocar la tarea y la actividad en la pila. Si la actividad se inicia en el modo de nueva tarea o la identificación de la tarea no existe en la pila de tareas, la tarea se devolverá a la pila y se colocará en la parte superior de la pila.
Nota: La tarea se inserta primero en la pila, luego la actividad se inserta en la pila. Están incluidas.
Ruta del código: frameworks/base/services/core/java/com/android/server/wm/Task.java

    void startActivityLocked(ActivityRecord r, @Nullable Task topTask, boolean newTask,
            boolean isTaskSwitch, ActivityOptions options, @Nullable ActivityRecord sourceRecord) {
    
    
        final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate(topTask);
        Task rTask = r.getTask();
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
        final boolean isOrhasTask = rTask == this || hasChild(rTask);
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
    
    
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            positionChildAtTop(rTask);
        }
        ......
    }

En este punto, se crea el ActivityRecord de la primera Actividad de la aplicación, se encuentra su Tarea y finalmente el ActivityRecord se inserta en la posición apropiada en la Tarea.

2.3 Obtenga la actividad principal en la pila y reanúdela, que se configurará en el estado de reanudación

mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
Ruta del código: frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
            boolean deferPause) {
    
    
        if (!mTaskSupervisor.readyToResume()) {
    
    
            return false;
        }

        boolean result = false;
        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                || getTopDisplayFocusedRootTask() == targetRootTask)) {
    
    
            result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                    deferPause);
        }
        ......

        return result;
    }

result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,deferPause);Ruta del código para llamar a resumeTopActivityUncheckedLocked
: frameworks/base/services/core/java/com/android/server/wm/Task.java

    /**
     * Ensure that the top activity in the root task is resumed.
     *
     * @param prev The previously resumed activity, for when in the process
     * of pausing; can be null to call from elsewhere.
     * @param options Activity options.
     * @param deferPause When {@code true}, this will not pause back tasks.
     *
     * @return Returns true if something is being resumed, or false if
     * nothing happened.
     *
     * NOTE: It is not safe to call this method directly as it can cause an activity in a
     *       non-focused root task to be resumed.
     *       Use {@link RootWindowContainer#resumeFocusedTasksTopActivities} to resume the
     *       right activity for the current system state.
     */
    @GuardedBy("mService")
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
    
    
        if (mInResumeTopActivity) {
    
    
            // Don't even start recursing.
            return false;
        }

        boolean someActivityResumed = false;
        try {
    
    
            // Protect against recursion.
            mInResumeTopActivity = true;

            if (isLeafTask()) {
    
    
                if (isFocusableAndVisible()) {
    
    
                    someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
                }
            } else {
    
    
                int idx = mChildren.size() - 1;
                while (idx >= 0) {
    
    
                    final Task child = (Task) getChildAt(idx--);
                    if (!child.isTopActivityFocusable()) {
    
    
                        continue;
                    }
                    if (child.getVisibility(null /* starting */)
                            != TASK_FRAGMENT_VISIBILITY_VISIBLE) {
    
    
                        break;
                    }

                    someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
                            deferPause);
                    // Doing so in order to prevent IndexOOB since hierarchy might changes while
                    // resuming activities, for example dismissing split-screen while starting
                    // non-resizeable activity.
                    if (idx >= mChildren.size()) {
    
    
                        idx = mChildren.size() - 1;
                    }
                }
            }

            // When resuming the top activity, it may be necessary to pause the top activity (for
            // example, returning to the lock screen. We suppress the normal pause logic in
            // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
            // end. We call the {@link ActivityTaskSupervisor#checkReadyForSleepLocked} again here
            // to ensure any necessary pause logic occurs. In the case where the Activity will be
            // shown regardless of the lock screen, the call to
            // {@link ActivityTaskSupervisor#checkReadyForSleepLocked} is skipped.
            final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
    
    
                checkReadyForSleep();
            }
        } finally {
    
    
            mInResumeTopActivity = false;
        }

        return someActivityResumed;
    }

someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);Currículum de llamadaTopActivityInnerLocked

    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
    
    
        if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
    
    
            // Not ready yet!
            return false;
        }

        final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
        if (topActivity == null) {
    
    
            // There are no activities left in this task, let's look somewhere else.
            return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

        final boolean[] resumed = new boolean[1];
        final TaskFragment topFragment = topActivity.getTaskFragment();
        resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
        forAllLeafTaskFragments(f -> {
    
    
            if (topFragment == f) {
    
    
                return;
            }
            if (!f.canBeResumed(null /* starting */)) {
    
    
                return;
            }
            resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
        }, true);
        return resumed[0];
    }

resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);Ruta del código para llamar a resumeTopActivity
: frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
    
    
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        if (next == null || !next.canResumeByCompat()) {
    
    
            return false;
        }

        next.delayedResume = false;
        final TaskDisplayArea taskDisplayArea = getDisplayArea();

        // If the top activity is the resumed one, nothing to do.
        if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
    
    
            // Ensure the visibility gets updated before execute app transition.
            taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                    false /* preserveWindows */, true /* notifyClients */);
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);

            // In a multi-resumed environment, like in a freeform device, the top
            // activity can be resumed, but it might not be the focused app.
            // Set focused app when top activity is resumed
            if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null
                    && taskDisplayArea.mDisplayContent.mFocusedApp != next) {
    
    
                taskDisplayArea.mDisplayContent.setFocusedApp(next);
            }
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity "
                    + "resumed %s", next);
            return false;
        }

        // If we are currently pausing an activity, then don't do anything until that is done.
        final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
        if (!allPausedComplete) {
    
    
            ProtoLog.v(WM_DEBUG_STATES,
                    "resumeTopActivity: Skip resume: some activity pausing.");
            return false;
        }

        // If we are sleeping, and there is no resumed activity, and the top activity is paused,
        // well that is the state we want.
        if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
    
    
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Going to sleep and"
                    + " all paused");
            return false;
        }

        // Make sure that the user who owns this activity is started.  If not,
        // we will just leave it as is because someone should be bringing
        // another user's activities to the top of the stack.
        if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {
    
    
            Slog.w(TAG, "Skipping resume of top activity " + next
                    + ": user " + next.mUserId + " is stopped");
            return false;
        }

        // The activity may be waiting for stop, but that is no longer
        // appropriate for it.
        mTaskSupervisor.mStoppingActivities.remove(next);

        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

        mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);

        ActivityRecord lastResumed = null;
        final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();
        if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTaskFragment().asTask()) {
    
    
            // So, why aren't we using prev here??? See the param comment on the method. prev
            // doesn't represent the last resumed activity. However, the last focus stack does if
            // it isn't null.
            lastResumed = lastFocusedRootTask.getTopResumedActivity();
        }

        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
        if (mResumedActivity != null) {
    
    
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);
            pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,
                    next, "resumeTopActivity");
        }
        if (pausing) {
    
    
            ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"
                    + " start pausing");
            // At this point we want to put the upcoming activity's process
            // at the top of the LRU list, since we know we will be needing it
            // very soon and it would be a waste to let it get killed if it
            // happens to be sitting towards the end.
            if (next.attachedToProcess()) {
    
    
                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                        true /* activityChange */, false /* updateOomAdj */,
                        false /* addPendingTopUid */);
            } else if (!next.isProcessRunning()) {
    
    
                // Since the start-process is asynchronous, if we already know the process of next
                // activity isn't running, we can start the process earlier to save the time to wait
                // for the current activity to be paused.
                final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
                mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                        isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
                                : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
            }
            if (lastResumed != null) {
    
    
                lastResumed.setWillCloseOrEnterPip(true);
            }
            return true;
        } else if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
    
    
            // It is possible for the activity to be resumed when we paused back stacks above if the
            // next activity doesn't have to wait for pause to complete.
            // So, nothing else to-do except:
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity resumed "
                    + "(dontWaitForPause) %s", next);
            return true;
        }

        // If the most recent activity was noHistory but was only stopped rather
        // than stopped+finished because the device went to sleep, we need to make
        // sure to finish it as we're making a new activity topmost.
        if (shouldSleepActivities()) {
    
    
            mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);
        }

        if (prev != null && prev != next && next.nowVisible) {
    
    
            // The next activity is already visible, so hide the previous
            // activity's windows right now so we can show the new one ASAP.
            // We only do this if the previous is finishing, which should mean
            // it is on top of the one being resumed so hiding it quickly
            // is good.  Otherwise, we want to do the normal route of allowing
            // the resumed activity to be shown so we can decide if the
            // previous should actually be hidden depending on whether the
            // new one is found to be full-screen or not.
            if (prev.finishing) {
    
    
                prev.setVisibility(false);
                if (DEBUG_SWITCH) {
    
    
                    Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev
                            + ", nowVisible=" + next.nowVisible);
                }
            } else {
    
    
                if (DEBUG_SWITCH) {
    
    
                    Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev
                            + ", nowVisible=" + next.nowVisible);
                }
            }
        }

        // Launching this app's activity, make sure the app is no longer
        // considered stopped.
        try {
    
    
            mTaskSupervisor.getActivityMetricsLogger()
                    .notifyBeforePackageUnstopped(next.packageName);
            mAtmService.getPackageManager().setPackageStoppedState(
                    next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
        } catch (RemoteException e1) {
    
    
        } catch (IllegalArgumentException e) {
    
    
            Slog.w(TAG, "Failed trying to unstop package "
                    + next.packageName + ": " + e);
        }

        // We are starting up the next activity, so tell the window manager
        // that the previous one will be hidden soon.  This way it can know
        // to ignore it when computing the desired screen orientation.
        boolean anim = true;
        final DisplayContent dc = taskDisplayArea.mDisplayContent;
        if (prev != null) {
    
    
            if (prev.finishing) {
    
    
                if (DEBUG_TRANSITION) {
    
    
                    Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev);
                }
                if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {
    
    
                    anim = false;
                    dc.prepareAppTransition(TRANSIT_NONE);
                } else {
    
    
                    dc.prepareAppTransition(TRANSIT_CLOSE);
                }
                prev.setVisibility(false);
            } else {
    
    
                if (DEBUG_TRANSITION) {
    
    
                    Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);
                }
                if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
    
    
                    anim = false;
                    dc.prepareAppTransition(TRANSIT_NONE);
                } else {
    
    
                    dc.prepareAppTransition(TRANSIT_OPEN,
                            next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);
                }
            }
        } else {
    
    
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
            if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
    
    
                anim = false;
                dc.prepareAppTransition(TRANSIT_NONE);
            } else {
    
    
                dc.prepareAppTransition(TRANSIT_OPEN);
            }
        }

        if (anim) {
    
    
            next.applyOptionsAnimation();
        } else {
    
    
            next.abortAndClearOptionsAnimation();
        }

        mTaskSupervisor.mNoAnimActivities.clear();

        if (next.attachedToProcess()) {
    
    
            if (DEBUG_SWITCH) {
    
    
                Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped
                        + " visibleRequested=" + next.mVisibleRequested);
            }

            // If the previous activity is translucent, force a visibility update of
            // the next activity, so that it's added to WM's opening app list, and
            // transition animation can be set up properly.
            // For example, pressing Home button with a translucent activity in focus.
            // Launcher is already visible in this case. If we don't add it to opening
            // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
            // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
            final boolean lastActivityTranslucent = inMultiWindowMode()
                    || mLastPausedActivity != null && !mLastPausedActivity.occludesParent();

            // This activity is now becoming visible.
            if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {
    
    
                next.app.addToPendingTop();
                next.setVisibility(true);
            }

            // schedule launch ticks to collect information about slow apps.
            next.startLaunchTickingLocked();

            ActivityRecord lastResumedActivity =
                    lastFocusedRootTask == null ? null
                            : lastFocusedRootTask.getTopResumedActivity();
            final ActivityRecord.State lastState = next.getState();

            mAtmService.updateCpuStats();

            ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);

            next.setState(RESUMED, "resumeTopActivity");

            // Have the window manager re-evaluate the orientation of
            // the screen based on the new activity order.
            boolean notUpdated = true;

            // Activity should also be visible if set mLaunchTaskBehind to true (see
            // ActivityRecord#shouldBeVisibleIgnoringKeyguard()).
            if (shouldBeVisible(next)) {
    
    
                // We have special rotation behavior when here is some active activity that
                // requests specific orientation or Keyguard is locked. Make sure all activity
                // visibilities are set correctly as well as the transition is updated if needed
                // to get the correct rotation behavior. Otherwise the following call to update
                // the orientation may cause incorrect configurations delivered to client as a
                // result of invisible window resize.
                // TODO: Remove this once visibilities are set correctly immediately when
                // starting an activity.
                notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
                        true /* markFrozenIfConfigChanged */, false /* deferResume */);
            }

            if (notUpdated) {
    
    
                // The configuration update wasn't able to keep the existing
                // instance of the activity, and instead started a new one.
                // We should be all done, but let's just make sure our activity
                // is still at the top and schedule another run if something
                // weird happened.
                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;
            }

            try {
    
    
                final ClientTransaction transaction =
                        ClientTransaction.obtain(next.app.getThread(), next.token);
                // Deliver all pending results.
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
    
    
                    final int size = a.size();
                    if (!next.finishing && size > 0) {
    
    
                        if (DEBUG_RESULTS) {
    
    
                            Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
                        }
                        transaction.addCallback(ActivityResultItem.obtain(a));
                    }
                }

                if (next.newIntents != null) {
    
    
                    transaction.addCallback(
                            NewIntentItem.obtain(next.newIntents, true /* resume */));
                }

                // Well the app will no longer be stopped.
                // Clear app token stopped state in window manager if needed.
                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);

                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);
            } catch (Exception e) {
    
    
                // Whoops, need to restart this activity!
                ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "
                        + "%s", lastState, next);
                next.setState(lastState, "resumeTopActivityInnerLocked");

                // lastResumedActivity being non-null implies there is a lastStack present.
                if (lastResumedActivity != null) {
    
    
                    lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                }

                Slog.i(TAG, "Restarting because process died: " + next);
                if (!next.hasBeenLaunched) {
    
    
                    next.hasBeenLaunched = true;
                } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null
                        && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {
    
    
                    next.showStartingWindow(false /* taskSwitch */);
                }
                mTaskSupervisor.startSpecificActivity(next, true, false);
                return true;
            }

            // From this point on, if something goes wrong there is no way
            // to recover the activity.
            try {
    
    
                next.completeResumeLocked();
            } catch (Exception e) {
    
    
                // If any exception gets thrown, toss away this
                // activity and try the next one.
                Slog.w(TAG, "Exception thrown during resume of " + next, e);
                next.finishIfPossible("resume-exception", true /* oomAdj */);
                return true;
            }
        } else {
    
    
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
    
    
                next.hasBeenLaunched = true;
            } else {
    
    
                if (SHOW_APP_STARTING_PREVIEW) {
    
    
                    next.showStartingWindow(false /* taskSwich */);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
            mTaskSupervisor.startSpecificActivity(next, true, true);
        }

        return true;
    }

Supongo que te gusta

Origin blog.csdn.net/yimelancholy/article/details/130515992
Recomendado
Clasificación