Android S从桌面点击图标启动APP流程

16 篇文章 1 订阅
6 篇文章 0 订阅

Android 12的源码链接:Searchicon-default.png?t=N7T8http://aospxref.com/android-12.0.0_r3/

1. Launcher  onClick

点击桌面图标会进入Launcher应用的click方法中。

    private static void onClick(View v) {
        // Make sure that rogue clicks don't get through while allapps is launching, or after the
        // view has detached (it's possible for this to happen if the view is removed mid touch).
        if (v.getWindowToken() == null) return;

        Launcher launcher = Launcher.getLauncher(v.getContext());
        if (!launcher.getWorkspace().isFinishedSwitchingState()) return;

        Object tag = v.getTag();
        if (tag instanceof WorkspaceItemInfo) {
            onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                onClickFolderIcon(v);
            }
        } else if (tag instanceof AppInfo) {
            startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
            );
        } else if (tag instanceof LauncherAppWidgetInfo) {
            if (v instanceof PendingAppWidgetHostView) {
                onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
            }
        } else if (tag instanceof SearchActionItemInfo) {
            onClickSearchAction(launcher, (SearchActionItemInfo) tag);
        }
    }

2. ItemClickHandler#onClickAppShortcut

往下走

packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.java
    public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher) {
        if (shortcut.isDisabled() && handleDisabledItemClicked(shortcut, launcher)) {
            return;
        }

        // Check for abandoned promise
        if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()) {
            String packageName = shortcut.getIntent().getComponent() != null
                    ? shortcut.getIntent().getComponent().getPackageName()
                    : shortcut.getIntent().getPackage();
            if (!TextUtils.isEmpty(packageName)) {
                onClickPendingAppItem(
                        v,
                        launcher,
                        packageName,
                        (shortcut.runtimeStatusFlags
                                & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0);
                return;
            }
        }

        // Start activities
启动activity
        startAppShortcutOrInfoActivity(v, shortcut, launcher);
    }

3.  ItemClickHandler#startAppShortcutOrInfoActivity

继而往下走

packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.java
    private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
        TestLogging.recordEvent(
                TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity");
        Intent intent;
        if (item instanceof ItemInfoWithIcon
                && (((ItemInfoWithIcon) item).runtimeStatusFlags 
                & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {//APP未在安装中
            ItemInfoWithIcon appInfo = (ItemInfoWithIcon) item;
根据点击的item解析出package name
            intent = new PackageManagerHelper(launcher)
                    .getMarketIntent(appInfo.getTargetComponent().getPackageName());
        } else {
根据点击的item得到intent
            intent = item.getIntent();
        }
        if (intent == null) {
            throw new IllegalArgumentException("Input must have a valid intent");
        }
        if (item instanceof WorkspaceItemInfo) {
            WorkspaceItemInfo si = (WorkspaceItemInfo) item;
            if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)
                    && Intent.ACTION_VIEW.equals(intent.getAction())) {
                // make a copy of the intent that has the package set to null
                // we do this because the platform sometimes disables instant
                // apps temporarily (triggered by the user) and fallbacks to the
                // web ui. This only works though if the package isn't set
                intent = new Intent(intent);
                intent.setPackage(null);
            }
        }
        if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {
            // Preload the icon to reduce latency b/w swapping the floating view with the original.
            FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
        }
将解析出的intent传入
        launcher.startActivitySafely(v, intent, item);
    }

4. Launcher#startActivitySafely

继而会走入super的startActivitySafely

packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
    @Override
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
//判断是否已经resumed
        if (!hasBeenResumed()) {
            // Workaround an issue where the WM launch animation is clobbered when finishing the
            // recents animation into launcher. Defer launching the activity until Launcher is
            // next resumed.
解决当完成从最近任务动画进入launcher时WM启动动画被破坏的问题
            addOnResumeCallback(() -> startActivitySafely(v, intent, item));
            if (mOnDeferredActivityLaunchCallback != null) {
                mOnDeferredActivityLaunchCallback.run();
                mOnDeferredActivityLaunchCallback = null;
            }
            return true;
        }
进入super的startActivitySafely
        boolean success = super.startActivitySafely(v, intent, item);
        if (success && v instanceof BubbleTextView) {
            // This is set to the view that launched the activity that navigated the user away
            // from launcher. Since there is no callback for when the activity has finished
            // launching, enable the press state and keep this reference to reset the press
            // state when we return to launcher.
            BubbleTextView btv = (BubbleTextView) v;
            btv.setStayPressed(true);
            addOnResumeCallback(() -> btv.setStayPressed(false));
        }
        return success;
    }
继承关系如下:
public class Launcher extends StatefulActivity<LauncherState> implements LauncherExterns,
        Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin> 

public abstract class StatefulActivity<STATE_TYPE extends BaseState<STATE_TYPE>>
        extends BaseDraggingActivity 
public abstract class BaseDraggingActivity extends BaseActivity
        implements OnColorsChangedListener, DisplayInfoChangeListener 

6. BaseDraggingActivity#startActivitySafely

最终走入BaseDraggingActivity的startActivitySafely

    public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
        if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
            Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
            return false;
        }
解析得到bundle
        Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
        UserHandle user = item == null ? null : item.user;

        // Prepare intent
