Merge "Only override ActivityEmbedding animation for embedded activities" into tm-qpr-dev
This commit is contained in:
@@ -39,13 +39,13 @@ interface ITaskFragmentOrganizerController {
|
||||
* animations if the transition only contains windows that belong to the organized
|
||||
* TaskFragments in the given Task.
|
||||
*/
|
||||
void registerRemoteAnimations(in ITaskFragmentOrganizer organizer, int taskId,
|
||||
void registerRemoteAnimations(in ITaskFragmentOrganizer organizer,
|
||||
in RemoteAnimationDefinition definition);
|
||||
|
||||
/**
|
||||
* Unregisters remote animations per transition type for the organizer.
|
||||
*/
|
||||
void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer, int taskId);
|
||||
void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer);
|
||||
|
||||
/**
|
||||
* Checks if an activity organized by a {@link android.window.TaskFragmentOrganizer} and
|
||||
|
||||
@@ -140,16 +140,13 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
|
||||
/**
|
||||
* Registers remote animations per transition type for the organizer. It will override the
|
||||
* animations if the transition only contains windows that belong to the organized
|
||||
* TaskFragments in the given Task.
|
||||
*
|
||||
* @param taskId overrides if the transition only contains windows belonging to this Task.
|
||||
* TaskFragments, and at least one of the transition window is embedded (not filling the Task).
|
||||
* @hide
|
||||
*/
|
||||
@CallSuper
|
||||
public void registerRemoteAnimations(int taskId,
|
||||
@NonNull RemoteAnimationDefinition definition) {
|
||||
public void registerRemoteAnimations(@NonNull RemoteAnimationDefinition definition) {
|
||||
try {
|
||||
getController().registerRemoteAnimations(mInterface, taskId, definition);
|
||||
getController().registerRemoteAnimations(mInterface, definition);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -160,9 +157,9 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
|
||||
* @hide
|
||||
*/
|
||||
@CallSuper
|
||||
public void unregisterRemoteAnimations(int taskId) {
|
||||
public void unregisterRemoteAnimations() {
|
||||
try {
|
||||
getController().unregisterRemoteAnimations(mInterface, taskId);
|
||||
getController().unregisterRemoteAnimations(mInterface);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import android.window.TaskFragmentOrganizer;
|
||||
import android.window.TaskFragmentTransaction;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -85,26 +84,20 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
@Override
|
||||
public void unregisterOrganizer() {
|
||||
if (mAnimationController != null) {
|
||||
mAnimationController.unregisterAllRemoteAnimations();
|
||||
mAnimationController.unregisterRemoteAnimations();
|
||||
mAnimationController = null;
|
||||
}
|
||||
super.unregisterOrganizer();
|
||||
}
|
||||
|
||||
/** Overrides the animation if the transition is on the given Task. */
|
||||
void startOverrideSplitAnimation(int taskId) {
|
||||
/**
|
||||
* Overrides the animation for transitions of embedded activities organized by this organizer.
|
||||
*/
|
||||
void overrideSplitAnimation() {
|
||||
if (mAnimationController == null) {
|
||||
mAnimationController = new TaskFragmentAnimationController(this);
|
||||
}
|
||||
mAnimationController.registerRemoteAnimations(taskId);
|
||||
}
|
||||
|
||||
/** No longer overrides the animation if the transition is on the given Task. */
|
||||
@GuardedBy("mLock")
|
||||
void stopOverrideSplitAnimation(int taskId) {
|
||||
if (mAnimationController != null) {
|
||||
mAnimationController.unregisterRemoteAnimations(taskId);
|
||||
}
|
||||
mAnimationController.registerRemoteAnimations();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -193,7 +193,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
continue;
|
||||
}
|
||||
updateContainersInTask(wct, taskContainer);
|
||||
updateAnimationOverride(taskContainer);
|
||||
}
|
||||
// The WCT should be applied and merged to the device state change transition if
|
||||
// there is one.
|
||||
@@ -208,9 +207,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
synchronized (mLock) {
|
||||
mSplitRules.clear();
|
||||
mSplitRules.addAll(rules);
|
||||
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
||||
updateAnimationOverride(mTaskContainers.valueAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,7 +608,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
if (taskContainer.isEmpty()) {
|
||||
// Cleanup the TaskContainer if it becomes empty.
|
||||
mPresenter.stopOverrideSplitAnimation(taskContainer.getTaskId());
|
||||
mTaskContainers.remove(taskContainer.getTaskId());
|
||||
}
|
||||
return;
|
||||
@@ -622,43 +617,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
@GuardedBy("mLock")
|
||||
private void onTaskContainerInfoChanged(@NonNull TaskContainer taskContainer,
|
||||
@NonNull Configuration config) {
|
||||
final boolean wasInPip = taskContainer.isInPictureInPicture();
|
||||
final boolean isInPIp = isInPictureInPicture(config);
|
||||
|
||||
// We need to check the animation override when enter/exit PIP or has bounds changed.
|
||||
boolean shouldUpdateAnimationOverride = wasInPip != isInPIp;
|
||||
if (taskContainer.setTaskBounds(config.windowConfiguration.getBounds())
|
||||
&& !isInPIp) {
|
||||
// We don't care the bounds change when it has already entered PIP.
|
||||
shouldUpdateAnimationOverride = true;
|
||||
}
|
||||
if (shouldUpdateAnimationOverride) {
|
||||
updateAnimationOverride(taskContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates if we should override transition animation. We only want to override if the Task
|
||||
* bounds is large enough for at least one split rule.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private void updateAnimationOverride(@NonNull TaskContainer taskContainer) {
|
||||
if (ENABLE_SHELL_TRANSITIONS) {
|
||||
// TODO(b/207070762): cleanup with legacy app transition
|
||||
// Animation will be handled by WM Shell with Shell transition enabled.
|
||||
return;
|
||||
}
|
||||
if (!taskContainer.isTaskBoundsInitialized()) {
|
||||
// We don't know about the Task bounds/windowingMode yet.
|
||||
return;
|
||||
}
|
||||
|
||||
// We only want to override if the TaskContainer may show split.
|
||||
if (mayShowSplit(taskContainer)) {
|
||||
mPresenter.startOverrideSplitAnimation(taskContainer.getTaskId());
|
||||
} else {
|
||||
mPresenter.stopOverrideSplitAnimation(taskContainer.getTaskId());
|
||||
}
|
||||
taskContainer.setTaskBounds(config.windowConfiguration.getBounds());
|
||||
}
|
||||
|
||||
/** Returns whether the given {@link TaskContainer} may show in split. */
|
||||
@@ -1283,7 +1242,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
|
||||
}
|
||||
}
|
||||
updateAnimationOverride(taskContainer);
|
||||
return container;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,11 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
super(executor, controller);
|
||||
mController = controller;
|
||||
registerOrganizer();
|
||||
if (!SplitController.ENABLE_SHELL_TRANSITIONS) {
|
||||
// TODO(b/207070762): cleanup with legacy app transition
|
||||
// Animation will be handled by WM Shell when Shell transition is enabled.
|
||||
overrideSplitAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,13 +18,10 @@ package androidx.window.extensions.embedding;
|
||||
|
||||
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
|
||||
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import android.view.RemoteAnimationDefinition;
|
||||
@@ -44,8 +41,7 @@ class TaskFragmentAnimationController {
|
||||
private final TaskFragmentAnimationRunner mRemoteRunner = new TaskFragmentAnimationRunner();
|
||||
@VisibleForTesting
|
||||
final RemoteAnimationDefinition mDefinition;
|
||||
/** Task Ids that we have registered for remote animation. */
|
||||
private final ArraySet<Integer> mRegisterTasks = new ArraySet<>();
|
||||
private boolean mIsRegistered;
|
||||
|
||||
TaskFragmentAnimationController(@NonNull TaskFragmentOrganizer organizer) {
|
||||
mOrganizer = organizer;
|
||||
@@ -54,39 +50,30 @@ class TaskFragmentAnimationController {
|
||||
new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */);
|
||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter);
|
||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter);
|
||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_OPEN, animationAdapter);
|
||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter);
|
||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter);
|
||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter);
|
||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter);
|
||||
}
|
||||
|
||||
void registerRemoteAnimations(int taskId) {
|
||||
void registerRemoteAnimations() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "registerRemoteAnimations");
|
||||
}
|
||||
if (mRegisterTasks.contains(taskId)) {
|
||||
if (mIsRegistered) {
|
||||
return;
|
||||
}
|
||||
mOrganizer.registerRemoteAnimations(taskId, mDefinition);
|
||||
mRegisterTasks.add(taskId);
|
||||
mOrganizer.registerRemoteAnimations(mDefinition);
|
||||
mIsRegistered = true;
|
||||
}
|
||||
|
||||
void unregisterRemoteAnimations(int taskId) {
|
||||
void unregisterRemoteAnimations() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "unregisterRemoteAnimations");
|
||||
}
|
||||
if (!mRegisterTasks.contains(taskId)) {
|
||||
if (!mIsRegistered) {
|
||||
return;
|
||||
}
|
||||
mOrganizer.unregisterRemoteAnimations(taskId);
|
||||
mRegisterTasks.remove(taskId);
|
||||
}
|
||||
|
||||
void unregisterAllRemoteAnimations() {
|
||||
final ArraySet<Integer> tasks = new ArraySet<>(mRegisterTasks);
|
||||
for (int taskId : tasks) {
|
||||
unregisterRemoteAnimations(taskId);
|
||||
}
|
||||
mOrganizer.unregisterRemoteAnimations();
|
||||
mIsRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,9 @@ import static android.os.Process.THREAD_PRIORITY_DISPLAY;
|
||||
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
|
||||
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -169,11 +167,9 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub {
|
||||
switch (transit) {
|
||||
case TRANSIT_OLD_ACTIVITY_OPEN:
|
||||
case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
|
||||
case TRANSIT_OLD_TASK_OPEN:
|
||||
return createOpenAnimationAdapters(targets);
|
||||
case TRANSIT_OLD_ACTIVITY_CLOSE:
|
||||
case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
|
||||
case TRANSIT_OLD_TASK_CLOSE:
|
||||
return createCloseAnimationAdapters(targets);
|
||||
case TRANSIT_OLD_TASK_FRAGMENT_CHANGE:
|
||||
return createChangeAnimationAdapters(targets);
|
||||
|
||||
@@ -18,7 +18,6 @@ package androidx.window.extensions.embedding;
|
||||
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
@@ -26,10 +25,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
@@ -85,35 +82,20 @@ public class JetpackTaskFragmentOrganizerTest {
|
||||
|
||||
@Test
|
||||
public void testUnregisterOrganizer() {
|
||||
mOrganizer.startOverrideSplitAnimation(TASK_ID);
|
||||
mOrganizer.startOverrideSplitAnimation(TASK_ID + 1);
|
||||
mOrganizer.overrideSplitAnimation();
|
||||
mOrganizer.unregisterOrganizer();
|
||||
|
||||
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
|
||||
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID + 1);
|
||||
verify(mOrganizer).unregisterRemoteAnimations();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartOverrideSplitAnimation() {
|
||||
public void testOverrideSplitAnimation() {
|
||||
assertNull(mOrganizer.mAnimationController);
|
||||
|
||||
mOrganizer.startOverrideSplitAnimation(TASK_ID);
|
||||
mOrganizer.overrideSplitAnimation();
|
||||
|
||||
assertNotNull(mOrganizer.mAnimationController);
|
||||
verify(mOrganizer).registerRemoteAnimations(TASK_ID,
|
||||
mOrganizer.mAnimationController.mDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopOverrideSplitAnimation() {
|
||||
mOrganizer.stopOverrideSplitAnimation(TASK_ID);
|
||||
|
||||
verify(mOrganizer, never()).unregisterRemoteAnimations(anyInt());
|
||||
|
||||
mOrganizer.startOverrideSplitAnimation(TASK_ID);
|
||||
mOrganizer.stopOverrideSplitAnimation(TASK_ID);
|
||||
|
||||
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
|
||||
verify(mOrganizer).registerRemoteAnimations(mOrganizer.mAnimationController.mDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
|
||||
package androidx.window.extensions.embedding;
|
||||
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -57,41 +54,31 @@ public class TaskFragmentAnimationControllerTest {
|
||||
|
||||
@Test
|
||||
public void testRegisterRemoteAnimations() {
|
||||
mAnimationController.registerRemoteAnimations(TASK_ID);
|
||||
mAnimationController.registerRemoteAnimations();
|
||||
|
||||
verify(mOrganizer).registerRemoteAnimations(TASK_ID, mAnimationController.mDefinition);
|
||||
verify(mOrganizer).registerRemoteAnimations(mAnimationController.mDefinition);
|
||||
|
||||
mAnimationController.registerRemoteAnimations(TASK_ID);
|
||||
mAnimationController.registerRemoteAnimations();
|
||||
|
||||
// No extra call if it has been registered.
|
||||
verify(mOrganizer).registerRemoteAnimations(TASK_ID, mAnimationController.mDefinition);
|
||||
verify(mOrganizer).registerRemoteAnimations(mAnimationController.mDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterRemoteAnimations() {
|
||||
mAnimationController.unregisterRemoteAnimations(TASK_ID);
|
||||
mAnimationController.unregisterRemoteAnimations();
|
||||
|
||||
// No call if it is not registered.
|
||||
verify(mOrganizer, never()).unregisterRemoteAnimations(anyInt());
|
||||
verify(mOrganizer, never()).unregisterRemoteAnimations();
|
||||
|
||||
mAnimationController.registerRemoteAnimations(TASK_ID);
|
||||
mAnimationController.unregisterRemoteAnimations(TASK_ID);
|
||||
mAnimationController.registerRemoteAnimations();
|
||||
mAnimationController.unregisterRemoteAnimations();
|
||||
|
||||
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
|
||||
verify(mOrganizer).unregisterRemoteAnimations();
|
||||
|
||||
mAnimationController.unregisterRemoteAnimations(TASK_ID);
|
||||
mAnimationController.unregisterRemoteAnimations();
|
||||
|
||||
// No extra call if it has been unregistered.
|
||||
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterAllRemoteAnimations() {
|
||||
mAnimationController.registerRemoteAnimations(TASK_ID);
|
||||
mAnimationController.registerRemoteAnimations(TASK_ID + 1);
|
||||
mAnimationController.unregisterAllRemoteAnimations();
|
||||
|
||||
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
|
||||
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID + 1);
|
||||
verify(mOrganizer).unregisterRemoteAnimations();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,6 +561,34 @@ public class AppTransitionController {
|
||||
|| shouldStartWallpaperAnimation(mDisplayContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the transition contains any embedded {@link TaskFragment} that does not fill the
|
||||
* parent {@link Task} before or after the transition.
|
||||
*/
|
||||
private boolean transitionContainsTaskFragmentWithBoundsOverride() {
|
||||
for (int i = mDisplayContent.mChangingContainers.size() - 1; i >= 0; i--) {
|
||||
final WindowContainer wc = mDisplayContent.mChangingContainers.valueAt(i);
|
||||
if (wc.isEmbedded()) {
|
||||
// Contains embedded TaskFragment with bounds changed.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
mTempTransitionWindows.clear();
|
||||
mTempTransitionWindows.addAll(mDisplayContent.mClosingApps);
|
||||
mTempTransitionWindows.addAll(mDisplayContent.mOpeningApps);
|
||||
boolean containsTaskFragmentWithBoundsOverride = false;
|
||||
for (int i = mTempTransitionWindows.size() - 1; i >= 0; i--) {
|
||||
final ActivityRecord r = mTempTransitionWindows.get(i).asActivityRecord();
|
||||
final TaskFragment tf = r.getTaskFragment();
|
||||
if (tf != null && tf.isEmbeddedWithBoundsOverride()) {
|
||||
containsTaskFragmentWithBoundsOverride = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mTempTransitionWindows.clear();
|
||||
return containsTaskFragmentWithBoundsOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the common parent {@link Task} that is parent of all embedded app windows in the
|
||||
* current transition.
|
||||
@@ -664,12 +692,17 @@ public class AppTransitionController {
|
||||
if (transitionMayContainNonAppWindows(transit)) {
|
||||
return false;
|
||||
}
|
||||
if (!transitionContainsTaskFragmentWithBoundsOverride()) {
|
||||
// No need to play TaskFragment remote animation if all embedded TaskFragment in the
|
||||
// transition fill the Task.
|
||||
return false;
|
||||
}
|
||||
|
||||
final Task task = findParentTaskForAllEmbeddedWindows();
|
||||
final ITaskFragmentOrganizer organizer = findTaskFragmentOrganizer(task);
|
||||
final RemoteAnimationDefinition definition = organizer != null
|
||||
? mDisplayContent.mAtmService.mTaskFragmentOrganizerController
|
||||
.getRemoteAnimationDefinition(organizer, task.mTaskId)
|
||||
.getRemoteAnimationDefinition(organizer)
|
||||
: null;
|
||||
final RemoteAnimationAdapter adapter = definition != null
|
||||
? definition.getAdapter(transit, activityTypes)
|
||||
|
||||
@@ -581,15 +581,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
|
||||
@Override
|
||||
boolean isEmbedded() {
|
||||
if (mIsEmbedded) {
|
||||
return true;
|
||||
}
|
||||
final WindowContainer<?> parent = getParent();
|
||||
if (parent != null) {
|
||||
final TaskFragment taskFragment = parent.asTaskFragment();
|
||||
return taskFragment != null && taskFragment.isEmbedded();
|
||||
}
|
||||
return false;
|
||||
return mIsEmbedded;
|
||||
}
|
||||
|
||||
@EmbeddingCheckResult
|
||||
@@ -2519,6 +2511,22 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
return mTaskFragmentOrganizer != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this is an embedded {@link TaskFragment} that does not fill the parent {@link Task}.
|
||||
*/
|
||||
boolean isEmbeddedWithBoundsOverride() {
|
||||
if (!mIsEmbedded) {
|
||||
return false;
|
||||
}
|
||||
final Task task = getTask();
|
||||
if (task == null) {
|
||||
return false;
|
||||
}
|
||||
final Rect taskBounds = task.getBounds();
|
||||
final Rect taskFragBounds = getBounds();
|
||||
return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds);
|
||||
}
|
||||
|
||||
/** Whether the Task should be visible. */
|
||||
boolean isTaskVisibleRequested() {
|
||||
final Task task = getTask();
|
||||
|
||||
@@ -36,7 +36,6 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -133,12 +132,11 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Map from Task Id to {@link RemoteAnimationDefinition}.
|
||||
* @see android.window.TaskFragmentOrganizer#registerRemoteAnimations(int,
|
||||
* RemoteAnimationDefinition) )
|
||||
* {@link RemoteAnimationDefinition} for embedded activities transition animation that is
|
||||
* organized by this organizer.
|
||||
*/
|
||||
private final SparseArray<RemoteAnimationDefinition> mRemoteAnimationDefinitions =
|
||||
new SparseArray<>();
|
||||
@Nullable
|
||||
private RemoteAnimationDefinition mRemoteAnimationDefinition;
|
||||
|
||||
/**
|
||||
* Map from {@link TaskFragmentTransaction#getTransactionToken()} to the
|
||||
@@ -455,7 +453,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer, int taskId,
|
||||
public void registerRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer,
|
||||
@NonNull RemoteAnimationDefinition definition) {
|
||||
final int pid = Binder.getCallingPid();
|
||||
final int uid = Binder.getCallingUid();
|
||||
@@ -468,20 +466,19 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
if (organizerState == null) {
|
||||
throw new IllegalStateException("The organizer hasn't been registered.");
|
||||
}
|
||||
if (organizerState.mRemoteAnimationDefinitions.contains(taskId)) {
|
||||
if (organizerState.mRemoteAnimationDefinition != null) {
|
||||
throw new IllegalStateException(
|
||||
"The organizer has already registered remote animations="
|
||||
+ organizerState.mRemoteAnimationDefinitions.get(taskId)
|
||||
+ " for TaskId=" + taskId);
|
||||
+ organizerState.mRemoteAnimationDefinition);
|
||||
}
|
||||
|
||||
definition.setCallingPidUid(pid, uid);
|
||||
organizerState.mRemoteAnimationDefinitions.put(taskId, definition);
|
||||
organizerState.mRemoteAnimationDefinition = definition;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer, int taskId) {
|
||||
public void unregisterRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer) {
|
||||
final int pid = Binder.getCallingPid();
|
||||
final long uid = Binder.getCallingUid();
|
||||
synchronized (mGlobalLock) {
|
||||
@@ -495,7 +492,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
return;
|
||||
}
|
||||
|
||||
organizerState.mRemoteAnimationDefinitions.remove(taskId);
|
||||
organizerState.mRemoteAnimationDefinition = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,16 +524,16 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
|
||||
/**
|
||||
* Gets the {@link RemoteAnimationDefinition} set on the given organizer if exists. Returns
|
||||
* {@code null} if it doesn't, or if the organizer has activity(ies) embedded in untrusted mode.
|
||||
* {@code null} if it doesn't.
|
||||
*/
|
||||
@Nullable
|
||||
public RemoteAnimationDefinition getRemoteAnimationDefinition(
|
||||
@NonNull ITaskFragmentOrganizer organizer, int taskId) {
|
||||
@NonNull ITaskFragmentOrganizer organizer) {
|
||||
synchronized (mGlobalLock) {
|
||||
final TaskFragmentOrganizerState organizerState =
|
||||
mTaskFragmentOrganizerState.get(organizer.asBinder());
|
||||
return organizerState != null
|
||||
? organizerState.mRemoteAnimationDefinitions.get(taskId)
|
||||
? organizerState.mRemoteAnimationDefinition
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -1085,16 +1082,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
return false;
|
||||
}
|
||||
final TaskFragment taskFragment = activity.getOrganizedTaskFragment();
|
||||
if (taskFragment == null) {
|
||||
return false;
|
||||
}
|
||||
final Task parentTask = taskFragment.getTask();
|
||||
if (parentTask != null) {
|
||||
final Rect taskBounds = parentTask.getBounds();
|
||||
final Rect taskFragBounds = taskFragment.getBounds();
|
||||
return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds);
|
||||
}
|
||||
return false;
|
||||
return taskFragment != null && taskFragment.isEmbeddedWithBoundsOverride();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_DREAM_ACTIVITY_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_DREAM_ACTIVITY_OPEN;
|
||||
@@ -56,6 +57,7 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Rect;
|
||||
import android.gui.DropInputMode;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
@@ -918,7 +920,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Create a TaskFragment with embedded activity.
|
||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||
@@ -934,12 +936,78 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
assertTrue(remoteAnimationRunner.isAnimationStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverrideTaskFragmentAdapter_noOverrideWithOnlyTaskFragmentFillingTask() {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final ActivityRecord closingActivity = createActivityRecord(task);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Create a TaskFragment with embedded activity.
|
||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||
|
||||
// Make sure the TaskFragment is not embedded.
|
||||
assertFalse(taskFragment.isEmbeddedWithBoundsOverride());
|
||||
final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
|
||||
prepareActivityForAppTransition(closingActivity);
|
||||
prepareActivityForAppTransition(openingActivity);
|
||||
final int uid = 12345;
|
||||
closingActivity.info.applicationInfo.uid = uid;
|
||||
openingActivity.info.applicationInfo.uid = uid;
|
||||
task.effectiveUid = uid;
|
||||
spyOn(mDisplayContent.mAppTransition);
|
||||
|
||||
// Prepare and start transition.
|
||||
prepareAndTriggerAppTransition(openingActivity, closingActivity,
|
||||
null /* changingTaskFragment */);
|
||||
mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
|
||||
|
||||
// Animation is not run by the remote handler because the activity is filling the Task.
|
||||
assertFalse(remoteAnimationRunner.isAnimationStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverrideTaskFragmentAdapter_overrideWithTaskFragmentNotFillingTask() {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final ActivityRecord closingActivity = createActivityRecord(task);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Create a TaskFragment with embedded activity.
|
||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||
|
||||
// Make sure the TaskFragment is embedded.
|
||||
taskFragment.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
|
||||
final Rect embeddedBounds = new Rect(task.getBounds());
|
||||
embeddedBounds.right = embeddedBounds.left + embeddedBounds.width() / 2;
|
||||
taskFragment.setBounds(embeddedBounds);
|
||||
assertTrue(taskFragment.isEmbeddedWithBoundsOverride());
|
||||
final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
|
||||
prepareActivityForAppTransition(closingActivity);
|
||||
prepareActivityForAppTransition(openingActivity);
|
||||
final int uid = 12345;
|
||||
closingActivity.info.applicationInfo.uid = uid;
|
||||
openingActivity.info.applicationInfo.uid = uid;
|
||||
task.effectiveUid = uid;
|
||||
spyOn(mDisplayContent.mAppTransition);
|
||||
|
||||
// Prepare and start transition.
|
||||
prepareAndTriggerAppTransition(openingActivity, closingActivity,
|
||||
null /* changingTaskFragment */);
|
||||
mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
|
||||
|
||||
// Animation run by the remote handler.
|
||||
assertTrue(remoteAnimationRunner.isAnimationStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverrideTaskFragmentAdapter_overrideWithNonEmbeddedActivity() {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Closing non-embedded activity.
|
||||
final ActivityRecord closingActivity = createActivityRecord(task);
|
||||
@@ -964,7 +1032,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Closing TaskFragment with embedded activity.
|
||||
final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||
@@ -991,7 +1059,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Closing activity in Task1.
|
||||
final ActivityRecord closingActivity = createActivityRecord(mDisplayContent);
|
||||
@@ -1015,7 +1083,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Closing TaskFragment with embedded activity.
|
||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||
@@ -1043,7 +1111,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Create a TaskFragment with embedded activity.
|
||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||
@@ -1069,7 +1137,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Create a TaskFragment with embedded activities, one is trusted embedded, and the other
|
||||
// one is untrusted embedded.
|
||||
@@ -1128,7 +1196,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Create a TaskFragment with only trusted embedded activity
|
||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||
@@ -1168,7 +1236,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
||||
|
||||
// Create a TaskFragment with only trusted embedded activity
|
||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||
@@ -1259,7 +1327,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
}
|
||||
|
||||
/** Registers remote animation for the organizer. */
|
||||
private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer, int taskId,
|
||||
private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer,
|
||||
TestRemoteAnimationRunner remoteAnimationRunner) {
|
||||
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
||||
remoteAnimationRunner, 10, 1);
|
||||
@@ -1268,9 +1336,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, adapter);
|
||||
definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, adapter);
|
||||
definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, adapter);
|
||||
definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, adapter);
|
||||
definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, adapter);
|
||||
mAtm.mTaskFragmentOrganizerController.registerOrganizer(iOrganizer);
|
||||
mAtm.mTaskFragmentOrganizerController.registerRemoteAnimations(iOrganizer, taskId,
|
||||
definition);
|
||||
mAtm.mTaskFragmentOrganizerController.registerRemoteAnimations(iOrganizer, definition);
|
||||
}
|
||||
|
||||
private static ITaskFragmentOrganizer getITaskFragmentOrganizer(
|
||||
|
||||
@@ -474,13 +474,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
|
||||
@Test
|
||||
public void testRegisterRemoteAnimations() {
|
||||
mController.registerRemoteAnimations(mIOrganizer, TASK_ID, mDefinition);
|
||||
mController.registerRemoteAnimations(mIOrganizer, mDefinition);
|
||||
|
||||
assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer, TASK_ID));
|
||||
assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer));
|
||||
|
||||
mController.unregisterRemoteAnimations(mIOrganizer, TASK_ID);
|
||||
mController.unregisterRemoteAnimations(mIOrganizer);
|
||||
|
||||
assertNull(mController.getRemoteAnimationDefinition(mIOrganizer, TASK_ID));
|
||||
assertNull(mController.getRemoteAnimationDefinition(mIOrganizer));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user