summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Arthur Hung <arthurhung@google.com> 2022-07-29 01:37:15 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2022-07-29 01:37:15 +0000
commit89c25ce1f45cb8197b84b33c4d84ffba8358f8a6 (patch)
treee31f0cbf1a34a5e7273fbc8a55bbbeaff852ff23
parent7e2c9cb36a524e86e2c7519d1297df0f2f8fce94 (diff)
parentf52b49886c3ad3a62109b704300e015c61674a8f (diff)
Merge "Cancel back invoke when window focus has lost" into tm-qpr-dev am: f52b49886c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19415501 Change-Id: I7d4fc2e6f3df820a4a4594b0368ff6bfbb12820f Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl5
-rw-r--r--core/java/android/view/ViewRootImpl.java1
-rw-r--r--core/java/android/window/BackNavigationInfo.java2
-rw-r--r--core/java/android/window/ImeOnBackInvokedDispatcher.java3
-rw-r--r--core/java/android/window/WindowOnBackInvokedDispatcher.java24
-rw-r--r--core/tests/coretests/src/android/window/BackNavigationTest.java3
-rw-r--r--core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java42
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java56
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/BackNavigationController.java71
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java18
12 files changed, 132 insertions, 129 deletions
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index dc6825c85705..0bf16a0c471b 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -69,6 +69,7 @@ import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
import android.view.IRecentsAnimationRunner;
import android.view.IRemoteAnimationRunner;
+import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
import android.window.IWindowOrganizerController;
@@ -352,6 +353,8 @@ interface IActivityTaskManager {
* Prepare the back navigation in the server. This setups the leashed for sysui to animate
* the back gesture and returns the data needed for the animation.
* @param requestAnimation true if the caller wishes to animate the back navigation
+ * @param focusObserver a remote callback to nofify shell when the focused window lost focus.
*/
- android.window.BackNavigationInfo startBackNavigation(in boolean requestAnimation);
+ android.window.BackNavigationInfo startBackNavigation(in boolean requestAnimation,
+ in IWindowFocusObserver focusObserver);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3347163a1683..9319b41a5b5d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3761,7 +3761,6 @@ public final class ViewRootImpl implements ViewParent,
}
}
mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
- mOnBackInvokedDispatcher.onWindowFocusChanged(hasWindowFocus);
// NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
// is lost, so we don't need to to force a flush - there might be other events such as
diff --git a/core/java/android/window/BackNavigationInfo.java b/core/java/android/window/BackNavigationInfo.java
index 0ab6db58ab4b..dd4901417671 100644
--- a/core/java/android/window/BackNavigationInfo.java
+++ b/core/java/android/window/BackNavigationInfo.java
@@ -118,7 +118,7 @@ public final class BackNavigationInfo implements Parcelable {
* back preview.
* @param onBackInvokedCallback The back callback registered by the current top level window.
*/
- public BackNavigationInfo(@BackTargetType int type,
+ private BackNavigationInfo(@BackTargetType int type,
@Nullable RemoteAnimationTarget departingAnimationTarget,
@Nullable SurfaceControl screenshotSurface,
@Nullable HardwareBuffer screenshotBuffer,
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index f1a052b61c59..14f52282b3aa 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -83,8 +83,7 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
final Bundle bundle = new Bundle();
// Always invoke back for ime without checking the window focus.
final IOnBackInvokedCallback iCallback =
- new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback,
- () -> true);
+ new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback);
bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
bundle.putInt(RESULT_KEY_PRIORITY, priority);
bundle.putInt(RESULT_KEY_ID, callback.hashCode());
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 02c5ebcc184e..1d396be6b478 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -32,7 +32,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
import java.util.TreeMap;
-import java.util.function.Supplier;
/**
* Provides window based implementation of {@link OnBackInvokedDispatcher}.
@@ -65,7 +64,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
private final TreeMap<Integer, ArrayList<OnBackInvokedCallback>>
mOnBackInvokedCallbacks = new TreeMap<>();
private final Checker mChecker;
- private boolean mHasFocus;
public WindowOnBackInvokedDispatcher(boolean applicationCallBackEnabled) {
mChecker = new Checker(applicationCallBackEnabled);
@@ -191,7 +189,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
.ImeOnBackInvokedCallback
? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
callback).getIOnBackInvokedCallback()
- : new OnBackInvokedCallbackWrapper(callback, this::hasFocus);
+ : new OnBackInvokedCallbackWrapper(callback);
callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
}
mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
@@ -200,17 +198,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
}
}
- /**
- * Called when window focus changed.
- */
- public void onWindowFocusChanged(boolean hasFocus) {
- mHasFocus = hasFocus;
- }
-
- private boolean hasFocus() {
- return mHasFocus;
- }
-
public OnBackInvokedCallback getTopCallback() {
if (mAllCallbacks.isEmpty()) {
return null;
@@ -234,11 +221,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
private final WeakReference<OnBackInvokedCallback> mCallback;
- private final Supplier<Boolean> mHasFocus;
- OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback,
- @NonNull Supplier<Boolean> hasFocus) {
+ OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) {
mCallback = new WeakReference<>(callback);
- mHasFocus = hasFocus;
}
@Override
@@ -278,10 +262,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
if (callback == null) {
return;
}
- if (!mHasFocus.get()) {
- Log.w(TAG, "Skip back invoke due to current focus has lost.");
- return;
- }
callback.onBackInvoked();
});
}
diff --git a/core/tests/coretests/src/android/window/BackNavigationTest.java b/core/tests/coretests/src/android/window/BackNavigationTest.java
index ce69f12a065b..bbbc4230903a 100644
--- a/core/tests/coretests/src/android/window/BackNavigationTest.java
+++ b/core/tests/coretests/src/android/window/BackNavigationTest.java
@@ -91,7 +91,8 @@ public class BackNavigationTest {
private void assertCallbackIsCalled(CountDownLatch latch) {
try {
mInstrumentation.getUiAutomation().waitForIdle(500, 1000);
- BackNavigationInfo info = ActivityTaskManager.getService().startBackNavigation(true);
+ BackNavigationInfo info = ActivityTaskManager.getService()
+ .startBackNavigation(true, null);
assertNotNull("BackNavigationInfo is null", info);
assertNotNull("OnBackInvokedCallback is null", info.getOnBackInvokedCallback());
info.getOnBackInvokedCallback().onBackInvoked();
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index b5194f637395..f448cb3091e7 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -66,7 +66,6 @@ public class WindowOnBackInvokedDispatcherTest {
MockitoAnnotations.initMocks(this);
mDispatcher = new WindowOnBackInvokedDispatcher(true /* applicationCallbackEnabled */);
mDispatcher.attachToWindow(mWindowSession, mWindow);
- mDispatcher.onWindowFocusChanged(true);
}
private void waitForIdle() {
@@ -153,31 +152,4 @@ public class WindowOnBackInvokedDispatcherTest {
waitForIdle();
verify(mCallback2).onBackStarted();
}
-
- @Test
- public void skipBackInvokeWhenNoFocus() throws RemoteException {
- ArgumentCaptor<OnBackInvokedCallbackInfo> captor =
- ArgumentCaptor.forClass(OnBackInvokedCallbackInfo.class);
-
- mDispatcher.registerOnBackInvokedCallback(
- OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback1);
-
- verify(mWindowSession, times(1)).setOnBackInvokedCallbackInfo(
- Mockito.eq(mWindow),
- captor.capture());
-
- verify(mWindowSession).setOnBackInvokedCallbackInfo(Mockito.eq(mWindow), captor.capture());
-
- // Should invoke back if it's still in focused.
- captor.getValue().getCallback().onBackInvoked();
- waitForIdle();
- verify(mCallback1).onBackInvoked();
-
- // In case the focus has lost during back gesture.
- mDispatcher.onWindowFocusChanged(false);
-
- captor.getValue().getCallback().onBackInvoked();
- waitForIdle();
- verifyZeroInteractions(mCallback1);
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index d53a98cf5b07..02211220822a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -32,11 +32,13 @@ import android.graphics.PointF;
import android.hardware.HardwareBuffer;
import android.net.Uri;
import android.os.Handler;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings.Global;
import android.util.Log;
+import android.view.IWindowFocusObserver;
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
@@ -107,6 +109,24 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
mTransitionInProgress = false;
};
+ @VisibleForTesting
+ final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() {
+ @Override
+ public void focusGained(IBinder inputToken) { }
+ @Override
+ public void focusLost(IBinder inputToken) {
+ mShellExecutor.execute(() -> {
+ if (!mBackGestureStarted || mTransitionInProgress) {
+ // If an uninterruptible transition is already in progress, we should ignore
+ // this due to the transition may cause focus lost. (alpha = 0)
+ return;
+ }
+ setTriggerBack(false);
+ onGestureFinished(false);
+ });
+ }
+ };
+
public BackAnimationController(
@NonNull @ShellMainThread ShellExecutor shellExecutor,
@NonNull @ShellBackgroundThread Handler backgroundHandler,
@@ -266,17 +286,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
// Let the animation initialized here to make sure the onPointerDownOutsideFocus
// could be happened when ACTION_DOWN, it may change the current focus that we
// would access it when startBackNavigation.
- initAnimation(touchX, touchY);
+ onGestureStarted(touchX, touchY);
}
onMove(touchX, touchY, swipeEdge);
} else if (keyAction == MotionEvent.ACTION_UP || keyAction == MotionEvent.ACTION_CANCEL) {
ProtoLog.d(WM_SHELL_BACK_PREVIEW,
"Finishing gesture with event action: %d", keyAction);
- onGestureFinished();
+ onGestureFinished(true);
}
}
- private void initAnimation(float touchX, float touchY) {
+ private void onGestureStarted(float touchX, float touchY) {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "initAnimation mMotionStarted=%b", mBackGestureStarted);
if (mBackGestureStarted || mBackNavigationInfo != null) {
Log.e(TAG, "Animation is being initialized but is already started.");
@@ -288,7 +308,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
try {
boolean requestAnimation = mEnableAnimations.get();
- mBackNavigationInfo = mActivityTaskManager.startBackNavigation(requestAnimation);
+ mBackNavigationInfo =
+ mActivityTaskManager.startBackNavigation(requestAnimation, mFocusObserver);
onBackNavigationInfoReceived(mBackNavigationInfo);
} catch (RemoteException remoteException) {
Log.e(TAG, "Failed to initAnimation", remoteException);
@@ -376,11 +397,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
dispatchOnBackProgressed(targetCallback, backEvent);
}
- private void onGestureFinished() {
+ private void onGestureFinished(boolean fromTouch) {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", mTriggerBack);
- if (!mBackGestureStarted || mBackNavigationInfo == null) {
+ if (fromTouch) {
+ // Let touch reset the flag otherwise it will start a new back navigation and refresh
+ // the info when received a new move event.
+ mBackGestureStarted = false;
+ }
+
+ if (mTransitionInProgress || mBackNavigationInfo == null) {
return;
}
+
int backType = mBackNavigationInfo.getType();
boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType);
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
@@ -470,7 +498,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
private void finishAnimation() {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishAnimation()");
- mBackGestureStarted = false;
mTouchEventDelta.set(0, 0);
mInitTouchLocation.set(0, 0);
BackNavigationInfo backNavigationInfo = mBackNavigationInfo;
@@ -480,6 +507,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
if (backNavigationInfo == null) {
return;
}
+
RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
if (animationTarget != null) {
if (animationTarget.leash != null && animationTarget.leash.isValid()) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 31e55e7116f0..ba81602054a8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -20,6 +20,7 @@ import static android.window.BackNavigationInfo.KEY_TRIGGER_BACK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -39,6 +40,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.os.Handler;
+import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.provider.Settings;
@@ -121,24 +123,22 @@ public class BackAnimationControllerTest extends ShellTestCase {
HardwareBuffer hardwareBuffer,
int backType,
IOnBackInvokedCallback onBackInvokedCallback) {
- BackNavigationInfo navigationInfo = new BackNavigationInfo(
- backType,
- topAnimationTarget,
- screenshotSurface,
- hardwareBuffer,
- new WindowConfiguration(),
- new RemoteCallback((bundle) -> {}),
- onBackInvokedCallback);
- try {
- doReturn(navigationInfo).when(mActivityTaskManager).startBackNavigation(anyBoolean());
- } catch (RemoteException ex) {
- ex.rethrowFromSystemServer();
- }
+ BackNavigationInfo.Builder builder = new BackNavigationInfo.Builder()
+ .setType(backType)
+ .setDepartingAnimationTarget(topAnimationTarget)
+ .setScreenshotSurface(screenshotSurface)
+ .setScreenshotBuffer(hardwareBuffer)
+ .setTaskWindowConfiguration(new WindowConfiguration())
+ .setOnBackNavigationDone(new RemoteCallback((bundle) -> {}))
+ .setOnBackInvokedCallback(onBackInvokedCallback);
+
+ createNavigationInfo(builder);
}
private void createNavigationInfo(BackNavigationInfo.Builder builder) {
try {
- doReturn(builder.build()).when(mActivityTaskManager).startBackNavigation(anyBoolean());
+ doReturn(builder.build()).when(mActivityTaskManager)
+ .startBackNavigation(anyBoolean(), any());
} catch (RemoteException ex) {
ex.rethrowFromSystemServer();
}
@@ -297,6 +297,34 @@ public class BackAnimationControllerTest extends ShellTestCase {
verify(mIOnBackInvokedCallback).onBackStarted();
}
+
+ @Test
+ public void cancelBackInvokeWhenLostFocus() throws RemoteException {
+ mController.setBackToLauncherCallback(mIOnBackInvokedCallback);
+ RemoteAnimationTarget animationTarget = createAnimationTarget();
+
+ createNavigationInfo(animationTarget, null, null,
+ BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
+
+ doMotionEvent(MotionEvent.ACTION_DOWN, 0);
+ // Check that back start and progress is dispatched when first move.
+ doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+ verify(mIOnBackInvokedCallback).onBackStarted();
+
+ // Check that back invocation is dispatched.
+ mController.setTriggerBack(true); // Fake trigger back
+
+ // In case the focus has been changed.
+ IBinder token = mock(IBinder.class);
+ mController.mFocusObserver.focusLost(token);
+ mShellExecutor.flushAll();
+ verify(mIOnBackInvokedCallback).onBackCancelled();
+
+ // No more back invoke.
+ doMotionEvent(MotionEvent.ACTION_UP, 0);
+ verify(mIOnBackInvokedCallback, never()).onBackInvoked();
+ }
+
private void doMotionEvent(int actionDown, int coordinate) {
mController.onMotionEvent(
coordinate, coordinate,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 9d8e0877584f..0260b78f49e4 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -222,6 +222,7 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.IRecentsAnimationRunner;
+import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
@@ -1027,7 +1028,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mTaskSupervisor.setWindowManager(wm);
mRootWindowContainer.setWindowManager(wm);
if (mBackNavigationController != null) {
- mBackNavigationController.setTaskSnapshotController(wm.mTaskSnapshotController);
+ mBackNavigationController.setWindowManager(wm);
}
}
}
@@ -1833,13 +1834,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public BackNavigationInfo startBackNavigation(boolean requestAnimation) {
+ public BackNavigationInfo startBackNavigation(boolean requestAnimation,
+ IWindowFocusObserver observer) {
mAmInternal.enforceCallingPermission(START_TASKS_FROM_RECENTS,
"startBackNavigation()");
if (mBackNavigationController == null) {
return null;
}
- return mBackNavigationController.startBackNavigation(mWindowManager, requestAnimation);
+ return mBackNavigationController.startBackNavigation(requestAnimation, observer);
}
/**
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 9295c18fe80e..f967cf995e67 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -31,6 +31,7 @@ import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.Slog;
+import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.window.BackNavigationInfo;
@@ -45,10 +46,9 @@ import com.android.server.LocalServices;
* Controller to handle actions related to the back gesture on the server side.
*/
class BackNavigationController {
-
private static final String TAG = "BackNavigationController";
- @Nullable
- private TaskSnapshotController mTaskSnapshotController;
+ private WindowManagerService mWindowManagerService;
+ private IWindowFocusObserver mFocusObserver;
/**
* Returns true if the back predictability feature is enabled
@@ -69,26 +69,13 @@ class BackNavigationController {
* for the animation, or null if we don't know how to animate the current window and need to
* fallback on dispatching the key event.
*/
- @Nullable
- BackNavigationInfo startBackNavigation(@NonNull WindowManagerService wmService,
- boolean requestAnimation) {
- return startBackNavigation(wmService, null, requestAnimation);
- }
-
- /**
- * @param tx, a transaction to be used for the attaching the animation leash.
- * This is used in tests. If null, the object will be initialized with a new {@link
- * SurfaceControl.Transaction}
- * @see #startBackNavigation(WindowManagerService, boolean)
- */
@VisibleForTesting
@Nullable
- BackNavigationInfo startBackNavigation(WindowManagerService wmService,
- @Nullable SurfaceControl.Transaction tx, boolean requestAnimation) {
-
- if (tx == null) {
- tx = new SurfaceControl.Transaction();
- }
+ BackNavigationInfo startBackNavigation(boolean requestAnimation,
+ IWindowFocusObserver observer) {
+ final WindowManagerService wmService = mWindowManagerService;
+ final SurfaceControl.Transaction tx = wmService.mTransactionFactory.get();
+ mFocusObserver = observer;
int backType = BackNavigationInfo.TYPE_UNDEFINED;
@@ -110,13 +97,14 @@ class BackNavigationController {
SurfaceControl animationLeashParent = null;
HardwareBuffer screenshotBuffer = null;
RemoteAnimationTarget topAppTarget = null;
+ WindowState window;
+
int prevTaskId;
int prevUserId;
boolean prepareAnimation;
BackNavigationInfo.Builder infoBuilder = new BackNavigationInfo.Builder();
synchronized (wmService.mGlobalLock) {
- WindowState window;
WindowConfiguration taskWindowConfiguration;
WindowManagerInternal windowManagerInternal =
LocalServices.getService(WindowManagerInternal.class);
@@ -189,6 +177,9 @@ class BackNavigationController {
backType = BackNavigationInfo.TYPE_CALLBACK;
}
infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback());
+ if (mFocusObserver != null) {
+ window.registerFocusObserver(mFocusObserver);
+ }
}
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation currentTask=%s, "
@@ -209,9 +200,13 @@ class BackNavigationController {
|| currentActivity == null
|| currentTask == null
|| currentActivity.isActivityTypeHome()) {
- return infoBuilder
- .setType(backType)
- .build();
+ infoBuilder.setType(BackNavigationInfo.TYPE_CALLBACK);
+ final WindowState finalFocusedWindow = window;
+ infoBuilder.setOnBackNavigationDone(new RemoteCallback(result ->
+ onBackNavigationDone(result, finalFocusedWindow, finalFocusedWindow,
+ BackNavigationInfo.TYPE_CALLBACK, null, null, false)));
+
+ return infoBuilder.setType(backType).build();
}
// We don't have an application callback, let's find the destination of the back gesture
@@ -345,11 +340,12 @@ class BackNavigationController {
}
int finalBackType = backType;
- ActivityRecord finalprevActivity = prevActivity;
- Task finalTask = currentTask;
+ final ActivityRecord finalprevActivity = prevActivity;
+ final Task finalTask = currentTask;
+ final WindowState finalFocusedWindow = window;
RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone(
- result, finalRemovedWindowContainer, finalBackType, finalTask,
- finalprevActivity, prepareAnimation));
+ result, finalFocusedWindow, finalRemovedWindowContainer, finalBackType,
+ finalTask, finalprevActivity, prepareAnimation));
infoBuilder.setOnBackNavigationDone(onBackNavigationDone);
}
@@ -382,8 +378,8 @@ class BackNavigationController {
}
private void onBackNavigationDone(
- Bundle result, WindowContainer<?> windowContainer, int backType,
- Task task, ActivityRecord prevActivity, boolean prepareAnimation) {
+ Bundle result, WindowState focusedWindow, WindowContainer<?> windowContainer,
+ int backType, Task task, ActivityRecord prevActivity, boolean prepareAnimation) {
SurfaceControl surfaceControl = windowContainer.getSurfaceControl();
boolean triggerBack = result != null && result.getBoolean(
BackNavigationInfo.KEY_TRIGGER_BACK);
@@ -412,6 +408,11 @@ class BackNavigationController {
task.mBackGestureStarted = false;
}
resetSurfaces(windowContainer);
+
+ if (mFocusObserver != null) {
+ focusedWindow.unregisterFocusObserver(mFocusObserver);
+ mFocusObserver = null;
+ }
}
private HardwareBuffer getActivitySnapshot(@NonNull Task task,
@@ -425,10 +426,10 @@ class BackNavigationController {
}
private HardwareBuffer getTaskSnapshot(int taskId, int userId) {
- if (mTaskSnapshotController == null) {
+ if (mWindowManagerService.mTaskSnapshotController == null) {
return null;
}
- TaskSnapshot snapshot = mTaskSnapshotController.getSnapshot(taskId,
+ TaskSnapshot snapshot = mWindowManagerService.mTaskSnapshotController.getSnapshot(taskId,
userId, true /* restoreFromDisk */, false /* isLowResolution */);
return snapshot != null ? snapshot.getHardwareBuffer() : null;
}
@@ -458,7 +459,7 @@ class BackNavigationController {
}
}
- void setTaskSnapshotController(@Nullable TaskSnapshotController taskSnapshotController) {
- mTaskSnapshotController = taskSnapshotController;
+ void setWindowManager(WindowManagerService wm) {
+ mWindowManagerService = wm;
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index fc41a94d3355..c2ca0a227f26 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -29,12 +29,9 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
@@ -42,7 +39,6 @@ import android.annotation.Nullable;
import android.hardware.HardwareBuffer;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
-import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.BackEvent;
import android.window.BackNavigationInfo;
@@ -75,8 +71,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
LocalServices.removeServiceForTest(WindowManagerInternal.class);
mWindowManagerInternal = mock(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
- TaskSnapshotController taskSnapshotController = createMockTaskSnapshotController();
- mBackNavigationController.setTaskSnapshotController(taskSnapshotController);
+ mBackNavigationController.setWindowManager(mWm);
}
@Test
@@ -84,19 +79,14 @@ public class BackNavigationControllerTests extends WindowTestsBase {
Task task = createTopTaskWithActivity();
IOnBackInvokedCallback callback = withSystemCallback(task);
- SurfaceControl.Transaction tx = mock(SurfaceControl.Transaction.class);
- BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(mWm,
- tx, true);
+ BackNavigationInfo backNavigationInfo =
+ mBackNavigationController.startBackNavigation(true, null);
assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
assertThat(backNavigationInfo.getDepartingAnimationTarget()).isNotNull();
assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
assertThat(typeToString(backNavigationInfo.getType()))
.isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
-
- verify(tx, atLeastOnce()).apply();
- verify(tx, times(1)).reparent(any(),
- eq(backNavigationInfo.getDepartingAnimationTarget().leash));
}
@Test
@@ -243,7 +233,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
@Nullable
private BackNavigationInfo startBackNavigation() {
- return mBackNavigationController.startBackNavigation(mWm, new StubTransaction(), true);
+ return mBackNavigationController.startBackNavigation(true, null);
}
@NonNull