Merge "Trigger onTaskAppeared when a task started from recents becomes ready." into rvc-dev am: 1c92e1f789
Change-Id: If4c0b104dadea9164db0baa2bec13511243d50b8
This commit is contained in:
@@ -192,6 +192,11 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase {
|
||||
Assume.assumeNoException(
|
||||
new AssertionError("onAnimationCanceled should not be called"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) throws RemoteException {
|
||||
/* no-op */
|
||||
}
|
||||
};
|
||||
|
||||
recentsSemaphore.tryAcquire();
|
||||
|
||||
@@ -114,4 +114,16 @@ interface IRecentsAnimationController {
|
||||
* animation is cancelled through fail safe mechanism.
|
||||
*/
|
||||
void setWillFinishToHome(boolean willFinishToHome);
|
||||
|
||||
/**
|
||||
* Stops controlling a task that is currently controlled by this recents animation.
|
||||
*
|
||||
* This method should be called when a task that has been received via {@link #onAnimationStart}
|
||||
* or {@link #onTaskAppeared} is no longer needed. After calling this method, the task will
|
||||
* either disappear from the screen, or jump to its final position in case it was the top task.
|
||||
*
|
||||
* @param taskId Id of the Task target to remove
|
||||
* @return {@code true} when target removed successfully, {@code false} otherwise.
|
||||
*/
|
||||
boolean removeTask(int taskId);
|
||||
}
|
||||
|
||||
@@ -56,4 +56,10 @@ oneway interface IRecentsAnimationRunner {
|
||||
void onAnimationStart(in IRecentsAnimationController controller,
|
||||
in RemoteAnimationTarget[] apps, in RemoteAnimationTarget[] wallpapers,
|
||||
in Rect homeContentInsets, in Rect minimizedHomeBounds) = 2;
|
||||
|
||||
/**
|
||||
* Called when the task of an activity that has been started while the recents animation
|
||||
* was running becomes ready for control.
|
||||
*/
|
||||
void onTaskAppeared(in RemoteAnimationTarget app) = 3;
|
||||
}
|
||||
|
||||
@@ -883,6 +883,12 @@
|
||||
"group": "WM_DEBUG_ORIENTATION",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"-242787066": {
|
||||
"message": "addTaskToRecentsAnimationIfNeeded, control: %s, task: %s, transit: %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/WindowContainer.java"
|
||||
},
|
||||
"-198463978": {
|
||||
"message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
|
||||
"level": "VERBOSE",
|
||||
@@ -901,6 +907,12 @@
|
||||
"group": "WM_DEBUG_ORIENTATION",
|
||||
"at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
|
||||
},
|
||||
"-172900257": {
|
||||
"message": "addTaskToTargets, target: %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
|
||||
},
|
||||
"-167822951": {
|
||||
"message": "Attempted to add starting window to token with already existing starting window",
|
||||
"level": "WARN",
|
||||
@@ -1525,6 +1537,12 @@
|
||||
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
|
||||
},
|
||||
"854237232": {
|
||||
"message": "addTaskToRecentsAnimationIfNeeded, control: %s, task: %s, transit: %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/Task.java"
|
||||
},
|
||||
"873914452": {
|
||||
"message": "goodToGo()",
|
||||
"level": "DEBUG",
|
||||
|
||||
@@ -261,6 +261,11 @@ public class ActivityManagerWrapper {
|
||||
animationHandler.onAnimationCanceled(
|
||||
taskSnapshot != null ? new ThumbnailData(taskSnapshot) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) {
|
||||
animationHandler.onTaskAppeared(new RemoteAnimationTargetCompat(app));
|
||||
}
|
||||
};
|
||||
}
|
||||
ActivityTaskManager.getService().startRecentsActivity(intent, receiver, runner);
|
||||
|
||||
@@ -109,4 +109,16 @@ public class RecentsAnimationControllerCompat {
|
||||
Log.e(TAG, "Failed to set overview reached state", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IRecentsAnimationController#removeTask
|
||||
*/
|
||||
public boolean removeTask(int taskId) {
|
||||
try {
|
||||
return mAnimationController.removeTask(taskId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to remove remote animation target", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,4 +32,10 @@ public interface RecentsAnimationListener {
|
||||
* Called when the animation into Recents was canceled. This call is made on the binder thread.
|
||||
*/
|
||||
void onAnimationCanceled(ThumbnailData thumbnailData);
|
||||
|
||||
/**
|
||||
* Called when the task of an activity that has been started while the recents animation
|
||||
* was running becomes ready for control.
|
||||
*/
|
||||
void onTaskAppeared(RemoteAnimationTargetCompat app);
|
||||
}
|
||||
|
||||
@@ -403,11 +403,18 @@ public class AppTransition implements Dump {
|
||||
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
|
||||
}
|
||||
|
||||
|
||||
boolean isNextAppTransitionOpenCrossProfileApps() {
|
||||
return mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS;
|
||||
}
|
||||
|
||||
boolean isNextAppTransitionCustomFromRecents() {
|
||||
final RecentTasks recentTasks = mService.mAtmService.getRecentTasks();
|
||||
final String recentsPackageName =
|
||||
(recentTasks != null) ? recentTasks.getRecentsComponent().getPackageName() : null;
|
||||
return mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM
|
||||
&& mNextAppTransitionPackage.equals(recentsPackageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if and only if we are currently fetching app transition specs from the future
|
||||
* passed into {@link #overridePendingAppTransitionMultiThumbFuture}
|
||||
|
||||
@@ -442,10 +442,6 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
|
||||
// Always prepare an app transition since we rely on the transition callbacks to cleanup
|
||||
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
|
||||
controller.setCancelOnNextTransitionStart();
|
||||
} else {
|
||||
// Just cancel directly to unleash from launcher when the next launching task is the
|
||||
// current top task.
|
||||
mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "stackOrderChanged");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IntArray;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -99,6 +100,8 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
private IRecentsAnimationRunner mRunner;
|
||||
private final RecentsAnimationCallbacks mCallbacks;
|
||||
private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
|
||||
private final IntArray mPendingNewTaskTargets = new IntArray(0);
|
||||
|
||||
private final ArrayList<WallpaperAnimationAdapter> mPendingWallpaperAnimations =
|
||||
new ArrayList<>();
|
||||
private final int mDisplayId;
|
||||
@@ -220,6 +223,10 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
if (mCanceled) {
|
||||
return;
|
||||
}
|
||||
// Remove all new task targets.
|
||||
for (int i = mPendingNewTaskTargets.size() - 1; i >= 0; i--) {
|
||||
removeTaskInternal(mPendingNewTaskTargets.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Note, the callback will handle its own synchronization, do not lock on WM lock
|
||||
@@ -310,6 +317,18 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
mWillFinishToHome = willFinishToHome;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeTask(int taskId) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mService.getWindowManagerLock()) {
|
||||
return removeTaskInternal(taskId);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -405,11 +424,17 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
|
||||
@VisibleForTesting
|
||||
AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) {
|
||||
return addAnimation(task, isRecentTaskInvisible, null /* finishedCallback */);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible,
|
||||
OnAnimationFinishedCallback finishedCallback) {
|
||||
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "addAnimation(%s)", task.getName());
|
||||
final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
|
||||
isRecentTaskInvisible);
|
||||
task.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */,
|
||||
ANIMATION_TYPE_RECENTS);
|
||||
ANIMATION_TYPE_RECENTS, finishedCallback);
|
||||
task.commitPendingTransaction();
|
||||
mPendingAnimations.add(taskAdapter);
|
||||
return taskAdapter;
|
||||
@@ -489,6 +514,49 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
void addTaskToTargets(Task task, OnAnimationFinishedCallback finishedCallback) {
|
||||
if (mRunner != null) {
|
||||
final RemoteAnimationTarget target = createTaskRemoteAnimation(task, finishedCallback);
|
||||
if (target == null) return;
|
||||
|
||||
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "addTaskToTargets, target: %s", target);
|
||||
try {
|
||||
mRunner.onTaskAppeared(target);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to report task appeared", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RemoteAnimationTarget createTaskRemoteAnimation(Task task,
|
||||
OnAnimationFinishedCallback finishedCallback) {
|
||||
final SparseBooleanArray recentTaskIds =
|
||||
mService.mAtmService.getRecentTasks().getRecentTaskIds();
|
||||
TaskAnimationAdapter adapter = (TaskAnimationAdapter) addAnimation(task,
|
||||
!recentTaskIds.get(task.mTaskId), finishedCallback);
|
||||
mPendingNewTaskTargets.add(task.mTaskId);
|
||||
return adapter.createRemoteAnimationTarget();
|
||||
}
|
||||
|
||||
private boolean removeTaskInternal(int taskId) {
|
||||
boolean result = false;
|
||||
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
|
||||
// Only allows when task target has became visible to user, to prevent
|
||||
// the flickering during remove animation and task visible.
|
||||
final TaskAnimationAdapter target = mPendingAnimations.get(i);
|
||||
if (target.mTask.mTaskId == taskId && target.mTask.isOnTop()) {
|
||||
removeAnimation(target);
|
||||
final int taskIndex = mPendingNewTaskTargets.indexOf(taskId);
|
||||
if (taskIndex != -1) {
|
||||
mPendingNewTaskTargets.remove(taskIndex);
|
||||
}
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private RemoteAnimationTarget[] createAppAnimations() {
|
||||
final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
|
||||
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
|
||||
|
||||
@@ -66,6 +66,7 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
|
||||
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
|
||||
import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
|
||||
import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
|
||||
import static com.android.server.wm.RootWindowContainerProto.PENDING_ACTIVITIES;
|
||||
@@ -1514,6 +1515,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
// Updates the extra information of the intent.
|
||||
if (fromHomeKey) {
|
||||
homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
|
||||
mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "startHomeActivity");
|
||||
}
|
||||
// Update the reason for ANR debugging to verify if the user activity is the one that
|
||||
// actually launched.
|
||||
|
||||
@@ -86,6 +86,8 @@ import static com.android.server.wm.IdentifierProto.HASH_CODE;
|
||||
import static com.android.server.wm.IdentifierProto.TITLE;
|
||||
import static com.android.server.wm.IdentifierProto.USER_ID;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
|
||||
import static com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
|
||||
import static com.android.server.wm.WindowContainerChildProto.TASK;
|
||||
@@ -135,6 +137,7 @@ import android.view.RemoteAnimationAdapter;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.window.ITaskOrganizer;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -3401,6 +3404,24 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
||||
int transit, boolean isVoiceInteraction,
|
||||
@Nullable OnAnimationFinishedCallback finishedCallback) {
|
||||
final RecentsAnimationController control = mWmService.getRecentsAnimationController();
|
||||
if (control != null && enter
|
||||
&& getDisplayContent().mAppTransition.isNextAppTransitionCustomFromRecents()) {
|
||||
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
|
||||
"addTaskToRecentsAnimationIfNeeded, control: %s, task: %s, transit: %s",
|
||||
control, asTask(), AppTransition.appTransitionToString(transit));
|
||||
// We let the transition to be controlled by RecentsAnimation, and callback task's
|
||||
// RemoteAnimationTarget for remote runner to animate.
|
||||
control.addTaskToTargets(getRootTask(), finishedCallback);
|
||||
} else {
|
||||
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
|
||||
super.dump(pw, prefix, dumpAll);
|
||||
|
||||
@@ -2076,8 +2076,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
* @see #getAnimationAdapter
|
||||
*/
|
||||
boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||
boolean isVoiceInteraction,
|
||||
@Nullable OnAnimationFinishedCallback animationFinishedCallback) {
|
||||
boolean isVoiceInteraction, @Nullable OnAnimationFinishedCallback finishedCallback) {
|
||||
if (mWmService.mDisableTransitionAnimation) {
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
|
||||
"applyAnimation: transition animation is disabled or skipped. "
|
||||
@@ -2092,22 +2091,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
try {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
|
||||
if (okToAnimate()) {
|
||||
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
|
||||
transit, enter, isVoiceInteraction);
|
||||
AnimationAdapter adapter = adapters.first;
|
||||
AnimationAdapter thumbnailAdapter = adapters.second;
|
||||
if (adapter != null) {
|
||||
startAnimation(getPendingTransaction(), adapter, !isVisible(),
|
||||
ANIMATION_TYPE_APP_TRANSITION, animationFinishedCallback);
|
||||
if (adapter.getShowWallpaper()) {
|
||||
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
|
||||
}
|
||||
if (thumbnailAdapter != null) {
|
||||
mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),
|
||||
thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION,
|
||||
(type, anim) -> { });
|
||||
}
|
||||
}
|
||||
applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
|
||||
} else {
|
||||
cancelAnimation();
|
||||
}
|
||||
@@ -2201,6 +2185,26 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
return resultAdapters;
|
||||
}
|
||||
|
||||
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
||||
int transit, boolean isVoiceInteraction,
|
||||
@Nullable OnAnimationFinishedCallback finishedCallback) {
|
||||
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
|
||||
transit, enter, isVoiceInteraction);
|
||||
AnimationAdapter adapter = adapters.first;
|
||||
AnimationAdapter thumbnailAdapter = adapters.second;
|
||||
if (adapter != null) {
|
||||
startAnimation(getPendingTransaction(), adapter, !isVisible(),
|
||||
ANIMATION_TYPE_APP_TRANSITION, finishedCallback);
|
||||
if (adapter.getShowWallpaper()) {
|
||||
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
|
||||
}
|
||||
if (thumbnailAdapter != null) {
|
||||
mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),
|
||||
thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> { });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final SurfaceAnimationRunner getSurfaceAnimationRunner() {
|
||||
return mWmService.mSurfaceAnimationRunner;
|
||||
}
|
||||
|
||||
@@ -238,9 +238,6 @@ public class RecentsAnimationTest extends ActivityTestsBase {
|
||||
assertTrue(targetActivity.mLaunchTaskBehind);
|
||||
|
||||
anotherHomeActivity.moveFocusableActivityToTop("launchAnotherHome");
|
||||
// The current top activity is not the recents so the animation should be canceled.
|
||||
verify(mService.mWindowManager, times(1)).cancelRecentsAnimation(
|
||||
eq(REORDER_KEEP_IN_PLACE), any() /* reason */);
|
||||
|
||||
// The test uses mocked RecentsAnimationController so we have to invoke the callback
|
||||
// manually to simulate the flow.
|
||||
@@ -279,10 +276,6 @@ public class RecentsAnimationTest extends ActivityTestsBase {
|
||||
|
||||
fullscreenStack.moveToFront("Activity start");
|
||||
|
||||
// Ensure that the recents animation was canceled by cancelAnimationSynchronously().
|
||||
verify(mService.mWindowManager, times(1)).cancelRecentsAnimation(
|
||||
eq(REORDER_KEEP_IN_PLACE), any());
|
||||
|
||||
// Assume recents animation already started, set a state that cancel recents animation
|
||||
// with screenshot.
|
||||
doReturn(true).when(mRecentsAnimationController).shouldDeferCancelUntilNextTransition();
|
||||
|
||||
Reference in New Issue
Block a user