Merge "Register remote animation per Task" into tm-dev
This commit is contained in:
@@ -35,15 +35,15 @@ interface ITaskFragmentOrganizerController {
|
|||||||
/**
|
/**
|
||||||
* Registers remote animations per transition type for the organizer. It will override the
|
* 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
|
* animations if the transition only contains windows that belong to the organized
|
||||||
* TaskFragments.
|
* TaskFragments in the given Task.
|
||||||
*/
|
*/
|
||||||
void registerRemoteAnimations(in ITaskFragmentOrganizer organizer,
|
void registerRemoteAnimations(in ITaskFragmentOrganizer organizer, int taskId,
|
||||||
in RemoteAnimationDefinition definition);
|
in RemoteAnimationDefinition definition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters remote animations per transition type for the organizer.
|
* Unregisters remote animations per transition type for the organizer.
|
||||||
*/
|
*/
|
||||||
void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer);
|
void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer, int taskId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an activity organized by a {@link android.window.TaskFragmentOrganizer} and
|
* Checks if an activity organized by a {@link android.window.TaskFragmentOrganizer} and
|
||||||
|
|||||||
@@ -94,13 +94,16 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
|
|||||||
/**
|
/**
|
||||||
* Registers remote animations per transition type for the organizer. It will override the
|
* 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
|
* animations if the transition only contains windows that belong to the organized
|
||||||
* TaskFragments.
|
* TaskFragments in the given Task.
|
||||||
|
*
|
||||||
|
* @param taskId overrides if the transition only contains windows belonging to this Task.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void registerRemoteAnimations(@NonNull RemoteAnimationDefinition definition) {
|
public void registerRemoteAnimations(int taskId,
|
||||||
|
@NonNull RemoteAnimationDefinition definition) {
|
||||||
try {
|
try {
|
||||||
getController().registerRemoteAnimations(mInterface, definition);
|
getController().registerRemoteAnimations(mInterface, taskId, definition);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
@@ -111,9 +114,9 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void unregisterRemoteAnimations() {
|
public void unregisterRemoteAnimations(int taskId) {
|
||||||
try {
|
try {
|
||||||
getController().unregisterRemoteAnimations(mInterface);
|
getController().unregisterRemoteAnimations(mInterface, taskId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import android.window.WindowContainerTransaction;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
@@ -56,7 +58,8 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
|||||||
final Map<IBinder, Configuration> mFragmentParentConfigs = new ArrayMap<>();
|
final Map<IBinder, Configuration> mFragmentParentConfigs = new ArrayMap<>();
|
||||||
|
|
||||||
private final TaskFragmentCallback mCallback;
|
private final TaskFragmentCallback mCallback;
|
||||||
private TaskFragmentAnimationController mAnimationController;
|
@VisibleForTesting
|
||||||
|
TaskFragmentAnimationController mAnimationController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback that notifies the controller about changes to task fragments.
|
* Callback that notifies the controller about changes to task fragments.
|
||||||
@@ -80,21 +83,25 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterOrganizer() {
|
public void unregisterOrganizer() {
|
||||||
stopOverrideSplitAnimation();
|
if (mAnimationController != null) {
|
||||||
mAnimationController = null;
|
mAnimationController.unregisterAllRemoteAnimations();
|
||||||
|
mAnimationController = null;
|
||||||
|
}
|
||||||
super.unregisterOrganizer();
|
super.unregisterOrganizer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void startOverrideSplitAnimation() {
|
/** Overrides the animation if the transition is on the given Task. */
|
||||||
|
void startOverrideSplitAnimation(int taskId) {
|
||||||
if (mAnimationController == null) {
|
if (mAnimationController == null) {
|
||||||
mAnimationController = new TaskFragmentAnimationController(this);
|
mAnimationController = new TaskFragmentAnimationController(this);
|
||||||
}
|
}
|
||||||
mAnimationController.registerRemoteAnimations();
|
mAnimationController.registerRemoteAnimations(taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopOverrideSplitAnimation() {
|
/** No longer overrides the animation if the transition is on the given Task. */
|
||||||
|
void stopOverrideSplitAnimation(int taskId) {
|
||||||
if (mAnimationController != null) {
|
if (mAnimationController != null) {
|
||||||
mAnimationController.unregisterRemoteAnimations();
|
mAnimationController.unregisterRemoteAnimations(taskId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import android.os.Bundle;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.window.TaskFragmentInfo;
|
import android.window.TaskFragmentInfo;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
@@ -75,10 +76,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
private Consumer<List<SplitInfo>> mEmbeddingCallback;
|
private Consumer<List<SplitInfo>> mEmbeddingCallback;
|
||||||
private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
|
private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
|
||||||
|
|
||||||
// We currently only support split activity embedding within the one root Task.
|
|
||||||
// TODO(b/207720388): move to TaskContainer
|
|
||||||
private final Rect mParentBounds = new Rect();
|
|
||||||
|
|
||||||
public SplitController() {
|
public SplitController() {
|
||||||
mPresenter = new SplitPresenter(new MainThreadExecutor(), this);
|
mPresenter = new SplitPresenter(new MainThreadExecutor(), this);
|
||||||
ActivityThread activityThread = ActivityThread.currentActivityThread();
|
ActivityThread activityThread = ActivityThread.currentActivityThread();
|
||||||
@@ -95,7 +92,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) {
|
public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) {
|
||||||
mSplitRules.clear();
|
mSplitRules.clear();
|
||||||
mSplitRules.addAll(rules);
|
mSplitRules.addAll(rules);
|
||||||
updateAnimationOverride();
|
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
||||||
|
updateAnimationOverride(mTaskContainers.keyAt(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -163,38 +162,49 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||||
TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
final TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
||||||
if (container == null) {
|
if (container != null) {
|
||||||
return;
|
// Cleanup if the TaskFragment vanished is not requested by the organizer.
|
||||||
|
mPresenter.cleanupContainer(container, true /* shouldFinishDependent */);
|
||||||
|
updateCallbackIfNecessary();
|
||||||
}
|
}
|
||||||
|
cleanupTaskFragment(taskFragmentInfo.getFragmentToken());
|
||||||
mPresenter.cleanupContainer(container, true /* shouldFinishDependent */);
|
|
||||||
updateCallbackIfNecessary();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
|
public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
|
||||||
@NonNull Configuration parentConfig) {
|
@NonNull Configuration parentConfig) {
|
||||||
onParentBoundsMayChange(parentConfig.windowConfiguration.getBounds());
|
|
||||||
TaskFragmentContainer container = getContainer(fragmentToken);
|
TaskFragmentContainer container = getContainer(fragmentToken);
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
|
onTaskBoundsMayChange(container.getTaskId(),
|
||||||
|
parentConfig.windowConfiguration.getBounds());
|
||||||
mPresenter.updateContainer(container);
|
mPresenter.updateContainer(container);
|
||||||
updateCallbackIfNecessary();
|
updateCallbackIfNecessary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onParentBoundsMayChange(Activity activity) {
|
/** Called on receiving {@link #onTaskFragmentVanished(TaskFragmentInfo)} for cleanup. */
|
||||||
if (activity.isFinishing()) {
|
private void cleanupTaskFragment(@NonNull IBinder taskFragmentToken) {
|
||||||
|
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
||||||
|
final TaskContainer taskContainer = mTaskContainers.valueAt(i);
|
||||||
|
if (!taskContainer.mFinishedContainer.remove(taskFragmentToken)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (taskContainer.isEmpty()) {
|
||||||
|
// Cleanup the TaskContainer if it becomes empty.
|
||||||
|
mPresenter.stopOverrideSplitAnimation(taskContainer.mTaskId);
|
||||||
|
mTaskContainers.remove(taskContainer.mTaskId);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onParentBoundsMayChange(mPresenter.getParentContainerBounds(activity));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onParentBoundsMayChange(Rect parentBounds) {
|
private void onTaskBoundsMayChange(int taskId, @NonNull Rect taskBounds) {
|
||||||
if (!parentBounds.isEmpty() && !mParentBounds.equals(parentBounds)) {
|
final TaskContainer taskContainer = mTaskContainers.get(taskId);
|
||||||
mParentBounds.set(parentBounds);
|
if (taskContainer != null && !taskBounds.isEmpty()
|
||||||
updateAnimationOverride();
|
&& !taskContainer.mTaskBounds.equals(taskBounds)) {
|
||||||
|
taskContainer.mTaskBounds.set(taskBounds);
|
||||||
|
updateAnimationOverride(taskId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,9 +212,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
* Updates if we should override transition animation. We only want to override if the Task
|
* 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.
|
* bounds is large enough for at least one split rule.
|
||||||
*/
|
*/
|
||||||
private void updateAnimationOverride() {
|
private void updateAnimationOverride(int taskId) {
|
||||||
if (mParentBounds.isEmpty()) {
|
final TaskContainer taskContainer = mTaskContainers.get(taskId);
|
||||||
// We don't know about the parent bounds yet.
|
if (taskContainer == null || !taskContainer.isTaskBoundsInitialized()) {
|
||||||
|
// We don't know about the Task bounds yet.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +225,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
if (!(rule instanceof SplitRule)) {
|
if (!(rule instanceof SplitRule)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mPresenter.shouldShowSideBySide(mParentBounds, (SplitRule) rule)) {
|
if (mPresenter.shouldShowSideBySide(taskContainer.mTaskBounds, (SplitRule) rule)) {
|
||||||
supportSplit = true;
|
supportSplit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -222,9 +233,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
|
|
||||||
// We only want to override if it supports split.
|
// We only want to override if it supports split.
|
||||||
if (supportSplit) {
|
if (supportSplit) {
|
||||||
mPresenter.startOverrideSplitAnimation();
|
mPresenter.startOverrideSplitAnimation(taskId);
|
||||||
} else {
|
} else {
|
||||||
mPresenter.stopOverrideSplitAnimation();
|
mPresenter.stopOverrideSplitAnimation(taskId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,11 +254,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
final TaskFragmentContainer currentContainer = getContainerWithActivity(
|
final TaskFragmentContainer currentContainer = getContainerWithActivity(
|
||||||
launchedActivity.getActivityToken());
|
launchedActivity.getActivityToken());
|
||||||
|
|
||||||
if (currentContainer == null) {
|
|
||||||
// Initial check before any TaskFragment is created.
|
|
||||||
onParentBoundsMayChange(launchedActivity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the activity is configured to always be expanded.
|
// Check if the activity is configured to always be expanded.
|
||||||
if (shouldExpand(launchedActivity, null, splitRules)) {
|
if (shouldExpand(launchedActivity, null, splitRules)) {
|
||||||
if (shouldContainerBeExpanded(currentContainer)) {
|
if (shouldContainerBeExpanded(currentContainer)) {
|
||||||
@@ -326,8 +332,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
// onTaskFragmentParentInfoChanged
|
// onTaskFragmentParentInfoChanged
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The bounds of the container may have been changed.
|
|
||||||
onParentBoundsMayChange(activity);
|
|
||||||
|
|
||||||
// Check if activity requires a placeholder
|
// Check if activity requires a placeholder
|
||||||
launchPlaceholderIfNecessary(activity);
|
launchPlaceholderIfNecessary(activity);
|
||||||
@@ -357,9 +361,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
TaskFragmentContainer newContainer(@Nullable Activity activity, int taskId) {
|
TaskFragmentContainer newContainer(@Nullable Activity activity, int taskId) {
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(activity, taskId);
|
final TaskFragmentContainer container = new TaskFragmentContainer(activity, taskId);
|
||||||
if (!mTaskContainers.contains(taskId)) {
|
if (!mTaskContainers.contains(taskId)) {
|
||||||
mTaskContainers.put(taskId, new TaskContainer());
|
mTaskContainers.put(taskId, new TaskContainer(taskId));
|
||||||
|
}
|
||||||
|
final TaskContainer taskContainer = mTaskContainers.get(taskId);
|
||||||
|
taskContainer.mContainers.add(container);
|
||||||
|
if (activity != null && !taskContainer.isTaskBoundsInitialized()) {
|
||||||
|
// Initial check before any TaskFragment has appeared.
|
||||||
|
onTaskBoundsMayChange(taskId, SplitPresenter.getTaskBoundsFromActivity(activity));
|
||||||
}
|
}
|
||||||
mTaskContainers.get(taskId).mContainers.add(container);
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,11 +400,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
taskContainer.mContainers.remove(container);
|
taskContainer.mContainers.remove(container);
|
||||||
if (taskContainer.mContainers.isEmpty()) {
|
// Marked as a pending removal which will be removed after it is actually removed on the
|
||||||
mTaskContainers.remove(taskId);
|
// server side (#onTaskFragmentVanished).
|
||||||
// No more TaskFragment in this Task, so no need to check split container.
|
// In this way, we can keep track of the Task bounds until we no longer have any
|
||||||
return;
|
// TaskFragment there.
|
||||||
}
|
taskContainer.mFinishedContainer.add(container.getTaskFragmentToken());
|
||||||
|
|
||||||
final List<SplitContainer> containersToRemove = new ArrayList<>();
|
final List<SplitContainer> containersToRemove = new ArrayList<>();
|
||||||
for (SplitContainer splitContainer : taskContainer.mSplitContainers) {
|
for (SplitContainer splitContainer : taskContainer.mSplitContainers) {
|
||||||
@@ -543,7 +552,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean launchPlaceholderIfNecessary(@NonNull Activity activity) {
|
boolean launchPlaceholderIfNecessary(@NonNull Activity activity) {
|
||||||
final TaskFragmentContainer container = getContainerWithActivity(
|
final TaskFragmentContainer container = getContainerWithActivity(
|
||||||
activity.getActivityToken());
|
activity.getActivityToken());
|
||||||
// Don't launch placeholder if the container is occluded.
|
// Don't launch placeholder if the container is occluded.
|
||||||
if (container != null && container != getTopActiveContainer(container.getTaskId())) {
|
if (container != null && container != getTopActiveContainer(container.getTaskId())) {
|
||||||
@@ -1035,7 +1044,30 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
/** Represents TaskFragments and split pairs below a Task. */
|
/** Represents TaskFragments and split pairs below a Task. */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static class TaskContainer {
|
static class TaskContainer {
|
||||||
|
/** The unique task id. */
|
||||||
|
final int mTaskId;
|
||||||
|
/** Active TaskFragments in this Task. */
|
||||||
final List<TaskFragmentContainer> mContainers = new ArrayList<>();
|
final List<TaskFragmentContainer> mContainers = new ArrayList<>();
|
||||||
|
/** Active split pairs in this Task. */
|
||||||
final List<SplitContainer> mSplitContainers = new ArrayList<>();
|
final List<SplitContainer> mSplitContainers = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* TaskFragments that the organizer has requested to be closed. They should be removed when
|
||||||
|
* the organizer receives {@link #onTaskFragmentVanished(TaskFragmentInfo)} event for them.
|
||||||
|
*/
|
||||||
|
final Set<IBinder> mFinishedContainer = new ArraySet<>();
|
||||||
|
/** Available window bounds of this Task. */
|
||||||
|
final Rect mTaskBounds = new Rect();
|
||||||
|
|
||||||
|
TaskContainer(int taskId) {
|
||||||
|
mTaskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEmpty() {
|
||||||
|
return mContainers.isEmpty() && mFinishedContainer.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isTaskBoundsInitialized() {
|
||||||
|
return !mTaskBounds.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -419,7 +419,11 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(b/190433398): Check if the client-side available info about parent bounds is enough.
|
return getTaskBoundsFromActivity(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
static Rect getTaskBoundsFromActivity(@NonNull Activity activity) {
|
||||||
if (!activity.isInMultiWindowMode()) {
|
if (!activity.isInMultiWindowMode()) {
|
||||||
// In fullscreen mode the max bounds should correspond to the task bounds.
|
// In fullscreen mode the max bounds should correspond to the task bounds.
|
||||||
return activity.getResources().getConfiguration().windowConfiguration.getMaxBounds();
|
return activity.getResources().getConfiguration().windowConfiguration.getMaxBounds();
|
||||||
|
|||||||
@@ -24,11 +24,14 @@ 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_FRAGMENT_OPEN;
|
||||||
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
|
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
|
||||||
|
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.RemoteAnimationAdapter;
|
import android.view.RemoteAnimationAdapter;
|
||||||
import android.view.RemoteAnimationDefinition;
|
import android.view.RemoteAnimationDefinition;
|
||||||
import android.window.TaskFragmentOrganizer;
|
import android.window.TaskFragmentOrganizer;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
/** Controls the TaskFragment remote animations. */
|
/** Controls the TaskFragment remote animations. */
|
||||||
class TaskFragmentAnimationController {
|
class TaskFragmentAnimationController {
|
||||||
|
|
||||||
@@ -37,8 +40,10 @@ class TaskFragmentAnimationController {
|
|||||||
|
|
||||||
private final TaskFragmentOrganizer mOrganizer;
|
private final TaskFragmentOrganizer mOrganizer;
|
||||||
private final TaskFragmentAnimationRunner mRemoteRunner = new TaskFragmentAnimationRunner();
|
private final TaskFragmentAnimationRunner mRemoteRunner = new TaskFragmentAnimationRunner();
|
||||||
private final RemoteAnimationDefinition mDefinition;
|
@VisibleForTesting
|
||||||
private boolean mIsRegister;
|
final RemoteAnimationDefinition mDefinition;
|
||||||
|
/** Task Ids that we have registered for remote animation. */
|
||||||
|
private final ArraySet<Integer> mRegisterTasks = new ArraySet<>();
|
||||||
|
|
||||||
TaskFragmentAnimationController(TaskFragmentOrganizer organizer) {
|
TaskFragmentAnimationController(TaskFragmentOrganizer organizer) {
|
||||||
mOrganizer = organizer;
|
mOrganizer = organizer;
|
||||||
@@ -54,25 +59,32 @@ class TaskFragmentAnimationController {
|
|||||||
mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter);
|
mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerRemoteAnimations() {
|
void registerRemoteAnimations(int taskId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.v(TAG, "registerRemoteAnimations");
|
Log.v(TAG, "registerRemoteAnimations");
|
||||||
}
|
}
|
||||||
if (mIsRegister) {
|
if (mRegisterTasks.contains(taskId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mOrganizer.registerRemoteAnimations(mDefinition);
|
mOrganizer.registerRemoteAnimations(taskId, mDefinition);
|
||||||
mIsRegister = true;
|
mRegisterTasks.add(taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterRemoteAnimations() {
|
void unregisterRemoteAnimations(int taskId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.v(TAG, "unregisterRemoteAnimations");
|
Log.v(TAG, "unregisterRemoteAnimations");
|
||||||
}
|
}
|
||||||
if (!mIsRegister) {
|
if (!mRegisterTasks.contains(taskId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mOrganizer.unregisterRemoteAnimations();
|
mOrganizer.unregisterRemoteAnimations(taskId);
|
||||||
mIsRegister = false;
|
mRegisterTasks.remove(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unregisterAllRemoteAnimations() {
|
||||||
|
final ArraySet<Integer> tasks = new ArraySet<>(mRegisterTasks);
|
||||||
|
for (int taskId : tasks) {
|
||||||
|
unregisterRemoteAnimations(taskId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package androidx.window.extensions.embedding;
|
||||||
|
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
|
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.never;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for {@link JetpackTaskFragmentOrganizer}.
|
||||||
|
*
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest WMJetpackUnitTests:JetpackTaskFragmentOrganizerTest
|
||||||
|
*/
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class JetpackTaskFragmentOrganizerTest {
|
||||||
|
private static final int TASK_ID = 10;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback;
|
||||||
|
private JetpackTaskFragmentOrganizer mOrganizer;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mOrganizer = new JetpackTaskFragmentOrganizer(Runnable::run, mCallback);
|
||||||
|
mOrganizer.registerOrganizer();
|
||||||
|
spyOn(mOrganizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnregisterOrganizer() {
|
||||||
|
mOrganizer.startOverrideSplitAnimation(TASK_ID);
|
||||||
|
mOrganizer.startOverrideSplitAnimation(TASK_ID + 1);
|
||||||
|
mOrganizer.unregisterOrganizer();
|
||||||
|
|
||||||
|
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
|
||||||
|
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStartOverrideSplitAnimation() {
|
||||||
|
assertNull(mOrganizer.mAnimationController);
|
||||||
|
|
||||||
|
mOrganizer.startOverrideSplitAnimation(TASK_ID);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,12 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for {@link SplitController}.
|
||||||
|
*
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest WMJetpackUnitTests:SplitController
|
||||||
|
*/
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class SplitControllerTest {
|
public class SplitControllerTest {
|
||||||
@@ -46,7 +52,7 @@ public class SplitControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTopActiveContainer() {
|
public void testGetTopActiveContainer() {
|
||||||
TaskContainer taskContainer = new TaskContainer();
|
TaskContainer taskContainer = new TaskContainer(TASK_ID);
|
||||||
// tf3 is finished so is not active.
|
// tf3 is finished so is not active.
|
||||||
TaskFragmentContainer tf3 = mock(TaskFragmentContainer.class);
|
TaskFragmentContainer tf3 = mock(TaskFragmentContainer.class);
|
||||||
doReturn(true).when(tf3).isFinished();
|
doReturn(true).when(tf3).isFinished();
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package androidx.window.extensions.embedding;
|
||||||
|
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
|
||||||
|
import android.window.TaskFragmentOrganizer;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for {@link TaskFragmentAnimationController}.
|
||||||
|
*
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest WMJetpackUnitTests:TaskFragmentAnimationControllerTest
|
||||||
|
*/
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class TaskFragmentAnimationControllerTest {
|
||||||
|
private static final int TASK_ID = 10;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private TaskFragmentOrganizer mOrganizer;
|
||||||
|
private TaskFragmentAnimationController mAnimationController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mAnimationController = new TaskFragmentAnimationController(mOrganizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterRemoteAnimations() {
|
||||||
|
mAnimationController.registerRemoteAnimations(TASK_ID);
|
||||||
|
|
||||||
|
verify(mOrganizer).registerRemoteAnimations(TASK_ID, mAnimationController.mDefinition);
|
||||||
|
|
||||||
|
mAnimationController.registerRemoteAnimations(TASK_ID);
|
||||||
|
|
||||||
|
// No extra call if it has been registered.
|
||||||
|
verify(mOrganizer).registerRemoteAnimations(TASK_ID, mAnimationController.mDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnregisterRemoteAnimations() {
|
||||||
|
mAnimationController.unregisterRemoteAnimations(TASK_ID);
|
||||||
|
|
||||||
|
// No call if it is not registered.
|
||||||
|
verify(mOrganizer, never()).unregisterRemoteAnimations(anyInt());
|
||||||
|
|
||||||
|
mAnimationController.registerRemoteAnimations(TASK_ID);
|
||||||
|
mAnimationController.unregisterRemoteAnimations(TASK_ID);
|
||||||
|
|
||||||
|
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
|
||||||
|
|
||||||
|
mAnimationController.unregisterRemoteAnimations(TASK_ID);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -653,7 +653,7 @@ public class AppTransitionController {
|
|||||||
final ITaskFragmentOrganizer organizer = findTaskFragmentOrganizer(task);
|
final ITaskFragmentOrganizer organizer = findTaskFragmentOrganizer(task);
|
||||||
final RemoteAnimationDefinition definition = organizer != null
|
final RemoteAnimationDefinition definition = organizer != null
|
||||||
? mDisplayContent.mAtmService.mTaskFragmentOrganizerController
|
? mDisplayContent.mAtmService.mTaskFragmentOrganizerController
|
||||||
.getRemoteAnimationDefinition(organizer)
|
.getRemoteAnimationDefinition(organizer, task.mTaskId)
|
||||||
: null;
|
: null;
|
||||||
final RemoteAnimationAdapter adapter = definition != null
|
final RemoteAnimationAdapter adapter = definition != null
|
||||||
? definition.getAdapter(transit, activityTypes)
|
? definition.getAdapter(transit, activityTypes)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import android.os.IBinder;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.view.RemoteAnimationDefinition;
|
import android.view.RemoteAnimationDefinition;
|
||||||
import android.window.ITaskFragmentOrganizer;
|
import android.window.ITaskFragmentOrganizer;
|
||||||
import android.window.ITaskFragmentOrganizerController;
|
import android.window.ITaskFragmentOrganizerController;
|
||||||
@@ -83,11 +84,12 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
new WeakHashMap<>();
|
new WeakHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see android.window.TaskFragmentOrganizer#registerRemoteAnimations(
|
* Map from Task Id to {@link RemoteAnimationDefinition}.
|
||||||
* RemoteAnimationDefinition)
|
* @see android.window.TaskFragmentOrganizer#registerRemoteAnimations(int,
|
||||||
|
* RemoteAnimationDefinition) )
|
||||||
*/
|
*/
|
||||||
@Nullable
|
private final SparseArray<RemoteAnimationDefinition> mRemoteAnimationDefinitions =
|
||||||
private RemoteAnimationDefinition mRemoteAnimationDefinition;
|
new SparseArray<>();
|
||||||
|
|
||||||
TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer) {
|
TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer) {
|
||||||
mOrganizer = organizer;
|
mOrganizer = organizer;
|
||||||
@@ -251,7 +253,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerRemoteAnimations(ITaskFragmentOrganizer organizer,
|
public void registerRemoteAnimations(ITaskFragmentOrganizer organizer, int taskId,
|
||||||
RemoteAnimationDefinition definition) {
|
RemoteAnimationDefinition definition) {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
@@ -264,19 +266,20 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
if (organizerState == null) {
|
if (organizerState == null) {
|
||||||
throw new IllegalStateException("The organizer hasn't been registered.");
|
throw new IllegalStateException("The organizer hasn't been registered.");
|
||||||
}
|
}
|
||||||
if (organizerState.mRemoteAnimationDefinition != null) {
|
if (organizerState.mRemoteAnimationDefinitions.contains(taskId)) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"The organizer has already registered remote animations="
|
"The organizer has already registered remote animations="
|
||||||
+ organizerState.mRemoteAnimationDefinition);
|
+ organizerState.mRemoteAnimationDefinitions.get(taskId)
|
||||||
|
+ " for TaskId=" + taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
definition.setCallingPidUid(pid, uid);
|
definition.setCallingPidUid(pid, uid);
|
||||||
organizerState.mRemoteAnimationDefinition = definition;
|
organizerState.mRemoteAnimationDefinitions.put(taskId, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterRemoteAnimations(ITaskFragmentOrganizer organizer) {
|
public void unregisterRemoteAnimations(ITaskFragmentOrganizer organizer, int taskId) {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final long uid = Binder.getCallingUid();
|
final long uid = Binder.getCallingUid();
|
||||||
synchronized (mGlobalLock) {
|
synchronized (mGlobalLock) {
|
||||||
@@ -290,7 +293,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
organizerState.mRemoteAnimationDefinition = null;
|
organizerState.mRemoteAnimationDefinitions.remove(taskId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,11 +303,13 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public RemoteAnimationDefinition getRemoteAnimationDefinition(
|
public RemoteAnimationDefinition getRemoteAnimationDefinition(
|
||||||
ITaskFragmentOrganizer organizer) {
|
ITaskFragmentOrganizer organizer, int taskId) {
|
||||||
synchronized (mGlobalLock) {
|
synchronized (mGlobalLock) {
|
||||||
final TaskFragmentOrganizerState organizerState =
|
final TaskFragmentOrganizerState organizerState =
|
||||||
mTaskFragmentOrganizerState.get(organizer.asBinder());
|
mTaskFragmentOrganizerState.get(organizer.asBinder());
|
||||||
return organizerState != null ? organizerState.mRemoteAnimationDefinition : null;
|
return organizerState != null
|
||||||
|
? organizerState.mRemoteAnimationDefinitions.get(taskId)
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -861,13 +861,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_overrideWithEmbeddedActivity() {
|
public void testOverrideTaskFragmentAdapter_overrideWithEmbeddedActivity() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
// Create a TaskFragment with embedded activity.
|
// Create a TaskFragment with embedded activity.
|
||||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(
|
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||||
createTask(mDisplayContent), organizer);
|
|
||||||
final ActivityRecord activity = taskFragment.getTopMostActivity();
|
final ActivityRecord activity = taskFragment.getTopMostActivity();
|
||||||
prepareActivityForAppTransition(activity);
|
prepareActivityForAppTransition(activity);
|
||||||
spyOn(mDisplayContent.mAppTransition);
|
spyOn(mDisplayContent.mAppTransition);
|
||||||
@@ -882,11 +882,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_overrideWithNonEmbeddedActivity() {
|
public void testOverrideTaskFragmentAdapter_overrideWithNonEmbeddedActivity() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
final Task task = createTask(mDisplayContent);
|
|
||||||
// Closing non-embedded activity.
|
// Closing non-embedded activity.
|
||||||
final ActivityRecord closingActivity = createActivityRecord(task);
|
final ActivityRecord closingActivity = createActivityRecord(task);
|
||||||
prepareActivityForAppTransition(closingActivity);
|
prepareActivityForAppTransition(closingActivity);
|
||||||
@@ -907,11 +907,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_overrideEmbeddedActivityWithDiffUid() {
|
public void testOverrideTaskFragmentAdapter_overrideEmbeddedActivityWithDiffUid() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
final Task task = createTask(mDisplayContent);
|
|
||||||
// Closing TaskFragment with embedded activity.
|
// Closing TaskFragment with embedded activity.
|
||||||
final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||||
final ActivityRecord closingActivity = taskFragment1.getTopMostActivity();
|
final ActivityRecord closingActivity = taskFragment1.getTopMostActivity();
|
||||||
@@ -934,16 +934,16 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_noOverrideWithTwoApps() {
|
public void testOverrideTaskFragmentAdapter_noOverrideWithTwoApps() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
// Closing activity in Task1.
|
// Closing activity in Task1.
|
||||||
final ActivityRecord closingActivity = createActivityRecord(mDisplayContent);
|
final ActivityRecord closingActivity = createActivityRecord(mDisplayContent);
|
||||||
prepareActivityForAppTransition(closingActivity);
|
prepareActivityForAppTransition(closingActivity);
|
||||||
// Opening TaskFragment with embedded activity in Task2.
|
// Opening TaskFragment with embedded activity in Task2.
|
||||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(
|
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||||
createTask(mDisplayContent), organizer);
|
|
||||||
final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
|
final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
|
||||||
prepareActivityForAppTransition(openingActivity);
|
prepareActivityForAppTransition(openingActivity);
|
||||||
spyOn(mDisplayContent.mAppTransition);
|
spyOn(mDisplayContent.mAppTransition);
|
||||||
@@ -958,11 +958,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_noOverrideNonEmbeddedActivityWithDiffUid() {
|
public void testOverrideTaskFragmentAdapter_noOverrideNonEmbeddedActivityWithDiffUid() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
final Task task = createTask(mDisplayContent);
|
|
||||||
// Closing TaskFragment with embedded activity.
|
// Closing TaskFragment with embedded activity.
|
||||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||||
final ActivityRecord closingActivity = taskFragment.getTopMostActivity();
|
final ActivityRecord closingActivity = taskFragment.getTopMostActivity();
|
||||||
@@ -986,13 +986,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_noOverrideWithWallpaper() {
|
public void testOverrideTaskFragmentAdapter_noOverrideWithWallpaper() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
// Create a TaskFragment with embedded activity.
|
// Create a TaskFragment with embedded activity.
|
||||||
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(
|
final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
|
||||||
createTask(mDisplayContent), organizer);
|
|
||||||
final ActivityRecord activity = taskFragment.getTopMostActivity();
|
final ActivityRecord activity = taskFragment.getTopMostActivity();
|
||||||
prepareActivityForAppTransition(activity);
|
prepareActivityForAppTransition(activity);
|
||||||
// Set wallpaper as visible.
|
// Set wallpaper as visible.
|
||||||
@@ -1012,13 +1012,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_inputProtectedForUntrustedAnimation() {
|
public void testOverrideTaskFragmentAdapter_inputProtectedForUntrustedAnimation() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
// Create a TaskFragment with embedded activities, one is trusted embedded, and the other
|
// Create a TaskFragment with embedded activities, one is trusted embedded, and the other
|
||||||
// one is untrusted embedded.
|
// one is untrusted embedded.
|
||||||
final Task task = createTask(mDisplayContent);
|
|
||||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||||
.setParentTask(task)
|
.setParentTask(task)
|
||||||
.createActivityCount(2)
|
.createActivityCount(2)
|
||||||
@@ -1071,12 +1071,12 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideTaskFragmentAdapter_inputProtectedForTrustedAnimation() {
|
public void testOverrideTaskFragmentAdapter_inputProtectedForTrustedAnimation() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
|
||||||
setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
|
setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner);
|
||||||
|
|
||||||
// Create a TaskFragment with only trusted embedded activity
|
// Create a TaskFragment with only trusted embedded activity
|
||||||
final Task task = createTask(mDisplayContent);
|
|
||||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||||
.setParentTask(task)
|
.setParentTask(task)
|
||||||
.createActivityCount(1)
|
.createActivityCount(1)
|
||||||
@@ -1170,7 +1170,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Registers remote animation for the organizer. */
|
/** Registers remote animation for the organizer. */
|
||||||
private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer,
|
private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer, int taskId,
|
||||||
TestRemoteAnimationRunner remoteAnimationRunner) {
|
TestRemoteAnimationRunner remoteAnimationRunner) {
|
||||||
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
||||||
remoteAnimationRunner, 10, 1);
|
remoteAnimationRunner, 10, 1);
|
||||||
@@ -1181,7 +1181,8 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
|||||||
definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, adapter);
|
definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, adapter);
|
||||||
definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, adapter);
|
definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, adapter);
|
||||||
mAtm.mTaskFragmentOrganizerController.registerOrganizer(iOrganizer);
|
mAtm.mTaskFragmentOrganizerController.registerOrganizer(iOrganizer);
|
||||||
mAtm.mTaskFragmentOrganizerController.registerRemoteAnimations(iOrganizer, definition);
|
mAtm.mTaskFragmentOrganizerController.registerRemoteAnimations(iOrganizer, taskId,
|
||||||
|
definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareAndTriggerAppTransition(@Nullable ActivityRecord openingActivity,
|
private void prepareAndTriggerAppTransition(@Nullable ActivityRecord openingActivity,
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import org.junit.runner.RunWith;
|
|||||||
@Presubmit
|
@Presubmit
|
||||||
@RunWith(WindowTestRunner.class)
|
@RunWith(WindowTestRunner.class)
|
||||||
public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||||
|
private static final int TASK_ID = 10;
|
||||||
|
|
||||||
private TaskFragmentOrganizerController mController;
|
private TaskFragmentOrganizerController mController;
|
||||||
private TaskFragmentOrganizer mOrganizer;
|
private TaskFragmentOrganizer mOrganizer;
|
||||||
@@ -219,13 +220,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
|||||||
@Test
|
@Test
|
||||||
public void testRegisterRemoteAnimations() {
|
public void testRegisterRemoteAnimations() {
|
||||||
mController.registerOrganizer(mIOrganizer);
|
mController.registerOrganizer(mIOrganizer);
|
||||||
mController.registerRemoteAnimations(mIOrganizer, mDefinition);
|
mController.registerRemoteAnimations(mIOrganizer, TASK_ID, mDefinition);
|
||||||
|
|
||||||
assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer));
|
assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer, TASK_ID));
|
||||||
|
|
||||||
mController.unregisterRemoteAnimations(mIOrganizer);
|
mController.unregisterRemoteAnimations(mIOrganizer, TASK_ID);
|
||||||
|
|
||||||
assertNull(mController.getRemoteAnimationDefinition(mIOrganizer));
|
assertNull(mController.getRemoteAnimationDefinition(mIOrganizer, TASK_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user