Merge "Fixes app crash when starts activity with FLAG_ACTIVITY_REORDER_TO_FRONT" into tm-qpr-dev

This commit is contained in:
Louis Chang
2022-11-17 02:56:54 +00:00
committed by Android (Google) Code Review
9 changed files with 84 additions and 24 deletions

View File

@@ -82,6 +82,12 @@ public final class TaskFragmentInfo implements Parcelable {
*/
private final boolean mIsTaskFragmentClearedForPip;
/**
* Whether the last running activity of the TaskFragment was removed because it was reordered to
* front of the Task.
*/
private final boolean mIsClearedForReorderActivityToFront;
/**
* The maximum {@link ActivityInfo.WindowLayout#minWidth} and
* {@link ActivityInfo.WindowLayout#minHeight} aggregated from the TaskFragment's child
@@ -96,7 +102,7 @@ public final class TaskFragmentInfo implements Parcelable {
@NonNull Configuration configuration, int runningActivityCount,
boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip,
@NonNull Point minimumDimensions) {
boolean isClearedForReorderActivityToFront, @NonNull Point minimumDimensions) {
mFragmentToken = requireNonNull(fragmentToken);
mToken = requireNonNull(token);
mConfiguration.setTo(configuration);
@@ -106,6 +112,7 @@ public final class TaskFragmentInfo implements Parcelable {
mPositionInParent.set(positionInParent);
mIsTaskClearedForReuse = isTaskClearedForReuse;
mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
mIsClearedForReorderActivityToFront = isClearedForReorderActivityToFront;
mMinimumDimensions.set(minimumDimensions);
}
@@ -160,6 +167,11 @@ public final class TaskFragmentInfo implements Parcelable {
return mIsTaskFragmentClearedForPip;
}
/** @hide */
public boolean isClearedForReorderActivityToFront() {
return mIsClearedForReorderActivityToFront;
}
@WindowingMode
public int getWindowingMode() {
return mConfiguration.windowConfiguration.getWindowingMode();
@@ -207,6 +219,7 @@ public final class TaskFragmentInfo implements Parcelable {
&& mPositionInParent.equals(that.mPositionInParent)
&& mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
&& mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
&& mIsClearedForReorderActivityToFront == that.mIsClearedForReorderActivityToFront
&& mMinimumDimensions.equals(that.mMinimumDimensions);
}
@@ -220,6 +233,7 @@ public final class TaskFragmentInfo implements Parcelable {
mPositionInParent.readFromParcel(in);
mIsTaskClearedForReuse = in.readBoolean();
mIsTaskFragmentClearedForPip = in.readBoolean();
mIsClearedForReorderActivityToFront = in.readBoolean();
mMinimumDimensions.readFromParcel(in);
}
@@ -235,6 +249,7 @@ public final class TaskFragmentInfo implements Parcelable {
mPositionInParent.writeToParcel(dest, flags);
dest.writeBoolean(mIsTaskClearedForReuse);
dest.writeBoolean(mIsTaskFragmentClearedForPip);
dest.writeBoolean(mIsClearedForReorderActivityToFront);
mMinimumDimensions.writeToParcel(dest, flags);
}
@@ -262,8 +277,9 @@ public final class TaskFragmentInfo implements Parcelable {
+ " activities=" + mActivities
+ " positionInParent=" + mPositionInParent
+ " isTaskClearedForReuse=" + mIsTaskClearedForReuse
+ " isTaskFragmentClearedForPip" + mIsTaskFragmentClearedForPip
+ " minimumDimensions" + mMinimumDimensions
+ " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip
+ " mIsClearedForReorderActivityToFront=" + mIsClearedForReorderActivityToFront
+ " minimumDimensions=" + mMinimumDimensions
+ "}";
}

View File

@@ -389,6 +389,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// launching activity in the Task.
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else if (taskFragmentInfo.isClearedForReorderActivityToFront()) {
// Do not finish the dependents if this TaskFragment was cleared to reorder
// the launching Activity to front of the Task.
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else if (!container.isWaitingActivityAppear()) {
// Do not finish the container before the expected activity appear until
// timeout.

View File

@@ -169,6 +169,7 @@ public class EmbeddingTestUtils {
new Point(),
false /* isTaskClearedForReuse */,
false /* isTaskFragmentClearedForPip */,
false /* isClearedForReorderActivityToFront */,
new Point());
}

View File

@@ -144,6 +144,6 @@ public class JetpackTaskFragmentOrganizerTest {
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
false /* isVisible */, new ArrayList<>(), new Point(),
false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
new Point());
false /* isClearedForReorderActivityToFront */, new Point());
}
}

View File

