Merge "Allow finishing activity to transfer starting window" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
32223af7cd
@@ -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,
|
||||
@@ -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*/);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -467,28 +467,33 @@ public class ActivityStartController {
|
||||
final ActivityRecord[] outActivity = new ActivityRecord[1];
|
||||
// Lock the loop to ensure the activities launched in a sequence.
|
||||
synchronized (mService.mGlobalLock) {
|
||||
for (int i = 0; i < starters.length; i++) {
|
||||
final int startResult = starters[i].setResultTo(resultTo)
|
||||
.setOutActivity(outActivity).execute();
|
||||
if (startResult < START_SUCCESS) {
|
||||
// Abort by error result and recycle unused starters.
|
||||
for (int j = i + 1; j < starters.length; j++) {
|
||||
mFactory.recycle(starters[j]);
|
||||
mService.deferWindowLayout();
|
||||
try {
|
||||
for (int i = 0; i < starters.length; i++) {
|
||||
final int startResult = starters[i].setResultTo(resultTo)
|
||||
.setOutActivity(outActivity).execute();
|
||||
if (startResult < START_SUCCESS) {
|
||||
// Abort by error result and recycle unused starters.
|
||||
for (int j = i + 1; j < starters.length; j++) {
|
||||
mFactory.recycle(starters[j]);
|
||||
}
|
||||
return startResult;
|
||||
}
|
||||
return startResult;
|
||||
}
|
||||
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.
|
||||
resultTo = started.appToken;
|
||||
} else {
|
||||
resultTo = sourceResultTo;
|
||||
// Different apps not adjacent to the caller are forced to be new task.
|
||||
if (i < starters.length - 1) {
|
||||
starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
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.
|
||||
resultTo = started.appToken;
|
||||
} else {
|
||||
resultTo = sourceResultTo;
|
||||
// Different apps not adjacent to the caller are forced to be new task.
|
||||
if (i < starters.length - 1) {
|
||||
starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
mService.continueWindowLayout();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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 */);
|
||||
|
||||
Reference in New Issue
Block a user