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
This commit is contained in:
Riddle Hsu
2023-05-18 21:16:53 +08:00
parent 9a50b8adbc
commit 041a5abbd5
4 changed files with 24 additions and 47 deletions

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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 */);

View File

@@ -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,