@@ -2394,7 +2394,7 @@ class ActivityStarter {
mStartActivity.mUserId);
if (act != null) {
final Task task = act.getTask();
boolean actuallyMoved = task.moveActivityToFrontLocked(act);
boolean actuallyMoved = task.moveActivityToFront(act);
if (actuallyMoved) {
// Only record if the activity actually moved.
mMovedToTopActivity = act;

View File

@@ -1408,13 +1408,26 @@ class Task extends TaskFragment {
* Reorder the history task so that the passed activity is brought to the front.
* @return whether it was actually moved (vs already being top).
*/
final boolean moveActivityToFrontLocked(ActivityRecord newTop) {
final boolean moveActivityToFront(ActivityRecord newTop) {
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Removing and adding activity %s to root task at top "
+ "callers=%s", newTop, Debug.getCallers(4));
int origDist = getDistanceFromTop(newTop);
positionChildAtTop(newTop);
final TaskFragment taskFragment = newTop.getTaskFragment();
boolean moved;
if (taskFragment != this) {
if (taskFragment.isEmbedded() && taskFragment.getNonFinishingActivityCount() == 1) {
taskFragment.mClearedForReorderActivityToFront = true;
}
newTop.reparent(this, POSITION_TOP);
moved = true;
if (taskFragment.isEmbedded()) {
mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController
.onActivityReparentedToTask(newTop);
}
} else {
moved = moveChildToFront(newTop);
}
updateEffectiveIntent();
return getDistanceFromTop(newTop) != origDist;
return moved;
}
@Override
@@ -3096,20 +3109,6 @@ class Task extends TaskFragment {
});
}
void positionChildAtTop(ActivityRecord child) {
positionChildAt(child, POSITION_TOP);
}
void positionChildAt(ActivityRecord child, int position) {
if (child == null) {
Slog.w(TAG_WM,
"Attempted to position of non-existing app");
return;
}
positionChildAt(position, child, false /* includeParents */);
}
void setTaskDescription(TaskDescription taskDescription) {
mTaskDescription = taskDescription;
}

View File

@@ -246,6 +246,12 @@ class TaskFragment extends WindowContainer<WindowContainer> {
*/
boolean mClearedTaskFragmentForPip;
/**
* The last running activity of the TaskFragment was removed and added to the top-most of the
* Task because it was launched with FLAG_ACTIVITY_REORDER_TO_FRONT.
*/
boolean mClearedForReorderActivityToFront;
/**
* When we are in the process of pausing an activity, before starting the
* next one, this variable holds the activity that is currently being paused.
@@ -1866,6 +1872,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
ActivityRecord r = topRunningActivity();
mClearedTaskForReuse = false;
mClearedTaskFragmentForPip = false;
mClearedForReorderActivityToFront = false;
final ActivityRecord addingActivity = child.asActivityRecord();
final boolean isAddingActivity = addingActivity != null;
@@ -2465,6 +2472,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
positionInParent,
mClearedTaskForReuse,
mClearedTaskFragmentForPip,
mClearedForReorderActivityToFront,
calculateMinDimension());
}
@@ -2743,6 +2751,16 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return callback.test(this) ? this : null;
}
/**
* Moves the passed child to front
* @return whether it was actually moved (vs already being top).
*/
boolean moveChildToFront(WindowContainer newTop) {
int origDist = getDistanceFromTop(newTop);
positionChildAt(POSITION_TOP, newTop, false /* includeParents */);
return getDistanceFromTop(newTop) != origDist;
}
String toFullString() {
final StringBuilder sb = new StringBuilder(128);
sb.append(this);

View File

@@ -2809,7 +2809,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final Task task = activity.getTask();
final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
topActivity.setVisible(false);
task.positionChildAt(topActivity, POSITION_TOP);
task.positionChildAt(POSITION_TOP, topActivity, false /* includeParents */);
activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
true, false, false, false);
waitUntilHandlersIdle();

View File

@@ -36,6 +36,7 @@ import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_90;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
@@ -82,6 +83,7 @@ import android.util.TypedXmlSerializer;
import android.util.Xml;
import android.view.Display;
import android.view.DisplayInfo;
import android.window.TaskFragmentOrganizer;
import androidx.test.filters.MediumTest;
@@ -1469,6 +1471,26 @@ public class TaskTests extends WindowTestsBase {
tf0, parentTask.getTaskFragment(TaskFragment::isOrganizedTaskFragment));
}
@Test
public void testReorderActivityToFront() {
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
doNothing().when(task).onActivityVisibleRequestedChanged();
final ActivityRecord activity = task.getTopMostActivity();
final TaskFragment fragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
final ActivityRecord embeddedActivity = fragment.getTopMostActivity();
task.moveActivityToFront(activity);
assertEquals("Activity must be moved to front", activity, task.getTopMostActivity());
doNothing().when(fragment).sendTaskFragmentInfoChanged();
task.moveActivityToFront(embeddedActivity);
assertEquals("Activity must be moved to front", embeddedActivity,
task.getTopMostActivity());
assertEquals("Activity must not be embedded", embeddedActivity,
task.getTopChild());
}
private Task getTestTask() {
final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
return task.getBottomMostTask();