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

Commit 041a5abb authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Skip snapshot task when finishing activity for shell transition

With shell transition, the snapshot from
ActivityRecord#finishIfPossible
is always replaced by
Transition#onTransactionReady -> TaskSnapshotController#recordSnapshot

And because currently SnapshotController#onTransitionReady is a
dead code so the task added by addSkipClosingAppSnapshotTasks
won't be cleared.

So the duplicated snapshot can be skipped that eliminates the
only one caller that will add task to mSkipClosingAppSnapshotTasks.
Which also makes finishActivity more efficient.

Also change mSkipClosingAppSnapshotTasks to store task id. So it
won't keep heavy references.

Bug: 283177730
Bug: 273198446
Test: TaskSnapshotControllerTest
Change-Id: I3d03c34d506d0f3b1c0e070b8702a6a66a4de3c1
parent 9a50b8ad
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3560,7 +3560,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                // Note that RecentsAnimation will handle task snapshot while switching apps with
                // the best capture timing (e.g. IME window capture),
                // No need additional task capture while task is controlled by RecentsAnimation.
                if (mAtmService.mWindowManager.mTaskSnapshotController != null
                if (!mTransitionController.isShellTransitionsEnabled()
                        && !task.isAnimatingByRecents()) {
                    final ArraySet<Task> tasks = Sets.newArraySet(task);
                    mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
+7 −41
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.graphics.Rect;
import android.os.Environment;
import android.os.Handler;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Slog;
import android.view.Display;
import android.window.ScreenCapture;
@@ -37,8 +38,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
import com.android.server.wm.BaseAppSnapshotPersister.PersistInfoProvider;

import com.google.android.collect.Sets;

import java.util.Set;

/**
@@ -58,7 +57,7 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
    static final String SNAPSHOTS_DIRNAME = "snapshots";

    private final TaskSnapshotPersister mPersister;
    private final ArraySet<Task> mSkipClosingAppSnapshotTasks = new ArraySet<>();
    private final IntArray mSkipClosingAppSnapshotTasks = new IntArray();
    private final ArraySet<Task> mTmpTasks = new ArraySet<>();
    private final Handler mHandler = new Handler();

@@ -134,26 +133,6 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
        mSkipClosingAppSnapshotTasks.clear();
    }

    /**
     * Called when the visibility of an app changes outside of the regular app transition flow.
     */
    void notifyAppVisibilityChanged(ActivityRecord appWindowToken, boolean visible) {
        if (!visible) {
            handleClosingApps(Sets.newArraySet(appWindowToken));
        }
    }

    private 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.
        getClosingTasks(closingApps, mTmpTasks);
        snapshotTasks(mTmpTasks);
        mSkipClosingAppSnapshotTasks.clear();
    }

    /**
     * Adds the given {@param tasks} to the list of tasks which should not have their snapshots
     * taken upon the next processing of the set of closing apps. The caller is responsible for
@@ -164,7 +143,9 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
        if (shouldDisableSnapshots()) {
            return;
        }
        mSkipClosingAppSnapshotTasks.addAll(tasks);
        for (Task task : tasks) {
            mSkipClosingAppSnapshotTasks.add(task.mTaskId);
        }
    }

    void snapshotTasks(ArraySet<Task> tasks) {
@@ -271,31 +252,16 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
        return source.getTaskDescription();
    }

    /**
     * Retrieves all closing tasks based on the list of closing apps during an app transition.
     */
    @VisibleForTesting
    void getClosingTasks(ArraySet<ActivityRecord> closingApps, ArraySet<Task> outClosingTasks) {
        outClosingTasks.clear();
        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, outClosingTasks);
        }
    }

    void getClosingTasksInner(Task task, ArraySet<Task> outClosingTasks) {
        // Since RecentsAnimation will handle task snapshot while switching apps with the
        // best capture timing (e.g. IME window capture),
        // No need additional task capture while task is controlled by RecentsAnimation.
        if (isAnimatingByRecents(task)) {
            mSkipClosingAppSnapshotTasks.add(task);
            mSkipClosingAppSnapshotTasks.add(task.mTaskId);
        }
        // If the task of the app is not visible anymore, it means no other app in that task
        // is opening. Thus, the task is closing.
        if (!task.isVisible() && !mSkipClosingAppSnapshotTasks.contains(task)) {
        if (!task.isVisible() && mSkipClosingAppSnapshotTasks.indexOf(task.mTaskId) < 0) {
            outClosingTasks.add(task);
        }
    }
+0 −2
Original line number Diff line number Diff line
@@ -298,8 +298,6 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
        assertTrue(mController.isAnimatingTask(activity.getTask()));

        spyOn(mWm.mTaskSnapshotController);
        doNothing().when(mWm.mTaskSnapshotController).notifyAppVisibilityChanged(any(),
                anyBoolean());
        doReturn(mMockTaskSnapshot).when(mWm.mTaskSnapshotController).getSnapshot(anyInt(),
                anyInt(), eq(false) /* restoreFromDisk */, eq(false) /* isLowResolution */);
        mController.setDeferredCancel(true /* deferred */, true /* screenshot */);
+16 −3
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
        closingApps.add(closingWindow.mActivityRecord);
        final ArraySet<Task> closingTasks = new ArraySet<>();
        mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
        getClosingTasks(closingApps, closingTasks);
        assertEquals(1, closingTasks.size());
        assertEquals(closingWindow.mActivityRecord.getTask(), closingTasks.valueAt(0));
    }
@@ -93,7 +93,7 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
        closingApps.add(closingWindow.mActivityRecord);
        final ArraySet<Task> closingTasks = new ArraySet<>();
        mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
        getClosingTasks(closingApps, closingTasks);
        assertEquals(0, closingTasks.size());
    }

@@ -108,10 +108,23 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
        final ArraySet<Task> closingTasks = new ArraySet<>();
        mWm.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(
                Sets.newArraySet(closingWindow.mActivityRecord.getTask()));
        mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
        getClosingTasks(closingApps, closingTasks);
        assertEquals(0, closingTasks.size());
    }

    /** Retrieves all closing tasks based on the list of closing apps during an app transition. */
    private void getClosingTasks(ArraySet<ActivityRecord> closingApps,
            ArraySet<Task> outClosingTasks) {
        outClosingTasks.clear();
        for (int i = closingApps.size() - 1; i >= 0; i--) {
            final ActivityRecord activity = closingApps.valueAt(i);
            final Task task = activity.getTask();
            if (task == null) continue;

            mWm.mTaskSnapshotController.getClosingTasksInner(task, outClosingTasks);
        }
    }

    @Test
    public void testGetSnapshotMode() {
        final WindowState disabledWindow = createWindow(null,