Merge changes from topic "remove-intermediate-callbacks" into sc-v2-dev

* changes:
  Adds Test that verifies an Activity is Still Reported...
  Do not send split info update when TaskFragmentContainer
  Include Activities That Have Not Been Assigned...
  Update toString methods for various Embedding...
This commit is contained in:
TreeHugger Robot
2021-11-10 03:18:50 +00:00
committed by Android (Google) Code Review
9 changed files with 110 additions and 24 deletions

View File

@@ -213,6 +213,7 @@ public final class TaskFragmentInfo implements Parcelable {
+ " isEmpty=" + mIsEmpty
+ " runningActivityCount=" + mRunningActivityCount
+ " isVisible=" + mIsVisible
+ " activities=" + mActivities
+ " positionInParent=" + mPositionInParent
+ " isTaskClearedForReuse=" + mIsTaskClearedForReuse
+ "}";

View File

@@ -83,4 +83,13 @@ class SplitContainer {
&& ((SplitPairRule) splitRule).shouldFinishSecondaryWithPrimary();
return shouldFinishSecondaryWithPrimary || isPlaceholderContainer;
}
@Override
public String toString() {
return "SplitContainer{"
+ " primaryContainer=" + mPrimaryContainer
+ " secondaryContainer=" + mSecondaryContainer
+ " splitRule=" + mSplitRule
+ "}";
}
}

View File

@@ -497,7 +497,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return;
}
List<SplitInfo> currentSplitStates = getActiveSplitStates();
if (mLastReportedSplitStates.equals(currentSplitStates)) {
if (currentSplitStates == null || mLastReportedSplitStates.equals(currentSplitStates)) {
return;
}
mLastReportedSplitStates.clear();
@@ -506,15 +506,19 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
/**
* Returns a list of descriptors for currently active split states.
* @return a list of descriptors for currently active split states. If the value returned is
* null, that indicates that the active split states are in an intermediate state and should
* not be reported.
*/
@Nullable
private List<SplitInfo> getActiveSplitStates() {
List<SplitInfo> splitStates = new ArrayList<>();
for (SplitContainer container : mSplitContainers) {
if (container.getPrimaryContainer().isEmpty()
|| container.getSecondaryContainer().isEmpty()) {
// Skipping containers that do not have any activities to report.
continue;
// We are in an intermediate state because either the split container is about to be
// removed or the primary or secondary container are about to receive an activity.
return null;
}
ActivityStack primaryContainer = container.getPrimaryContainer().toActivityStack();
ActivityStack secondaryContainer = container.getSecondaryContainer().toActivityStack();

View File

@@ -27,6 +27,7 @@ import android.window.TaskFragmentInfo;
import android.window.WindowContainerTransaction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
@@ -267,4 +268,42 @@ class TaskFragmentContainer {
mLastRequestedBounds.set(bounds);
}
}
@Override
public String toString() {
return toString(true /* includeContainersToFinishOnExit */);
}
/**
* @return string for this TaskFragmentContainer and includes containers to finish on exit
* based on {@code includeContainersToFinishOnExit}. If containers to finish on exit are always
* included in the string, then calling {@link #toString()} on a container that mutually
* finishes with another container would cause a stack overflow.
*/
private String toString(boolean includeContainersToFinishOnExit) {
return "TaskFragmentContainer{"
+ " token=" + mToken
+ " info=" + mInfo
+ " topNonFinishingActivity=" + getTopNonFinishingActivity()
+ " pendingAppearedActivities=" + mPendingAppearedActivities
+ (includeContainersToFinishOnExit ? " containersToFinishOnExit="
+ containersToFinishOnExitToString() : "")
+ " activitiesToFinishOnExit=" + mActivitiesToFinishOnExit
+ " isFinished=" + mIsFinished
+ " lastRequestedBounds=" + mLastRequestedBounds
+ "}";
}
private String containersToFinishOnExitToString() {
StringBuilder sb = new StringBuilder("[");
Iterator<TaskFragmentContainer> containerIterator = mContainersToFinishOnExit.iterator();
while (containerIterator.hasNext()) {
sb.append(containerIterator.next().toString(
false /* includeContainersToFinishOnExit */));
if (containerIterator.hasNext()) {
sb.append(", ");
}
}
return sb.append("]").toString();
}
}

View File

@@ -31,6 +31,7 @@ import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.os.Process.INVALID_UID;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -221,6 +222,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
/** Organizer that organizing this TaskFragment. */
@Nullable
private ITaskFragmentOrganizer mTaskFragmentOrganizer;
private int mTaskFragmentOrganizerUid = INVALID_UID;
private @Nullable String mTaskFragmentOrganizerProcessName;
/** Client assigned unique token for this TaskFragment if this is created by an organizer. */
@Nullable
@@ -233,13 +236,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
*/
private boolean mDelayLastActivityRemoval;
/**
* The PID of the organizer that created this TaskFragment. It should be the same as the PID
* of {@link android.window.TaskFragmentCreationParams#getOwnerToken()}.
* {@link ActivityRecord#INVALID_PID} if this is not an organizer-created TaskFragment.
*/
private int mTaskFragmentOrganizerPid = ActivityRecord.INVALID_PID;
final Point mLastSurfaceSize = new Point();
private final Rect mTmpInsets = new Rect();
@@ -338,9 +334,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
mDelayLastActivityRemoval = false;
}
void setTaskFragmentOrganizer(TaskFragmentOrganizerToken organizer, int pid) {
void setTaskFragmentOrganizer(@NonNull TaskFragmentOrganizerToken organizer, int uid,
@NonNull String processName) {
mTaskFragmentOrganizer = ITaskFragmentOrganizer.Stub.asInterface(organizer.asBinder());
mTaskFragmentOrganizerPid = pid;
mTaskFragmentOrganizerUid = uid;
mTaskFragmentOrganizerProcessName = processName;
}
/** Whether this TaskFragment is organized by the given {@code organizer}. */
@@ -2180,9 +2178,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
List<IBinder> childActivities = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
WindowContainer wc = getChildAt(i);
if (mTaskFragmentOrganizerPid != ActivityRecord.INVALID_PID
if (mTaskFragmentOrganizerUid != INVALID_UID
&& wc.asActivityRecord() != null
&& wc.asActivityRecord().getPid() == mTaskFragmentOrganizerPid) {
&& wc.asActivityRecord().info.processName.equals(
mTaskFragmentOrganizerProcessName)
&& wc.asActivityRecord().getUid() == mTaskFragmentOrganizerUid) {
// Only includes Activities that belong to the organizer process for security.
childActivities.add(wc.asActivityRecord().appToken);
}

View File

@@ -1205,8 +1205,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
creationParams.getFragmentToken(), true /* createdByOrganizer */);
// Set task fragment organizer immediately, since it might have to be notified about further
// actions.
taskFragment.setTaskFragmentOrganizer(
creationParams.getOrganizer(), ownerActivity.getPid());
taskFragment.setTaskFragmentOrganizer(creationParams.getOrganizer(),
ownerActivity.getUid(), ownerActivity.info.processName);
ownerActivity.getTask().addChild(taskFragment, POSITION_TOP);
taskFragment.setWindowingMode(creationParams.getWindowingMode());
taskFragment.setBounds(creationParams.getInitialBounds());

View File

@@ -254,7 +254,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
});
// Allow transaction to change a TaskFragment created by the organizer.
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */);
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
}
@@ -276,7 +277,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
});
// Allow transaction to change a TaskFragment created by the organizer.
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */);
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
}
@@ -301,7 +303,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
});
// Allow transaction to change a TaskFragment created by the organizer.
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */);
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
clearInvocations(mAtm.mRootWindowContainer);
mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
@@ -337,8 +340,10 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
});
// Allow transaction to change a TaskFragment created by the organizer.
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */);
taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */);
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
clearInvocations(mAtm.mRootWindowContainer);
mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
@@ -391,7 +396,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
});
// Allow transaction to change a TaskFragment created by the organizer.
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */);
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
clearInvocations(mAtm.mRootWindowContainer);
mAtm.getWindowOrganizerController().applyTransaction(mTransaction);