添加FLAG_ACTIVITY_NEW_TASK
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            boolean isShortcut = (item instanceof WorkspaceItemInfo)
                    && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                    || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                    && !((WorkspaceItemInfo) item).isPromise();
            if (isShortcut) {
                // Shortcuts need some special checks due to legacy reasons.
                startShortcutIntentSafely(intent, optsBundle, item);
            } else if (user == null || user.equals(Process.myUserHandle())) {
                // Could be launching some bookkeeping activity
启动activity
                startActivity(intent, optsBundle);
            } else {
                getSystemService(LauncherApps.class).startMainActivity(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
            if (item != null) {
                InstanceId instanceId = new InstanceIdSequence().newInstanceId();
                logAppLaunch(item, instanceId);
            }
            return true;
        } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
        }
        return false;
    }

7. Activity#startActivityForResult

然后会调用基类的

frameworks/base/core/java/android/app/Activity.java中的

startActivityForResult方法

frameworks/base/core/java/android/app/Activity.java
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
                && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
            if (TextUtils.equals(getPackageName(),
                    intent.resolveActivity(getPackageManager()).getPackageName())) {
                // Apply Autofill restore mechanism on the started activity by startActivity()
                final IBinder token =
                        mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
                // Remove restore ability from current activity
                mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
                mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
                // Put restore token
                intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
                intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
            }
        }
        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);
        }
    }

8. Activity#startActivityForResult

然后在当前类中继续往下走,调用startActivityForResult

frameworks/base/core/java/android/app/Activity.java
    @Override
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void startActivityForResult(
            String who, Intent intent, int requestCode, @Nullable Bundle options) {
        Uri referrer = onProvideReferrer();
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        options = transferSpringboardActivityOptions(options);
通过Instrumentation跨进程启动activity
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, who,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, who, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
        cancelInputsAndStartExitTransition(options);
    }

9. Instrumentation#startActivityForResult

然后走到了Instrumentation中,Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态,替换和修改类定义等。

frameworks/base/core/java/android/app/Instrumentation.java

frameworks/base/core/java/android/app/Instrumentation.java
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
...
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
获取ATMS的binder对象,通过对象调用startActivity方法
            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;
    }

10. ActivityTaskManager#getService

然后走到了ActivityTaskManager中,通过AIDL获取到了ActivityTaskManagerService的实例

frameworks/base/core/java/android/app/ActivityTaskManager.java

frameworks/base/core/java/android/app/ActivityTaskManager.java
    public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }
    @UnsupportedAppUsage(trackingBug = 129726065)
    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {
获取ACTIVITY_TASK_SERVICE服务
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
返回Binder实例
                    return IActivityTaskManager.Stub.asInterface(b);
                }
            };

------------------------------------------------------------------------------------------------------------------

11. ActivityTaskManagerService#startActivity

     ActivityTaskManagerService#startActivityAsUser

从这里开始就走进入系统进程SystemServer中的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) {
        assertPackageMatchesCallingUid(callingPackage);
        enforceNotIsolatedCaller("startActivityAsUser");

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
将相关设置参数等都设置进去
call:发起者context
callPackage:发起者包名
        // 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
                .execute();

    }

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

    private ActivityStartController mActivityStartController;
    ActivityStartController getActivityStartController() {
        return mActivityStartController;
    }
    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    

12. ActivityStarter#execute

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() {
...
                res = resolveToHeavyWeightSwitcherIfNeeded();
                if (res != START_SUCCESS) {
                    return res;
                }
                res = executeRequest(mRequest);
...           
     mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res, newActivityCreated, mLastStartActivityRecord, originalOptions);
10-08 23:28:37.883  1601  1817 I ActivityTaskManager: notifyActivityLaunched resultCode=0 launchedActivity=ActivityRecord{37cd946 u0 com.example.android.locationattribution/.MainActivity t9} processRunning=true processSwitch=true newActivityCreated=true info=null
10-08 23:28:37.883  1601  1817 I ActivityTaskManager: notifyActivityLaunched successful
    }

