Merge "Port IME tasksnapshot over to shell transitions" into sc-v2-dev am: 4097e44f2a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15819924 Change-Id: I1ee4e3f23de9ee715f3171caa634863ccfe3eb08
This commit is contained in:
@@ -4890,8 +4890,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
* @param visible {@code true} if this {@link ActivityRecord} should become visible, otherwise
|
||||
* this should become invisible.
|
||||
* @param performLayout if {@code true}, perform surface placement after committing visibility.
|
||||
* @param fromTransition {@code true} if this is part of finishing a transition.
|
||||
*/
|
||||
void commitVisibility(boolean visible, boolean performLayout) {
|
||||
void commitVisibility(boolean visible, boolean performLayout, boolean fromTransition) {
|
||||
// Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually
|
||||
// been set by the app now.
|
||||
mVisibleSetFromTransferredStartingWindow = false;
|
||||
@@ -4941,7 +4942,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
|
||||
mUseTransferredAnimation = false;
|
||||
|
||||
postApplyAnimation(visible);
|
||||
postApplyAnimation(visible, fromTransition);
|
||||
}
|
||||
|
||||
void commitVisibility(boolean visible, boolean performLayout) {
|
||||
commitVisibility(visible, performLayout, false /* fromTransition */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4952,8 +4957,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
*
|
||||
* @param visible {@code true} if this {@link ActivityRecord} has become visible, otherwise
|
||||
* this has become invisible.
|
||||
* @param fromTransition {@code true} if this call is part of finishing a transition. This is
|
||||
* needed because the shell transition is no-longer active by the time
|
||||
* commitVisibility is called.
|
||||
*/
|
||||
private void postApplyAnimation(boolean visible) {
|
||||
private void postApplyAnimation(boolean visible, boolean fromTransition) {
|
||||
final boolean usingShellTransitions = mTransitionController.isShellTransitionsEnabled();
|
||||
final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN,
|
||||
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION
|
||||
@@ -4994,7 +5002,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
|
||||
final DisplayContent displayContent = getDisplayContent();
|
||||
if (!displayContent.mClosingApps.contains(this)
|
||||
&& !displayContent.mOpeningApps.contains(this)) {
|
||||
&& !displayContent.mOpeningApps.contains(this)
|
||||
&& !fromTransition) {
|
||||
// Take the screenshot before possibly hiding the WSA, otherwise the screenshot
|
||||
// will not be taken.
|
||||
mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
|
||||
|
||||
@@ -991,6 +991,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
synchronized (mGlobalLock) {
|
||||
mWindowManager = wm;
|
||||
mRootWindowContainer = wm.mRoot;
|
||||
mWindowOrganizerController.setWindowManager(wm);
|
||||
mTempConfig.setToDefaults();
|
||||
mTempConfig.setLocales(LocaleList.getDefault());
|
||||
mConfigurationSeq = mTempConfig.seq = 1;
|
||||
|
||||
@@ -178,43 +178,46 @@ class TaskSnapshotController {
|
||||
snapshotTasks(tasks, false /* allowSnapshotHome */);
|
||||
}
|
||||
|
||||
void recordTaskSnapshot(Task task, boolean allowSnapshotHome) {
|
||||
final TaskSnapshot snapshot;
|
||||
final boolean snapshotHome = allowSnapshotHome && task.isActivityTypeHome();
|
||||
if (snapshotHome) {
|
||||
snapshot = snapshotTask(task);
|
||||
} else {
|
||||
switch (getSnapshotMode(task)) {
|
||||
case SNAPSHOT_MODE_NONE:
|
||||
return;
|
||||
case SNAPSHOT_MODE_APP_THEME:
|
||||
snapshot = drawAppThemeSnapshot(task);
|
||||
break;
|
||||
case SNAPSHOT_MODE_REAL:
|
||||
snapshot = snapshotTask(task);
|
||||
break;
|
||||
default:
|
||||
snapshot = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (snapshot != null) {
|
||||
final HardwareBuffer buffer = snapshot.getHardwareBuffer();
|
||||
if (buffer.getWidth() == 0 || buffer.getHeight() == 0) {
|
||||
buffer.close();
|
||||
Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x"
|
||||
+ buffer.getHeight());
|
||||
} else {
|
||||
mCache.putSnapshot(task, snapshot);
|
||||
// Don't persist or notify the change for the temporal snapshot.
|
||||
if (!snapshotHome) {
|
||||
mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
|
||||
task.onSnapshotChanged(snapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void snapshotTasks(ArraySet<Task> tasks, boolean allowSnapshotHome) {
|
||||
for (int i = tasks.size() - 1; i >= 0; i--) {
|
||||
final Task task = tasks.valueAt(i);
|
||||
final TaskSnapshot snapshot;
|
||||
final boolean snapshotHome = allowSnapshotHome && task.isActivityTypeHome();
|
||||
if (snapshotHome) {
|
||||
snapshot = snapshotTask(task);
|
||||
} else {
|
||||
switch (getSnapshotMode(task)) {
|
||||
case SNAPSHOT_MODE_NONE:
|
||||
continue;
|
||||
case SNAPSHOT_MODE_APP_THEME:
|
||||
snapshot = drawAppThemeSnapshot(task);
|
||||
break;
|
||||
case SNAPSHOT_MODE_REAL:
|
||||
snapshot = snapshotTask(task);
|
||||
break;
|
||||
default:
|
||||
snapshot = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (snapshot != null) {
|
||||
final HardwareBuffer buffer = snapshot.getHardwareBuffer();
|
||||
if (buffer.getWidth() == 0 || buffer.getHeight() == 0) {
|
||||
buffer.close();
|
||||
Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x"
|
||||
+ buffer.getHeight());
|
||||
} else {
|
||||
mCache.putSnapshot(task, snapshot);
|
||||
// Don't persist or notify the change for the temporal snapshot.
|
||||
if (!snapshotHome) {
|
||||
mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
|
||||
task.onSnapshotChanged(snapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
recordTaskSnapshot(tasks.valueAt(i), allowSnapshotHome);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -415,7 +415,16 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
if (commitVisibility) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
" Commit activity becoming invisible: %s", ar);
|
||||
ar.commitVisibility(false /* visible */, false /* performLayout */);
|
||||
final Task task = ar.getTask();
|
||||
if (task != null && !task.isVisibleRequested()
|
||||
&& mTransientLaunches != null) {
|
||||
// If transition is transient, then snapshots are taken at end of
|
||||
// transition.
|
||||
mController.mTaskSnapshotController.recordTaskSnapshot(
|
||||
task, false /* allowSnapshotHome */);
|
||||
}
|
||||
ar.commitVisibility(false /* visible */, false /* performLayout */,
|
||||
true /* fromTransition */);
|
||||
activitiesWentInvisible = true;
|
||||
}
|
||||
}
|
||||
@@ -558,6 +567,19 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
mVisibleAtTransitionEndTokens.add(wc.asWindowToken());
|
||||
}
|
||||
|
||||
// Take task snapshots before the animation so that we can capture IME before it gets
|
||||
// transferred. If transition is transient, IME won't be moved during the transition and
|
||||
// the tasks are still live, so we take the snapshot at the end of the transition instead.
|
||||
if (mTransientLaunches == null) {
|
||||
for (int i = mParticipants.size() - 1; i >= 0; --i) {
|
||||
final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
|
||||
if (ar == null || ar.isVisibleRequested() || ar.getTask() == null
|
||||
|| ar.getTask().isVisibleRequested()) continue;
|
||||
mController.mTaskSnapshotController.recordTaskSnapshot(
|
||||
ar.getTask(), false /* allowSnapshotHome */);
|
||||
}
|
||||
}
|
||||
|
||||
mStartTransaction = transaction;
|
||||
mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
|
||||
buildFinishTransaction(mFinishTransaction, info.getRootLeash());
|
||||
|
||||
@@ -59,6 +59,7 @@ class TransitionController {
|
||||
|
||||
private ITransitionPlayer mTransitionPlayer;
|
||||
final ActivityTaskManagerService mAtm;
|
||||
final TaskSnapshotController mTaskSnapshotController;
|
||||
|
||||
private final ArrayList<WindowManagerInternal.AppTransitionListener> mLegacyListeners =
|
||||
new ArrayList<>();
|
||||
@@ -79,9 +80,11 @@ class TransitionController {
|
||||
// TODO(b/188595497): remove when not needed.
|
||||
final StatusBarManagerInternal mStatusBar;
|
||||
|
||||
TransitionController(ActivityTaskManagerService atm) {
|
||||
TransitionController(ActivityTaskManagerService atm,
|
||||
TaskSnapshotController taskSnapshotController) {
|
||||
mAtm = atm;
|
||||
mStatusBar = LocalServices.getService(StatusBarManagerInternal.class);
|
||||
mTaskSnapshotController = taskSnapshotController;
|
||||
mTransitionPlayerDeath = () -> {
|
||||
synchronized (mAtm.mGlobalLock) {
|
||||
// Clean-up/finish any playing transitions.
|
||||
|
||||
@@ -117,7 +117,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||
final DisplayAreaOrganizerController mDisplayAreaOrganizerController;
|
||||
final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
|
||||
|
||||
final TransitionController mTransitionController;
|
||||
TransitionController mTransitionController;
|
||||
/**
|
||||
* A Map which manages the relationship between
|
||||
* {@link TaskFragmentCreationParams#getFragmentToken()} and {@link TaskFragment}
|
||||
@@ -131,7 +131,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||
mTaskOrganizerController = new TaskOrganizerController(mService);
|
||||
mDisplayAreaOrganizerController = new DisplayAreaOrganizerController(mService);
|
||||
mTaskFragmentOrganizerController = new TaskFragmentOrganizerController(atm);
|
||||
mTransitionController = new TransitionController(atm);
|
||||
}
|
||||
|
||||
void setWindowManager(WindowManagerService wms) {
|
||||
mTransitionController = new TransitionController(mService, wms.mTaskSnapshotController);
|
||||
}
|
||||
|
||||
TransitionController getTransitionController() {
|
||||
|
||||
@@ -34,8 +34,11 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -448,7 +451,8 @@ public class TransitionTests extends WindowTestsBase {
|
||||
|
||||
@Test
|
||||
public void testIntermediateVisibility() {
|
||||
final TransitionController controller = new TransitionController(mAtm);
|
||||
final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
|
||||
final TransitionController controller = new TransitionController(mAtm, snapshotController);
|
||||
final ITransitionPlayer player = new ITransitionPlayer.Default();
|
||||
controller.registerTransitionPlayer(player);
|
||||
ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
|
||||
@@ -511,6 +515,71 @@ public class TransitionTests extends WindowTestsBase {
|
||||
assertTrue(activity2.isVisible());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransientLaunch() {
|
||||
final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
|
||||
final TransitionController controller = new TransitionController(mAtm, snapshotController);
|
||||
final ITransitionPlayer player = new ITransitionPlayer.Default();
|
||||
controller.registerTransitionPlayer(player);
|
||||
ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
|
||||
final Transition openTransition = controller.createTransition(TRANSIT_OPEN);
|
||||
|
||||
// Start out with task2 visible and set up a transition that closes task2 and opens task1
|
||||
final Task task1 = createTask(mDisplayContent);
|
||||
task1.mTaskOrganizer = mockOrg;
|
||||
final ActivityRecord activity1 = createActivityRecord(task1);
|
||||
activity1.mVisibleRequested = false;
|
||||
activity1.setVisible(false);
|
||||
final Task task2 = createTask(mDisplayContent);
|
||||
task2.mTaskOrganizer = mockOrg;
|
||||
final ActivityRecord activity2 = createActivityRecord(task2);
|
||||
activity2.mVisibleRequested = true;
|
||||
activity2.setVisible(true);
|
||||
|
||||
openTransition.collectExistenceChange(task1);
|
||||
openTransition.collectExistenceChange(activity1);
|
||||
openTransition.collectExistenceChange(task2);
|
||||
openTransition.collectExistenceChange(activity2);
|
||||
|
||||
activity1.mVisibleRequested = true;
|
||||
activity1.setVisible(true);
|
||||
activity2.mVisibleRequested = false;
|
||||
|
||||
// Using abort to force-finish the sync (since we can't wait for drawing in unit test).
|
||||
// We didn't call abort on the transition itself, so it will still run onTransactionReady
|
||||
// normally.
|
||||
mWm.mSyncEngine.abort(openTransition.getSyncId());
|
||||
|
||||
verify(snapshotController, times(1)).recordTaskSnapshot(eq(task2), eq(false));
|
||||
|
||||
openTransition.finishTransition();
|
||||
|
||||
// We are now going to simulate closing task1 to return back to (open) task2.
|
||||
final Transition closeTransition = controller.createTransition(TRANSIT_CLOSE);
|
||||
|
||||
closeTransition.collectExistenceChange(task1);
|
||||
closeTransition.collectExistenceChange(activity1);
|
||||
closeTransition.collectExistenceChange(task2);
|
||||
closeTransition.collectExistenceChange(activity2);
|
||||
closeTransition.setTransientLaunch(activity2);
|
||||
|
||||
activity1.mVisibleRequested = false;
|
||||
activity2.mVisibleRequested = true;
|
||||
|
||||
// Using abort to force-finish the sync (since we obviously can't wait for drawing).
|
||||
// We didn't call abort on the actual transition, so it will still run onTransactionReady
|
||||
// normally.
|
||||
mWm.mSyncEngine.abort(closeTransition.getSyncId());
|
||||
|
||||
// Make sure we haven't called recordSnapshot (since we are transient, it shouldn't be
|
||||
// called until finish).
|
||||
verify(snapshotController, times(0)).recordTaskSnapshot(eq(task1), eq(false));
|
||||
|
||||
closeTransition.finishTransition();
|
||||
|
||||
verify(snapshotController, times(1)).recordTaskSnapshot(eq(task1), eq(false));
|
||||
}
|
||||
|
||||
/** Fill the change map with all the parents of top. Change maps are usually fully populated */
|
||||
private static void fillChangeMap(ArrayMap<WindowContainer, Transition.ChangeInfo> changes,
|
||||
WindowContainer top) {
|
||||
|
||||
Reference in New Issue
Block a user