diff options
3 files changed, 127 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 7c57dc17e802..72878cfeaa12 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<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); } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 834b708f3f9a..8685723a5807 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<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++) { 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 378e8bed3524..99ab715ab987 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 |