13. ActivityStarter#executeRequest

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

    /**执行活动启动请求并开始启动活动的旅程。这里首先执行几个初步检查。正常的活动启动流将通过 {@link #startActivityUnchecked} 到 {@link #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) {
... 
//初始值       
int err = ActivityManager.START_SUCCESS;
...  
//根据各参数判断当前是否启动失败
      if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            // We couldn't find a class that can handle the given Intent.
            // That's the end of that!
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }

        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
            // We couldn't find the specific class specified in the Intent.
            // Also the end of the line.
            err = ActivityManager.START_CLASS_NOT_FOUND;
        }
...   
//设置ActivityRecord的各种信息,ActivityRecord就代表一个activity,可通过ActivityRecord获取activity的各种信息
     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();
...
//启动activity
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
                restrictedBgActivity, intentGrants);
...

15. ActivityStarter#startActivityUnchecked

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

​
    /**在完成大部分初步检查并确认调用方拥有执行此操作的必要权限时启动activity 。此处还可确保在启动不成功时删除启动activity 。
     * 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, 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.
立即创建一个过渡,以记录在 startActivityInner 中执行的操作的原始意图。否则,startActivityInner 中的逻辑可能会根据子操作启动不同的转换。只在这里创建(并推迟requestStart),因为startActivityInside可能会中止。
        final Transition newTransition = (!mService.getTransitionController().isCollecting() && mService.getTransitionController().getTransitionPlayer() != null) ? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null;
        IRemoteTransition remoteTransition = r.takeRemoteTransition();
        if (newTransition != null && remoteTransition != null) {
            newTransition.setRemoteTransition(remoteTransition);
        }
        mService.getTransitionController().collect(r);
​
        try {
//延迟绘制
            mService.deferWindowLayout();
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
//start activity
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            startedActivityRootTask = handleStartResult(r, result);
//continue绘制
            mService.continueWindowLayout();

10-08 23:28:37.882  1601  1817 I ActivityTaskManager: continueWindowLayout reason=0
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    /** @see WindowSurfacePlacer#continueLayout */
    void continueWindowLayout() {
        mWindowManager.mWindowPlacerLocked.continueLayout(mLayoutReasons != 0);
        if (DEBUG_ALL && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
            Slog.i(TAG, "continueWindowLayout reason=" + mLayoutReasons);
        }
    }
    /** @see WindowSurfacePlacer#deferLayout */
    void deferWindowLayout() {
        if (!mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
            // Reset the reasons at the first entrance because we only care about the changes in the deferred scope.
            mLayoutReasons = 0;
        }
        mWindowManager.mWindowPlacerLocked.deferLayout();
    }

​

 
           mSupervisor.mUserLeaving = false;

            // Transition housekeeping
            if (!ActivityManager.isStartResultSuccessful(result)) {
                if (newTransition != null) {
                    newTransition.abort();
                }
            } else {
                if (!mAvoidMoveToFront && mDoResume
                        && mRootWindowContainer.hasVisibleWindowAboveButDoesNotOwnNotificationShade( r.launchedFromUid)) {
                    // If the UID launching the activity has a visible window on top of the notification shade and it's launching an activity that's going to be at the front, we should move the shade out of the way so the user can see it. We want to avoid the case where the activity is launched on top of a background task which is not moved to the front.
如果正在启动的activity 的 UID 在通知栏的顶部有一个可见窗口,并且它启动的activity 将位于前面,我们应该将底页移开,以便用户可以看到它。我们希望避免在未移动到前面的后台任务之上启动activity 的情况。
                    StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
                    if (statusBar != null) {
                   // This results in a async call since the interface is one-way
                        这会导致异步调用,因为接口是单向的
                        statusBar.collapsePanels();
                    }
                }
                if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
                    // The activity is started new rather than just brought forward, so record it as an existence change.
activity 是新开始的,而不仅仅是提前开始的,因此请将其记录为存在更改。
                    mService.getTransitionController().collectExistenceChange(r);
                }
                if (newTransition != null) {
                    mService.getTransitionController().requestStartTransition(newTransition,
                            mTargetTask, remoteTransition);
                } else {
              // Make the collecting transition wait until this request is ready.
              使ollecting transition等到此请求准备就绪。
                    mService.getTransitionController().setReady(false);
                }
            }
        }

        postStartActivityProcessing(r, result, startedActivityRootTask);

        return result;
    }
​

 17. ActivityStarter#startActivityInner

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

​
    /**启动activity并确定该activity是应添加到现有任务的顶部,还是应将新意向交付到现有activity。还将activity task操作到请求的或有效的根任务/显示上。
     * 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, boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,voiceInteractor, restrictedBgActivity);
        computeLaunchingTaskFlags();
        computeSourceRootTask();
        mIntent.setFlags(mLaunchFlags);
        final Task reusedTask = getReusableTask();
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,  voiceInteractor, restrictedBgActivity);

        computeLaunchingTaskFlags();

        computeSourceRootTask();

        mIntent.setFlags(mLaunchFlags);

        final Task reusedTask = getReusableTask();

        // If requested, freeze the task list
        if (mOptions != null && mOptions.freezeRecentTasksReordering()
                && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid)
                && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) {
            mFrozeTaskList = true;
            mSupervisor.mRecentTasks.setFreezeTaskListReordering();
        }

        // Compute if there is an existing task that should be used for.
        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
        final boolean newTask = targetTask == null;
        mTargetTask = targetTask;
        computeLaunchParams(r, sourceRecord, targetTask);
        // Check if starting activity on given task or on a new task is allowed.
        int startResult = isAllowedToStart(r, newTask, targetTask);
        if (startResult != START_SUCCESS) {
            return startResult;
        }

        final ActivityRecord targetTaskTop = newTask
                ? null : targetTask.getTopNonFinishingActivity();
        if (targetTaskTop != null) {
            // Recycle the target task for this launch.
            startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        } else {
            mAddingToTask = true;
        }

        // If the activity being launched is the same as the one currently at the top, then we need to check if it should only be launched once.
        final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
        if (topRootTask != null) {
            startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        }

        if (mTargetRootTask == null) {
            mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
        }
        if (newTask) {
            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)  ? mSourceRecord.getTask() : null;
            setNewTask(taskToAffiliate);
        } else if (mAddingToTask) {
            addOrReparentStartingActivity(targetTask, "adding to task");
        }

        if (!mAvoidMoveToFront && mDoResume) {
            mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
            if (mOptions != null) {
                if (mOptions.getTaskAlwaysOnTop()) {
                    mTargetRootTask.setAlwaysOnTop(true);
                }
            }
            if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.mInternal.isDreaming()) {
                // Launching underneath dream activity (fullscreen, always-on-top). Run the launch- -behind transition so the Activity gets created and starts in visible state.
                mLaunchTaskBehind = true;
                r.mLaunchTaskBehind = true;
            }
        }

        mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,
                mStartActivity.getUriPermissionsLocked());
        if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) {
            // we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs
            final PackageManagerInternal pmInternal =
                    mService.getPackageManagerInternalLocked();
            final int resultToUid = pmInternal.getPackageUid(
                    mStartActivity.resultTo.info.packageName, 0 /* flags */,
                    mStartActivity.mUserId);
            pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,
                    UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/, resultToUid /*visible*/, true /*direct*/);
        }
        if (newTask) {
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId,
                    mStartActivity.getTask().mTaskId);
        }
        mStartActivity.logStartActivity(
                EventLogTags.WM_CREATE_ACTIVITY, mStartActivity.getTask());

        mTargetRootTask.mLastPausedActivity = null;
