From f22e6b03efc694d30e450aac0b293c8cc4dc5fdf Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Fri, 1 Jul 2022 15:28:47 +0800 Subject: [PATCH] Inject back key events if no focus window found. If user applied a back gesture but core cannot find a focus window, inject back key event, so that event can dispatch to client once it gain focus window. And since the gesture was happened, treat it as onBackPressed. And if device is playing recents animation but the focus window is point to live tile, we can also inject back key because Home/Recents activity shall not have the same behavior as normal app. Bug: 237629607 Test: cross test that back gesture can finish recents with legacy/shell transition on Nexus/3rd launcher. Test: test on BackTestApp for both 3btn mode and gesture mode. Test: atest AnrTests BackNavigationLegacyGestureTest Test: atest OnBackInvokedDispatcherTest KeyboardVisibilityControlTest BackInvokedOnWidgetTest BackNavigationTests BackNavigationControllerTests Change-Id: If754e66ea7c1c4ec313c45d17d7f6c10bfc2c465 --- core/java/android/view/ViewRootImpl.java | 4 +- .../window/ProxyOnBackInvokedDispatcher.java | 2 +- .../shell/back/BackAnimationController.java | 40 +++++++++++++- .../server/wm/BackNavigationController.java | 29 +++++----- .../server/wm/RecentsAnimationController.java | 53 ------------------- 5 files changed, 57 insertions(+), 71 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 8ec32a6d6b5b6..90821659c36d6 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -10858,8 +10858,8 @@ public final class ViewRootImpl implements ViewParent, private void registerCompatOnBackInvokedCallback() { mCompatOnBackInvokedCallback = () -> { - sendBackKeyEvent(KeyEvent.ACTION_DOWN); - sendBackKeyEvent(KeyEvent.ACTION_UP); + sendBackKeyEvent(KeyEvent.ACTION_DOWN); + sendBackKeyEvent(KeyEvent.ACTION_UP); }; mOnBackInvokedDispatcher.registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback); diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java index 8ad109317f4b1..49acde9dc2953 100644 --- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java +++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java @@ -122,7 +122,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } for (Pair callbackPair : mCallbacks) { int priority = callbackPair.second; - if (priority >= 0) { + if (priority >= PRIORITY_DEFAULT) { mActualDispatcher.registerOnBackInvokedCallback(priority, callbackPair.first); } else { mActualDispatcher.registerSystemOnBackInvokedCallback(callbackPair.first); 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 02211220822a7..05fafc54c2737 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 @@ -30,15 +30,20 @@ import android.database.ContentObserver; import android.graphics.Point; import android.graphics.PointF; import android.hardware.HardwareBuffer; +import android.hardware.input.InputManager; import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings.Global; import android.util.Log; import android.view.IWindowFocusObserver; +import android.view.InputDevice; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; @@ -292,6 +297,9 @@ public class BackAnimationController implements RemoteCallable !r.finishing && r.getTask() == finalTask && !r.isTopRunningActivity()); - if (window.getParent().getChildCount() > 1 && window.getParent().getChildAt(0) - != window) { + // TODO Dialog window does not need to attach on activity, check + // window.mAttrs.type != TYPE_BASE_APPLICATION + if ((window.getParent().getChildCount() > 1 + && window.getParent().getChildAt(0) != window)) { // Are we the top window of our parent? If not, we are a window on top of the // activity, we won't close the activity. backType = BackNavigationInfo.TYPE_DIALOG_CLOSE; @@ -379,7 +381,8 @@ class BackNavigationController { private void onBackNavigationDone( Bundle result, WindowState focusedWindow, WindowContainer windowContainer, - int backType, Task task, ActivityRecord prevActivity, boolean prepareAnimation) { + int backType, @Nullable Task task, @Nullable ActivityRecord prevActivity, + boolean prepareAnimation) { SurfaceControl surfaceControl = windowContainer.getSurfaceControl(); boolean triggerBack = result != null && result.getBoolean( BackNavigationInfo.KEY_TRIGGER_BACK); @@ -404,7 +407,7 @@ class BackNavigationController { "Setting Activity.mLauncherTaskBehind to false. Activity=%s", prevActivity); } - } else { + } else if (task != null) { task.mBackGestureStarted = false; } resetSurfaces(windowContainer); diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 53f1fe6abec5f..1cff693346795 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -19,12 +19,10 @@ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; -import static android.hardware.input.InputManager.INJECT_INPUT_EVENT_MODE_ASYNC; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; -import static android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; @@ -41,7 +39,6 @@ import android.graphics.GraphicBuffer; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; -import android.hardware.input.InputManager; import android.os.Binder; import android.os.IBinder.DeathRecipient; import android.os.RemoteException; @@ -54,18 +51,12 @@ import android.util.SparseBooleanArray; import android.util.proto.ProtoOutputStream; import android.view.IRecentsAnimationController; import android.view.IRecentsAnimationRunner; -import android.view.InputDevice; import android.view.InputWindowHandle; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; import android.view.WindowInsets.Type; -import android.window.BackEvent; -import android.window.IOnBackInvokedCallback; -import android.window.OnBackInvokedCallbackInfo; import android.window.PictureInPictureSurfaceTransaction; import android.window.TaskSnapshot; @@ -195,46 +186,6 @@ public class RecentsAnimationController implements DeathRecipient { } }; - /** - * Back invoked callback for legacy recents transition with the new back dispatch system. - */ - final IOnBackInvokedCallback mBackCallback = new IOnBackInvokedCallback.Stub() { - @Override - public void onBackStarted() { - // Do nothing - } - - @Override - public void onBackProgressed(BackEvent backEvent) { - // Do nothing - } - - @Override - public void onBackCancelled() { - // Do nothing - } - - @Override - public void onBackInvoked() { - sendBackEvent(KeyEvent.ACTION_DOWN); - sendBackEvent(KeyEvent.ACTION_UP); - } - - private void sendBackEvent(int action) { - if (mTargetActivityRecord == null) { - return; - } - long when = SystemClock.uptimeMillis(); - final KeyEvent ev = new KeyEvent(when, when, action, - KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */, - KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */, - KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, - InputDevice.SOURCE_KEYBOARD); - ev.setDisplayId(mTargetActivityRecord.getDisplayId()); - InputManager.getInstance().injectInputEvent(ev, INJECT_INPUT_EVENT_MODE_ASYNC); - } - }; - public interface RecentsAnimationCallbacks { /** Callback when recents animation is finished. */ void onAnimationFinished(@ReorderMode int reorderMode, boolean sendUserLeaveHint); @@ -1112,10 +1063,6 @@ public class RecentsAnimationController implements DeathRecipient { return mTargetActivityRecord.findMainWindow(); } - OnBackInvokedCallbackInfo getBackInvokedInfo() { - return new OnBackInvokedCallbackInfo(mBackCallback, PRIORITY_DEFAULT); - } - DisplayArea getTargetAppDisplayArea() { if (mTargetActivityRecord == null) { return null;