Loading data/etc/services.core.protolog.json +27 −9 Original line number Diff line number Diff line Loading @@ -1309,6 +1309,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-711194343": { "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "-706481945": { "message": "TaskFragment parent info changed name=%s parentTaskId=%d", "level": "VERBOSE", Loading Loading @@ -2587,6 +2593,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/WindowState.java" }, "599897753": { "message": "Previous Activity is %s. Back type is %s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "600140673": { "message": "checkBootAnimationComplete: Waiting for anim complete", "level": "INFO", Loading Loading @@ -2671,12 +2683,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "664667685": { "message": "Activity %s: enableOnBackInvokedCallback=false. Returning null BackNavigationInfo.", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "665256544": { "message": "All windows drawn!", "level": "DEBUG", Loading Loading @@ -2887,6 +2893,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, "948208142": { "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "950074526": { "message": "setLockTaskMode: Can't lock due to auth", "level": "WARN", Loading Loading @@ -3103,6 +3115,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "1172542963": { "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "1178653181": { "message": "Old wallpaper still the target.", "level": "VERBOSE", Loading Loading @@ -3415,11 +3433,11 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "1554795024": { "message": "Previous Activity is %s", "1544805551": { "message": "Skipping app transition animation. task=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" "at": "com\/android\/server\/wm\/Task.java" }, "1557732761": { "message": "For Intent %s bringing to top: %s", Loading libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +21 −8 Original line number Diff line number Diff line Loading @@ -52,14 +52,17 @@ import com.android.wm.shell.common.annotations.ShellMainThread; */ public class BackAnimationController implements RemoteCallable<BackAnimationController> { private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability"; public static final boolean IS_ENABLED = SystemProperties .getInt(BACK_PREDICTABILITY_PROP, 1) > 0; private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP = "persist.debug.back_predictability_progress_threshold"; // By default, enable new back dispatching without any animations. private static final int BACK_PREDICTABILITY_PROP = SystemProperties.getInt("persist.debug.back_predictability", 1); public static final boolean IS_ENABLED = BACK_PREDICTABILITY_PROP > 0; private static final int PROGRESS_THRESHOLD = SystemProperties .getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1); private static final String TAG = "BackAnimationController"; @VisibleForTesting boolean mEnableAnimations = (BACK_PREDICTABILITY_PROP & (1 << 1)) != 0; /** * Location of the initial touch event of the back gesture. Loading Loading @@ -255,7 +258,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont backNavigationInfo.getTaskWindowConfiguration()); } mTransaction.apply(); } else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) { } else if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; } else if (backType == BackNavigationInfo.TYPE_CALLBACK) { targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); Loading Loading @@ -309,7 +312,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget); IOnBackInvokedCallback targetCallback = null; if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) { if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; } else if (backType == BackNavigationInfo.TYPE_CROSS_TASK || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) { Loading @@ -330,8 +333,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; } int backType = mBackNavigationInfo.getType(); boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && mBackToLauncherCallback != null; boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType); IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher ? mBackToLauncherCallback : mBackNavigationInfo.getOnBackInvokedCallback(); Loading @@ -356,6 +358,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } private boolean shouldDispatchToLauncher(int backType) { return backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && mBackToLauncherCallback != null && mEnableAnimations; } @VisibleForTesting void setEnableAnimations(boolean shouldEnable) { mEnableAnimations = shouldEnable; } private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) { if (callback == null) { return; Loading Loading @@ -468,7 +481,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; } RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget(); if (animationTarget != null && mTriggerBack) { if (animationTarget != null) { if (animationTarget.leash != null && animationTarget.leash.isValid()) { mTransaction.remove(animationTarget.leash); } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ public class BackAnimationControllerTest { MockitoAnnotations.initMocks(this); mController = new BackAnimationController( mShellExecutor, mTransaction, mActivityTaskManager, mContext); mController.setEnableAnimations(true); } private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget, Loading services/core/java/com/android/server/wm/BackNavigationController.java +93 −27 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.content.ComponentName; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.os.Bundle; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.SystemProperties; Loading @@ -44,7 +45,11 @@ import com.android.internal.protolog.common.ProtoLog; class BackNavigationController { private static final String TAG = "BackNavigationController"; private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability"; // By default, enable new back dispatching without any animations. private static final int BACK_PREDICTABILITY_PROP = SystemProperties.getInt("persist.debug.back_predictability", 1); private static final int ANIMATIONS_MASK = 1 << 1; private static final int SCREENSHOT_MASK = 1 << 2; @Nullable private TaskSnapshotController mTaskSnapshotController; Loading @@ -53,11 +58,15 @@ class BackNavigationController { * Returns true if the back predictability feature is enabled */ static boolean isEnabled() { return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 1) > 0; return BACK_PREDICTABILITY_PROP > 0; } static boolean isScreenshotEnabled() { return false; return (BACK_PREDICTABILITY_PROP & SCREENSHOT_MASK) != 0; } private static boolean isAnimationEnabled() { return (BACK_PREDICTABILITY_PROP & ANIMATIONS_MASK) != 0; } /** Loading Loading @@ -93,14 +102,17 @@ class BackNavigationController { ActivityRecord prev; WindowContainer<?> removedWindowContainer; ActivityRecord activityRecord; ActivityRecord prevTaskTopActivity = null; SurfaceControl animationLeashParent; WindowConfiguration taskWindowConfiguration; HardwareBuffer screenshotBuffer = null; SurfaceControl screenshotSurface; int prevTaskId; int prevUserId; RemoteAnimationTarget topAppTarget; SurfaceControl animLeash; IOnBackInvokedCallback callback = null; IOnBackInvokedCallback applicationCallback = null; IOnBackInvokedCallback systemCallback = null; synchronized (task.mWmService.mGlobalLock) { Loading @@ -116,15 +128,14 @@ class BackNavigationController { removedWindowContainer = activityRecord; taskWindowConfiguration = window.getWindowConfiguration(); } IOnBackInvokedCallback applicationCallback = null; IOnBackInvokedCallback systemCallback = null; if (window != null) { applicationCallback = window.getApplicationOnBackInvokedCallback(); callback = applicationCallback; if (callback == null) { systemCallback = window.getSystemOnBackInvokedCallback(); callback = systemCallback; } if (applicationCallback == null && systemCallback == null) { // Return null when either there's no window, or apps have just initialized and // have not finished registering callbacks. return null; } ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, " Loading @@ -133,24 +144,24 @@ class BackNavigationController { task, activityRecord, applicationCallback, systemCallback); // TODO Temp workaround for Sysui until b/221071505 is fixed if (activityRecord == null && callback != null) { if (activityRecord == null && applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, callback /* onBackInvokedCallback */); applicationCallback /* onBackInvokedCallback */); } // For IME and Home, either a callback is registered, or we do nothing. In both cases, // we don't need to pass the leashes below. if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible() || activityRecord.isActivityTypeHome()) { if (callback != null) { if (applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, callback /* onBackInvokedCallback */); applicationCallback /* onBackInvokedCallback */); } else { return null; } Loading @@ -159,12 +170,12 @@ class BackNavigationController { prev = task.getActivity( (r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity()); if (callback != null) { if (applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, callback /* onBackInvokedCallback */); applicationCallback /* onBackInvokedCallback */); } else if (prev != null) { backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY; } else if (task.returnsToHomeRootTask()) { Loading @@ -188,8 +199,8 @@ class BackNavigationController { prevTaskId = prevTask != null ? prevTask.mTaskId : 0; prevUserId = prevTask != null ? prevTask.mUserId : 0; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s", prev != null ? prev.mActivityComponent : null); ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s. " + "Back type is %s", prev != null ? prev.mActivityComponent : null, backType); //TODO(207481538) Remove once the infrastructure to support per-activity screenshot is // implemented. For now we simply have the mBackScreenshots hash map that dumbly Loading @@ -204,6 +215,7 @@ class BackNavigationController { return null; } // Prepare a leash to animate the current top window // TODO(b/220934562): Use surface animator to better manage animation conflicts. animLeash = removedWindowContainer.makeAnimationLeash() .setName("BackPreview Leash for " + removedWindowContainer) .setHidden(false) Loading Loading @@ -231,12 +243,30 @@ class BackNavigationController { activityRecord.windowType); } SurfaceControl.Builder builder = new SurfaceControl.Builder() screenshotSurface = new SurfaceControl.Builder() .setName("BackPreview Screenshot for " + prev) .setParent(animationLeashParent) .setHidden(false) .setBLASTLayer(); SurfaceControl screenshotSurface = builder.build(); .setBLASTLayer() .build(); if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { task.mBackGestureStarted = true; // Make launcher show from behind by marking its top activity as visible and // launch-behind to bump its visibility for the duration of the back gesture. prevTaskTopActivity = prevTask.getTopNonFinishingActivity(); if (prevTaskTopActivity != null) { if (!prevTaskTopActivity.mVisibleRequested) { prevTaskTopActivity.setVisibility(true); } prevTaskTopActivity.mLaunchTaskBehind = true; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to true. Activity=%s", prevTaskTopActivity); prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible( null /* starting */, 0 /* configChanges */, false /* preserveWindows */); } } // Find a screenshot of the previous activity Loading @@ -253,17 +283,20 @@ class BackNavigationController { WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer; try { activityRecord.token.linkToDeath( () -> resetSurfaces(finalRemovedWindowContainer), 0); activityRecord.token.linkToDeath(() -> resetSurfaces(finalRemovedWindowContainer), 0); } catch (RemoteException e) { Slog.e(TAG, "Failed to link to death", e); resetSurfaces(removedWindowContainer); return null; } RemoteCallback onBackNavigationDone = new RemoteCallback( result -> resetSurfaces(finalRemovedWindowContainer )); int finalBackType = backType; final IOnBackInvokedCallback callback = applicationCallback != null ? applicationCallback : systemCallback; ActivityRecord finalPrevTaskTopActivity = prevTaskTopActivity; RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone( result, finalRemovedWindowContainer, finalBackType, task, finalPrevTaskTopActivity)); return new BackNavigationInfo(backType, topAppTarget, screenshotSurface, Loading @@ -273,6 +306,39 @@ class BackNavigationController { callback); } private void onBackNavigationDone( Bundle result, WindowContainer windowContainer, int backType, Task task, ActivityRecord prevTaskTopActivity) { SurfaceControl surfaceControl = windowContainer.getSurfaceControl(); boolean triggerBack = result != null ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK) : false; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, " + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity); if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { if (triggerBack) { if (surfaceControl != null && surfaceControl.isValid()) { // When going back to home, hide the task surface before it is re-parented to // avoid flicker. SurfaceControl.Transaction t = windowContainer.getSyncTransaction(); t.hide(surfaceControl); t.apply(); } } if (prevTaskTopActivity != null && !triggerBack) { // Restore the launch-behind state. task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token); prevTaskTopActivity.mLaunchTaskBehind = false; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to false. Activity=%s", prevTaskTopActivity); } } else { task.mBackGestureStarted = false; } resetSurfaces(windowContainer); } private HardwareBuffer getActivitySnapshot(@NonNull Task task, ComponentName activityComponent) { Loading services/core/java/com/android/server/wm/Task.java +15 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP; import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES; Loading Loading @@ -609,6 +610,12 @@ class Task extends TaskFragment { boolean mLastSurfaceShowing = true; /** * Tracks if a back gesture is in progress. * Skips any system transition animations if this is set to {@code true}. */ boolean mBackGestureStarted = false; private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, String _rootAffinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, Loading Loading @@ -3322,6 +3329,14 @@ class Task extends TaskFragment { } }); } } else if (mBackGestureStarted) { // Cancel playing transitions if a back navigation animation is in progress. // This bit is set by {@link BackNavigationController} when a back gesture is started. // It is used as a one-off transition overwrite that is cleared when the back gesture // is committed and triggers a transition, or when the gesture is cancelled. mBackGestureStarted = false; mDisplayContent.mSkipAppTransitionAnimation = true; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Skipping app transition animation. task=%s", this); } else { super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources); } Loading Loading
data/etc/services.core.protolog.json +27 −9 Original line number Diff line number Diff line Loading @@ -1309,6 +1309,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-711194343": { "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "-706481945": { "message": "TaskFragment parent info changed name=%s parentTaskId=%d", "level": "VERBOSE", Loading Loading @@ -2587,6 +2593,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/WindowState.java" }, "599897753": { "message": "Previous Activity is %s. Back type is %s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "600140673": { "message": "checkBootAnimationComplete: Waiting for anim complete", "level": "INFO", Loading Loading @@ -2671,12 +2683,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "664667685": { "message": "Activity %s: enableOnBackInvokedCallback=false. Returning null BackNavigationInfo.", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "665256544": { "message": "All windows drawn!", "level": "DEBUG", Loading Loading @@ -2887,6 +2893,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, "948208142": { "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "950074526": { "message": "setLockTaskMode: Can't lock due to auth", "level": "WARN", Loading Loading @@ -3103,6 +3115,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "1172542963": { "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "1178653181": { "message": "Old wallpaper still the target.", "level": "VERBOSE", Loading Loading @@ -3415,11 +3433,11 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "1554795024": { "message": "Previous Activity is %s", "1544805551": { "message": "Skipping app transition animation. task=%s", "level": "DEBUG", "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" "at": "com\/android\/server\/wm\/Task.java" }, "1557732761": { "message": "For Intent %s bringing to top: %s", Loading
libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +21 −8 Original line number Diff line number Diff line Loading @@ -52,14 +52,17 @@ import com.android.wm.shell.common.annotations.ShellMainThread; */ public class BackAnimationController implements RemoteCallable<BackAnimationController> { private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability"; public static final boolean IS_ENABLED = SystemProperties .getInt(BACK_PREDICTABILITY_PROP, 1) > 0; private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP = "persist.debug.back_predictability_progress_threshold"; // By default, enable new back dispatching without any animations. private static final int BACK_PREDICTABILITY_PROP = SystemProperties.getInt("persist.debug.back_predictability", 1); public static final boolean IS_ENABLED = BACK_PREDICTABILITY_PROP > 0; private static final int PROGRESS_THRESHOLD = SystemProperties .getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1); private static final String TAG = "BackAnimationController"; @VisibleForTesting boolean mEnableAnimations = (BACK_PREDICTABILITY_PROP & (1 << 1)) != 0; /** * Location of the initial touch event of the back gesture. Loading Loading @@ -255,7 +258,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont backNavigationInfo.getTaskWindowConfiguration()); } mTransaction.apply(); } else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) { } else if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; } else if (backType == BackNavigationInfo.TYPE_CALLBACK) { targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); Loading Loading @@ -309,7 +312,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget); IOnBackInvokedCallback targetCallback = null; if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) { if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; } else if (backType == BackNavigationInfo.TYPE_CROSS_TASK || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) { Loading @@ -330,8 +333,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; } int backType = mBackNavigationInfo.getType(); boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && mBackToLauncherCallback != null; boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType); IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher ? mBackToLauncherCallback : mBackNavigationInfo.getOnBackInvokedCallback(); Loading @@ -356,6 +358,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } private boolean shouldDispatchToLauncher(int backType) { return backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && mBackToLauncherCallback != null && mEnableAnimations; } @VisibleForTesting void setEnableAnimations(boolean shouldEnable) { mEnableAnimations = shouldEnable; } private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) { if (callback == null) { return; Loading Loading @@ -468,7 +481,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return; } RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget(); if (animationTarget != null && mTriggerBack) { if (animationTarget != null) { if (animationTarget.leash != null && animationTarget.leash.isValid()) { mTransaction.remove(animationTarget.leash); } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +1 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ public class BackAnimationControllerTest { MockitoAnnotations.initMocks(this); mController = new BackAnimationController( mShellExecutor, mTransaction, mActivityTaskManager, mContext); mController.setEnableAnimations(true); } private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget, Loading
services/core/java/com/android/server/wm/BackNavigationController.java +93 −27 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.content.ComponentName; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.os.Bundle; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.SystemProperties; Loading @@ -44,7 +45,11 @@ import com.android.internal.protolog.common.ProtoLog; class BackNavigationController { private static final String TAG = "BackNavigationController"; private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability"; // By default, enable new back dispatching without any animations. private static final int BACK_PREDICTABILITY_PROP = SystemProperties.getInt("persist.debug.back_predictability", 1); private static final int ANIMATIONS_MASK = 1 << 1; private static final int SCREENSHOT_MASK = 1 << 2; @Nullable private TaskSnapshotController mTaskSnapshotController; Loading @@ -53,11 +58,15 @@ class BackNavigationController { * Returns true if the back predictability feature is enabled */ static boolean isEnabled() { return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 1) > 0; return BACK_PREDICTABILITY_PROP > 0; } static boolean isScreenshotEnabled() { return false; return (BACK_PREDICTABILITY_PROP & SCREENSHOT_MASK) != 0; } private static boolean isAnimationEnabled() { return (BACK_PREDICTABILITY_PROP & ANIMATIONS_MASK) != 0; } /** Loading Loading @@ -93,14 +102,17 @@ class BackNavigationController { ActivityRecord prev; WindowContainer<?> removedWindowContainer; ActivityRecord activityRecord; ActivityRecord prevTaskTopActivity = null; SurfaceControl animationLeashParent; WindowConfiguration taskWindowConfiguration; HardwareBuffer screenshotBuffer = null; SurfaceControl screenshotSurface; int prevTaskId; int prevUserId; RemoteAnimationTarget topAppTarget; SurfaceControl animLeash; IOnBackInvokedCallback callback = null; IOnBackInvokedCallback applicationCallback = null; IOnBackInvokedCallback systemCallback = null; synchronized (task.mWmService.mGlobalLock) { Loading @@ -116,15 +128,14 @@ class BackNavigationController { removedWindowContainer = activityRecord; taskWindowConfiguration = window.getWindowConfiguration(); } IOnBackInvokedCallback applicationCallback = null; IOnBackInvokedCallback systemCallback = null; if (window != null) { applicationCallback = window.getApplicationOnBackInvokedCallback(); callback = applicationCallback; if (callback == null) { systemCallback = window.getSystemOnBackInvokedCallback(); callback = systemCallback; } if (applicationCallback == null && systemCallback == null) { // Return null when either there's no window, or apps have just initialized and // have not finished registering callbacks. return null; } ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, " Loading @@ -133,24 +144,24 @@ class BackNavigationController { task, activityRecord, applicationCallback, systemCallback); // TODO Temp workaround for Sysui until b/221071505 is fixed if (activityRecord == null && callback != null) { if (activityRecord == null && applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, callback /* onBackInvokedCallback */); applicationCallback /* onBackInvokedCallback */); } // For IME and Home, either a callback is registered, or we do nothing. In both cases, // we don't need to pass the leashes below. if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible() || activityRecord.isActivityTypeHome()) { if (callback != null) { if (applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, callback /* onBackInvokedCallback */); applicationCallback /* onBackInvokedCallback */); } else { return null; } Loading @@ -159,12 +170,12 @@ class BackNavigationController { prev = task.getActivity( (r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity()); if (callback != null) { if (applicationCallback != null) { return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK, null /* topWindowLeash */, null /* screenshotSurface */, null /* screenshotBuffer */, null /* taskWindowConfiguration */, null /* onBackNavigationDone */, callback /* onBackInvokedCallback */); applicationCallback /* onBackInvokedCallback */); } else if (prev != null) { backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY; } else if (task.returnsToHomeRootTask()) { Loading @@ -188,8 +199,8 @@ class BackNavigationController { prevTaskId = prevTask != null ? prevTask.mTaskId : 0; prevUserId = prevTask != null ? prevTask.mUserId : 0; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s", prev != null ? prev.mActivityComponent : null); ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s. " + "Back type is %s", prev != null ? prev.mActivityComponent : null, backType); //TODO(207481538) Remove once the infrastructure to support per-activity screenshot is // implemented. For now we simply have the mBackScreenshots hash map that dumbly Loading @@ -204,6 +215,7 @@ class BackNavigationController { return null; } // Prepare a leash to animate the current top window // TODO(b/220934562): Use surface animator to better manage animation conflicts. animLeash = removedWindowContainer.makeAnimationLeash() .setName("BackPreview Leash for " + removedWindowContainer) .setHidden(false) Loading Loading @@ -231,12 +243,30 @@ class BackNavigationController { activityRecord.windowType); } SurfaceControl.Builder builder = new SurfaceControl.Builder() screenshotSurface = new SurfaceControl.Builder() .setName("BackPreview Screenshot for " + prev) .setParent(animationLeashParent) .setHidden(false) .setBLASTLayer(); SurfaceControl screenshotSurface = builder.build(); .setBLASTLayer() .build(); if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { task.mBackGestureStarted = true; // Make launcher show from behind by marking its top activity as visible and // launch-behind to bump its visibility for the duration of the back gesture. prevTaskTopActivity = prevTask.getTopNonFinishingActivity(); if (prevTaskTopActivity != null) { if (!prevTaskTopActivity.mVisibleRequested) { prevTaskTopActivity.setVisibility(true); } prevTaskTopActivity.mLaunchTaskBehind = true; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to true. Activity=%s", prevTaskTopActivity); prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible( null /* starting */, 0 /* configChanges */, false /* preserveWindows */); } } // Find a screenshot of the previous activity Loading @@ -253,17 +283,20 @@ class BackNavigationController { WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer; try { activityRecord.token.linkToDeath( () -> resetSurfaces(finalRemovedWindowContainer), 0); activityRecord.token.linkToDeath(() -> resetSurfaces(finalRemovedWindowContainer), 0); } catch (RemoteException e) { Slog.e(TAG, "Failed to link to death", e); resetSurfaces(removedWindowContainer); return null; } RemoteCallback onBackNavigationDone = new RemoteCallback( result -> resetSurfaces(finalRemovedWindowContainer )); int finalBackType = backType; final IOnBackInvokedCallback callback = applicationCallback != null ? applicationCallback : systemCallback; ActivityRecord finalPrevTaskTopActivity = prevTaskTopActivity; RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone( result, finalRemovedWindowContainer, finalBackType, task, finalPrevTaskTopActivity)); return new BackNavigationInfo(backType, topAppTarget, screenshotSurface, Loading @@ -273,6 +306,39 @@ class BackNavigationController { callback); } private void onBackNavigationDone( Bundle result, WindowContainer windowContainer, int backType, Task task, ActivityRecord prevTaskTopActivity) { SurfaceControl surfaceControl = windowContainer.getSurfaceControl(); boolean triggerBack = result != null ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK) : false; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, " + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity); if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { if (triggerBack) { if (surfaceControl != null && surfaceControl.isValid()) { // When going back to home, hide the task surface before it is re-parented to // avoid flicker. SurfaceControl.Transaction t = windowContainer.getSyncTransaction(); t.hide(surfaceControl); t.apply(); } } if (prevTaskTopActivity != null && !triggerBack) { // Restore the launch-behind state. task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token); prevTaskTopActivity.mLaunchTaskBehind = false; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to false. Activity=%s", prevTaskTopActivity); } } else { task.mBackGestureStarted = false; } resetSurfaces(windowContainer); } private HardwareBuffer getActivitySnapshot(@NonNull Task task, ComponentName activityComponent) { Loading
services/core/java/com/android/server/wm/Task.java +15 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP; import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES; Loading Loading @@ -609,6 +610,12 @@ class Task extends TaskFragment { boolean mLastSurfaceShowing = true; /** * Tracks if a back gesture is in progress. * Skips any system transition animations if this is set to {@code true}. */ boolean mBackGestureStarted = false; private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, String _rootAffinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, Loading Loading @@ -3322,6 +3329,14 @@ class Task extends TaskFragment { } }); } } else if (mBackGestureStarted) { // Cancel playing transitions if a back navigation animation is in progress. // This bit is set by {@link BackNavigationController} when a back gesture is started. // It is used as a one-off transition overwrite that is cleared when the back gesture // is committed and triggers a transition, or when the gesture is cancelled. mBackGestureStarted = false; mDisplayContent.mSkipAppTransitionAnimation = true; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Skipping app transition animation. task=%s", this); } else { super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources); } Loading