Merge changes I1978ce3a,I79160004 into tm-dev

* changes:
  Add workaround for new back flow with legacy recents animation
  Ensure recents input consumer can be focused in Overview
This commit is contained in:
Winson Chung
2022-05-18 17:23:38 +00:00
committed by Android (Google) Code Review
7 changed files with 95 additions and 38 deletions

View File

@@ -1657,6 +1657,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/Task.java"
},
"-451552570": {
"message": "Current focused window being animated by recents. Overriding back callback to recents controller callback.",
"level": "DEBUG",
"group": "WM_DEBUG_BACK_PREVIEW",
"at": "com\/android\/server\/wm\/BackNavigationController.java"
},
"-449118559": {
"message": "Trying to update display configuration for invalid process, pid=%d",
"level": "WARN",
@@ -2917,12 +2923,6 @@
"group": "WM_DEBUG_LOCKTASK",
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
},
"716528224": {
"message": "Focused window found using wmService.getFocusedWindowLocked()",
"level": "DEBUG",
"group": "WM_DEBUG_BACK_PREVIEW",
"at": "com\/android\/server\/wm\/BackNavigationController.java"
},
"726205185": {
"message": "Moving to DESTROYED: %s (destroy skipped)",
"level": "VERBOSE",

View File

@@ -145,6 +145,27 @@ class BackNavigationController {
"Focused window found using getFocusedWindowToken");
}
OnBackInvokedCallbackInfo overrideCallbackInfo = null;
if (window != null) {
// This is needed to bridge the old and new back behavior with recents. While in
// Overview with live tile enabled, the previous app is technically focused but we
// add an input consumer to capture all input that would otherwise go to the apps
// being controlled by the animation. This means that the window resolved is not
// the right window to consume back while in overview, so we need to route it to
// launcher and use the legacy behavior of injecting KEYCODE_BACK since the existing
// compat callback in VRI only works when the window is focused.
final RecentsAnimationController recentsAnimationController =
wmService.getRecentsAnimationController();
if (recentsAnimationController != null
&& recentsAnimationController.shouldApplyInputConsumer(
window.getActivityRecord())) {
window = recentsAnimationController.getTargetAppMainWindow();
overrideCallbackInfo = recentsAnimationController.getBackInvokedInfo();
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Current focused window being animated by "
+ "recents. Overriding back callback to recents controller callback.");
}
}
if (window == null) {
// We don't have any focused window, fallback ont the top currentTask of the focused
// display.
@@ -159,7 +180,9 @@ class BackNavigationController {
if (window != null) {
currentActivity = window.mActivityRecord;
currentTask = window.getTask();
callbackInfo = window.getOnBackInvokedCallbackInfo();
callbackInfo = overrideCallbackInfo != null
? overrideCallbackInfo
: window.getOnBackInvokedCallbackInfo();
if (callbackInfo == null) {
Slog.e(TAG, "No callback registered, returning null.");
return null;

View File

@@ -5440,13 +5440,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
final Region local = Region.obtain();
final int[] remainingLeftRight =
{mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
final RecentsAnimationController recentsAnimationController =
mWmService.getRecentsAnimationController();
// Traverse all windows top down to assemble the gesture exclusion rects.
// For each window, we only take the rects that fall within its touchable region.
forAllWindows(w -> {
final boolean ignoreRecentsAnimationTarget = recentsAnimationController != null
&& recentsAnimationController.shouldApplyInputConsumer(w.getActivityRecord());
if (!w.canReceiveTouchInput() || !w.isVisible()
|| (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
|| unhandled.isEmpty()) {
|| unhandled.isEmpty()
|| ignoreRecentsAnimationTarget) {
return;
}

View File

@@ -559,12 +559,7 @@ final class InputMonitor {
@Override
public void accept(WindowState w) {
final InputWindowHandleWrapper inputWindowHandle = w.mInputWindowHandle;
final RecentsAnimationController recentsAnimationController =
mService.getRecentsAnimationController();
final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null
&& recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord);
if (w.mInputChannelToken == null || w.mRemoved
|| (!w.canReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
if (w.mInputChannelToken == null || w.mRemoved || !w.canReceiveTouchInput()) {
if (w.mWinAnimator.hasSurface()) {
// Make sure the input info can't receive input event. It may be omitted from
// occlusion detection depending on the type or if it's a trusted overlay.
@@ -580,6 +575,10 @@ final class InputMonitor {
final int privateFlags = w.mAttrs.privateFlags;
// This only works for legacy transitions.
final RecentsAnimationController recentsAnimationController =
mService.getRecentsAnimationController();
final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null
&& recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord);
if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
if (recentsAnimationController.updateInputConsumerForApp(
mRecentsAnimationInputConsumer.mWindowHandle)) {

View File

@@ -19,10 +19,12 @@ 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;
@@ -39,6 +41,7 @@ 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;
@@ -51,12 +54,18 @@ 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;
@@ -194,6 +203,46 @@ 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);
@@ -1104,6 +1153,10 @@ public class RecentsAnimationController implements DeathRecipient {
return mTargetActivityRecord.findMainWindow();
}
OnBackInvokedCallbackInfo getBackInvokedInfo() {
return new OnBackInvokedCallbackInfo(mBackCallback, PRIORITY_DEFAULT);
}
DisplayArea getTargetAppDisplayArea() {
if (mTargetActivityRecord == null) {
return null;

View File

@@ -3220,19 +3220,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
return !mActivityRecord.getTask().getRootTask().shouldIgnoreInput()
&& mActivityRecord.mVisibleRequested
&& !isRecentsAnimationConsumingAppInput();
}
/**
* Returns {@code true} if the window is animating to home as part of the recents animation and
* it is consuming input from the app.
*/
private boolean isRecentsAnimationConsumingAppInput() {
final RecentsAnimationController recentsAnimationController =
mWmService.getRecentsAnimationController();
return recentsAnimationController != null
&& recentsAnimationController.shouldApplyInputConsumer(mActivityRecord);
&& mActivityRecord.mVisibleRequested;
}
/**

View File

@@ -730,17 +730,6 @@ public class WindowStateTests extends WindowTestsBase {
assertThat(mWm.mResizingWindows).doesNotContain(win);
}
@Test
public void testCantReceiveTouchDuringRecentsAnimation() {
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
// Mock active recents animation
RecentsAnimationController recentsController = mock(RecentsAnimationController.class);
when(recentsController.shouldApplyInputConsumer(win0.mActivityRecord)).thenReturn(true);
mWm.setRecentsAnimationController(recentsController);
assertFalse(win0.canReceiveTouchInput());
}
@Test
public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");