Merge "Implement back to launcher animation from shell and WM animation controllers." into tm-dev
This commit is contained in:
@@ -1309,6 +1309,12 @@
|
|||||||
"group": "WM_DEBUG_STATES",
|
"group": "WM_DEBUG_STATES",
|
||||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
"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": {
|
"-706481945": {
|
||||||
"message": "TaskFragment parent info changed name=%s parentTaskId=%d",
|
"message": "TaskFragment parent info changed name=%s parentTaskId=%d",
|
||||||
"level": "VERBOSE",
|
"level": "VERBOSE",
|
||||||
@@ -2587,6 +2593,12 @@
|
|||||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||||
"at": "com\/android\/server\/wm\/WindowState.java"
|
"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": {
|
"600140673": {
|
||||||
"message": "checkBootAnimationComplete: Waiting for anim complete",
|
"message": "checkBootAnimationComplete: Waiting for anim complete",
|
||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
@@ -2671,12 +2683,6 @@
|
|||||||
"group": "WM_ERROR",
|
"group": "WM_ERROR",
|
||||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
"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": {
|
"665256544": {
|
||||||
"message": "All windows drawn!",
|
"message": "All windows drawn!",
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
@@ -2887,6 +2893,12 @@
|
|||||||
"group": "WM_DEBUG_STATES",
|
"group": "WM_DEBUG_STATES",
|
||||||
"at": "com\/android\/server\/wm\/TaskFragment.java"
|
"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": {
|
"950074526": {
|
||||||
"message": "setLockTaskMode: Can't lock due to auth",
|
"message": "setLockTaskMode: Can't lock due to auth",
|
||||||
"level": "WARN",
|
"level": "WARN",
|
||||||
@@ -3103,6 +3115,12 @@
|
|||||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||||
"at": "com\/android\/server\/wm\/DisplayContent.java"
|
"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": {
|
"1178653181": {
|
||||||
"message": "Old wallpaper still the target.",
|
"message": "Old wallpaper still the target.",
|
||||||
"level": "VERBOSE",
|
"level": "VERBOSE",
|
||||||
@@ -3415,11 +3433,11 @@
|
|||||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||||
},
|
},
|
||||||
"1554795024": {
|
"1544805551": {
|
||||||
"message": "Previous Activity is %s",
|
"message": "Skipping app transition animation. task=%s",
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
"group": "WM_DEBUG_BACK_PREVIEW",
|
"group": "WM_DEBUG_BACK_PREVIEW",
|
||||||
"at": "com\/android\/server\/wm\/BackNavigationController.java"
|
"at": "com\/android\/server\/wm\/Task.java"
|
||||||
},
|
},
|
||||||
"1557732761": {
|
"1557732761": {
|
||||||
"message": "For Intent %s bringing to top: %s",
|
"message": "For Intent %s bringing to top: %s",
|
||||||
|
|||||||
@@ -52,14 +52,17 @@ import com.android.wm.shell.common.annotations.ShellMainThread;
|
|||||||
*/
|
*/
|
||||||
public class BackAnimationController implements RemoteCallable<BackAnimationController> {
|
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 =
|
private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP =
|
||||||
"persist.debug.back_predictability_progress_threshold";
|
"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
|
private static final int PROGRESS_THRESHOLD = SystemProperties
|
||||||
.getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1);
|
.getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1);
|
||||||
private static final String TAG = "BackAnimationController";
|
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.
|
* Location of the initial touch event of the back gesture.
|
||||||
@@ -255,7 +258,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
backNavigationInfo.getTaskWindowConfiguration());
|
backNavigationInfo.getTaskWindowConfiguration());
|
||||||
}
|
}
|
||||||
mTransaction.apply();
|
mTransaction.apply();
|
||||||
} else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
|
} else if (shouldDispatchToLauncher(backType)) {
|
||||||
targetCallback = mBackToLauncherCallback;
|
targetCallback = mBackToLauncherCallback;
|
||||||
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
|
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
|
||||||
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
|
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
|
||||||
@@ -309,7 +312,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
|
|
||||||
BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget);
|
BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget);
|
||||||
IOnBackInvokedCallback targetCallback = null;
|
IOnBackInvokedCallback targetCallback = null;
|
||||||
if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
|
if (shouldDispatchToLauncher(backType)) {
|
||||||
targetCallback = mBackToLauncherCallback;
|
targetCallback = mBackToLauncherCallback;
|
||||||
} else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
|
} else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
|
||||||
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
|
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
|
||||||
@@ -330,8 +333,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int backType = mBackNavigationInfo.getType();
|
int backType = mBackNavigationInfo.getType();
|
||||||
boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
|
boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType);
|
||||||
&& mBackToLauncherCallback != null;
|
|
||||||
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
|
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
|
||||||
? mBackToLauncherCallback
|
? mBackToLauncherCallback
|
||||||
: mBackNavigationInfo.getOnBackInvokedCallback();
|
: mBackNavigationInfo.getOnBackInvokedCallback();
|
||||||
@@ -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) {
|
private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
return;
|
return;
|
||||||
@@ -468,7 +481,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
|
RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
|
||||||
if (animationTarget != null && mTriggerBack) {
|
if (animationTarget != null) {
|
||||||
if (animationTarget.leash != null && animationTarget.leash.isValid()) {
|
if (animationTarget.leash != null && animationTarget.leash.isValid()) {
|
||||||
mTransaction.remove(animationTarget.leash);
|
mTransaction.remove(animationTarget.leash);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class BackAnimationControllerTest {
|
|||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mController = new BackAnimationController(
|
mController = new BackAnimationController(
|
||||||
mShellExecutor, mTransaction, mActivityTaskManager, mContext);
|
mShellExecutor, mTransaction, mActivityTaskManager, mContext);
|
||||||
|
mController.setEnableAnimations(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget,
|
private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.content.ComponentName;
|
|||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.hardware.HardwareBuffer;
|
import android.hardware.HardwareBuffer;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
@@ -44,7 +45,11 @@ import com.android.internal.protolog.common.ProtoLog;
|
|||||||
class BackNavigationController {
|
class BackNavigationController {
|
||||||
|
|
||||||
private static final String TAG = "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
|
@Nullable
|
||||||
private TaskSnapshotController mTaskSnapshotController;
|
private TaskSnapshotController mTaskSnapshotController;
|
||||||
@@ -53,11 +58,15 @@ class BackNavigationController {
|
|||||||
* Returns true if the back predictability feature is enabled
|
* Returns true if the back predictability feature is enabled
|
||||||
*/
|
*/
|
||||||
static boolean isEnabled() {
|
static boolean isEnabled() {
|
||||||
return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 1) > 0;
|
return BACK_PREDICTABILITY_PROP > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isScreenshotEnabled() {
|
static boolean isScreenshotEnabled() {
|
||||||
return false;
|
return (BACK_PREDICTABILITY_PROP & SCREENSHOT_MASK) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isAnimationEnabled() {
|
||||||
|
return (BACK_PREDICTABILITY_PROP & ANIMATIONS_MASK) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,14 +102,17 @@ class BackNavigationController {
|
|||||||
ActivityRecord prev;
|
ActivityRecord prev;
|
||||||
WindowContainer<?> removedWindowContainer;
|
WindowContainer<?> removedWindowContainer;
|
||||||
ActivityRecord activityRecord;
|
ActivityRecord activityRecord;
|
||||||
|
ActivityRecord prevTaskTopActivity = null;
|
||||||
SurfaceControl animationLeashParent;
|
SurfaceControl animationLeashParent;
|
||||||
WindowConfiguration taskWindowConfiguration;
|
WindowConfiguration taskWindowConfiguration;
|
||||||
HardwareBuffer screenshotBuffer = null;
|
HardwareBuffer screenshotBuffer = null;
|
||||||
|
SurfaceControl screenshotSurface;
|
||||||
int prevTaskId;
|
int prevTaskId;
|
||||||
int prevUserId;
|
int prevUserId;
|
||||||
RemoteAnimationTarget topAppTarget;
|
RemoteAnimationTarget topAppTarget;
|
||||||
SurfaceControl animLeash;
|
SurfaceControl animLeash;
|
||||||
IOnBackInvokedCallback callback = null;
|
IOnBackInvokedCallback applicationCallback = null;
|
||||||
|
IOnBackInvokedCallback systemCallback = null;
|
||||||
|
|
||||||
synchronized (task.mWmService.mGlobalLock) {
|
synchronized (task.mWmService.mGlobalLock) {
|
||||||
|
|
||||||
@@ -116,15 +128,14 @@ class BackNavigationController {
|
|||||||
removedWindowContainer = activityRecord;
|
removedWindowContainer = activityRecord;
|
||||||
taskWindowConfiguration = window.getWindowConfiguration();
|
taskWindowConfiguration = window.getWindowConfiguration();
|
||||||
}
|
}
|
||||||
IOnBackInvokedCallback applicationCallback = null;
|
|
||||||
IOnBackInvokedCallback systemCallback = null;
|
|
||||||
if (window != null) {
|
if (window != null) {
|
||||||
applicationCallback = window.getApplicationOnBackInvokedCallback();
|
applicationCallback = window.getApplicationOnBackInvokedCallback();
|
||||||
callback = applicationCallback;
|
|
||||||
if (callback == null) {
|
|
||||||
systemCallback = window.getSystemOnBackInvokedCallback();
|
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, "
|
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, "
|
||||||
@@ -133,24 +144,24 @@ class BackNavigationController {
|
|||||||
task, activityRecord, applicationCallback, systemCallback);
|
task, activityRecord, applicationCallback, systemCallback);
|
||||||
|
|
||||||
// TODO Temp workaround for Sysui until b/221071505 is fixed
|
// 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,
|
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
|
||||||
null /* topWindowLeash */, null /* screenshotSurface */,
|
null /* topWindowLeash */, null /* screenshotSurface */,
|
||||||
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
||||||
null /* onBackNavigationDone */,
|
null /* onBackNavigationDone */,
|
||||||
callback /* onBackInvokedCallback */);
|
applicationCallback /* onBackInvokedCallback */);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For IME and Home, either a callback is registered, or we do nothing. In both cases,
|
// 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.
|
// we don't need to pass the leashes below.
|
||||||
if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible()
|
if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible()
|
||||||
|| activityRecord.isActivityTypeHome()) {
|
|| activityRecord.isActivityTypeHome()) {
|
||||||
if (callback != null) {
|
if (applicationCallback != null) {
|
||||||
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
|
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
|
||||||
null /* topWindowLeash */, null /* screenshotSurface */,
|
null /* topWindowLeash */, null /* screenshotSurface */,
|
||||||
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
||||||
null /* onBackNavigationDone */,
|
null /* onBackNavigationDone */,
|
||||||
callback /* onBackInvokedCallback */);
|
applicationCallback /* onBackInvokedCallback */);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -159,12 +170,12 @@ class BackNavigationController {
|
|||||||
prev = task.getActivity(
|
prev = task.getActivity(
|
||||||
(r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity());
|
(r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity());
|
||||||
|
|
||||||
if (callback != null) {
|
if (applicationCallback != null) {
|
||||||
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
|
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
|
||||||
null /* topWindowLeash */, null /* screenshotSurface */,
|
null /* topWindowLeash */, null /* screenshotSurface */,
|
||||||
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
||||||
null /* onBackNavigationDone */,
|
null /* onBackNavigationDone */,
|
||||||
callback /* onBackInvokedCallback */);
|
applicationCallback /* onBackInvokedCallback */);
|
||||||
} else if (prev != null) {
|
} else if (prev != null) {
|
||||||
backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
|
backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
|
||||||
} else if (task.returnsToHomeRootTask()) {
|
} else if (task.returnsToHomeRootTask()) {
|
||||||
@@ -188,8 +199,8 @@ class BackNavigationController {
|
|||||||
prevTaskId = prevTask != null ? prevTask.mTaskId : 0;
|
prevTaskId = prevTask != null ? prevTask.mTaskId : 0;
|
||||||
prevUserId = prevTask != null ? prevTask.mUserId : 0;
|
prevUserId = prevTask != null ? prevTask.mUserId : 0;
|
||||||
|
|
||||||
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s",
|
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s. "
|
||||||
prev != null ? prev.mActivityComponent : null);
|
+ "Back type is %s", prev != null ? prev.mActivityComponent : null, backType);
|
||||||
|
|
||||||
//TODO(207481538) Remove once the infrastructure to support per-activity screenshot is
|
//TODO(207481538) Remove once the infrastructure to support per-activity screenshot is
|
||||||
// implemented. For now we simply have the mBackScreenshots hash map that dumbly
|
// implemented. For now we simply have the mBackScreenshots hash map that dumbly
|
||||||
@@ -204,6 +215,7 @@ class BackNavigationController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Prepare a leash to animate the current top window
|
// Prepare a leash to animate the current top window
|
||||||
|
// TODO(b/220934562): Use surface animator to better manage animation conflicts.
|
||||||
animLeash = removedWindowContainer.makeAnimationLeash()
|
animLeash = removedWindowContainer.makeAnimationLeash()
|
||||||
.setName("BackPreview Leash for " + removedWindowContainer)
|
.setName("BackPreview Leash for " + removedWindowContainer)
|
||||||
.setHidden(false)
|
.setHidden(false)
|
||||||
@@ -231,12 +243,30 @@ class BackNavigationController {
|
|||||||
activityRecord.windowType);
|
activityRecord.windowType);
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceControl.Builder builder = new SurfaceControl.Builder()
|
screenshotSurface = new SurfaceControl.Builder()
|
||||||
.setName("BackPreview Screenshot for " + prev)
|
.setName("BackPreview Screenshot for " + prev)
|
||||||
.setParent(animationLeashParent)
|
.setParent(animationLeashParent)
|
||||||
.setHidden(false)
|
.setHidden(false)
|
||||||
.setBLASTLayer();
|
.setBLASTLayer()
|
||||||
SurfaceControl screenshotSurface = builder.build();
|
.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
|
// Find a screenshot of the previous activity
|
||||||
|
|
||||||
@@ -253,17 +283,20 @@ class BackNavigationController {
|
|||||||
|
|
||||||
WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
|
WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
|
||||||
try {
|
try {
|
||||||
activityRecord.token.linkToDeath(
|
activityRecord.token.linkToDeath(() -> resetSurfaces(finalRemovedWindowContainer), 0);
|
||||||
() -> resetSurfaces(finalRemovedWindowContainer), 0);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.e(TAG, "Failed to link to death", e);
|
Slog.e(TAG, "Failed to link to death", e);
|
||||||
resetSurfaces(removedWindowContainer);
|
resetSurfaces(removedWindowContainer);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteCallback onBackNavigationDone = new RemoteCallback(
|
int finalBackType = backType;
|
||||||
result -> resetSurfaces(finalRemovedWindowContainer
|
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,
|
return new BackNavigationInfo(backType,
|
||||||
topAppTarget,
|
topAppTarget,
|
||||||
screenshotSurface,
|
screenshotSurface,
|
||||||
@@ -273,6 +306,39 @@ class BackNavigationController {
|
|||||||
callback);
|
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,
|
private HardwareBuffer getActivitySnapshot(@NonNull Task task,
|
||||||
ComponentName activityComponent) {
|
ComponentName activityComponent) {
|
||||||
|
|||||||
@@ -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_FOCUSED_HEIGHT_IN_DIP;
|
||||||
import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_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_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_LOCKTASK;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
|
||||||
@@ -609,6 +610,12 @@ class Task extends TaskFragment {
|
|||||||
|
|
||||||
boolean mLastSurfaceShowing = true;
|
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,
|
private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
|
||||||
Intent _affinityIntent, String _affinity, String _rootAffinity,
|
Intent _affinityIntent, String _affinity, String _rootAffinity,
|
||||||
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
|
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
|
||||||
@@ -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 {
|
} else {
|
||||||
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
|
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ import static org.mockito.Mockito.when;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.hardware.HardwareBuffer;
|
import android.hardware.HardwareBuffer;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.window.BackEvent;
|
||||||
import android.window.BackNavigationInfo;
|
import android.window.BackNavigationInfo;
|
||||||
|
import android.window.IOnBackInvokedCallback;
|
||||||
|
import android.window.OnBackInvokedDispatcher;
|
||||||
import android.window.TaskSnapshot;
|
import android.window.TaskSnapshot;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -42,15 +45,19 @@ import org.junit.runner.RunWith;
|
|||||||
public class BackNavigationControllerTests extends WindowTestsBase {
|
public class BackNavigationControllerTests extends WindowTestsBase {
|
||||||
|
|
||||||
private BackNavigationController mBackNavigationController;
|
private BackNavigationController mBackNavigationController;
|
||||||
|
private IOnBackInvokedCallback mOnBackInvokedCallback;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
mBackNavigationController = new BackNavigationController();
|
mBackNavigationController = new BackNavigationController();
|
||||||
|
mOnBackInvokedCallback = createBackCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void backTypeHomeWhenBackToLauncher() {
|
public void backTypeHomeWhenBackToLauncher() {
|
||||||
Task task = createTopTaskWithActivity();
|
Task task = createTopTaskWithActivity();
|
||||||
|
registerSystemOnBackInvokedCallback();
|
||||||
|
|
||||||
BackNavigationInfo backNavigationInfo =
|
BackNavigationInfo backNavigationInfo =
|
||||||
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
||||||
assertThat(backNavigationInfo).isNotNull();
|
assertThat(backNavigationInfo).isNotNull();
|
||||||
@@ -63,6 +70,8 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
|||||||
Task taskA = createTask(mDefaultDisplay);
|
Task taskA = createTask(mDefaultDisplay);
|
||||||
createActivityRecord(taskA);
|
createActivityRecord(taskA);
|
||||||
Task task = createTopTaskWithActivity();
|
Task task = createTopTaskWithActivity();
|
||||||
|
registerSystemOnBackInvokedCallback();
|
||||||
|
|
||||||
BackNavigationInfo backNavigationInfo =
|
BackNavigationInfo backNavigationInfo =
|
||||||
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
||||||
assertThat(backNavigationInfo).isNotNull();
|
assertThat(backNavigationInfo).isNotNull();
|
||||||
@@ -75,6 +84,8 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
|||||||
Task task = createTopTaskWithActivity();
|
Task task = createTopTaskWithActivity();
|
||||||
mAtm.setFocusedTask(task.mTaskId,
|
mAtm.setFocusedTask(task.mTaskId,
|
||||||
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window").mActivityRecord);
|
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window").mActivityRecord);
|
||||||
|
registerSystemOnBackInvokedCallback();
|
||||||
|
|
||||||
BackNavigationInfo backNavigationInfo =
|
BackNavigationInfo backNavigationInfo =
|
||||||
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
||||||
assertThat(backNavigationInfo).isNotNull();
|
assertThat(backNavigationInfo).isNotNull();
|
||||||
@@ -89,6 +100,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
|||||||
public void backNavInfoFullyPopulated() {
|
public void backNavInfoFullyPopulated() {
|
||||||
Task task = createTopTaskWithActivity();
|
Task task = createTopTaskWithActivity();
|
||||||
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window");
|
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window");
|
||||||
|
registerSystemOnBackInvokedCallback();
|
||||||
|
|
||||||
// We need a mock screenshot so
|
// We need a mock screenshot so
|
||||||
TaskSnapshotController taskSnapshotController = createMockTaskSnapshotController();
|
TaskSnapshotController taskSnapshotController = createMockTaskSnapshotController();
|
||||||
@@ -104,6 +116,30 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
|||||||
assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
|
assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void preparesForBackToHome() {
|
||||||
|
Task task = createTopTaskWithActivity();
|
||||||
|
ActivityRecord activity = task.getTopActivity(false, false);
|
||||||
|
registerSystemOnBackInvokedCallback();
|
||||||
|
|
||||||
|
BackNavigationInfo backNavigationInfo =
|
||||||
|
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
||||||
|
assertThat(typeToString(backNavigationInfo.getType()))
|
||||||
|
.isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void backTypeCallback() {
|
||||||
|
Task task = createTopTaskWithActivity();
|
||||||
|
ActivityRecord activity = task.getTopActivity(false, false);
|
||||||
|
registerApplicationOnBackInvokedCallback();
|
||||||
|
|
||||||
|
BackNavigationInfo backNavigationInfo =
|
||||||
|
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
||||||
|
assertThat(typeToString(backNavigationInfo.getType()))
|
||||||
|
.isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private TaskSnapshotController createMockTaskSnapshotController() {
|
private TaskSnapshotController createMockTaskSnapshotController() {
|
||||||
TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class);
|
TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class);
|
||||||
@@ -126,4 +162,30 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
|||||||
mAtm.setFocusedTask(task.mTaskId, record);
|
mAtm.setFocusedTask(task.mTaskId, record);
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerSystemOnBackInvokedCallback() {
|
||||||
|
mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
|
||||||
|
mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_SYSTEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerApplicationOnBackInvokedCallback() {
|
||||||
|
mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
|
||||||
|
mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IOnBackInvokedCallback createBackCallback() {
|
||||||
|
return new IOnBackInvokedCallback.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onBackStarted() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackProgressed(BackEvent backEvent) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackCancelled() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackInvoked() { }
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user