​
        mRootWindowContainer.startPowerModeLaunchIfNeeded(
                false /* forceSend */, mStartActivity);
        mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,mKeepCurTransition, mOptions, sourceRecord);
10-08 23:28:37.875  1601  1817 V ActivityTaskManager: Prepare open transition: starting ActivityRecord{37cd946 u0 com.example.android.locationattribution/.MainActivity t9}
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetRootTask.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) {
//
                  mTargetRootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS);
//
                  mTargetRootTask.mDisplayContent.executeAppTransition();
            } else {
//
                  if (mTargetRootTask.isTopActivityFocusable()
 && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                    mTargetRootTask.moveToFront("startActivityInner");
                  }
               mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
10-08 23:28:37.877  1601  1817 V ActivityTaskManager: Resuming ActivityRecord{37cd946 u0 com.example.android.locationattribution/.MainActivity t9}
10-08 23:28:37.878  1601  1817 D ActivityTaskManager: setResumedActivity task:Task{f939720 #6 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1} + from: ActivityRecord{38ca623 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6} to:null reason:startPausingLocked - onActivityStateChanged
            }
        }
        mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);
        //活动开始时立即更新近期任务列表
        // Update the recent tasks list immediately when the activity starts
        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
10-08 23:28:37.879  1601  1817 D ActivityTaskManager: add: task=Task{8800707 #9 type=standard A=10077:com.example.android.locationattribution U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}
10-08 23:28:37.879  1601  1817 D ActivityTaskManager: addRecent: trimming tasks for Task{8800707 #9 type=standard A=10077:com.example.android.locationattribution U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}
10-08 23:28:37.880  1601  1817 D ActivityTaskManager: addRecent: adding Task{8800707 #9 type=standard A=10077:com.example.android.locationattribution U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}

        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
             mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);

        return START_SUCCESS;
    }
​

    void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
            boolean newTask, boolean keepCurTransition, ActivityOptions options,
            @Nullable ActivityRecord sourceRecord) {
        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);
        }
        Task task = null;
        if (!newTask && isOrhasTask) {
            // Starting activity cannot be occluding activity, otherwise starting window could be remove immediately without transferring to starting activity.
            final ActivityRecord occludingActivity = getOccludingActivityAbove(r);
            if (occludingActivity != null) {
                // Here it is!  Now, if this is not yet visible (occluded by another task) to the user, then just add it without starting; it will get started when the user navigates back to it.
                ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
                                + "callers: %s", r, task,
                        new RuntimeException("here").fillInStackTrace());
                rTask.positionChildAtTop(r);
                ActivityOptions.abort(options);
                return;
            }
        }

        // Place a new activity at top of root task, so it is next to interact with the user. If we are not placing the new activity frontmost, we do not want to deliver the onUserLeaving callback to the actual frontmost activity
        final Task activityTask = r.getTask();
        if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) {
            mTaskSupervisor.mUserLeaving = false;
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "startActivity() behind front, mUserLeaving=false");
        }

        task = activityTask;

        // Slot the activity into the history root task and proceed
        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
                        + "callers: %s", r, task, new RuntimeException("here").fillInStackTrace());
        task.positionChildAtTop(r);

        // The transition animation and starting window are not needed if {@code allowMoveToFront} is false, because the activity won't be visible.
        if ((!isHomeOrRecentsRootTask() || hasActivity()) && allowMoveToFront) {
            final DisplayContent dc = mDisplayContent;
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
10-08 23:28:37.875  1601  1817 V ActivityTaskManager: Prepare open transition: starting ActivityRecord{37cd946 u0 com.example.android.locationattribution/.MainActivity t9}
            // TODO(shell-transitions): record NO_ANIMATION flag somewhere.
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                dc.prepareAppTransition(TRANSIT_NONE);
                mTaskSupervisor.mNoAnimActivities.add(r);
            } else {
                int transit = TRANSIT_OLD_ACTIVITY_OPEN;
                if (newTask) {
                    if (r.mLaunchTaskBehind) {
                        transit = TRANSIT_OLD_TASK_OPEN_BEHIND;
                    } else {
                        // If a new task is being launched, then mark the existing top activity as supporting picture-in-picture while pausing only if the starting activity would not be considered an overlay on top of the current activity(eg. not fullscreen, or the assistant)
                        if (canEnterPipOnTaskSwitch(focusedTopActivity,
                                null /* toFrontTask */, r, options)) {
                            focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
                        }
                        transit = TRANSIT_OLD_TASK_OPEN;
                    }
                }
                dc.prepareAppTransition(TRANSIT_OPEN);
                mTaskSupervisor.mNoAnimActivities.remove(r);
            }
            boolean doShow = true;
            if (newTask) {
                // Even though this activity is starting fresh, we still need to reset it to make sure we apply affinities to move any existing activities from other tasks in to it. If the caller has requested that the target task be reset, then do so.
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeeded(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && options.getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                doShow = false;
            }
            if (r.mLaunchTaskBehind) {
                // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we tell WindowManager that r is visible even though it is at the back of the root task.
                r.setVisibility(true);
                ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
                // Go ahead to execute app transition for this activity since the app transition will not be triggered through the resume channel.
                mDisplayContent.executeAppTransition();
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                // Figure out if we are transitioning from another activity that is "has the same starting icon" as the next one.  This allows the window manager to keep the previous window it had previously created, if it still had one.
                Task prevTask = r.getTask();
                ActivityRecord prev = prevTask.topActivityWithStartingWindow();
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if: (1) The current activity is in a different task.
                    if (prev.getTask() != prevTask) {
                        prev = null;
                    }
                    // (2) The current activity is already displayed.
                    else if (prev.nowVisible) {
                        prev = null;
                    }
                }

                r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity),true /* startActivity */, sourceRecord);
            }
        } else {
            // If this is the first activity, don't do any fancy animations, because there is nothing for it to animate on top of.
            ActivityOptions.abort(options);
        }
    }

