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
This commit is contained in:
Chris Li
2022-10-20 16:55:45 +08:00
parent fe8b17d49d
commit 4659d8a49c
4 changed files with 84 additions and 6 deletions

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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);

View File

@@ -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();