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

Commit 4659d8a4 authored by Chris Li's avatar Chris Li
Browse files

Show bg color during ActivityEmbedding change anim with Shell transition

When switching between horizontal split and vertical split, it will
leave part of the screen empty. Show background color to cover that.

Also fix the leash start position.

Bug: 241043533
Bug: 254090083
Test: atest WmTests:TransitionTests#testChangeSetBackgroundColor
Test: verify with horizontal demo app
Change-Id: I125db07a631b19bd33bcff9935fe39f263cbb263
parent fe8b17d4
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -303,6 +303,7 @@ class ActivityEmbeddingAnimationRunner {
        // 3. Animate the TaskFragment using Activity Change info (start/end bounds).
        // This is because the TaskFragment surface/change won't contain the Activity's before its
        // reparent.
        Animation changeAnimation = null;
        for (TransitionInfo.Change change : info.getChanges()) {
            if (change.getMode() != TRANSIT_CHANGE
                    || change.getStartAbsBounds().equals(change.getEndAbsBounds())) {
@@ -325,8 +326,14 @@ class ActivityEmbeddingAnimationRunner {
                }
            }

            // There are two animations in the array. The first one is for the start leash
            // (snapshot), and the second one is for the end leash (TaskFragment).
            final Animation[] animations = mAnimationSpec.createChangeBoundsChangeAnimations(change,
                    boundsAnimationChange.getEndAbsBounds());
            // Keep track as we might need to add background color for the animation.
            // Although there may be multiple change animation, record one of them is sufficient
            // because the background color will be added to the root leash for the whole animation.
            changeAnimation = animations[1];

            // Create a screenshot based on change, but attach it to the top of the
            // boundsAnimationChange.
@@ -345,6 +352,9 @@ class ActivityEmbeddingAnimationRunner {
                    animations[1], boundsAnimationChange));
        }

        // If there is no corresponding open/close window with the change, we should show background
        // color to cover the empty part of the screen.
        boolean shouldShouldBackgroundColor = true;
        // Handle the other windows that don't have bounds change in the same transition.
        for (TransitionInfo.Change change : info.getChanges()) {
            if (handledChanges.contains(change)) {
@@ -359,11 +369,20 @@ class ActivityEmbeddingAnimationRunner {
                animation = ActivityEmbeddingAnimationSpec.createNoopAnimation(change);
            } else if (Transitions.isClosingType(change.getMode())) {
                animation = mAnimationSpec.createChangeBoundsCloseAnimation(change);
                shouldShouldBackgroundColor = false;
            } else {
                animation = mAnimationSpec.createChangeBoundsOpenAnimation(change);
                shouldShouldBackgroundColor = false;
            }
            adapters.add(new ActivityEmbeddingAnimationAdapter(animation, change));
        }

        if (shouldShouldBackgroundColor && changeAnimation != null) {
            // Change animation may leave part of the screen empty. Show background color to cover
            // that.
            changeAnimation.setShowBackdrop(true);
        }

        return adapters;
    }

+1 −1
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ class ActivityEmbeddingAnimationSpec {
        // The position should be 0-based as we will post translate in
        // ActivityEmbeddingAnimationAdapter#onAnimationUpdate
        final Animation endTranslate = new TranslateAnimation(startBounds.left - endBounds.left, 0,
                0, 0);
                startBounds.top - endBounds.top, 0);
        endTranslate.setDuration(CHANGE_ANIMATION_DURATION);
        endSet.addAnimation(endTranslate);
        // The end leash is resizing, we should update the window crop based on the clip rect.
