Loading libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +19 −0 Original line number Diff line number Diff line Loading @@ -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())) { Loading @@ -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. Loading @@ -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)) { Loading @@ -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; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +1 −1 Original line number Diff line number Diff line Loading @@ -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. Loading services/core/java/com/android/server/wm/Transition.java +16 −5 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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. Loading @@ -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); Loading services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +48 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +19 −0 Original line number Diff line number Diff line Loading @@ -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())) { Loading @@ -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. Loading @@ -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)) { Loading @@ -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; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +1 −1 Original line number Diff line number Diff line Loading @@ -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. Loading
services/core/java/com/android/server/wm/Transition.java +16 −5 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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. Loading @@ -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); Loading
services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +48 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading