Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e1b5698 authored by Wei Sheng Shih's avatar Wei Sheng Shih Committed by Automerger Merge Worker
Browse files

Merge "Optimize activity snapshot for shell transition." into udc-qpr-dev am: 5f494802

parents 87e1d284 5f494802
Loading
Loading
Loading
Loading
+194 −95
Original line number Diff line number Diff line
@@ -16,16 +16,14 @@

package com.android.server.wm;

import static com.android.server.wm.SnapshotController.ACTIVITY_CLOSE;
import static com.android.server.wm.SnapshotController.ACTIVITY_OPEN;
import static com.android.server.wm.SnapshotController.TASK_CLOSE;
import static com.android.server.wm.SnapshotController.TASK_OPEN;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.os.Environment;
import android.os.SystemProperties;
import android.os.Trace;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
@@ -35,7 +33,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.BaseAppSnapshotPersister.PersistInfoProvider;
import com.android.server.wm.SnapshotController.TransitionState;

import java.io.File;
import java.util.ArrayList;
@@ -61,12 +58,6 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord

    static final String SNAPSHOTS_DIRNAME = "activity_snapshots";

    /**
     * The pending activities which should capture snapshot when process transition finish.
     */
    @VisibleForTesting
    final ArraySet<ActivityRecord> mPendingCaptureActivity = new ArraySet<>();

    /**
     * The pending activities which should remove snapshot from memory when process transition
     * finish.
@@ -86,6 +77,10 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
    @VisibleForTesting
    final ArraySet<ActivityRecord> mPendingLoadActivity = new ArraySet<>();

    private final ArraySet<ActivityRecord> mOnBackPressedActivities = new ArraySet<>();

    private final ArrayList<ActivityRecord> mTmpBelowActivities = new ArrayList<>();
    private final ArrayList<WindowContainer> mTmpTransitionParticipants = new ArrayList<>();
    private final SnapshotPersistQueue mSnapshotPersistQueue;
    private final PersistInfoProvider mPersistInfoProvider;
    private final AppSnapshotLoader mSnapshotLoader;
@@ -117,20 +112,6 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
        setSnapshotEnabled(snapshotEnabled);
    }

    void systemReady() {
        if (shouldDisableSnapshots()) {
            return;
        }
        mService.mSnapshotController.registerTransitionStateConsumer(
                ACTIVITY_OPEN, this::handleOpenActivityTransition);
        mService.mSnapshotController.registerTransitionStateConsumer(
                ACTIVITY_CLOSE, this::handleCloseActivityTransition);
        mService.mSnapshotController.registerTransitionStateConsumer(
                TASK_OPEN, this::handleOpenTaskTransition);
        mService.mSnapshotController.registerTransitionStateConsumer(
                TASK_CLOSE, this::handleCloseTaskTransition);
    }

    @Override
    protected float initSnapshotScale() {
        final float config = mService.mContext.getResources().getFloat(
@@ -173,6 +154,7 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord

                        @Override
                        void write() {
                            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "cleanUpUserFiles");
                            final File file = mPersistInfoProvider.getDirectory(userId);
                            if (file.exists()) {
                                final File[] contents = file.listFiles();
@@ -182,15 +164,30 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
                                    }
                                }
                            }
                            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                        }
                    });
        }
    }

    void addOnBackPressedActivity(ActivityRecord ar) {
        if (shouldDisableSnapshots()) {
            return;
        }
        mOnBackPressedActivities.add(ar);
    }

    void clearOnBackPressedActivities() {
        if (shouldDisableSnapshots()) {
            return;
        }
        mOnBackPressedActivities.clear();
    }

    /**
     * Prepare to handle on transition start. Clear all temporary fields.
     * Prepare to collect any change for snapshots processing. Clear all temporary fields.
     */
    void preTransitionStart() {
    void beginSnapshotProcess() {
        if (shouldDisableSnapshots()) {
            return;
        }
@@ -198,18 +195,22 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
    }

    /**
     * on transition start has notified, start process data.
     * End collect any change for snapshots processing, start process data.
     */
    void postTransitionStart() {
    void endSnapshotProcess() {
        if (shouldDisableSnapshots()) {
            return;
        }
        onCommitTransition();
        for (int i = mOnBackPressedActivities.size() - 1; i >= 0; --i) {
            handleActivityTransition(mOnBackPressedActivities.valueAt(i));
        }
        mOnBackPressedActivities.clear();
        mTmpTransitionParticipants.clear();
        postProcess();
    }

    @VisibleForTesting
    void resetTmpFields() {
        mPendingCaptureActivity.clear();
        mPendingRemoveActivity.clear();
        mPendingDeleteActivity.clear();
        mPendingLoadActivity.clear();
@@ -218,31 +219,13 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
    /**
     * Start process all pending activities for a transition.
     */
    private void onCommitTransition() {
    private void postProcess() {
        if (DEBUG) {
            Slog.d(TAG, "ActivitySnapshotController#onCommitTransition result:"
                    + " capture " + mPendingCaptureActivity
            Slog.d(TAG, "ActivitySnapshotController#postProcess result:"
                    + " remove " + mPendingRemoveActivity
                    + " delete " + mPendingDeleteActivity
                    + " load " + mPendingLoadActivity);
        }
        // task snapshots
        for (int i = mPendingCaptureActivity.size() - 1; i >= 0; i--) {
            recordSnapshot(mPendingCaptureActivity.valueAt(i));
        }
        // clear mTmpRemoveActivity from cache
        for (int i = mPendingRemoveActivity.size() - 1; i >= 0; i--) {
            final ActivityRecord ar = mPendingRemoveActivity.valueAt(i);
            final int code = getSystemHashCode(ar);
            mCache.onIdRemoved(code);
        }
        // clear snapshot on cache and delete files
        for (int i = mPendingDeleteActivity.size() - 1; i >= 0; i--) {
            final ActivityRecord ar = mPendingDeleteActivity.valueAt(i);
            final int code = getSystemHashCode(ar);
            mCache.onIdRemoved(code);
            removeIfUserSavedFileExist(code, ar.mUserId);
        }
        // load snapshot to cache
        for (int i = mPendingLoadActivity.size() - 1; i >= 0; i--) {
            final ActivityRecord ar = mPendingLoadActivity.valueAt(i);
@@ -258,6 +241,8 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
                            new SnapshotPersistQueue.WriteQueueItem(mPersistInfoProvider) {
                                @Override
                                void write() {
                                    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                                            "load_activity_snapshot");
                                    final TaskSnapshot snapshot = mSnapshotLoader.loadTask(code,
                                            userId, false /* loadLowResolutionBitmap */);
                                    synchronized (mService.getWindowManagerLock()) {
@@ -265,16 +250,36 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
                                            mCache.putSnapshot(ar, snapshot);
                                        }
                                    }
                                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                                }
                            });
                }
            }
        }
        // clear mTmpRemoveActivity from cache
        for (int i = mPendingRemoveActivity.size() - 1; i >= 0; i--) {
            final ActivityRecord ar = mPendingRemoveActivity.valueAt(i);
            final int code = getSystemHashCode(ar);
            mCache.onIdRemoved(code);
        }
        // clear snapshot on cache and delete files
        for (int i = mPendingDeleteActivity.size() - 1; i >= 0; i--) {
            final ActivityRecord ar = mPendingDeleteActivity.valueAt(i);
            final int code = getSystemHashCode(ar);
            mCache.onIdRemoved(code);
            removeIfUserSavedFileExist(code, ar.mUserId);
        }
        // don't keep any reference
        resetTmpFields();
    }

    private void recordSnapshot(ActivityRecord activity) {
    void recordSnapshot(ActivityRecord activity) {
        if (shouldDisableSnapshots()) {
            return;
        }
        if (DEBUG) {
            Slog.d(TAG, "ActivitySnapshotController#recordSnapshot " + activity);
        }
        final TaskSnapshot snapshot = recordSnapshotInner(activity, false /* allowSnapshotHome */);
        if (snapshot != null) {
            final int code = getSystemHashCode(activity);
@@ -285,15 +290,20 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
    /**
     * Called when the visibility of an app changes outside the regular app transition flow.
     */
    void notifyAppVisibilityChanged(ActivityRecord appWindowToken, boolean visible) {
    void notifyAppVisibilityChanged(ActivityRecord ar, boolean visible) {
        if (shouldDisableSnapshots()) {
            return;
        }
        final Task task = ar.getTask();
        if (task == null) {
            return;
        }
        // Doesn't need to capture activity snapshot when it converts from translucent.
        if (!visible) {
            resetTmpFields();
            addBelowTopActivityIfExist(appWindowToken.getTask(), mPendingRemoveActivity,
            addBelowActivityIfExist(ar, mPendingRemoveActivity, false,
                    "remove-snapshot");
            onCommitTransition();
            postProcess();
        }
    }

@@ -301,65 +311,146 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
        return System.identityHashCode(activity);
    }

    void handleOpenActivityTransition(TransitionState<ActivityRecord> transitionState) {
        ArraySet<ActivityRecord> participant = transitionState.getParticipant(false /* open */);
        for (ActivityRecord ar : participant) {
            mPendingCaptureActivity.add(ar);
            // remove the snapshot for the one below close
            final ActivityRecord below = ar.getTask().getActivityBelow(ar);
            if (below != null) {
                mPendingRemoveActivity.add(below);
    @VisibleForTesting
    void handleTransitionFinish(@NonNull ArrayList<WindowContainer> windows) {
        mTmpTransitionParticipants.clear();
        mTmpTransitionParticipants.addAll(windows);
        for (int i = mTmpTransitionParticipants.size() - 1; i >= 0; --i) {
            final WindowContainer next = mTmpTransitionParticipants.get(i);
            if (next.asTask() != null) {
                handleTaskTransition(next.asTask());
            } else if (next.asTaskFragment() != null) {
                final TaskFragment tf = next.asTaskFragment();
                final ActivityRecord ar = tf.getTopMostActivity();
                if (ar != null) {
                    handleActivityTransition(ar);
                }
            } else if (next.asActivityRecord() != null) {
                handleActivityTransition(next.asActivityRecord());
            }
        }
    }

    void handleCloseActivityTransition(TransitionState<ActivityRecord> transitionState) {
        ArraySet<ActivityRecord> participant = transitionState.getParticipant(true /* open */);
        for (ActivityRecord ar : participant) {
    private void handleActivityTransition(@NonNull ActivityRecord ar) {
        if (shouldDisableSnapshots()) {
            return;
        }
        if (ar.isVisibleRequested()) {
            mPendingDeleteActivity.add(ar);
            // load next one if exists.
            final ActivityRecord below = ar.getTask().getActivityBelow(ar);
            if (below != null) {
                mPendingLoadActivity.add(below);
            }
            addBelowActivityIfExist(ar, mPendingLoadActivity, true, "load-snapshot");
        } else {
            // remove the snapshot for the one below close
            addBelowActivityIfExist(ar, mPendingRemoveActivity, true, "remove-snapshot");
        }
    }

    void handleCloseTaskTransition(TransitionState<Task> closeTaskTransitionRecord) {
        ArraySet<Task> participant = closeTaskTransitionRecord.getParticipant(false /* open */);
        for (Task close : participant) {
            // this is close task transition
            // remove the N - 1 from cache
            addBelowTopActivityIfExist(close, mPendingRemoveActivity, "remove-snapshot");
    private void handleTaskTransition(Task task) {
        if (shouldDisableSnapshots()) {
            return;
        }
        final ActivityRecord topActivity = task.getTopMostActivity();
        if (topActivity == null) {
            return;
        }

    void handleOpenTaskTransition(TransitionState<Task> openTaskTransitionRecord) {
        ArraySet<Task> participant = openTaskTransitionRecord.getParticipant(true /* open */);
        for (Task open : participant) {
            // this is close task transition
            // remove the N - 1 from cache
            addBelowTopActivityIfExist(open, mPendingLoadActivity, "load-snapshot");
        if (task.isVisibleRequested()) {
            // this is open task transition
            // load the N - 1 to cache
            addBelowActivityIfExist(topActivity, mPendingLoadActivity, true, "load-snapshot");
            // Move the activities to top of mSavedFilesInOrder, so when purge happen, there
            // will trim the persisted files from the most non-accessed.
            adjustSavedFileOrder(open);
            adjustSavedFileOrder(task);
        } else {
            // this is close task transition
            // remove the N - 1 from cache
            addBelowActivityIfExist(topActivity, mPendingRemoveActivity, true, "remove-snapshot");
        }
    }

    // Add the top -1 activity to a set if it exists.
    private void addBelowTopActivityIfExist(Task task, ArraySet<ActivityRecord> set,
            String debugMessage) {
        final ActivityRecord topActivity = task.getTopMostActivity();
        if (topActivity != null) {
            final ActivityRecord below = task.getActivityBelow(topActivity);
            if (below != null) {
                set.add(below);
    /**
     * Add the top -1 activity to a set if it exists.
     * @param inTransition true if the activity must participant in transition.
     */
    private void addBelowActivityIfExist(ActivityRecord currentActivity,
            ArraySet<ActivityRecord> set, boolean inTransition, String debugMessage) {
        getActivityBelow(currentActivity, inTransition, mTmpBelowActivities);
        for (int i = mTmpBelowActivities.size() - 1; i >= 0; --i) {
            set.add(mTmpBelowActivities.get(i));
            if (DEBUG) {
                Slog.d(TAG, "ActivitySnapshotController#addBelowTopActivityIfExist "
                            + below + " from " + debugMessage);
                        + mTmpBelowActivities.get(i) + " from " + debugMessage);
            }
        }
        mTmpBelowActivities.clear();
    }

    private void getActivityBelow(ActivityRecord currentActivity, boolean inTransition,
            ArrayList<ActivityRecord> result) {
        final Task currentTask = currentActivity.getTask();
        if (currentTask == null) {
            return;
        }
        final ActivityRecord initPrev = currentTask.getActivityBelow(currentActivity);
        if (initPrev == null) {
            return;
        }
        final TaskFragment currTF = currentActivity.getTaskFragment();
        final TaskFragment prevTF = initPrev.getTaskFragment();
        final TaskFragment prevAdjacentTF = prevTF != null
                ? prevTF.getAdjacentTaskFragment() : null;
        if (currTF == prevTF && currTF != null || prevAdjacentTF == null) {
            // Current activity and previous one is in the same task fragment, or
            // previous activity is not in a task fragment, or
            // previous activity's task fragment doesn't adjacent to any others.
            if (!inTransition || isInParticipant(initPrev, mTmpTransitionParticipants)) {
                result.add(initPrev);
            }
            return;
        }

        if (prevAdjacentTF == currTF) {
            // previous activity A is adjacent to current activity B.
            // Try to find anyone below previous activityA, which are C and D if exists.
            // A | B
            // C (| D)
            getActivityBelow(initPrev, inTransition, result);
        } else {
            // previous activity C isn't adjacent to current activity A.
            // A
            // B | C
            final Task prevAdjacentTask = prevAdjacentTF.getTask();
            if (prevAdjacentTask == currentTask) {
                final int currentIndex = currTF != null
                        ? currentTask.mChildren.indexOf(currTF)
                        : currentTask.mChildren.indexOf(currentActivity);
                final int prevAdjacentIndex =
                        prevAdjacentTask.mChildren.indexOf(prevAdjacentTF);
                // prevAdjacentTF already above currentActivity
                if (prevAdjacentIndex > currentIndex) {
                    return;
                }
            }
            if (!inTransition || isInParticipant(initPrev, mTmpTransitionParticipants)) {
                result.add(initPrev);
            }
            // prevAdjacentTF is adjacent to another one
            final ActivityRecord prevAdjacentActivity = prevAdjacentTF.getTopMostActivity();
            if (prevAdjacentActivity != null && (!inTransition
                    || isInParticipant(prevAdjacentActivity, mTmpTransitionParticipants))) {
                result.add(prevAdjacentActivity);
            }
        }
    }

    static boolean isInParticipant(ActivityRecord ar,
            ArrayList<WindowContainer> transitionParticipants) {
        for (int i = transitionParticipants.size() - 1; i >= 0; --i) {
            final WindowContainer wc = transitionParticipants.get(i);
            if (ar == wc || ar.isDescendantOf(wc)) {
                return true;
            }
        }
        return false;
    }

    private void adjustSavedFileOrder(Task nextTopTask) {
@@ -376,6 +467,9 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord

    @Override
    void onAppRemoved(ActivityRecord activity) {
        if (shouldDisableSnapshots()) {
            return;
        }
        super.onAppRemoved(activity);
        final int code = getSystemHashCode(activity);
        removeIfUserSavedFileExist(code, activity.mUserId);
@@ -386,6 +480,9 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord

    @Override
    void onAppDied(ActivityRecord activity) {
        if (shouldDisableSnapshots()) {
            return;
        }
        super.onAppDied(activity);
        final int code = getSystemHashCode(activity);
        removeIfUserSavedFileExist(code, activity.mUserId);
@@ -440,7 +537,7 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
    private void removeIfUserSavedFileExist(int code, int userId) {
        final UserSavedFile usf = getUserFiles(userId).get(code);
        if (usf != null) {
            mUserSavedFiles.remove(code);
            mUserSavedFiles.get(userId).remove(code);
            mSavedFilesInOrder.remove(usf);
            mPersister.removeSnap(code, userId);
        }
@@ -490,11 +587,13 @@ class ActivitySnapshotController extends AbsAppSnapshotController<ActivityRecord
                    new SnapshotPersistQueue.WriteQueueItem(mPersistInfoProvider) {
                        @Override
                        void write() {
                            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activity_remove_files");
                            for (int i = files.size() - 1; i >= 0; --i) {
                                final UserSavedFile usf = files.get(i);
                                mSnapshotPersistQueue.deleteSnapshot(
                                        usf.mFileId, usf.mUserId, mPersistInfoProvider);
                            }
                            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                        }
                    });
        }
+7 −0
Original line number Diff line number Diff line
@@ -1177,6 +1177,8 @@ class BackNavigationController {
                if (!composeAnimations(mCloseTarget, mOpenTarget, openActivity)) {
                    return null;
                }
                mCloseTarget.mTransitionController.mSnapshotController
                        .mActivitySnapshotController.clearOnBackPressedActivities();
                applyPreviewStrategy(mOpenAdaptor, openActivity);

                final IBackAnimationFinishedCallback callback = makeAnimationFinishedCallback();
@@ -1222,6 +1224,8 @@ class BackNavigationController {
            // Call it again to make sure the activity could be visible while handling the pending
            // animation.
            activity.commitVisibility(true, true);
            activity.mTransitionController.mSnapshotController
                    .mActivitySnapshotController.addOnBackPressedActivity(activity);
        }
        activity.mLaunchTaskBehind = true;

@@ -1248,6 +1252,9 @@ class BackNavigationController {
        // Restore the launch-behind state.
        activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
        activity.mLaunchTaskBehind = false;
        // Ignore all change
        activity.mTransitionController.mSnapshotController
                .mActivitySnapshotController.clearOnBackPressedActivities();
        ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
                "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
                activity);
+54 −253

File changed.

Preview size limit exceeded, changes collapsed.

+6 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.wm;

import static android.graphics.Bitmap.CompressFormat.JPEG;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;

import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -26,6 +27,7 @@ import android.annotation.TestApi;
import android.graphics.Bitmap;
import android.os.Process;
import android.os.SystemClock;
import android.os.Trace;
import android.util.AtomicFile;
import android.util.Slog;
import android.window.TaskSnapshot;
@@ -249,6 +251,7 @@ class SnapshotPersistQueue {

        @Override
        void write() {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "StoreWriteQueueItem");
            if (!mPersistInfoProvider.createDirectory(mUserId)) {
                Slog.e(TAG, "Unable to create snapshot directory for user dir="
                        + mPersistInfoProvider.getDirectory(mUserId));
@@ -263,6 +266,7 @@ class SnapshotPersistQueue {
            if (failed) {
                deleteSnapshot(mId, mUserId, mPersistInfoProvider);
            }
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }

        boolean writeProto() {
@@ -373,7 +377,9 @@ class SnapshotPersistQueue {

        @Override
        void write() {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "DeleteWriteQueueItem");
            deleteSnapshot(mId, mUserId, mPersistInfoProvider);
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
}
+11 −16
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.wm;

import static com.android.server.wm.SnapshotController.TASK_CLOSE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

@@ -77,13 +76,6 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
        setSnapshotEnabled(snapshotEnabled);
    }

    void systemReady() {
        if (!shouldDisableSnapshots()) {
            mService.mSnapshotController.registerTransitionStateConsumer(TASK_CLOSE,
                    this::handleTaskClose);
        }
    }

    static PersistInfoProvider createPersistInfoProvider(WindowManagerService service,
            BaseAppSnapshotPersister.DirectoryResolver resolver) {
        final float highResTaskSnapshotScale = service.mContext.getResources().getFloat(
@@ -116,20 +108,23 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
                enableLowResSnapshots, lowResScaleFactor, use16BitFormat);
    }

    void handleTaskClose(SnapshotController.TransitionState<Task> closeTaskTransitionRecord) {
    // Still needed for legacy transition.(AppTransitionControllerTest)
    void handleClosingApps(ArraySet<ActivityRecord> closingApps) {
        if (shouldDisableSnapshots()) {
            return;
        }
        // We need to take a snapshot of the task if and only if all activities of the task are
        // either closing or hidden.
        mTmpTasks.clear();
        final ArraySet<Task> tasks = closeTaskTransitionRecord.getParticipant(false /* open */);
        if (mService.mAtmService.getTransitionController().isShellTransitionsEnabled()) {
            mTmpTasks.addAll(tasks);
        } else {
            for (Task task : tasks) {
        for (int i = closingApps.size() - 1; i >= 0; i--) {
            final ActivityRecord activity = closingApps.valueAt(i);
            final Task task = activity.getTask();
            if (task == null) continue;

            getClosingTasksInner(task, mTmpTasks);
        }
        }
        snapshotTasks(mTmpTasks);
        mTmpTasks.clear();
        mSkipClosingAppSnapshotTasks.clear();
    }

Loading