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:
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user