Do not look for in-process activities if contains other process activities

The #findActivityBelow looks for the in-process activities first to
get the activity behind the given activity. However, it may not be
correct if the container contains activities of another process.

Bug: 271769839
Test: SplitControllerTest
Change-Id: I8794c55a56712113dc318aa4a0f440c90589378d
This commit is contained in:
Louis Chang
2023-03-06 02:37:09 +00:00
parent 1090db2ef1
commit f553c62afc
3 changed files with 41 additions and 1 deletions

View File

@@ -1000,7 +1000,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
Activity findActivityBelow(@NonNull Activity activity) {
Activity activityBelow = null;
final TaskFragmentContainer container = getContainerWithActivity(activity);
if (container != null) {
// Looking for the activity below from the information we already have if the container
// only embeds activities of the same process because activities of other processes are not
// available in this embedding host process for security concern.
if (container != null && !container.hasCrossProcessActivities()) {
final List<Activity> containerActivities = container.collectNonFinishingActivities();
final int index = containerActivities.indexOf(activity);
if (index > 0) {

View File

@@ -152,6 +152,11 @@ class TaskFragmentContainer {
@Nullable
Runnable mAppearEmptyTimeout;
/**
* Whether this TaskFragment contains activities of another process/package.
*/
private boolean mHasCrossProcessActivities;
/**
* Creates a container with an existing activity that will be re-parented to it in a window
* container transaction.
@@ -418,10 +423,18 @@ class TaskFragmentContainer {
mAppearEmptyTimeout = null;
}
mHasCrossProcessActivities = false;
mInfo = info;
if (mInfo == null || mInfo.isEmpty()) {
return;
}
// Contains activities of another process if the activities size is not matched to the
// running activity count
if (mInfo.getRunningActivityCount() != mInfo.getActivities().size()) {
mHasCrossProcessActivities = true;
}
// Only track the pending Intent when the container is empty.
mPendingAppearedIntent = null;
if (mPendingAppearedActivities.isEmpty()) {
@@ -751,6 +764,11 @@ class TaskFragmentContainer {
return mPendingAppearedInRequestedTaskFragmentActivities.contains(activityToken);
}
/** Whether contains activities of another process */
boolean hasCrossProcessActivities() {
return mHasCrossProcessActivities;
}
/** Gets the parent leaf Task id. */
int getTaskId() {
return mTaskContainer.getTaskId();

View File

@@ -1013,6 +1013,25 @@ public class SplitControllerTest {
verify(mSplitPresenter, never()).createNewSplitContainer(any(), any(), any(), any());
}
@Test
public void testFindActivityBelow() {
// Create a container with two activities
final TaskFragmentContainer container = createMockTaskFragmentContainer(mActivity);
final Activity pendingAppearedActivity = createMockActivity();
container.addPendingAppearedActivity(pendingAppearedActivity);
// Ensure the activity below matches
assertEquals(mActivity,
mSplitController.findActivityBelow(pendingAppearedActivity));
// Ensure that the activity look up won't search for the in-process activities and should
// IPC to WM core to get the activity below. It should be `null` for this mock test.
spyOn(container);
doReturn(true).when(container).hasCrossProcessActivities();
assertNotEquals(mActivity,
mSplitController.findActivityBelow(pendingAppearedActivity));
}
@Test
public void testResolveActivityToContainer_inUnknownTaskFragment() {
doReturn(new Binder()).when(mSplitController)