Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1be62539 authored by Riddle Hsu's avatar Riddle Hsu Committed by Automerger Merge Worker
Browse files

Merge "Keep visible process state if process embeds visible activity" into...

Merge "Keep visible process state if process embeds visible activity" into udc-dev am: d374dc63 am: 3454caa7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22132895



Change-Id: Ic3d31aab95103d4791900b008041495d80dbdc62
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 8ec4e1b4 3454caa7
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -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);
        }
+80 −11
Original line number Diff line number Diff line
@@ -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++) {
+11 −0
Original line number Diff line number Diff line
@@ -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