Merge "Keep visible process state if process embeds visible activity" into udc-dev
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user