diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 7c57dc17e8024..72878cfeaa128 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -458,6 +458,22 @@ class TaskFragment extends 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 { 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 { 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 { 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); } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 834b708f3f9a4..8685723a5807d 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -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 mHostActivities = new ArrayList<>(); + private ArrayMap mRemoteActivities; /** Whether our process is currently running a {@link RecentsAnimation} */ private boolean mRunningRecentsAnimation; @@ -857,7 +867,7 @@ public class WindowProcessController extends ConfigurationContainer= 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(); + } + 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= 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= 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++) { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index 378e8bed35246..99ab715ab9871 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -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