Merge "Allow finishing activity to transfer starting window" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-05-28 02:53:26 +00:00
committed by Android (Google) Code Review
5 changed files with 72 additions and 24 deletions

View File

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

View File

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

View File

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

View File

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

View File

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