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

Commit f70053c0 authored by Charles Chen's avatar Charles Chen
Browse files

Apply WindowAttributes for overlay container

Also consolidate most logic to update overlay containers to
 #applyActivityStackAttributes.

Test: atest OverlayPresentationTest
Bug: 243518738
Change-Id: Ic0a3e2b01876591fb1daf638682645d844d4bc35
parent b56d2e55
Loading
Loading
Loading
Loading
+33 −57
Original line number Diff line number Diff line
@@ -42,10 +42,10 @@ import static androidx.window.extensions.embedding.SplitContainer.isStickyPlaceh
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenAdjacent;
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
import static androidx.window.extensions.embedding.SplitPresenter.RESULT_EXPAND_FAILED_NO_TF_INFO;
import static androidx.window.extensions.embedding.SplitPresenter.boundsSmallerThanMinDimensions;
import static androidx.window.extensions.embedding.SplitPresenter.getActivitiesMinDimensionsPair;
import static androidx.window.extensions.embedding.SplitPresenter.getActivityIntentMinDimensionsPair;
import static androidx.window.extensions.embedding.SplitPresenter.getMinDimensions;
import static androidx.window.extensions.embedding.SplitPresenter.sanitizeBounds;
import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSplit;

import android.annotation.CallbackExecutor;
@@ -574,7 +574,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen

            final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
            final WindowContainerTransaction wct = transactionRecord.getTransaction();
            mPresenter.applyActivityStackAttributes(wct, container, attributes);
            mPresenter.applyActivityStackAttributes(wct, container, attributes,
                    container.getMinDimensions());
            transactionRecord.apply(false /* shouldApplyIndependently */);
        }
    }
