diff options
4 files changed, 84 insertions, 6 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java index 490975cce956..921861ae0913 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java @@ -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; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java index 58b23667dc18..2bb73692b457 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java @@ -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. diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 46253c1933b6..32f61978d730 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -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); diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 9fd085021d66..66e46a2bb187 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -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; @@ -1384,6 +1388,50 @@ public class TransitionTests extends WindowTestsBase { } @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(); final ActivityRecord app = createActivityRecord(mDisplayContent); |