​

18. RootWindowContainer#resumeFocusedTasksTopActivities

 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    boolean resumeFocusedTasksTopActivities() {
        return resumeFocusedTasksTopActivities(null, null, null);
    }
----------------------------------------------------------------------------------
    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) {
        return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions, false /* deferPause */);
    }
----------------------------------------------------------------------------------
    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);
        }

        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            final DisplayContent display = getChildAt(displayNdx);
            final boolean curResult = result;
            boolean[] resumedOnDisplay = new boolean[1];
            display.forAllRootTasks(rootTask -> {
                final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
                if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
                    return;
                }
                if (rootTask == targetRootTask) {
//
                    resumedOnDisplay[0] |= curResult;
                    return;
                }
                if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                        && topRunningActivity.isState(RESUMED)) {
//
                    rootTask.executeAppTransition(targetOptions);
                } else {
                    resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
                }
            });
            result |= resumedOnDisplay[0];
            if (!resumedOnDisplay[0]) {
//
                final Task focusedRoot = display.getFocusedRootTask();
                if (focusedRoot != null) {
                    result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);
                } else if (targetRootTask == null) {
                    result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea());
                }
            }
        }

        return result;
    }

19. RootWindowContainer#resumeTopActivityUncheckedLocked

 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);
    }    
----------------------------------------------------------------------------
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_VISIBILITY_VISIBLE) {
                        break;
                    }

                    someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options, deferPause);
//
                    if (idx >= mChildren.size()) {
                        idx = mChildren.size() - 1;
                    }
                }
            }

//
            final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mInResumeTopActivity = false;
        }

        return someActivityResumed;
    }

20. RootWindowContainer#resumeTopActivityInnerLocked

 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
...

        next代表将要去resume的activity
        ActivityRecord next = topRunningActivity(true /* focusableOnly */);

        final boolean hasRunningActivity = next != null;

        // TODO: Maybe this entire condition can get removed?
        if (hasRunningActivity && !isAttached()) {
            return false;
        }

        mRootWindowContainer.cancelInitializingActivities();

        if (!hasRunningActivity) {//如果将要启动的activity为null
            // There are no activities left in the root task, let's look somewhere else.

            根任务中没有activitiy,让我们看看其他地方。
            return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

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

        // If the top activity is the resumed one, nothing to do.

       如果top activity是resumed的activity,则无需执行任何操作。
        if (mResumedActivity == next && next.isState(RESUMED)
                && taskDisplayArea.allResumedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there should be nothing left to do at this point.确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
            executeAppTransition(options);
            // For devices that are not in fullscreen mode (e.g. freeform windows), it's possible we still want to check if the visibility of other windows have changed (e.g. bringing a fullscreen window forward to cover another freeform activity.)对于未处于全屏模式的设备(例如自由格式窗口),我们可能仍希望检查其他窗口的可见性是否已更改(例如,将全屏窗口向前移动以覆盖另一个自由格式活动)。
            if (taskDisplayArea.inMultiWindowMode()) {
                taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                        false /* preserveWindows */, true /* notifyClients */);
            }
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity "
                    + "resumed %s", next);
            return false;
        }

        if (!next.canResumeByCompat()) {
            return false;
        }

        // If we are currently pausing an activity, then don't do anything until that is done.

         如果我们当前正在暂停一个activity,那么在暂停之前不要执行任何操作。
        final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
        if (!allPausedComplete) {
            ProtoLog.v(WM_DEBUG_STATES,
                    "resumeTopActivityLocked: 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.如果我们在sleeping,并且没有resumed的activity,并且顶级activity暂停,那么这就是我们想要的状态。
        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, "resumeTopActivityLocked: 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.

确保拥有此activity的用户已启动。 如果没有,我们将保持原样,因为有人应该将其他用户的activity带到堆栈的顶部。
        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.

         activity可能正在等待停止,但这不再适合它。
        mTaskSupervisor.mStoppingActivities.remove(next);

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

10-08 23:28:37.877  1601  1817 V ActivityTaskManager: Resuming ActivityRecord{37cd946 u0 com.example.android.locationattribution/.MainActivity t9}

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

        ActivityRecord lastResumed = null;
        final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();
        if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTask()) {
            // 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.

那么,我们为什么不在这里使用 prev呢???请参阅有关该方法的参数注释。“上一个”不表示上次resumed的activity。但是,如果最后一个焦点堆栈不为 null,则它执行。
            lastResumed = lastFocusedRootTask.getResumedActivity();
        }

        boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);

 10-08 23:28:37.879  1601  1817 I wm_pause_activity: [0,59549219,com.android.launcher3/.uioverrides.QuickstepLauncher,userLeaving=true,pauseBackTasks]
        if (mResumedActivity != null) {
            ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
            pausing |= startPausingLocked(false /* uiSleeping */, next,
                    "resumeTopActivityInnerLocked");
        }

21. Task#startPausingLocked

    /**
     * Start pausing the currently resumed activity.  It is an error to call this if there
     * is already an activity being paused or there is no resumed activity.
     *
     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
     * @param uiSleeping True if this is happening with the user interface going to sleep (the
     * screen turning off).
     * @param resuming The activity we are currently trying to resume or null if this is not being  called as part of resuming the top activity, so we shouldn't try to instigate  a resume here if not null.
     * @param reason The reason of pausing the activity.
     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for it to tell us when it is done.
     */
    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, String reason) {
        if (!isLeafTask()) {
            final int[] pausing = {0};
            forAllLeafTasks((t) -> {
                if (t.startPausingLocked(userLeaving, uiSleeping, resuming, reason)) {
                    pausing[0]++;
                }
            }, true /* traverseTopToBottom */);
            return pausing[0] > 0;
        }

        if (mPausingActivity != null) {
            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
                    + " state=" + mPausingActivity.getState());
            if (!shouldSleepActivities()) {
                // Avoid recursion among check for sleep and complete pause during sleeping. Because activity will be paused immediately after resume, just let pause be completed by the order of activity paused from clients.

避免检查睡眠时递归,并在睡眠期间完全暂停。由于activity 将在resume后立即暂停,因此只需让暂停按客户端暂停的activity 顺序完成即可。
                completePauseLocked(false, resuming);
            }
        }
        ActivityRecord prev = mResumedActivity;

        if (prev == null) {
            if (resuming == null) {
                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
                mRootWindowContainer.resumeFocusedTasksTopActivities();
            }
            return false;
        }

        if (prev == resuming) {
            Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
            return false;
        }

        ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        if (prev.isNoHistory() && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
            mTaskSupervisor.mNoHistoryActivities.add(prev);
        }
        prev.setState(PAUSING, "startPausingLocked");

10-08 23:28:37.878  1601  1817 D ActivityTaskManager: setResumedActivity taskFrag:Task{f939720 #6 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1} + from: ActivityRecord{38ca623 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6} to:null reason:startPausingLocked - onActivityStateChanged
        prev.getTask().touchActiveTime();

        mAtmService.updateCpuStats();

        boolean pauseImmediately = false;
        boolean shouldAutoPip = false;
        if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
            // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity to be paused, while at the same time resuming the new resume activity only if the previous activity can't go into Pip since we want to give Pip activities a chance to enter Pip before resuming the next activity.

如果设置了标志RESUME_WHILE_PAUSING,则继续安排暂停上一个activity ,同时仅当上一个activity 无法进入 Pip 时才恢复新的resumed activity 活动,因为我们希望让 Pip 活动有机会在恢复下一个activity 之前进入 Pip。
            final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState("shouldResumeWhilePausing", userLeaving);
            if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
                shouldAutoPip = true;
            } else if (!lastResumedCanPip) {
                pauseImmediately = true;
            } else {
                // The previous activity may still enter PIP even though it did not allow auto-PIP.
            }
        }

        boolean didAutoPip = false;
        if (prev.attachedToProcess()) {
            if (shouldAutoPip) {//进入PIP
                ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
                        + "directly: %s", prev);

                didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs);
                mPausingActivity = null;
            } else {
                ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
                try {
                    EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),  prev.shortComponentName, "userLeaving=" + userLeaving, reason);

mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,  prev.configChangeFlags, pauseImmediately));
                } catch (Exception e) {
...

22. Server端-ClientLifecycleManager#scheduleTransaction

这里和有一个aidl通信的,具体文件如下

frameworks/base/core/java/android/app/IApplicationThread.aidl server端代码如下:

    /**
     * @return A new instance of {@link ClientTransaction} with a single callback invocation.
     *
     * @see ClientTransaction
     * @see ClientTransactionItem
     */
    private static ClientTransaction transactionWithCallback(@NonNull IApplicationThread client,
            IBinder activityToken, @NonNull ClientTransactionItem callback) {
        final ClientTransaction clientTransaction = ClientTransaction.obtain(client, activityToken);
        clientTransaction.addCallback(callback);//将PauseActivityItem.obtain添加进callback
        return clientTransaction;
    }


22.1 ClientTransaction#getClient


    /** Target client. */
    private IApplicationThread mClient;
    /** Get the target client of the transaction. */
    public IApplicationThread getClient() {
        return mClient;
    }
​

23. Client端-ApplicationThread#scheduleTransaction

    private class ApplicationThread extends IApplicationThread.Stub {
...
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }
...
}

由于ActivityThread中没有重写scheduleTransaction,所以会调用到ActivityThread的父类ClientTransactionHandler中,ClientTransactionHandler中的scheduleTransaction方法如下。

frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {//继承父类,调用父类的方法
​
frameworks/base/core/java/android/app/ClientTransactionHandler.java
public abstract class ClientTransactionHandler {

    // Schedule phase related logic and handlers.

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
​
frameworks/base/core/java/android/app/ActivityThread.java
    void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1) {
        sendMessage(what, obj, arg1, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2) {
        sendMessage(what, obj, arg1, arg2, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) {
            Slog.v(TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
        }
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }
​
    // An executor that performs multi-step transactions.
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
    class H extends Handler {
...
                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side instead of ClientLifecycleManager to avoid being cleared before this message is handled.系统进程内的客户端事务在客户端而不是 ClientLifecycle Manager 上回收,以避免在处理此消息之前被清除。
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;
...
}
​

frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

    /**
     * Resolve transaction.
     * First all callbacks will be executed in the order they appear in the list. If a callback requires a certain pre- or post-execution state, the client will be transitioned accordingly. Then the client will cycle to the final lifecycle state if provided. Otherwise, it will either remain in the initial state, or last state needed by a callback.
    解析事务。
     * 首先,所有回调将按照它们在列表中出现的顺序执行。如果回调需要特定的执行前或执行后状态,则客户端将相应地进行转换。 然后客户端将循环到最终生命周期状态(如果提供)。否则,它将保持初始状态或回调所需的最后一个状态。
     */
    public void execute(ClientTransaction transaction) {
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
        final IBinder token = transaction.getActivityToken();
        if (token != null) {
            final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
                    mTransactionHandler.getActivitiesToBeDestroyed();
            final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
            if (destroyItem != null) {
                if (transaction.getLifecycleStateRequest() == destroyItem) {
                    // It is going to execute the transaction that will destroy activity with the token, so the corresponding to-be-destroyed record can be removed.
它将执行销毁token对应的activity的事务,因此可以删除相应的待销毁记录。
                    activitiesToBeDestroyed.remove(token);
                }
                if (mTransactionHandler.getActivityClient(token) == null) {
                    // The activity has not been created but has been requested to destroy, so all transactions for the token are just like being cancelled.
该activity尚未创建,但已被请求销毁,因此token的所有交易就像被取消一样。​​​​​​​
                    Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"+ transactionToString(transaction, mTransactionHandler));
                    return;
                }
            }
        }
        if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));
        executeCallbacks(transaction);
        executeLifecycleState(transaction);
        mPendingActions.clear();
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
    }
​
​

frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

  /** Cycle through all states requested by callbacks and execute them at proper times. */循环遍历回调请求的所有状态,并在适当的时候执行它们。
    @VisibleForTesting
    public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
        if (callbacks == null || callbacks.isEmpty()) {
            // No callbacks to execute, return early.
            return;
        }
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callbacks in transaction");

        final IBinder token = transaction.getActivityToken();
        ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

        // In case when post-execution state of the last callback matches the final state requested for the activity in this transaction, we won't do the last transition here and do it when moving to final state instead (because it may contain additional parameters from server).
如果当最后一个回调的执行后状态与此事务中的activity请求的最终状态匹配时,我们不会在此处执行最后一次转换,而是在移动到最终状态时执行此操作(因为它可能包含来自服务器的其他参数)。
        final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
        final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()  : UNDEFINED;
        // Index of the last callback that requests some post-execution state.
        请求某个执行后状态的最后一个回调的索引。​​​​​​​
        final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);

        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
//对应22,那里将PauseActivityItem.obtain add进了callback,所以此处可以get到这个callback
            if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
            final int postExecutionState = item.getPostExecutionState();
            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,  item.getPostExecutionState());
            if (closestPreExecutionState != UNDEFINED) {
                cycleToPath(r, closestPreExecutionState, transaction);
            }
-----------------------执行完execute后,会再执行postExecute通知Server端
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
            if (r == null) {
                // Launch activity request will create an activity record.
                r = mTransactionHandler.getActivityClient(token);
            }

            if (postExecutionState != UNDEFINED && r != null) {
                // Skip the very last transition and perform it by explicit state request instead.
                final boolean shouldExcludeLastTransition =
                      i == lastCallbackRequestingState && finalState == postExecutionState;
                cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
            }
        }
    }
​

24. PauseActivityItem#execute

