Merge "Keep visible process state if process embeds visible activity" into udc-dev

This commit is contained in:
Riddle Hsu
2023-03-20 08:43:19 +00:00
committed by Android (Google) Code Review
3 changed files with 127 additions and 12 deletions

View File

@@ -458,6 +458,22 @@ class TaskFragment extends WindowContainer<WindowContainer> {
&& organizer.asBinder().equals(mTaskFragmentOrganizer.asBinder());
}
/**
* Returns the process of organizer if this TaskFragment is organized and the activity lives in
* a different process than the organizer.
*/
@Nullable
private WindowProcessController getOrganizerProcessIfDifferent(@Nullable ActivityRecord r) {
if ((r == null || mTaskFragmentOrganizerProcessName == null)
|| (mTaskFragmentOrganizerProcessName.equals(r.processName)
&& mTaskFragmentOrganizerUid == r.getUid())) {
// No organizer or the process is the same.
return null;
}
return mAtmService.getProcessController(mTaskFragmentOrganizerProcessName,
mTaskFragmentOrganizerUid);
}
void setAnimationParams(@NonNull TaskFragmentAnimationParams animationParams) {
mAnimationParams = animationParams;
}
@@ -815,6 +831,16 @@ class TaskFragment extends WindowContainer<WindowContainer> {
setResumedActivity(record, reason + " - onActivityStateChanged");
mTaskSupervisor.mRecentTasks.add(record.getTask());
}
// Update the process state for the organizer process if the activity is in a different
// process in case the organizer process may not have activity state change in its process.
final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(record);
if (hostProcess != null) {
mTaskSupervisor.onProcessActivityStateChanged(hostProcess, false /* forceBatch */);
hostProcess.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, true /* updateOomAdj */,
false /* addPendingTopUid */);
}
}
/**
@@ -1942,6 +1968,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
addingActivity.inHistory = true;
task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
}
final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(addingActivity);
if (hostProcess != null) {
hostProcess.addEmbeddedActivity(addingActivity);
}
}
@Override
@@ -2757,14 +2788,18 @@ class TaskFragment extends WindowContainer<WindowContainer> {
void removeChild(WindowContainer child, boolean removeSelfIfPossible) {
super.removeChild(child);
final ActivityRecord r = child.asActivityRecord();
if (BackNavigationController.isScreenshotEnabled()) {
//TODO(b/207481538) Remove once the infrastructure to support per-activity screenshot is
// implemented
ActivityRecord r = child.asActivityRecord();
if (r != null) {
mBackScreenshots.remove(r.mActivityComponent.flattenToString());
}
}
final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(r);
if (hostProcess != null) {
hostProcess.removeEmbeddedActivity(r);
}
if (removeSelfIfPossible && shouldRemoveSelfOnLastChildRemoval() && !hasChild()) {
removeImmediately("removeLastChild " + child);
}

View File

@@ -69,6 +69,7 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -228,8 +229,17 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
* in another process. This is used to check if the process is currently showing anything
* visible to the user.
*/
private static final int REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY = 1;
/** The activity in a different process is embedded in a task created by this process. */
private static final int REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY = 1 << 1;
/**
* Activities that run on different processes while this process shows something in these
* activities or the appearance of the activities are controlled by this process. The value of
* map is an array of size 1 to store the kinds of remote.
*/
@Nullable
private final ArrayList<ActivityRecord> mHostActivities = new ArrayList<>();
private ArrayMap<ActivityRecord, int[]> mRemoteActivities;
/** Whether our process is currently running a {@link RecentsAnimation} */
private boolean mRunningRecentsAnimation;
@@ -857,7 +867,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return true;
}
}
if (isEmbedded()) {
if (hasEmbeddedWindow()) {
return true;
}
}
@@ -868,9 +878,13 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
* @return {@code true} if this process is rendering content on to a window shown by
* another process.
*/
private boolean isEmbedded() {
for (int i = mHostActivities.size() - 1; i >= 0; --i) {
final ActivityRecord r = mHostActivities.get(i);
private boolean hasEmbeddedWindow() {
if (mRemoteActivities == null) return false;
for (int i = mRemoteActivities.size() - 1; i >= 0; --i) {
if ((mRemoteActivities.valueAt(i)[0] & REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY) == 0) {
continue;
}
final ActivityRecord r = mRemoteActivities.keyAt(i);
if (r.isInterestingToUserLocked()) {
return true;
}
@@ -1038,15 +1052,46 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
/** Adds an activity that hosts UI drawn by the current process. */
void addHostActivity(ActivityRecord r) {
if (mHostActivities.contains(r)) {
return;
}
mHostActivities.add(r);
final int[] flags = getRemoteActivityFlags(r);
flags[0] |= REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY;
}
/** Removes an activity that hosts UI drawn by the current process. */
void removeHostActivity(ActivityRecord r) {
mHostActivities.remove(r);
removeRemoteActivityFlags(r, REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY);
}
/** Adds an embedded activity in a different process to this process that organizes it. */
void addEmbeddedActivity(ActivityRecord r) {
final int[] flags = getRemoteActivityFlags(r);
flags[0] |= REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY;
}
/** Removes an embedded activity which was added by {@link #addEmbeddedActivity}. */
void removeEmbeddedActivity(ActivityRecord r) {
removeRemoteActivityFlags(r, REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY);
}
private int[] getRemoteActivityFlags(ActivityRecord r) {
if (mRemoteActivities == null) {
mRemoteActivities = new ArrayMap<>();
}
int[] flags = mRemoteActivities.get(r);
if (flags == null) {
mRemoteActivities.put(r, flags = new int[1]);
}
return flags;
}
private void removeRemoteActivityFlags(ActivityRecord r, int flags) {
if (mRemoteActivities == null) return;
final int index = mRemoteActivities.indexOfKey(r);
if (index < 0) return;
final int[] currentFlags = mRemoteActivities.valueAt(index);
currentFlags[0] &= ~flags;
if (currentFlags[0] == 0) {
mRemoteActivities.removeAt(index);
}
}
public interface ComputeOomAdjCallback {
@@ -1121,6 +1166,16 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
}
}
if (mRemoteActivities != null) {
// Make this process have visible state if its organizer embeds visible activities of
// other process, so this process can be responsive for the organizer events.
for (int i = mRemoteActivities.size() - 1; i >= 0; i--) {
if ((mRemoteActivities.valueAt(i)[0] & REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY) != 0
&& mRemoteActivities.keyAt(i).isVisibleRequested()) {
stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE;
}
}
}
stateFlags |= minTaskLayer & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
if (visible) {
@@ -1795,7 +1850,21 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
pw.print(prefix); pw.print(" - "); pw.println(mActivities.get(i));
}
}
if (mRemoteActivities != null && !mRemoteActivities.isEmpty()) {
pw.print(prefix); pw.println("Remote Activities:");
for (int i = mRemoteActivities.size() - 1; i >= 0; i--) {
pw.print(prefix); pw.print(" - ");
pw.print(mRemoteActivities.keyAt(i)); pw.print(" flags=");
final int flags = mRemoteActivities.valueAt(i)[0];
if ((flags & REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY) != 0) {
pw.print("host ");
}
if ((flags & REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY) != 0) {
pw.print("embedded");
}
pw.println();
}
}
if (mRecentTasks.size() > 0) {
pw.println(prefix + "Recent Tasks:");
for (int i = 0; i < mRecentTasks.size(); i++) {

View File

@@ -398,6 +398,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
public void testOnActivityReparentedToTask_activityNotInOrganizerProcess_useTemporaryToken() {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final WindowProcessController organizerProc = mSystemServicesTestRule.addProcess(
"pkg.organizer", DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME, pid, uid);
mTaskFragment.setTaskFragmentOrganizer(mOrganizer.getOrganizerToken(), uid,
DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
@@ -436,6 +438,15 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
// The temporary token can only be used once.
assertNull(mController.getReparentActivityFromTemporaryToken(mIOrganizer,
change.getActivityToken()));
// The organizer process should also have visible state by the visible activity in a
// different process.
activity.setVisibleRequested(true);
activity.setState(ActivityRecord.State.RESUMED, "test");
assertTrue(organizerProc.hasVisibleActivities());
activity.setVisibleRequested(false);
activity.setState(ActivityRecord.State.STOPPED, "test");
assertFalse(organizerProc.hasVisibleActivities());
}
@Test