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

Commit 9ca93538 authored by Louis Chang's avatar Louis Chang Committed by Automerger Merge Worker
Browse files

Merge "Prevent the launching activity be reparented into embedded task" into...

Merge "Prevent the launching activity be reparented into embedded task" into sc-v2-dev am: faf3acad am: 2c121cf2

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

Change-Id: Ia146e8b3d45702dee8d78acc03bb339654797022
parents 1f54973a 2c121cf2
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2784,7 +2784,8 @@ class ActivityStarter {
            }
        } else {
            // Use the child TaskFragment (if any) as the new parent if the activity can be embedded
            final ActivityRecord top = task.topRunningActivity();
            final ActivityRecord top = task.topRunningActivity(false /* focusableOnly */,
                    false /* includingEmbeddedTask */);
            newParent = top != null ? top.getTaskFragment() : task;
        }

+19 −1
Original line number Diff line number Diff line
@@ -365,8 +365,26 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                return false;
            }

            if (matchingCandidate(task)) {
                return true;
            }

            // Looking for the embedded tasks (if any)
            return !task.isLeafTaskFragment() && task.forAllLeafTaskFragments(
                    this::matchingCandidate);
        }

        boolean matchingCandidate(TaskFragment taskFragment) {
            final Task task = taskFragment.asTask();
            if (task == null) {
                return false;
            }

            // Overlays should not be considered as the task's logical top activity.
            final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
            // Activities of the tasks that embedded from this one should not be used.
            final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */,
                    false /* includingEmbeddedTask */);

            if (r == null || r.finishing || r.mUserId != userId
                    || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r);
+44 −10
Original line number Diff line number Diff line
@@ -1394,14 +1394,6 @@ class Task extends TaskFragment {
        return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
    }

    ActivityRecord getTopNonFinishingActivity() {
        return getTopNonFinishingActivity(true /* includeOverlays */);
    }

    ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
        return getTopActivity(false /*includeFinishing*/, includeOverlays);
    }

    ActivityRecord topRunningActivityLocked() {
        if (getParent() == null) {
            return null;
@@ -2976,11 +2968,53 @@ class Task extends TaskFragment {
    /** Returns the top-most activity that occludes the given one, or {@code null} if none. */
    @Nullable
    ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
        final ActivityRecord top = getActivity(ActivityRecord::occludesParent,
                true /* traverseTopToBottom */, activity);
        final ActivityRecord top = getActivity(r -> {
            if (!r.occludesParent()) {
                return false;
            }
            if (r == activity) {
                // Reached the given activity, return the activity to stop searching.
                return true;
            }

            TaskFragment parent = r.getTaskFragment();
            if (parent == activity.getTaskFragment()) {
                // Found it. This activity on top of the given activity on the same TaskFragment.
                return true;
            }
            if (isSelfOrNonEmbeddedTask(parent.asTask())) {
                // Found it. This activity is the direct child of a leaf Task without being
                // embedded.
                return true;
            }
            // The candidate activity is being embedded. Checking if the bounds of the containing
            // TaskFragment equals to the outer TaskFragment.
            TaskFragment grandParent = parent.getParent().asTaskFragment();
            while (grandParent != null) {
                if (!parent.getBounds().equals(grandParent.getBounds())) {
                    // Not occluding the grandparent.
                    break;
                }
                if (isSelfOrNonEmbeddedTask(grandParent.asTask())) {
                    // Found it. The activity occludes its parent TaskFragment and the parent
                    // TaskFragment also occludes its parent all the way up.
                    return true;
                }
                parent = grandParent;
                grandParent = parent.getParent().asTaskFragment();
            }
            return false;
        });
        return top != activity ? top : null;
    }

    private boolean isSelfOrNonEmbeddedTask(Task task) {
        if (task == this) {
            return true;
        }
        return task != null && !task.isEmbedded();
    }

    @Override
    public SurfaceControl.Builder makeAnimationLeash() {
        return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId);
+54 −3
Original line number Diff line number Diff line
@@ -614,17 +614,68 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        return false;
    }

    ActivityRecord getTopNonFinishingActivity() {
        return getTopNonFinishingActivity(true /* includeOverlays */);
    }

    ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
        return getTopNonFinishingActivity(includeOverlays, true /* includingEmbeddedTask */);
    }

    /**
     * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to
     * the current user.
     * @param includeOverlays whether the task overlay activity should be included.
     * @param includingEmbeddedTask whether the activity in a task that being embedded from this
     *                              one should be included.
     * @see #topRunningActivity(boolean, boolean)
     * @see ActivityRecord#okToShowLocked()
     */
    ActivityRecord getTopNonFinishingActivity(boolean includeOverlays,
            boolean includingEmbeddedTask) {
        // Split into 4 to avoid object creation due to variable capture.
        if (includeOverlays) {
            if (includingEmbeddedTask) {
                return getActivity((r) -> !r.finishing);
            }
            return getActivity((r) -> !r.finishing && r.getTask() == this.getTask());
        }

        if (includingEmbeddedTask) {
            return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
        }
        return getActivity(
                (r) -> !r.finishing && !r.isTaskOverlay() && r.getTask() == this.getTask());
    }

    ActivityRecord topRunningActivity() {
        return topRunningActivity(false /* focusableOnly */);
    }

    ActivityRecord topRunningActivity(boolean focusableOnly) {
        // Split into 2 to avoid object creation due to variable capture.
        return topRunningActivity(focusableOnly, true /* includingEmbeddedTask */);
    }

    /**
     * Returns the top-most running activity, which the activity is non-finishing and ok to show
     * to the current user.
     *
     * @see ActivityRecord#canBeTopRunning()
     */
    ActivityRecord topRunningActivity(boolean focusableOnly, boolean includingEmbeddedTask) {
        // Split into 4 to avoid object creation due to variable capture.
        if (focusableOnly) {
            if (includingEmbeddedTask) {
                return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
        } else {
            }
            return getActivity(
                    (r) -> r.canBeTopRunning() && r.isFocusable() && r.getTask() == this.getTask());
        }

        if (includingEmbeddedTask) {
            return getActivity(ActivityRecord::canBeTopRunning);
        }
        return getActivity((r) -> r.canBeTopRunning() && r.getTask() == this.getTask());
    }

    boolean isTopActivityFocusable() {