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

Commit 0399d9c9 authored by Louis Chang's avatar Louis Chang Committed by Charles Chen
Browse files

Block split Activity in lock task mode

Before this CL, Activity was only blocked from finishing if it is the
last Activity in th Task to start lock task mode.
However, it may make half of screen black if the finishing Activity is
in one of adjacent TaskFragments.
This CL considers the scenario that two adjacent TaskFragments side-by-side.
If a finishing Activity leads to TaskFragment empty, and also make the
adjacent TaskFragment finish, block the Activity from finishing.

Bug: 205813709
Test: manual - use Settings in task pinning mode

Change-Id: I6116d644aeccc13460d302fe3b40953fa67dca6c
parent a5f83144
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -293,11 +293,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            @NonNull TaskFragmentContainer primaryContainer, @NonNull Activity primaryActivity,
            @NonNull TaskFragmentContainer secondaryContainer,
            @NonNull SplitRule splitRule) {
        SplitContainer splitContainer = new SplitContainer(primaryContainer, primaryActivity,
                secondaryContainer, splitRule);
        // Remove container later to prevent pinning escaping toast showing in lock task mode.
        if (splitRule instanceof SplitPairRule && ((SplitPairRule) splitRule).shouldClearTop()) {
            removeExistingSecondaryContainers(wct, primaryContainer);
        }
        SplitContainer splitContainer = new SplitContainer(primaryContainer, primaryActivity,
                secondaryContainer, splitRule);
        mSplitContainers.add(splitContainer);
    }

+18 −6
Original line number Diff line number Diff line
@@ -112,8 +112,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        secondaryContainer.setLastRequestedBounds(secondaryRectBounds);

        // Set adjacent to each other so that the containers below will be invisible.
        setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                secondaryContainer.getTaskFragmentToken(), rule);
        setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);

        mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);

@@ -149,8 +148,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
                secondaryActivity, secondaryRectBounds, primaryContainer);

        // Set adjacent to each other so that the containers below will be invisible.
        setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                secondaryContainer.getTaskFragmentToken(), rule);
        setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);

        mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);

@@ -269,8 +267,22 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer();
        resizeTaskFragmentIfRegistered(wct, secondaryContainer, secondaryRectBounds);

        setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
    }

    private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer primaryContainer,
            @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule) {
        final Rect parentBounds = getParentContainerBounds(primaryContainer);
        // Clear adjacent TaskFragments if the container is shown in fullscreen, or the
        // secondaryContainer could not be finished.
        if (!shouldShowSideBySide(parentBounds, splitRule)) {
            setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                secondaryContainer.getTaskFragmentToken(), rule);
                    null /* secondary */, null /* splitRule */);
        } else {
            setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                    secondaryContainer.getTaskFragmentToken(), splitRule);
        }
    }

    /**
+40 −8
Original line number Diff line number Diff line
@@ -251,16 +251,48 @@ public class LockTaskController {
     */
    boolean activityBlockedFromFinish(ActivityRecord activity) {
        final Task task = activity.getTask();
        if (activity == task.getRootActivity()
                && activity == task.getTopNonFinishingActivity()
                && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
                && isRootTask(task)) {
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV || !isRootTask(task)) {
            return false;
        }

        final ActivityRecord taskTop = task.getTopNonFinishingActivity();
        final ActivityRecord taskRoot = task.getRootActivity();
        // If task has more than one Activity, verify if there's only adjacent TaskFragments that
        // should be finish together in the Task.
        if (activity != taskRoot || activity != taskTop) {
            final TaskFragment taskFragment = activity.getTaskFragment();
            final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
            if (taskFragment.asTask() != null
                    || !taskFragment.isDelayLastActivityRemoval()
                    || adjacentTaskFragment == null) {
                // Don't block activity from finishing if the TaskFragment don't have any adjacent
                // TaskFragment, or it won't finish together with its adjacent TaskFragment.
                return false;
            }

            final boolean hasOtherActivityInTaskFragment =
                    taskFragment.getActivity(a -> !a.finishing && a != activity) != null;
            if (hasOtherActivityInTaskFragment) {
                // Don't block activity from finishing if there's other Activity in the same
                // TaskFragment.
                return false;
            }

            final boolean hasOtherActivityInTask = task.getActivity(a -> !a.finishing
                    && a != activity && a.getTaskFragment() != adjacentTaskFragment) != null;
            if (hasOtherActivityInTask) {
                // Do not block activity from finishing if there are another running activities
                // after the current and adjacent TaskFragments are removed. Note that we don't
                // check activities in adjacent TaskFragment because it will be finished together
                // with TaskFragment regardless of numbers of activities.
                return false;
            }
        }

        Slog.i(TAG, "Not finishing task in lock task mode");
        showLockTaskToast();
        return true;
    }
        return false;
    }

    /**
     * @return whether the given task can be moved to the back of the stack with
+1 −1
Original line number Diff line number Diff line
@@ -232,7 +232,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
    /**
     * Whether to delay the last activity of TaskFragment being immediately removed while finishing.
     * This should only be set on a embedded TaskFragment, where the organizer can have the
     * opportunity to perform other actions or animations.
     * opportunity to perform animations and finishing the adjacent TaskFragment.
     */
    private boolean mDelayLastActivityRemoval;