Merge "Fix index out of bounds when removing deferred containers" into rvc-dev am: 8da7870ba5 am: c69836c81e
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12035041 Change-Id: Ic8d5effbb9fb4e6692bd7430894e9021c663f1b5
This commit is contained in:
@@ -3146,11 +3146,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean checkCompleteDeferredRemoval() {
|
||||
boolean handleCompleteDeferredRemoval() {
|
||||
if (mIsExiting) {
|
||||
removeIfPossible();
|
||||
}
|
||||
return super.checkCompleteDeferredRemoval();
|
||||
return super.handleCompleteDeferredRemoval();
|
||||
}
|
||||
|
||||
void onRemovedFromDisplay() {
|
||||
|
||||
@@ -86,7 +86,6 @@ import static com.android.server.wm.TaskProto.ACTIVITY_TYPE;
|
||||
import static com.android.server.wm.TaskProto.ANIMATING_BOUNDS;
|
||||
import static com.android.server.wm.TaskProto.BOUNDS;
|
||||
import static com.android.server.wm.TaskProto.CREATED_BY_ORGANIZER;
|
||||
import static com.android.server.wm.TaskProto.DEFER_REMOVAL;
|
||||
import static com.android.server.wm.TaskProto.DISPLAY_ID;
|
||||
import static com.android.server.wm.TaskProto.FILLS_PARENT;
|
||||
import static com.android.server.wm.TaskProto.LAST_NON_FULLSCREEN_BOUNDS;
|
||||
@@ -248,11 +247,6 @@ class ActivityStack extends Task {
|
||||
private Rect mTmpRect = new Rect();
|
||||
private Rect mTmpRect2 = new Rect();
|
||||
|
||||
/** Detach this stack from its display when animation completes. */
|
||||
// TODO: maybe tie this to WindowContainer#removeChild some how...
|
||||
// TODO: This is no longer set. Okay to remove or was the set removed by accident?
|
||||
private boolean mDeferRemoval;
|
||||
|
||||
// If this is true, we are in the bounds animating mode. The task will be down or upscaled to
|
||||
// perfectly fit the region it would have been cropped to. We may also avoid certain logic we
|
||||
// would otherwise apply while resizing, while resizing in the bounds animating mode.
|
||||
@@ -3232,9 +3226,6 @@ class ActivityStack extends Task {
|
||||
|
||||
@Override
|
||||
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
if (mDeferRemoval) {
|
||||
pw.println(prefix + "mDeferRemoval=true");
|
||||
}
|
||||
super.dump(pw, prefix, dumpAll);
|
||||
if (!mExitingActivities.isEmpty()) {
|
||||
pw.println();
|
||||
@@ -3304,15 +3295,12 @@ class ActivityStack extends Task {
|
||||
}
|
||||
|
||||
/** Returns true if a removal action is still being deferred. */
|
||||
boolean checkCompleteDeferredRemoval() {
|
||||
boolean handleCompleteDeferredRemoval() {
|
||||
if (isAnimating(TRANSITION | CHILDREN)) {
|
||||
return true;
|
||||
}
|
||||
if (mDeferRemoval) {
|
||||
removeImmediately();
|
||||
}
|
||||
|
||||
return super.checkCompleteDeferredRemoval();
|
||||
return super.handleCompleteDeferredRemoval();
|
||||
}
|
||||
|
||||
public DisplayInfo getDisplayInfo() {
|
||||
@@ -3380,7 +3368,6 @@ class ActivityStack extends Task {
|
||||
mLastNonFullscreenBounds.dumpDebug(proto, LAST_NON_FULLSCREEN_BOUNDS);
|
||||
}
|
||||
|
||||
proto.write(DEFER_REMOVAL, mDeferRemoval);
|
||||
proto.write(ANIMATING_BOUNDS, mBoundsAnimating);
|
||||
|
||||
if (mSurfaceControl != null) {
|
||||
|
||||
@@ -2739,6 +2739,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
@Override
|
||||
void removeImmediately() {
|
||||
mRemovingDisplay = true;
|
||||
mDeferredRemoval = false;
|
||||
try {
|
||||
if (mParentWindow != null) {
|
||||
mParentWindow.removeEmbeddedDisplayContent(this);
|
||||
@@ -2771,31 +2772,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
/** Returns true if a removal action is still being deferred. */
|
||||
@Override
|
||||
boolean checkCompleteDeferredRemoval() {
|
||||
boolean stillDeferringRemoval = false;
|
||||
|
||||
for (int i = getChildCount() - 1; i >= 0; --i) {
|
||||
final DisplayChildWindowContainer child = getChildAt(i);
|
||||
stillDeferringRemoval |= child.checkCompleteDeferredRemoval();
|
||||
if (getChildCount() == 0) {
|
||||
// If this display is pending to be removed because it contains an activity with
|
||||
// {@link ActivityRecord#mIsExiting} is true, this display may be removed when
|
||||
// completing the removal of the last activity from
|
||||
// {@link ActivityRecord#checkCompleteDeferredRemoval}.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
boolean handleCompleteDeferredRemoval() {
|
||||
final boolean stillDeferringRemoval = super.handleCompleteDeferredRemoval();
|
||||
|
||||
if (!stillDeferringRemoval && mDeferredRemoval) {
|
||||
removeImmediately();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @return 'true' if removal of this display content is deferred due to active animation. */
|
||||
boolean isRemovalDeferred() {
|
||||
return mDeferredRemoval;
|
||||
return stillDeferringRemoval;
|
||||
}
|
||||
|
||||
void adjustForImeIfNeeded() {
|
||||
|
||||
@@ -990,9 +990,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
}
|
||||
|
||||
// Remove all deferred displays stacks, tasks, and activities.
|
||||
for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
|
||||
mChildren.get(displayNdx).checkCompleteDeferredRemoval();
|
||||
}
|
||||
handleCompleteDeferredRemoval();
|
||||
|
||||
forAllDisplays(dc -> {
|
||||
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
|
||||
|
||||
@@ -1044,13 +1044,25 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
return mChildren.peekLast();
|
||||
}
|
||||
|
||||
/** Returns true if there is still a removal being deferred */
|
||||
boolean checkCompleteDeferredRemoval() {
|
||||
/**
|
||||
* Removes the containers which were deferred.
|
||||
*
|
||||
* @return {@code true} if there is still a removal being deferred.
|
||||
*/
|
||||
boolean handleCompleteDeferredRemoval() {
|
||||
boolean stillDeferringRemoval = false;
|
||||
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = mChildren.get(i);
|
||||
stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
|
||||
stillDeferringRemoval |= wc.handleCompleteDeferredRemoval();
|
||||
if (!hasChild()) {
|
||||
// All child containers of current level could be removed from a removal of
|
||||
// descendant. E.g. if a display is pending to be removed because it contains an
|
||||
// activity with {@link ActivityRecord#mIsExiting} is true, the display may be
|
||||
// removed when completing the removal of the last activity from
|
||||
// {@link ActivityRecord#checkCompleteDeferredRemoval}.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return stillDeferringRemoval;
|
||||
|
||||
@@ -27,6 +27,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||
@@ -824,6 +825,31 @@ public class WindowContainerTests extends WindowTestsBase {
|
||||
assertEquals(newDc, activity.mDisplayContent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCompleteDeferredRemoval() {
|
||||
final DisplayContent displayContent = createNewDisplay();
|
||||
// Do not reparent activity to default display when removing the display.
|
||||
doReturn(true).when(displayContent).shouldDestroyContentOnRemove();
|
||||
final ActivityRecord r = new ActivityTestsBase.StackBuilder(mWm.mRoot)
|
||||
.setDisplay(displayContent).build().getTopMostActivity();
|
||||
// Add a window and make the activity animating so the removal of activity is deferred.
|
||||
createWindow(null, TYPE_BASE_APPLICATION, r, "win");
|
||||
doReturn(true).when(r).isAnimating(anyInt(), anyInt());
|
||||
|
||||
displayContent.remove();
|
||||
// Ensure that ActivityRecord#onRemovedFromDisplay is called.
|
||||
r.destroyed("test");
|
||||
// The removal is deferred, so the activity is still in the display.
|
||||
assertEquals(r, displayContent.getTopMostActivity());
|
||||
|
||||
// Assume the animation is done so the deferred removal can continue.
|
||||
doReturn(false).when(r).isAnimating(anyInt(), anyInt());
|
||||
|
||||
assertFalse(displayContent.handleCompleteDeferredRemoval());
|
||||
assertFalse(displayContent.hasChild());
|
||||
assertFalse(r.hasChild());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTaskCanApplyAnimation() {
|
||||
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
||||
|
||||
Reference in New Issue
Block a user