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

Commit 7704ad90 authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "[3/n] Pin ActivityStack" into udc-qpr-dev

parents 03514987 4944e8e0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ public class WindowExtensionsImpl implements WindowExtensions {
    // TODO(b/241126279) Introduce constants to better version functionality
    @Override
    public int getVendorApiLevel() {
        return 3;
        return 4;
    }

    @NonNull
+26 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import androidx.window.extensions.core.util.function.Function;
 */
class SplitContainer {
    @NonNull
    private final TaskFragmentContainer mPrimaryContainer;
    private TaskFragmentContainer mPrimaryContainer;
    @NonNull
    private final TaskFragmentContainer mSecondaryContainer;
    @NonNull
@@ -46,17 +46,35 @@ class SplitContainer {
    @NonNull
    private final IBinder mToken;

    /**
     * Whether the selection of which container is primary can be changed at runtime. Runtime
     * updates is currently possible only for {@link SplitPinContainer}
     *
     * @see SplitPinContainer
     */
    private final boolean mIsPrimaryContainerMutable;

    SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
            @NonNull Activity primaryActivity,
            @NonNull TaskFragmentContainer secondaryContainer,
            @NonNull SplitRule splitRule,
            @NonNull SplitAttributes splitAttributes) {
        this(primaryContainer, primaryActivity, secondaryContainer, splitRule, splitAttributes,
                false /* isPrimaryContainerMutable */);
    }

    SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
            @NonNull Activity primaryActivity,
            @NonNull TaskFragmentContainer secondaryContainer,
            @NonNull SplitRule splitRule,
            @NonNull SplitAttributes splitAttributes, boolean isPrimaryContainerMutable) {
        mPrimaryContainer = primaryContainer;
        mSecondaryContainer = secondaryContainer;
        mSplitRule = splitRule;
        mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
        mCurrentSplitAttributes = splitAttributes;
        mToken = new Binder("SplitContainer");
        mIsPrimaryContainerMutable = isPrimaryContainerMutable;

        if (shouldFinishPrimaryWithSecondary(splitRule)) {
            if (mPrimaryContainer.getRunningActivityCount() == 1
@@ -74,6 +92,13 @@ class SplitContainer {
        }
    }

    void setPrimaryContainer(@NonNull TaskFragmentContainer primaryContainer) {
        if (!mIsPrimaryContainerMutable) {
            throw new IllegalStateException("Cannot update primary TaskFragmentContainer");
        }
        mPrimaryContainer = primaryContainer;
    }

    @NonNull
    TaskFragmentContainer getPrimaryContainer() {
        return mPrimaryContainer;
+59 −5
Original line number Diff line number Diff line
@@ -212,6 +212,56 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        }
    }

    @Override
    public boolean pinTopActivityStack(int taskId, @NonNull SplitPinRule splitPinRule) {
        synchronized (mLock) {
            final TaskContainer task = getTaskContainer(taskId);
            if (task == null) {
                Log.e(TAG, "Cannot find the task for id: " + taskId);
                return false;
            }

            final TaskFragmentContainer topContainer =
                    task.getTopNonFinishingTaskFragmentContainer();
            // Cannot pin the TaskFragment if no other TaskFragment behind it.
            if (topContainer == null || task.indexOf(topContainer) <= 0) {
                Log.w(TAG, "Cannot find an ActivityStack to pin or split");
                return false;
            }
            // Abort if the top container is already pinned.
            if (task.getSplitPinContainer() != null) {
                Log.w(TAG, "There is already a pinned ActivityStack.");
                return false;
            }

            // Find a valid adjacent TaskFragmentContainer
            final TaskFragmentContainer primaryContainer =
                    task.getNonFinishingTaskFragmentContainerBelow(topContainer);
            if (primaryContainer == null) {
                Log.w(TAG, "Cannot find another ActivityStack to split");
                return false;
            }

            // Registers a Split
            final SplitPinContainer splitPinContainer = new SplitPinContainer(primaryContainer,
                    topContainer, splitPinRule, splitPinRule.getDefaultSplitAttributes());
            task.addSplitContainer(splitPinContainer);

            // Updates the Split
            final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
            final WindowContainerTransaction wct = transactionRecord.getTransaction();
            mPresenter.updateSplitContainer(splitPinContainer, wct);
            transactionRecord.apply(false /* shouldApplyIndependently */);
            updateCallbackIfNecessary();
            return true;
        }
    }

    @Override
    public void unpinTopActivityStack(int taskId){
        // TODO
    }

    @Override
    public void setSplitAttributesCalculator(
            @NonNull Function<SplitAttributesCalculatorParams, SplitAttributes> calculator) {
@@ -672,7 +722,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        if (targetContainer == null) {
            // When there is no embedding rule matched, try to place it in the top container
            // like a normal launch.
            targetContainer = taskContainer.getTopTaskFragmentContainer();
            targetContainer = taskContainer.getTopNonFinishingTaskFragmentContainer();
        }
        if (targetContainer == null) {
            return;
@@ -791,7 +841,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen

        final TaskFragmentContainer container = getContainerWithActivity(activity);
        if (!isOnReparent && container != null
                && container.getTaskContainer().getTopTaskFragmentContainer() != container) {
                && container.getTaskContainer().getTopNonFinishingTaskFragmentContainer()
                        != container) {
            // Do not resolve if the launched activity is not the top-most container in the Task.
            return true;
        }
@@ -888,7 +939,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        if (taskContainer == null) {
            return;
        }
        final TaskFragmentContainer targetContainer = taskContainer.getTopTaskFragmentContainer();
        final TaskFragmentContainer targetContainer =
                taskContainer.getTopNonFinishingTaskFragmentContainer();
        if (targetContainer == null) {
            return;
        }
@@ -1213,11 +1265,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen

        // 3. Whether the top activity (if any) should be split with the new activity intent.
        final TaskContainer taskContainer = getTaskContainer(taskId);
        if (taskContainer == null || taskContainer.getTopTaskFragmentContainer() == null) {
        if (taskContainer == null
                || taskContainer.getTopNonFinishingTaskFragmentContainer() == null) {
            // There is no other activity in the Task to check split with.
            return null;
        }
        final TaskFragmentContainer topContainer = taskContainer.getTopTaskFragmentContainer();
        final TaskFragmentContainer topContainer =
                taskContainer.getTopNonFinishingTaskFragmentContainer();
        final Activity topActivity = topContainer.getTopNonFinishingActivity();
        if (topActivity != null && topActivity != launchingActivity) {
            final TaskFragmentContainer container = getSecondaryContainerForSplitIfAny(wct,
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.window.extensions.embedding;

import androidx.annotation.NonNull;

/**
 * Client-side descriptor of a split that holds two containers while the secondary
 * container is pinned on top of the Task and the primary container is the container that is
 * currently below the secondary container. The primary container could be updated to
 * another container whenever the existing primary container is removed or no longer
 * be the container that's right behind the secondary container.
 */
class SplitPinContainer extends SplitContainer {

    SplitPinContainer(@NonNull TaskFragmentContainer primaryContainer,
            @NonNull TaskFragmentContainer secondaryContainer,
            @NonNull SplitPinRule splitPinRule,
            @NonNull SplitAttributes splitAttributes) {
        super(primaryContainer, primaryContainer.getTopNonFinishingActivity(), secondaryContainer,
                splitPinRule, splitAttributes, true /* isPrimaryContainerMutable */);
    }

    @Override
    public String toString() {
        return "SplitPinContainer{"
                + " primaryContainer=" + getPrimaryContainer()
                + " secondaryContainer=" + getSecondaryContainer()
                + " splitPinRule=" + getSplitRule()
                + " splitAttributes" + getCurrentSplitAttributes()
                + "}";
    }
}
+0 −4
Original line number Diff line number Diff line
@@ -336,10 +336,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        // value.
        final SplitRule rule = splitContainer.getSplitRule();
        final TaskFragmentContainer primaryContainer = splitContainer.getPrimaryContainer();
        final Activity activity = primaryContainer.getTopNonFinishingActivity();
        if (activity == null) {
            return;
        }
        final TaskContainer taskContainer = splitContainer.getTaskContainer();
        final TaskProperties taskProperties = taskContainer.getTaskProperties();
        final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
Loading