Loading services/core/java/com/android/server/wm/ActivityRecord.java +3 −2 Original line number Diff line number Diff line Loading @@ -3366,8 +3366,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing starting %s from %s", tStartingWindow, fromActivity); fromActivity.removeChild(tStartingWindow); fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow); fromActivity.mVisibleSetFromTransferredStartingWindow = false; addWindow(tStartingWindow); // Propagate other interesting state between the tokens. If the old token is displayed, Loading @@ -3394,6 +3392,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // we've transferred the animation. mUseTransferredAnimation = true; } // Post cleanup after the visibility and animation are transferred. fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow); fromActivity.mVisibleSetFromTransferredStartingWindow = false; mWmService.updateFocusedWindowLocked( UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/); Loading services/core/java/com/android/server/wm/ActivityStack.java +1 −1 Original line number Diff line number Diff line Loading @@ -2128,7 +2128,7 @@ class ActivityStack extends Task { // window manager to keep the previous window it had previously // created, if it still had one. Task prevTask = r.getTask(); ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked(); 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. Loading services/core/java/com/android/server/wm/ActivityStartController.java +24 −19 Original line number Diff line number Diff line Loading @@ -467,6 +467,8 @@ public class ActivityStartController { final ActivityRecord[] outActivity = new ActivityRecord[1]; // Lock the loop to ensure the activities launched in a sequence. synchronized (mService.mGlobalLock) { mService.deferWindowLayout(); try { for (int i = 0; i < starters.length; i++) { final int startResult = starters[i].setResultTo(resultTo) .setOutActivity(outActivity).execute(); Loading @@ -479,8 +481,8 @@ public class ActivityStartController { } final ActivityRecord started = outActivity[0]; if (started != null && started.getUid() == filterCallingUid) { // Only the started activity which has the same uid as the source caller can // be the caller of next activity. // Only the started activity which has the same uid as the source caller // can be the caller of next activity. resultTo = started.appToken; } else { resultTo = sourceResultTo; Loading @@ -490,6 +492,9 @@ public class ActivityStartController { } } } } finally { mService.continueWindowLayout(); } } } finally { Binder.restoreCallingIdentity(origId); Loading services/core/java/com/android/server/wm/Task.java +2 −2 Original line number Diff line number Diff line Loading @@ -1309,12 +1309,12 @@ class Task extends WindowContainer<WindowContainer> { return isUidPresent; } ActivityRecord topRunningActivityWithStartingWindowLocked() { ActivityRecord topActivityWithStartingWindow() { if (getParent() == null) { return null; } return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN && r.canBeTopRunning()); && r.okToShowLocked()); } /** Loading services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +42 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; Loading @@ -47,6 +48,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; Loading Loading @@ -390,6 +392,46 @@ public class AppWindowTokenTests extends WindowTestsBase { onAnimationFinishedCallback)); } @Test public void testTransferStartingWindowFromFinishingActivity() { mActivity.addStartingWindow(mPackageName, android.R.style.Theme, null /* compatInfo */, "Test", 0 /* labelRes */, 0 /* icon */, 0 /* logo */, 0 /* windowFlags */, null /* transferFrom */, true /* newTask */, true /* taskSwitch */, false /* processRunning */, false /* allowTaskSnapshot */, false /* activityCreate */); waitUntilHandlersIdle(); assertHasStartingWindow(mActivity); mActivity.mStartingWindowState = ActivityRecord.STARTING_WINDOW_SHOWN; doCallRealMethod().when(mStack).startActivityLocked( any(), any(), anyBoolean(), anyBoolean(), any()); // Make mVisibleSetFromTransferredStartingWindow true. final ActivityRecord middle = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService) .setTask(mTask).build(); mStack.startActivityLocked(middle, null /* focusedTopActivity */, false /* newTask */, false /* keepCurTransition */, null /* options */); middle.makeFinishingLocked(); assertNull(mActivity.startingWindow); assertHasStartingWindow(middle); final ActivityRecord top = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService) .setTask(mTask).build(); // Expect the visibility should be updated to true when transferring starting window from // a visible activity. top.setVisible(false); // The finishing middle should be able to transfer starting window to top. mStack.startActivityLocked(top, null /* focusedTopActivity */, false /* newTask */, false /* keepCurTransition */, null /* options */); assertNull(middle.startingWindow); assertHasStartingWindow(top); assertTrue(top.isVisible()); // The activity was visible by mVisibleSetFromTransferredStartingWindow, so after its // starting window is transferred, it should restore to invisible. assertFalse(middle.isVisible()); } private ActivityRecord createIsolatedTestActivityRecord() { final ActivityStack taskStack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(taskStack, 0 /* userId */); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +3 −2 Original line number Diff line number Diff line Loading @@ -3366,8 +3366,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing starting %s from %s", tStartingWindow, fromActivity); fromActivity.removeChild(tStartingWindow); fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow); fromActivity.mVisibleSetFromTransferredStartingWindow = false; addWindow(tStartingWindow); // Propagate other interesting state between the tokens. If the old token is displayed, Loading @@ -3394,6 +3392,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // we've transferred the animation. mUseTransferredAnimation = true; } // Post cleanup after the visibility and animation are transferred. fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow); fromActivity.mVisibleSetFromTransferredStartingWindow = false; mWmService.updateFocusedWindowLocked( UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/); Loading
services/core/java/com/android/server/wm/ActivityStack.java +1 −1 Original line number Diff line number Diff line Loading @@ -2128,7 +2128,7 @@ class ActivityStack extends Task { // window manager to keep the previous window it had previously // created, if it still had one. Task prevTask = r.getTask(); ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked(); 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. Loading
services/core/java/com/android/server/wm/ActivityStartController.java +24 −19 Original line number Diff line number Diff line Loading @@ -467,6 +467,8 @@ public class ActivityStartController { final ActivityRecord[] outActivity = new ActivityRecord[1]; // Lock the loop to ensure the activities launched in a sequence. synchronized (mService.mGlobalLock) { mService.deferWindowLayout(); try { for (int i = 0; i < starters.length; i++) { final int startResult = starters[i].setResultTo(resultTo) .setOutActivity(outActivity).execute(); Loading @@ -479,8 +481,8 @@ public class ActivityStartController { } final ActivityRecord started = outActivity[0]; if (started != null && started.getUid() == filterCallingUid) { // Only the started activity which has the same uid as the source caller can // be the caller of next activity. // Only the started activity which has the same uid as the source caller // can be the caller of next activity. resultTo = started.appToken; } else { resultTo = sourceResultTo; Loading @@ -490,6 +492,9 @@ public class ActivityStartController { } } } } finally { mService.continueWindowLayout(); } } } finally { Binder.restoreCallingIdentity(origId); Loading
services/core/java/com/android/server/wm/Task.java +2 −2 Original line number Diff line number Diff line Loading @@ -1309,12 +1309,12 @@ class Task extends WindowContainer<WindowContainer> { return isUidPresent; } ActivityRecord topRunningActivityWithStartingWindowLocked() { ActivityRecord topActivityWithStartingWindow() { if (getParent() == null) { return null; } return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN && r.canBeTopRunning()); && r.okToShowLocked()); } /** Loading
services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +42 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; Loading @@ -47,6 +48,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; Loading Loading @@ -390,6 +392,46 @@ public class AppWindowTokenTests extends WindowTestsBase { onAnimationFinishedCallback)); } @Test public void testTransferStartingWindowFromFinishingActivity() { mActivity.addStartingWindow(mPackageName, android.R.style.Theme, null /* compatInfo */, "Test", 0 /* labelRes */, 0 /* icon */, 0 /* logo */, 0 /* windowFlags */, null /* transferFrom */, true /* newTask */, true /* taskSwitch */, false /* processRunning */, false /* allowTaskSnapshot */, false /* activityCreate */); waitUntilHandlersIdle(); assertHasStartingWindow(mActivity); mActivity.mStartingWindowState = ActivityRecord.STARTING_WINDOW_SHOWN; doCallRealMethod().when(mStack).startActivityLocked( any(), any(), anyBoolean(), anyBoolean(), any()); // Make mVisibleSetFromTransferredStartingWindow true. final ActivityRecord middle = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService) .setTask(mTask).build(); mStack.startActivityLocked(middle, null /* focusedTopActivity */, false /* newTask */, false /* keepCurTransition */, null /* options */); middle.makeFinishingLocked(); assertNull(mActivity.startingWindow); assertHasStartingWindow(middle); final ActivityRecord top = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService) .setTask(mTask).build(); // Expect the visibility should be updated to true when transferring starting window from // a visible activity. top.setVisible(false); // The finishing middle should be able to transfer starting window to top. mStack.startActivityLocked(top, null /* focusedTopActivity */, false /* newTask */, false /* keepCurTransition */, null /* options */); assertNull(middle.startingWindow); assertHasStartingWindow(top); assertTrue(top.isVisible()); // The activity was visible by mVisibleSetFromTransferredStartingWindow, so after its // starting window is transferred, it should restore to invisible. assertFalse(middle.isVisible()); } private ActivityRecord createIsolatedTestActivityRecord() { final ActivityStack taskStack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(taskStack, 0 /* userId */); Loading