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

Commit ad77976e authored by Liran Binyamin's avatar Liran Binyamin Committed by Android (Google) Code Review
Browse files

Merge "Animate dragged bubble to full screen" into main

parents 2474371b 85fca4bb
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -2643,9 +2643,9 @@ public class BubbleController implements ConfigurationChangeListener,
        mBubbleData.setSelectedBubbleAndExpandStack(bubbleToSelect);
    }

    private void moveBubbleToFullscreen(String key) {
    private void moveDraggedBubbleToFullscreen(String key, Point dropLocation) {
        Bubble b = mBubbleData.getBubbleInStackWithKey(key);
        mBubbleTransitions.startDraggedBubbleIconToFullscreen(b);
        mBubbleTransitions.startDraggedBubbleIconToFullscreen(b, dropLocation);
    }

    private boolean isDeviceLocked() {
@@ -2936,8 +2936,9 @@ public class BubbleController implements ConfigurationChangeListener,
        }

        @Override
        public void moveBubbleToFullscreen(String key) {
            mMainExecutor.execute(() -> mController.moveBubbleToFullscreen(key));
        public void moveDraggedBubbleToFullscreen(String key, Point dropLocation) {
            mMainExecutor.execute(
                    () -> mController.moveDraggedBubbleToFullscreen(key, dropLocation));
        }
    }

+50 −4
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.Context;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.IBinder;
@@ -42,6 +43,11 @@ import android.window.TransitionRequestInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import androidx.core.animation.Animator;
import androidx.core.animation.Animator.AnimatorUpdateListener;
import androidx.core.animation.AnimatorListenerAdapter;
import androidx.core.animation.ValueAnimator;

import com.android.internal.annotations.VisibleForTesting;
import com.android.launcher3.icons.BubbleIconFactory;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -114,8 +120,8 @@ public class BubbleTransitions {
    }

    /** Starts a transition that converts a dragged bubble icon to a full screen task. */
    public BubbleTransition startDraggedBubbleIconToFullscreen(Bubble bubble) {
        return new DraggedBubbleIconToFullscreen(bubble);
    public BubbleTransition startDraggedBubbleIconToFullscreen(Bubble bubble, Point dropLocation) {
        return new DraggedBubbleIconToFullscreen(bubble, dropLocation);
    }

    /**
@@ -673,9 +679,19 @@ public class BubbleTransitions {

        IBinder mTransition;
        final Bubble mBubble;
        final Point mDropLocation;
        final TransactionProvider mTransactionProvider;

        DraggedBubbleIconToFullscreen(Bubble bubble, Point dropLocation) {
            this(bubble, dropLocation, SurfaceControl.Transaction::new);
        }

        DraggedBubbleIconToFullscreen(Bubble bubble) {
        @VisibleForTesting
        DraggedBubbleIconToFullscreen(Bubble bubble, Point dropLocation,
                TransactionProvider transactionProvider) {
            mBubble = bubble;
            mDropLocation = dropLocation;
            mTransactionProvider = transactionProvider;
            bubble.setPreparingTransition(this);
            WindowContainerToken token = bubble.getTaskView().getTaskInfo().getToken();
            WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -723,8 +739,34 @@ public class BubbleTransitions {
            }
            mRepository.remove(taskViewTaskController);

            final SurfaceControl taskLeash = change.getLeash();
            // set the initial position of the task with 0 scale
            startTransaction.setPosition(taskLeash, mDropLocation.x, mDropLocation.y);
            startTransaction.setScale(taskLeash, 0, 0);
            startTransaction.apply();

            final SurfaceControl.Transaction animT = mTransactionProvider.get();
            ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
            animator.setDuration(250);
            animator.addUpdateListener(new AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(@NonNull Animator animation) {
                    float progress = animator.getAnimatedFraction();
                    float x = mDropLocation.x * (1 - progress);
                    float y = mDropLocation.y * (1 - progress);
                    animT.setPosition(taskLeash, x, y);
                    animT.setScale(taskLeash, progress, progress);
                    animT.apply();
                }
            });
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(@NonNull Animator animation) {
                    animT.close();
                    finishCallback.onTransitionFinished(null);
                }
            });
            animator.start();
            taskViewTaskController.notifyTaskRemovalStarted(mBubble.getTaskView().getTaskInfo());
            mTaskViewTransitions.onExternalDone(transition);
            return true;
@@ -774,4 +816,8 @@ public class BubbleTransitions {
            mTaskViewTransitions.onExternalDone(transition);
        }
    }

    interface TransactionProvider {
        SurfaceControl.Transaction get();
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.bubbles;

import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.UserHandle;
import com.android.wm.shell.bubbles.IBubblesListener;
@@ -59,5 +60,5 @@ interface IBubbles {

    oneway void showDropTarget(in boolean show, in @nullable BubbleBarLocation location) = 15;

    oneway void moveBubbleToFullscreen(in String key) = 16;
    oneway void moveDraggedBubbleToFullscreen(in String key, in Point dropLocation) = 16;
}
 No newline at end of file
+26 −6
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -37,6 +38,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.ActivityManager;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.IBinder;
@@ -47,7 +49,9 @@ import android.window.TransitionInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import androidx.core.animation.AnimatorTestRule;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.launcher3.icons.BubbleIconFactory;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -65,6 +69,7 @@ import com.android.wm.shell.taskview.TaskViewTransitions;
import com.android.wm.shell.transition.Transitions;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -76,6 +81,8 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class BubbleTransitionsTest extends ShellTestCase {

    @Rule public final AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule();

    private static final int FULLSCREEN_TASK_WIDTH = 200;
    private static final int FULLSCREEN_TASK_HEIGHT = 100;

@@ -292,24 +299,37 @@ public class BubbleTransitionsTest extends ShellTestCase {
    @Test
    public void convertDraggedBubbleToFullscreen() {
        ActivityManager.RunningTaskInfo taskInfo = setupBubble();
        SurfaceControl.Transaction animT = mock(SurfaceControl.Transaction.class);
        BubbleTransitions.TransactionProvider transactionProvider = () -> animT;
        final DraggedBubbleIconToFullscreen bt =
                (DraggedBubbleIconToFullscreen) mBubbleTransitions
                        .startDraggedBubbleIconToFullscreen(mBubble);
                mBubbleTransitions.new DraggedBubbleIconToFullscreen(
                        mBubble, new Point(100, 50), transactionProvider);
        verify(mTransitions).startTransition(anyInt(), any(), eq(bt));

        SurfaceControl taskLeash = new SurfaceControl.Builder().setName("taskLeash").build();
        final TransitionInfo info = new TransitionInfo(TRANSIT_TO_FRONT, 0);
        final TransitionInfo.Change chg = new TransitionInfo.Change(taskInfo.token,
                mock(SurfaceControl.class));
        final TransitionInfo.Change chg = new TransitionInfo.Change(taskInfo.token, taskLeash);
        chg.setMode(TRANSIT_TO_FRONT);
        chg.setTaskInfo(taskInfo);
        info.addChange(chg);
        info.addRoot(new TransitionInfo.Root(0, mock(SurfaceControl.class), 0, 0));
        SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
        SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
        Transitions.TransitionFinishCallback finishCb = wct -> {};
        boolean[] transitionFinished = {false};
        Transitions.TransitionFinishCallback finishCb = wct -> transitionFinished[0] = true;
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            bt.startAnimation(bt.mTransition, info, startT, finishT, finishCb);
            mAnimatorTestRule.advanceTimeBy(250);
        });
        verify(startT).setScale(taskLeash, 0, 0);
        verify(startT).setPosition(taskLeash, 100, 50);
        verify(startT).apply();
        verify(animT).setScale(taskLeash, 1, 1);
        verify(animT).setPosition(taskLeash, 0, 0);
        verify(animT, atLeastOnce()).apply();
        verify(animT).close();
        assertFalse(mTaskViewTransitions.hasPending());
        assertTrue(transitionFinished[0]);
    }

    @Test