@@ -1567,7 +1568,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    private TaskFragmentContainer createEmptyExpandedContainer(
            @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId,
            @Nullable Activity launchingActivity) {
        return createEmptyContainer(wct, intent, taskId, new Rect(), launchingActivity,
        return createEmptyContainer(wct, intent, taskId,
                new ActivityStackAttributes.Builder().build(), launchingActivity,
                null /* overlayTag */, null /* launchOptions */);
    }

@@ -1581,8 +1583,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    @Nullable
    TaskFragmentContainer createEmptyContainer(
            @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId,
            @NonNull Rect bounds, @Nullable Activity launchingActivity,
            @Nullable String overlayTag, @Nullable Bundle launchOptions) {
            @NonNull ActivityStackAttributes activityStackAttributes,
            @Nullable Activity launchingActivity, @Nullable String overlayTag,
            @Nullable Bundle launchOptions) {
        // We need an activity in the organizer process in the same Task to use as the owner
        // activity, as well as to get the Task window info.
        final Activity activityInTask;
@@ -1605,42 +1608,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        // Note that taskContainer will not exist before calling #newContainer if the container
        // is the first embedded TF in the task.
        final TaskContainer taskContainer = container.getTaskContainer();
        final Rect taskBounds = taskContainer.getTaskProperties().getTaskMetrics().getBounds();
        final Rect sanitizedBounds = sanitizeBounds(bounds, intent, taskBounds);
        // TODO(b/265271880): remove redundant logic after all TF operations take fragmentToken.
        final Rect taskBounds = taskContainer.getBounds();
        final Rect sanitizedBounds = sanitizeBounds(activityStackAttributes.getRelativeBounds(),
                getMinDimensions(intent), taskBounds);
        final int windowingMode = taskContainer
                .getWindowingModeForTaskFragment(sanitizedBounds);
        mPresenter.createTaskFragment(wct, taskFragmentToken, activityInTask.getActivityToken(),
                sanitizedBounds, windowingMode);
        mPresenter.updateAnimationParams(wct, taskFragmentToken,
                TaskFragmentAnimationParams.DEFAULT);
        mPresenter.setTaskFragmentIsolatedNavigation(wct, taskFragmentToken,
                overlayTag != null && !sanitizedBounds.isEmpty());
        mPresenter.applyActivityStackAttributes(wct, container, activityStackAttributes,
                getMinDimensions(intent));

        return container;
    }

    /**
     * Returns the expanded bounds if the {@code bounds} violate minimum dimension or are not fully
     * covered by the task bounds. Otherwise, returns {@code bounds}.
     */
    @NonNull
    private static Rect sanitizeBounds(@NonNull Rect bounds, @NonNull Intent intent,
            @NonNull Rect taskBounds) {
        if (bounds.isEmpty()) {
            // Don't need to check if the bounds follows the task bounds.
            return bounds;
        }
        if (boundsSmallerThanMinDimensions(bounds, getMinDimensions(intent))) {
            // Expand the bounds if the bounds are smaller than minimum dimensions.
            return new Rect();
        }
        if (!taskBounds.contains(bounds)) {
            // Expand the bounds if the bounds exceed the task bounds.
            return new Rect();
        }
        return bounds;
    }

    /**
     * Returns a container for the new activity intent to launch into as splitting with the primary
     * activity.
@@ -1958,6 +1939,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            return;
        }

        if (mActivityStackAttributesCalculator == null) {
            Log.e(TAG, "ActivityStackAttributesCalculator is not set. Thus the overlay container"
                    + " can not be updated.");
            return;
        }

        if (mActivityStackAttributesCalculator != null) {
            final ActivityStackAttributesCalculatorParams params =
                    new ActivityStackAttributesCalculatorParams(
@@ -1967,7 +1954,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                            container.getLaunchOptions());
            final ActivityStackAttributes attributes = mActivityStackAttributesCalculator
                    .apply(params);
            mPresenter.applyActivityStackAttributes(wct, container, attributes);
            mPresenter.applyActivityStackAttributes(wct, container, attributes,
                    container.getMinDimensions());
        }
    }

@@ -2603,15 +2591,15 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                        mPresenter.createParentContainerInfoFromTaskProperties(
                                mPresenter.getTaskProperties(launchActivity)), overlayTag, options);
        // Fallback to expand the bounds if there's no activityStackAttributes calculator.
        final Rect relativeBounds = mActivityStackAttributesCalculator != null
                ? new Rect(mActivityStackAttributesCalculator.apply(params).getRelativeBounds())
                : new Rect();
        final boolean shouldExpandContainer = boundsSmallerThanMinDimensions(relativeBounds,
                getMinDimensions(intent));
        // Expand the bounds if the requested bounds are smaller than minimum dimensions.
        if (shouldExpandContainer) {
            relativeBounds.setEmpty();
        final ActivityStackAttributes attrs;
        if (mActivityStackAttributesCalculator != null) {
            attrs = mActivityStackAttributesCalculator.apply(params);
        } else {
            attrs = new ActivityStackAttributes.Builder().build();
            Log.e(TAG, "ActivityStackAttributesCalculator isn't set. Fallback to set overlay "
                    + "container as expected.");
        }

        final int taskId = getTaskId(launchActivity);
        if (!overlayContainers.isEmpty()) {
            for (final TaskFragmentContainer overlayContainer : overlayContainers) {
@@ -2631,20 +2619,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                }
                if (overlayTag.equals(overlayContainer.getOverlayTag())
                        && taskId == overlayContainer.getTaskId()) {
                    // If there's an overlay container with the same tag and task ID, we treat
                    // the OverlayCreateParams as the update to the container.
                    final IBinder overlayToken = overlayContainer.getTaskFragmentToken();
                    final TaskContainer taskContainer = overlayContainer.getTaskContainer();
                    final Rect taskBounds = taskContainer.getTaskProperties().getTaskMetrics()
                            .getBounds();
                    final Rect sanitizedBounds = sanitizeBounds(relativeBounds, intent, taskBounds);

                    mPresenter.resizeTaskFragment(wct, overlayToken, sanitizedBounds);
                    final int windowingMode = taskContainer
                            .getWindowingModeForTaskFragment(sanitizedBounds);
                    mPresenter.updateWindowingMode(wct, overlayToken, windowingMode);
                    mPresenter.setTaskFragmentIsolatedNavigation(wct, overlayContainer,
                            !sanitizedBounds.isEmpty());
                    mPresenter.applyActivityStackAttributes(wct, overlayContainer, attrs,
                            getMinDimensions(intent));
                    // We can just return the updated overlay container and don't need to
                    // check other condition since we only have one OverlayCreateParams, and
                    // if the tag and task are matched, it's impossible to match another task
@@ -2654,7 +2630,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            }
        }
        // Launch the overlay container to the task with taskId.
        return createEmptyContainer(wct, intent, taskId, relativeBounds, launchActivity, overlayTag,
        return createEmptyContainer(wct, intent, taskId, attrs, launchActivity, overlayTag,
                options);
    }

+50 −10
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package androidx.window.extensions.embedding;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.PackageManager.MATCH_ALL;

import static androidx.window.extensions.embedding.WindowAttributes.DIM_AREA_ON_TASK;
@@ -426,7 +424,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
     * creation has not been reported from the server yet.
     */
    // TODO(b/190433398): Handle resize if the fragment hasn't appeared yet.
    private void resizeTaskFragmentIfRegistered(@NonNull WindowContainerTransaction wct,
    @VisibleForTesting
    void resizeTaskFragmentIfRegistered(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container,
            @Nullable Rect relBounds) {
        if (container.getInfo() == null) {
@@ -435,7 +434,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        resizeTaskFragment(wct, container.getTaskFragmentToken(), relBounds);
    }

    private void updateTaskFragmentWindowingModeIfRegistered(
    @VisibleForTesting
    void updateTaskFragmentWindowingModeIfRegistered(
            @NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container,
            @WindowingMode int windowingMode) {
@@ -579,13 +579,53 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        super.setCompanionTaskFragment(wct, primary, secondary);
    }

    void applyActivityStackAttributes(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container, @NonNull ActivityStackAttributes attributes) {
        final Rect bounds = attributes.getRelativeBounds();
    void applyActivityStackAttributes(
            @NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container,
            @NonNull ActivityStackAttributes attributes,
            @Nullable Size minDimensions) {
        final Rect taskBounds = container.getTaskContainer().getBounds();
        final Rect relativeBounds = sanitizeBounds(attributes.getRelativeBounds(), minDimensions,
                taskBounds);
        final boolean isFillParent = relativeBounds.isEmpty();
        final boolean isIsolatedNavigated = !isFillParent && container.isOverlay();
        final boolean dimOnTask = !isFillParent
                && attributes.getWindowAttributes().getDimArea() == DIM_AREA_ON_TASK
                && Flags.fullscreenDimFlag();
        final IBinder fragmentToken = container.getTaskFragmentToken();

        // TODO(b/243518738): Update to resizeTaskFragment after we migrate WCT#setRelativeBounds
        //  and WCT#setWindowingMode to take fragmentToken.
        resizeTaskFragmentIfRegistered(wct, container, relativeBounds);
        int windowingMode = container.getTaskContainer().getWindowingModeForTaskFragment(
                relativeBounds);
        updateTaskFragmentWindowingModeIfRegistered(wct, container, windowingMode);
        // Always use default animation for standalone ActivityStack.
        updateAnimationParams(wct, fragmentToken, TaskFragmentAnimationParams.DEFAULT);
        setTaskFragmentIsolatedNavigation(wct, container, isIsolatedNavigated);
        setTaskFragmentDimOnTask(wct, fragmentToken, dimOnTask);
    }

        resizeTaskFragment(wct, container.getTaskFragmentToken(), bounds);
        updateWindowingMode(wct, container.getTaskFragmentToken(),
                bounds.isEmpty() ? WINDOWING_MODE_FULLSCREEN : WINDOWING_MODE_MULTI_WINDOW);
    /**
     * Returns the expanded bounds if the {@code bounds} violate minimum dimension or are not fully
     * covered by the task bounds. Otherwise, returns {@code bounds}.
     */
    @NonNull
    static Rect sanitizeBounds(@NonNull Rect bounds, @Nullable Size minDimension,
                               @NonNull Rect taskBounds) {
        if (bounds.isEmpty()) {
            // Don't need to check if the bounds follows the task bounds.
            return bounds;
        }
        if (boundsSmallerThanMinDimensions(bounds, minDimension)) {
            // Expand the bounds if the bounds are smaller than minimum dimensions.
            return new Rect();
        }
        if (!taskBounds.contains(bounds)) {
            // Expand the bounds if the bounds exceed the task bounds.
            return new Rect();
        }
        return bounds;
    }

    @Override
+5 −0
Original line number Diff line number Diff line
@@ -125,6 +125,11 @@ class TaskContainer {
        return mHasDirectActivity;
    }

    @NonNull
    Rect getBounds() {
        return mConfiguration.windowConfiguration.getBounds();
    }

    @NonNull
    TaskProperties getTaskProperties() {
        return new TaskProperties(mDisplayId, mConfiguration);
+100 −52

File changed.

Preview size limit exceeded, changes collapsed.