View File

@@ -20,12 +20,15 @@ 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.verify;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.clearInvocations;
import android.graphics.Rect;
import android.os.Binder;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
import android.window.ITaskFragmentOrganizer;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentOrganizer;
import androidx.test.filters.MediumTest;
@@ -64,6 +67,7 @@ public class TaskFragmentTest extends WindowTestsBase {
mTaskFragment = new TaskFragmentBuilder(mAtm)
.setCreateParentTask()
.setOrganizer(mOrganizer)
.setFragmentToken(new Binder())
.build();
mLeash = mTaskFragment.getSurfaceControl();
spyOn(mTaskFragment);
@@ -103,4 +107,23 @@ public class TaskFragmentTest extends WindowTestsBase {
verify(mTransaction).setPosition(mLeash, 500, 500);
verify(mTransaction).setWindowCrop(mLeash, 500, 500);
}
/**
* Tests that when a {@link TaskFragmentInfo} is generated from a {@link TaskFragment}, an
* activity that has not yet been attached to a process because it is being initialized but
* belongs to the TaskFragmentOrganizer process is still reported in the TaskFragmentInfo.
*/
@Test
public void testActivityStillReported_NotYetAssignedToProcess() {
mTaskFragment.addChild(new ActivityBuilder(mAtm).setUid(DEFAULT_TASK_FRAGMENT_ORGANIZER_UID)
.setProcessName(DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME).build());
final ActivityRecord activity = mTaskFragment.getTopMostActivity();
// Remove the process to simulate an activity that has not yet been attached to a process
activity.app = null;
final TaskFragmentInfo info = activity.getTaskFragment().getTaskFragmentInfo();
assertEquals(1, info.getRunningActivityCount());
assertEquals(1, info.getActivities().size());
assertEquals(false, info.isEmpty());
assertEquals(activity.token, info.getActivities().get(0));
}
}

View File

@@ -128,6 +128,9 @@ class WindowTestsBase extends SystemServiceTestsBase {
// Default package name
static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo";
static final int DEFAULT_TASK_FRAGMENT_ORGANIZER_UID = 10000;
static final String DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME = "Test:TaskFragmentOrganizer";
// Default base activity name
private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity";
@@ -1243,7 +1246,8 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
if (mOrganizer != null) {
taskFragment.setTaskFragmentOrganizer(
mOrganizer.getOrganizerToken(), 10000 /* pid */);
mOrganizer.getOrganizerToken(), DEFAULT_TASK_FRAGMENT_ORGANIZER_UID,
DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
}
return taskFragment;
}