这里就走到了PauseActivityItem,马上要开始真正的pause操作了, ActivityThread继承了ClientTransactionHandler,所以最终会走进ActivityThread。

frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java

public class PauseActivityItem extends ActivityLifecycleItem {
...
    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
        client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions, "PAUSE_ACTIVITY_ITEM");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
...

25. ActivityThread#handlePauseActivity

​
frameworks/base/core/java/android/app/ActivityThread.java

    @Override
    public void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, String reason) {
        if (userLeaving) {
            performUserLeavingActivity(r);
        }

        r.activity.mConfigChangeFlags |= configChanges;
        performPauseActivity(r, finished, reason, pendingActions);

        // Make sure any pending writes are now committed.
        if (r.isPreHoneycomb()) {
            QueuedWork.waitToFinish();
        }
        mSomeActivitiesChanged = true;
    }
​

26. ActivityThread#performPauseActivity

​
final Bundle performPauseActivity(IBinder token, boolean finished, String reason, PendingTransactionActions pendingActions) { 
     ActivityClientRecord r = mActivities.get(token); return r != null ? 
     performPauseActivity(r, finished, reason, pendingActions) : null;
}

​

 27. ActivityThread#performPauseActivity

    /** Pause the activity.
     * @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.*/
    private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason, PendingTransactionActions pendingActions) {

        if (r.paused) {
            if (r.activity.mFinished) {
                // If we are finishing, we won't call onResume() in certain cases.
                // So here we likewise don't want to call onPause() if the activity
                // isn't resumed.
                return null;
            }
            RuntimeException e = new RuntimeException(
                    "Performing pause of activity that is not resumed: "
                    + r.intent.getComponent().toShortString());
            Slog.e(TAG, e.getMessage(), e);
        }
        if (finished) {
            r.activity.mFinished = true;
        }

        // Pre-Honeycomb apps always save their state before pausing
        final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
        if (shouldSaveState) {
            callActivityOnSaveInstanceState(r);
        }
       performPauseActivityIfNeeded(r, reason);

...
        return shouldSaveState ? r.state : null;
    }

28. ActivityThread#performPauseActivityIfNeeded

​
    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        if (r.paused) {
            // You are already paused silly...
            return;
        }

        // Always reporting top resumed position loss when pausing an activity. If necessary, it will be restored in performResumeActivity().
当pause activity时,始终报告top resumed的位置。如有必要,它将在 performResumeActivity() 中恢复。
        reportTopResumedActivityChanged(r, false /* onTop */, "pausing");

        try {
            r.activity.mCalled = false;
            mInstrumentation.callActivityOnPause​​​​​​​(r.activity);
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent) + " did not call through to super.onPause()");
            }
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException("Unable to pause activity "
                 + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
            }
        }
        r.setState(ON_PAUSE);//更新pause的值
    }
        /** Update the current lifecycle state for internal bookkeeping. */
        public void setState(@LifecycleState int newLifecycleState) {
            mLifecycleState = newLifecycleState;
            switch (mLifecycleState) {
                case ON_CREATE:
                    paused = true;
                    stopped = true;
                    break;
                case ON_START:
                    paused = true;
                    stopped = false;
                    break;
                case ON_RESUME:
                    paused = false;
                    stopped = false;
                    break;
                case ON_PAUSE:
                    paused = true;
                    stopped = false;
                    break;
                case ON_STOP:
                    paused = true;
                    stopped = true;
                    break;
            }
        }
​

29. Instrumentation#callActivityOnPause

执行到这里,马上就要调用到prev activity的onPause方法了。

frameworks/base/core/java/android/app/Instrumentation.java
 /** Perform calling of an activity's {@link Activity#onPause} method.  The default implementation simply calls through to that method.开始调用Activity的的onpause方法
     * @param activity The activity being paused.
     */
    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }
​

30. Activity#performPause

终于调用到应用的onPause方法了,就开始执行activity的pause操作 

frameworks/base/core/java/android/app/Activity.java
    final void performPause() {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performPause:"
                    + mComponent.getClassName());
        }
        dispatchActivityPrePaused();
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        EventLogTags.writeWmOnPausedCalled(mIdent, getComponentName().getClassName(), "performPause");
10-08 23:28:37.908  2465  2465 I wm_on_paused_called: [59549219,com.android.launcher3.uioverrides.QuickstepLauncher,performPause]
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        dispatchActivityPostPaused();
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
    }
​

31. Activity#onPause​​​​​​​

    protected void onPause() {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
        dispatchActivityPaused();
        if (mAutoFillResetNeeded) {
            if (!mAutoFillIgnoreFirstResumePause) {
                if (DEBUG_LIFECYCLE) Slog.v(TAG, "autofill notifyViewExited " + this);
                View focus = getCurrentFocus();
                if (focus != null && focus.canNotifyAutofillEnterExitEvent()) {
                    getAutofillManager().notifyViewExited(focus);
                }
            } else {
                // reset after first pause()
                if (DEBUG_LIFECYCLE) Slog.v(TAG, "autofill got first pause " + this);
                mAutoFillIgnoreFirstResumePause = false;
            }
        }

        notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_PAUSE);
        mCalled = true;
    }  
​

一篇文章太长了,分成几部分

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值