Loading packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +11 −0 Original line number Diff line number Diff line Loading @@ -315,6 +315,17 @@ public class ActivityManagerWrapper { } } /** * Cancels the remote recents animation started from {@link #startRecentsActivity}. */ public void cancelRecentsAnimation() { try { ActivityManager.getService().cancelRecentsAnimation(); } catch (RemoteException e) { Log.e(TAG, "Failed to cancel recents animation", e); } } /** * Starts a task from Recents. * Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +2 −5 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import com.android.systemui.Dependency; import com.android.systemui.OverviewProxyService; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface; import com.android.systemui.shared.system.ActivityManagerWrapper; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; Loading Loading @@ -269,11 +270,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface { if (doIt) { // If there was a pending remote recents animation, then we need to // cancel the animation now before we handle the button itself try { ActivityManager.getService().cancelRecentsAnimation(); } catch (RemoteException e) { Log.e(TAG, "Could not cancel recents animation", e); } ActivityManagerWrapper.getInstance().cancelRecentsAnimation(); sendEvent(KeyEvent.ACTION_UP, 0); sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); } else { Loading services/core/java/com/android/server/am/RecentsAnimation.java +45 −19 Original line number Diff line number Diff line Loading @@ -28,7 +28,9 @@ import android.app.ActivityOptions; import android.content.ComponentName; import android.content.Intent; import android.os.Handler; import android.os.RemoteException; import android.os.Trace; import android.util.Slog; import android.view.IRecentsAnimationRunner; import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks; import com.android.server.wm.WindowManagerService; Loading Loading @@ -63,6 +65,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks { mHandler = new Handler(mStackSupervisor.mLooper); mWindowManager = wm; mUserController = userController; mCancelAnimationRunnable = () -> { // The caller has not finished the animation in a predefined amount of time, so // force-cancel the animation Loading @@ -73,13 +76,33 @@ class RecentsAnimation implements RecentsAnimationCallbacks { void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner, ComponentName recentsComponent, int recentsUid) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity"); if (!mWindowManager.canStartRecentsAnimation()) { notifyAnimationCancelBeforeStart(recentsAnimationRunner); return; } // If the existing home activity is already on top, then cancel ActivityRecord homeActivity = mStackSupervisor.getHomeActivity(); final boolean hasExistingHomeActivity = homeActivity != null; if (hasExistingHomeActivity) { final ActivityDisplay display = homeActivity.getDisplay(); mRestoreHomeBehindStack = display.getStackAboveHome(); if (mRestoreHomeBehindStack == null) { notifyAnimationCancelBeforeStart(recentsAnimationRunner); return; } } mWindowManager.deferSurfaceLayout(); try { // Cancel the previous recents animation if necessary mWindowManager.cancelRecentsAnimation(); final boolean hasExistingHomeActivity = mStackSupervisor.getHomeActivity() != null; if (!hasExistingHomeActivity) { final ActivityDisplay display; if (hasExistingHomeActivity) { // Move the home activity into place for the animation if it is not already top most display = homeActivity.getDisplay(); display.moveHomeStackBehindBottomMostVisibleStack(); } else { // No home activity final ActivityOptions opts = ActivityOptions.makeBasic(); opts.setLaunchActivityType(ACTIVITY_TYPE_HOME); Loading @@ -95,25 +118,20 @@ class RecentsAnimation implements RecentsAnimationCallbacks { .execute(); mWindowManager.prepareAppTransition(TRANSIT_NONE, false); homeActivity = mStackSupervisor.getHomeActivity(); display = homeActivity.getDisplay(); // TODO: Maybe wait for app to draw in this particular case? } final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity(); final ActivityDisplay display = homeActivity.getDisplay(); // Save the initial position of the home activity stack to be restored to after the // animation completes mRestoreHomeBehindStack = hasExistingHomeActivity ? display.getStackAboveHome() : null; // Move the home activity into place for the animation display.moveHomeStackBehindBottomMostVisibleStack(); // Mark the home activity as launch-behind to bump its visibility for the // duration of the gesture that is driven by the recents component homeActivity.mLaunchTaskBehind = true; // Post a timeout for the animation. This needs to happen before initializing the // recents animation on the WM side since we may decide to cancel the animation there mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT); // Fetch all the surface controls and pass them to the client to get the animation // started mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this, Loading @@ -122,9 +140,6 @@ class RecentsAnimation implements RecentsAnimationCallbacks { // If we updated the launch-behind state, update the visibility of the activities after // we fetch the visible tasks to be controlled by the animation mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); // Post a timeout for the animation mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT); } finally { mWindowManager.continueSurfaceLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); Loading Loading @@ -178,4 +193,15 @@ class RecentsAnimation implements RecentsAnimationCallbacks { }); } } /** * Called only when the animation should be canceled prior to starting. */ private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) { try { recentsAnimationRunner.onAnimationCanceled(); } catch (RemoteException e) { Slog.e(TAG, "Failed to cancel recents animation before start", e); } } } services/core/java/com/android/server/wm/RecentsAnimationController.java +21 −11 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ public class RecentsAnimationController { private final IRecentsAnimationRunner mRunner; private final RecentsAnimationCallbacks mCallbacks; private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>(); private final int mDisplayId; // The recents component app token that is shown behind the visibile tasks private AppWindowToken mHomeAppToken; Loading Loading @@ -159,8 +160,6 @@ public class RecentsAnimationController { }; /** * Initializes a new RecentsAnimationController. * * @param remoteAnimationRunner The remote runner which should be notified when the animation is * ready to start or has been canceled * @param callbacks Callbacks to be made when the animation finishes Loading @@ -171,16 +170,19 @@ public class RecentsAnimationController { mService = service; mRunner = remoteAnimationRunner; mCallbacks = callbacks; final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); if (visibleTasks.isEmpty()) { cancelAnimation(); return; mDisplayId = displayId; } /** * Initializes the recents animation controller. This is a separate call from the constructor * because it may call cancelAnimation() which needs to properly clean up the controller * in the window manager. */ public void initialize() { // Make leashes for each of the visible tasks and add it to the recents animation to be // started final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId); final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); final int taskCount = visibleTasks.size(); for (int i = 0; i < taskCount; i++) { final Task task = visibleTasks.get(i); Loading @@ -193,6 +195,12 @@ public class RecentsAnimationController { addAnimation(task); } // Skip the animation if there is nothing to animate if (mPendingAnimations.isEmpty()) { cancelAnimation(); return; } // Adjust the wallpaper visibility for the showing home activity final AppWindowToken recentsComponentAppToken = dc.getHomeStack().getTopChild().getTopFullscreenAppToken(); Loading Loading @@ -222,8 +230,10 @@ public class RecentsAnimationController { } void startAnimation() { if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart); if (!mPendingStart) { if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart + " mCanceled=" + mCanceled); if (!mPendingStart || mCanceled) { // Skip starting if we've already started or canceled the animation return; } try { Loading services/core/java/com/android/server/wm/WindowManagerService.java +14 −0 Original line number Diff line number Diff line Loading @@ -2680,6 +2680,7 @@ public class WindowManagerService extends IWindowManager.Stub cancelRecentsAnimation(); mRecentsAnimationController = new RecentsAnimationController(this, recentsAnimationRunner, callbacks, displayId); mRecentsAnimationController.initialize(); } } Loading @@ -2687,6 +2688,19 @@ public class WindowManagerService extends IWindowManager.Stub return mRecentsAnimationController; } /** * @return Whether the next recents animation can continue to start. Called from * {@link RecentsAnimation#startRecentsActivity}. */ public boolean canStartRecentsAnimation() { synchronized (mWindowMap) { if (mAppTransition.isTransitionSet()) { return false; } return true; } } public void cancelRecentsAnimation() { synchronized (mWindowMap) { if (mRecentsAnimationController != null) { Loading Loading
packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +11 −0 Original line number Diff line number Diff line Loading @@ -315,6 +315,17 @@ public class ActivityManagerWrapper { } } /** * Cancels the remote recents animation started from {@link #startRecentsActivity}. */ public void cancelRecentsAnimation() { try { ActivityManager.getService().cancelRecentsAnimation(); } catch (RemoteException e) { Log.e(TAG, "Failed to cancel recents animation", e); } } /** * Starts a task from Recents. * Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +2 −5 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import com.android.systemui.Dependency; import com.android.systemui.OverviewProxyService; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface; import com.android.systemui.shared.system.ActivityManagerWrapper; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; Loading Loading @@ -269,11 +270,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface { if (doIt) { // If there was a pending remote recents animation, then we need to // cancel the animation now before we handle the button itself try { ActivityManager.getService().cancelRecentsAnimation(); } catch (RemoteException e) { Log.e(TAG, "Could not cancel recents animation", e); } ActivityManagerWrapper.getInstance().cancelRecentsAnimation(); sendEvent(KeyEvent.ACTION_UP, 0); sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); } else { Loading
services/core/java/com/android/server/am/RecentsAnimation.java +45 −19 Original line number Diff line number Diff line Loading @@ -28,7 +28,9 @@ import android.app.ActivityOptions; import android.content.ComponentName; import android.content.Intent; import android.os.Handler; import android.os.RemoteException; import android.os.Trace; import android.util.Slog; import android.view.IRecentsAnimationRunner; import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks; import com.android.server.wm.WindowManagerService; Loading Loading @@ -63,6 +65,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks { mHandler = new Handler(mStackSupervisor.mLooper); mWindowManager = wm; mUserController = userController; mCancelAnimationRunnable = () -> { // The caller has not finished the animation in a predefined amount of time, so // force-cancel the animation Loading @@ -73,13 +76,33 @@ class RecentsAnimation implements RecentsAnimationCallbacks { void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner, ComponentName recentsComponent, int recentsUid) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity"); if (!mWindowManager.canStartRecentsAnimation()) { notifyAnimationCancelBeforeStart(recentsAnimationRunner); return; } // If the existing home activity is already on top, then cancel ActivityRecord homeActivity = mStackSupervisor.getHomeActivity(); final boolean hasExistingHomeActivity = homeActivity != null; if (hasExistingHomeActivity) { final ActivityDisplay display = homeActivity.getDisplay(); mRestoreHomeBehindStack = display.getStackAboveHome(); if (mRestoreHomeBehindStack == null) { notifyAnimationCancelBeforeStart(recentsAnimationRunner); return; } } mWindowManager.deferSurfaceLayout(); try { // Cancel the previous recents animation if necessary mWindowManager.cancelRecentsAnimation(); final boolean hasExistingHomeActivity = mStackSupervisor.getHomeActivity() != null; if (!hasExistingHomeActivity) { final ActivityDisplay display; if (hasExistingHomeActivity) { // Move the home activity into place for the animation if it is not already top most display = homeActivity.getDisplay(); display.moveHomeStackBehindBottomMostVisibleStack(); } else { // No home activity final ActivityOptions opts = ActivityOptions.makeBasic(); opts.setLaunchActivityType(ACTIVITY_TYPE_HOME); Loading @@ -95,25 +118,20 @@ class RecentsAnimation implements RecentsAnimationCallbacks { .execute(); mWindowManager.prepareAppTransition(TRANSIT_NONE, false); homeActivity = mStackSupervisor.getHomeActivity(); display = homeActivity.getDisplay(); // TODO: Maybe wait for app to draw in this particular case? } final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity(); final ActivityDisplay display = homeActivity.getDisplay(); // Save the initial position of the home activity stack to be restored to after the // animation completes mRestoreHomeBehindStack = hasExistingHomeActivity ? display.getStackAboveHome() : null; // Move the home activity into place for the animation display.moveHomeStackBehindBottomMostVisibleStack(); // Mark the home activity as launch-behind to bump its visibility for the // duration of the gesture that is driven by the recents component homeActivity.mLaunchTaskBehind = true; // Post a timeout for the animation. This needs to happen before initializing the // recents animation on the WM side since we may decide to cancel the animation there mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT); // Fetch all the surface controls and pass them to the client to get the animation // started mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this, Loading @@ -122,9 +140,6 @@ class RecentsAnimation implements RecentsAnimationCallbacks { // If we updated the launch-behind state, update the visibility of the activities after // we fetch the visible tasks to be controlled by the animation mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); // Post a timeout for the animation mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT); } finally { mWindowManager.continueSurfaceLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); Loading Loading @@ -178,4 +193,15 @@ class RecentsAnimation implements RecentsAnimationCallbacks { }); } } /** * Called only when the animation should be canceled prior to starting. */ private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) { try { recentsAnimationRunner.onAnimationCanceled(); } catch (RemoteException e) { Slog.e(TAG, "Failed to cancel recents animation before start", e); } } }
services/core/java/com/android/server/wm/RecentsAnimationController.java +21 −11 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ public class RecentsAnimationController { private final IRecentsAnimationRunner mRunner; private final RecentsAnimationCallbacks mCallbacks; private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>(); private final int mDisplayId; // The recents component app token that is shown behind the visibile tasks private AppWindowToken mHomeAppToken; Loading Loading @@ -159,8 +160,6 @@ public class RecentsAnimationController { }; /** * Initializes a new RecentsAnimationController. * * @param remoteAnimationRunner The remote runner which should be notified when the animation is * ready to start or has been canceled * @param callbacks Callbacks to be made when the animation finishes Loading @@ -171,16 +170,19 @@ public class RecentsAnimationController { mService = service; mRunner = remoteAnimationRunner; mCallbacks = callbacks; final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); if (visibleTasks.isEmpty()) { cancelAnimation(); return; mDisplayId = displayId; } /** * Initializes the recents animation controller. This is a separate call from the constructor * because it may call cancelAnimation() which needs to properly clean up the controller * in the window manager. */ public void initialize() { // Make leashes for each of the visible tasks and add it to the recents animation to be // started final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId); final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); final int taskCount = visibleTasks.size(); for (int i = 0; i < taskCount; i++) { final Task task = visibleTasks.get(i); Loading @@ -193,6 +195,12 @@ public class RecentsAnimationController { addAnimation(task); } // Skip the animation if there is nothing to animate if (mPendingAnimations.isEmpty()) { cancelAnimation(); return; } // Adjust the wallpaper visibility for the showing home activity final AppWindowToken recentsComponentAppToken = dc.getHomeStack().getTopChild().getTopFullscreenAppToken(); Loading Loading @@ -222,8 +230,10 @@ public class RecentsAnimationController { } void startAnimation() { if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart); if (!mPendingStart) { if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart + " mCanceled=" + mCanceled); if (!mPendingStart || mCanceled) { // Skip starting if we've already started or canceled the animation return; } try { Loading
services/core/java/com/android/server/wm/WindowManagerService.java +14 −0 Original line number Diff line number Diff line Loading @@ -2680,6 +2680,7 @@ public class WindowManagerService extends IWindowManager.Stub cancelRecentsAnimation(); mRecentsAnimationController = new RecentsAnimationController(this, recentsAnimationRunner, callbacks, displayId); mRecentsAnimationController.initialize(); } } Loading @@ -2687,6 +2688,19 @@ public class WindowManagerService extends IWindowManager.Stub return mRecentsAnimationController; } /** * @return Whether the next recents animation can continue to start. Called from * {@link RecentsAnimation#startRecentsActivity}. */ public boolean canStartRecentsAnimation() { synchronized (mWindowMap) { if (mAppTransition.isTransitionSet()) { return false; } return true; } } public void cancelRecentsAnimation() { synchronized (mWindowMap) { if (mRecentsAnimationController != null) { Loading