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

Commit 1149807e authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Handle bubble transitions if the launch is collected into another transition" into main

parents 08c1bf52 99b0eef1
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -3370,16 +3370,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
    }

    /** @return whether the transition-request implies entering bubbles from split. */
    public boolean requestImpliesSplitToBubble(TransitionRequestInfo request) {
        final TaskInfo triggerTask = request.getTriggerTask();
    /** @return whether the opening task implies entering bubbles from split. */
    public boolean requestImpliesSplitToBubble(TaskInfo openingTask) {
        if (!isSplitActive()
                || triggerTask == null
                || triggerTask.displayId != mDisplayId) {
                || openingTask == null
                || openingTask.displayId != mDisplayId) {
            return false;
        }

        int stageForTask = getStageOfTask(triggerTask.taskId);
        int stageForTask = getStageOfTask(openingTask.taskId);
        if (stageForTask == STAGE_TYPE_UNDEFINED) {
            return false;
        }
+32 −2
Original line number Diff line number Diff line
@@ -331,7 +331,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler,
        if (requestHasBubbleEnter(request)) {
            consumeRemoteTransitionIfNecessary(transition, request.getRemoteTransition());

            if (mSplitHandler.requestImpliesSplitToBubble(request)) {
            if (mSplitHandler.requestImpliesSplitToBubble(request.getTriggerTask())) {
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                        " Got a Bubble-enter request from a split task");
                mBubbleTransitions.storePendingEnterTransition(transition, request);
@@ -361,7 +361,7 @@ public class DefaultMixedHandler implements MixedTransitionHandler,
        } else if (requestHasBubbleEnterFromAppBubbleOrExistingBubble(request)) {
            consumeRemoteTransitionIfNecessary(transition, request.getRemoteTransition());

            if (mSplitHandler.requestImpliesSplitToBubble(request)) {
            if (mSplitHandler.requestImpliesSplitToBubble(request.getTriggerTask())) {
                // TODO: Handle from split
            } else {
                // Note: This will currently "intercept" launches even while the bubble is collapsed
@@ -581,6 +581,24 @@ public class DefaultMixedHandler implements MixedTransitionHandler,
            break;
        }

        // If there was no requested transition but the transition includes an opening bubble task
        // then handle it here now
        TransitionInfo.Change bubbleChange =
                transitionHasBubbleEnterFromAppBubbleOrExistingBubble(info);
        if (mixed == null && bubbleChange != null) {
            if (mSplitHandler.requestImpliesSplitToBubble(bubbleChange.getTaskInfo())) {
                // TODO: Handle from split
            } else {
                // Add a mixed transition
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a Bubble-enter "
                        + "transition from an app bubble or for an existing bubble");
                mixed = createDefaultMixedTransition(
                        MixedTransition.TYPE_LAUNCH_OR_CONVERT_TO_BUBBLE_FROM_EXISTING_BUBBLE,
                        transition);
                mActiveTransitions.add(mixed);
            }
        }

        // Offer Keyguard the opportunity to take over lock transitions - ideally we could know by
        // the time of handleRequest, but we need more information than is available at that time.
        if (KeyguardTransitionHandler.handles(info)) {
@@ -836,6 +854,18 @@ public class DefaultMixedHandler implements MixedTransitionHandler,
                && mBubbleTransitions.shouldBeAppBubble(request.getTriggerTask());
    }

    /**
     * Returns the associated change for the bubbled task in the given started transition if it is
     * from an app bubble or for an existing bubble and should be handled by the bubbles transition
     */
    public TransitionInfo.Change transitionHasBubbleEnterFromAppBubbleOrExistingBubble(
            @NonNull TransitionInfo info) {
        if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) {
            return null;
        }
        return DefaultMixedTransition.getChangeForBubblingTask(info, mBubbleTransitions);
    }

    /**
     * Notifies the remote transition that it will not be played and is consumed by another
     * transition (and it can clean up accordingly).
+1 −1
Original line number Diff line number Diff line
@@ -453,7 +453,7 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition {
        return true;
    }

    private static @Nullable TransitionInfo.Change getChangeForBubblingTask(
    static @Nullable TransitionInfo.Change getChangeForBubblingTask(
            @NonNull TransitionInfo info, BubbleTransitions bubbleTransitions) {
        for (int i = 0; i < info.getChanges().size(); i++) {
            final TransitionInfo.Change chg = info.getChanges().get(i);
+44 −0
Original line number Diff line number Diff line
@@ -17,12 +17,16 @@
package com.android.wm.shell.transition

import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
import android.os.Binder
import android.platform.test.annotations.EnableFlags
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_OPEN
import android.window.IRemoteTransition
import android.window.RemoteTransition
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerToken
import androidx.test.filters.SmallTest
import com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE
import com.android.wm.shell.ShellTestCase
@@ -45,6 +49,7 @@ import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.stub
import org.mockito.kotlin.verify

@@ -218,6 +223,44 @@ class DefaultMixedHandlerTest : ShellTestCase() {
        verify(remoteTransition).onTransitionConsumed(any(), eq(false))
    }

    @Test
    @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE)
    fun test_startAnimation_NoBubbleEnterFromAppBubble() {
        val info = TransitionInfo(TRANSIT_OPEN, 0)

        bubbleTransitions.stub {
            on { isShowingAsBubbleBar } doReturn true
            on { shouldBeAppBubble(any()) } doReturn true
        }

        mixedHandler.startAnimation(Binder(), info, mock<SurfaceControl.Transaction>(),
            mock<SurfaceControl.Transaction>(), mock<Transitions.TransitionFinishCallback>())

        verify(bubbleTransitions, never()).startBubbleToBubbleLaunchOrExistingBubbleConvert(
            any(), any(), any());
    }

    @Test
    @EnableFlags(FLAG_ENABLE_CREATE_ANY_BUBBLE)
    fun test_startAnimation_bubbleEnterFromAppBubble() {
        val change = TransitionInfo.Change(mock<WindowContainerToken>(), mock<SurfaceControl>())
        change.mode = TRANSIT_OPEN
        change.taskInfo = createRunningTask()
        val info = TransitionInfo(TRANSIT_OPEN, 0)
        info.addChange(change)

        bubbleTransitions.stub {
            on { isShowingAsBubbleBar } doReturn true
            on { shouldBeAppBubble(any()) } doReturn true
        }

        mixedHandler.startAnimation(Binder(), info, mock<SurfaceControl.Transaction>(),
            mock<SurfaceControl.Transaction>(), mock<Transitions.TransitionFinishCallback>())

        verify(bubbleTransitions).startBubbleToBubbleLaunchOrExistingBubbleConvert(
            any(), any(), any());
    }

    private fun createTransitionRequestInfo(
        runningTask: RunningTaskInfo? = null,
        remote: RemoteTransition? = null,
@@ -228,6 +271,7 @@ class DefaultMixedHandlerTest : ShellTestCase() {
    private fun createRunningTask(taskId: Int = 0): RunningTaskInfo {
        return RunningTaskInfo().apply {
            this.taskId = taskId
            this.configuration.windowConfiguration.activityType = ACTIVITY_TYPE_STANDARD
        }
    }
}