+16 −5
Original line number Diff line number Diff line
@@ -1602,7 +1602,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            change.setMode(info.getTransitMode(target));
            change.setStartAbsBounds(info.mAbsoluteBounds);
            change.setFlags(info.getChangeFlags(target));

            final Task task = target.asTask();
            final TaskFragment taskFragment = target.asTaskFragment();
            final ActivityRecord activityRecord = target.asActivityRecord();

            if (task != null) {
                final ActivityManager.RunningTaskInfo tinfo = new ActivityManager.RunningTaskInfo();
                task.fillTaskInfo(tinfo);
@@ -1636,12 +1640,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            change.setEndRelOffset(bounds.left - parentBounds.left,
                    bounds.top - parentBounds.top);
            int endRotation = target.getWindowConfiguration().getRotation();
            final ActivityRecord activityRecord = target.asActivityRecord();
            if (activityRecord != null) {
                final Task arTask = activityRecord.getTask();
                final int backgroundColor = ColorUtils.setAlphaComponent(
                        arTask.getTaskDescription().getBackgroundColor(), 255);
                change.setBackgroundColor(backgroundColor);
                // TODO(b/227427984): Shell needs to aware letterbox.
                // Always use parent bounds of activity because letterbox area (e.g. fixed aspect
                // ratio or size compat mode) should be included in the animation.
@@ -1654,6 +1653,18 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            } else {
                change.setEndAbsBounds(bounds);
            }

            if (activityRecord != null || (taskFragment != null && taskFragment.isEmbedded())) {
                // Set background color to Task theme color for activity and embedded TaskFragment
                // in case we want to show background during the animation.
                final Task parentTask = activityRecord != null
                        ? activityRecord.getTask()
                        : taskFragment.getTask();
                final int backgroundColor = ColorUtils.setAlphaComponent(
                        parentTask.getTaskDescription().getBackgroundColor(), 255);
                change.setBackgroundColor(backgroundColor);
            }

            change.setRotation(info.mRotation, endRotation);
            if (info.mSnapshot != null) {
                change.setSnapshot(info.mSnapshot, info.mSnapshotLuma);
+48 −0
Original line number Diff line number Diff line
@@ -59,7 +59,9 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.app.ActivityManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
@@ -79,6 +81,8 @@ import android.window.TransitionInfo;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;

import com.android.internal.graphics.ColorUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -1383,6 +1387,50 @@ public class TransitionTests extends WindowTestsBase {
        assertTrue(targets.contains(activity));
    }

    @Test
    public void testChangeSetBackgroundColor() {
        final Transition transition = createTestTransition(TRANSIT_CHANGE);
        final ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
        final ArraySet<WindowContainer> participants = transition.mParticipants;

        // Test background color for Activity and embedded TaskFragment.
        final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
        mAtm.mTaskFragmentOrganizerController.registerOrganizer(
                ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder()));
        final Task task = createTask(mDisplayContent);
        final TaskFragment embeddedTf = createTaskFragmentWithEmbeddedActivity(task, organizer);
        final ActivityRecord embeddedActivity = embeddedTf.getTopMostActivity();
        final ActivityRecord nonEmbeddedActivity = createActivityRecord(task);
        final ActivityManager.TaskDescription taskDescription =
                new ActivityManager.TaskDescription.Builder()
                        .setBackgroundColor(Color.YELLOW)
                        .build();
        task.setTaskDescription(taskDescription);

        // Start states:
        embeddedActivity.mVisibleRequested = true;
        nonEmbeddedActivity.mVisibleRequested = false;
        changes.put(embeddedTf, new Transition.ChangeInfo(embeddedTf));
        changes.put(nonEmbeddedActivity, new Transition.ChangeInfo(nonEmbeddedActivity));
        // End states:
        embeddedActivity.mVisibleRequested = false;
        nonEmbeddedActivity.mVisibleRequested = true;

        participants.add(embeddedTf);
        participants.add(nonEmbeddedActivity);
        final ArrayList<WindowContainer> targets = Transition.calculateTargets(
                participants, changes);
        final TransitionInfo info = Transition.calculateTransitionInfo(transition.mType,
                0 /* flags */, targets, changes, mMockT);

        // Background color should be set on both Activity and embedded TaskFragment.
        final int expectedBackgroundColor = ColorUtils.setAlphaComponent(
                taskDescription.getBackgroundColor(), 255);
        assertEquals(2, info.getChanges().size());
        assertEquals(expectedBackgroundColor, info.getChanges().get(0).getBackgroundColor());
        assertEquals(expectedBackgroundColor, info.getChanges().get(1).getBackgroundColor());
    }

    @Test
    public void testTransitionVisibleChange() {
        registerTestTransitionPlayer();