Merge "Fixes app crash when starts activity with FLAG_ACTIVITY_REORDER_TO_FRONT" into tm-qpr-dev am: d0767e2bc2 am: 3d4d9d8876
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20310351 Change-Id: I178f472772bf5318300bacdc4c5292580feafac5 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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
|
||||
+ "}";
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -169,6 +169,7 @@ public class EmbeddingTestUtils {
|
||||
new Point(),
|
||||
false /* isTaskClearedForReuse */,
|
||||
false /* isTaskFragmentClearedForPip */,
|
||||
false /* isClearedForReorderActivityToFront */,
|
||||
new Point());
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2136,7 +2136,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;
|
||||
|
||||
@@ -1401,13 +1401,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
|
||||
@@ -3075,20 +3088,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;
|
||||
}
|
||||
|
||||
@@ -248,6 +248,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.
|
||||
@@ -1868,6 +1874,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;
|
||||
@@ -2456,6 +2463,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
positionInParent,
|
||||
mClearedTaskForReuse,
|
||||
mClearedTaskFragmentForPip,
|
||||
mClearedForReorderActivityToFront,
|
||||
calculateMinDimension());
|
||||
}
|
||||
|
||||
@@ -2742,6 +2750,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);
|
||||
|
||||
@@ -2806,7 +2806,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();
|
||||
|
||||
@@ -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;
|
||||
@@ -80,6 +81,7 @@ import android.util.DisplayMetrics;
|
||||
import android.util.Xml;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.window.TaskFragmentOrganizer;
|
||||
|
||||
import androidx.test.filters.MediumTest;
|
||||
|
||||
@@ -1489,6 +1491,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();
|
||||
|
||||
Reference in New Issue
Block a user