diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index d5559aaa71467..6639fbf9551e5 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -187,8 +187,7 @@ public final class SurfaceControl implements Parcelable { private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject, InputWindowHandle handle); - private static native void nativeTransferTouchFocus(long transactionObj, IBinder fromToken, - IBinder toToken); + private static native boolean nativeGetProtectedContentSupport(); private static native void nativeSetMetadata(long transactionObj, long nativeObject, int key, Parcel data); @@ -2238,22 +2237,6 @@ public final class SurfaceControl implements Parcelable { return this; } - /** - * Transfers touch focus from one window to another. It is possible for multiple windows to - * have touch focus if they support split touch dispatch - * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this - * method only transfers touch focus of the specified window without affecting - * other windows that may also have touch focus at the same time. - * @param fromToken The token of a window that currently has touch focus. - * @param toToken The token of the window that should receive touch focus in - * place of the first. - * @hide - */ - public Transaction transferTouchFocus(IBinder fromToken, IBinder toToken) { - nativeTransferTouchFocus(mNativeObject, fromToken, toToken); - return this; - } - /** * Waits until any changes to input windows have been sent from SurfaceFlinger to * InputFlinger before returning. diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index bf0f10eb50c6b..1ca9383b920f6 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -458,15 +458,6 @@ static void nativeSetInputWindowInfo(JNIEnv* env, jclass clazz, jlong transactio transaction->setInputWindowInfo(ctrl, *handle->getInfo()); } -static void nativeTransferTouchFocus(JNIEnv* env, jclass clazz, jlong transactionObj, - jobject fromTokenObj, jobject toTokenObj) { - auto transaction = reinterpret_cast(transactionObj); - - sp fromToken(ibinderForJavaObject(env, fromTokenObj)); - sp toToken(ibinderForJavaObject(env, toTokenObj)); - transaction->transferTouchFocus(fromToken, toToken); -} - static void nativeSyncInputWindows(JNIEnv* env, jclass clazz, jlong transactionObj) { auto transaction = reinterpret_cast(transactionObj); transaction->syncInputWindows(); @@ -1381,8 +1372,6 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeCaptureLayers }, {"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V", (void*)nativeSetInputWindowInfo }, - {"nativeTransferTouchFocus", "(JLandroid/os/IBinder;Landroid/os/IBinder;)V", - (void*)nativeTransferTouchFocus }, {"nativeSetMetadata", "(JJILandroid/os/Parcel;)V", (void*)nativeSetMetadata }, {"nativeGetDisplayedContentSamplingAttributes", diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 75b9705e10457..8fbad4c5910bd 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -220,6 +220,8 @@ public class InputManagerService extends IInputManager.Stub private static native void nativeSetFocusedApplication(long ptr, int displayId, InputApplicationHandle application); private static native void nativeSetFocusedDisplay(long ptr, int displayId); + private static native boolean nativeTransferTouchFocus(long ptr, + InputChannel fromChannel, InputChannel toChannel); private static native void nativeSetPointerSpeed(long ptr, int speed); private static native void nativeSetShowTouches(long ptr, boolean enabled); private static native void nativeSetInteractive(long ptr, boolean interactive); @@ -1533,6 +1535,29 @@ public class InputManagerService extends IInputManager.Stub nativeSetSystemUiVisibility(mPtr, visibility); } + /** + * Atomically transfers touch focus from one window to another as identified by + * their input channels. It is possible for multiple windows to have + * touch focus if they support split touch dispatch + * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this + * method only transfers touch focus of the specified window without affecting + * other windows that may also have touch focus at the same time. + * @param fromChannel The channel of a window that currently has touch focus. + * @param toChannel The channel of the window that should receive touch focus in + * place of the first. + * @return True if the transfer was successful. False if the window with the + * specified channel did not actually have touch focus at the time of the request. + */ + public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) { + if (fromChannel == null) { + throw new IllegalArgumentException("fromChannel must not be null."); + } + if (toChannel == null) { + throw new IllegalArgumentException("toChannel must not be null."); + } + return nativeTransferTouchFocus(mPtr, fromChannel, toChannel); + } + @Override // Binder call public void tryPointerSpeed(int speed) { if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java index f8f6334b04dc5..d5f403f856212 100644 --- a/services/core/java/com/android/server/wm/DragDropController.java +++ b/services/core/java/com/android/server/wm/DragDropController.java @@ -113,7 +113,7 @@ class DragDropController { final WindowState callingWin = mService.windowForClientLocked( null, window, false); - if (callingWin == null) { + if (callingWin == null || callingWin.cantReceiveTouchInput()) { Slog.w(TAG_WM, "Bad requesting window " + window); return null; // !!! TODO: throw here? } @@ -167,8 +167,7 @@ class DragDropController { final SurfaceControl surfaceControl = mDragState.mSurfaceControl; if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> OPEN TRANSACTION performDrag"); - final SurfaceControl.Transaction transaction = - callingWin.getPendingTransaction(); + final SurfaceControl.Transaction transaction = mDragState.mTransaction; transaction.setAlpha(surfaceControl, mDragState.mOriginalAlpha); transaction.setPosition( surfaceControl, touchX - thumbCenterX, touchY - thumbCenterY); diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 17daabfe3e797..3c616945f7629 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -120,7 +120,7 @@ class DragState { // A surface used to catch input events for the drag-and-drop operation. SurfaceControl mInputSurface; - private final SurfaceControl.Transaction mTransaction; + final SurfaceControl.Transaction mTransaction; private final Rect mTmpClipRect = new Rect(); @@ -129,7 +129,6 @@ class DragState { * {@code true} when {@link #closeLocked()} is called. */ private boolean mIsClosing; - IBinder mTransferTouchFromToken; DragState(WindowManagerService service, DragDropController controller, IBinder token, SurfaceControl surface, int flags, IBinder localWin) { @@ -167,12 +166,11 @@ class DragState { mTmpClipRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); mTransaction.setWindowCrop(mInputSurface, mTmpClipRect); - mTransaction.transferTouchFocus(mTransferTouchFromToken, h.token); - mTransferTouchFromToken = null; - // syncInputWindows here to ensure the input channel isn't removed before the transfer. + // syncInputWindows here to ensure the input window info is sent before the + // transferTouchFocus is called. mTransaction.syncInputWindows(); - mTransaction.apply(); + mTransaction.apply(true); } /** diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 42866f97b4b89..fc8a27d64fce8 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -50,6 +50,7 @@ import android.view.InputDevice; import android.view.InputEvent; import android.view.InputWindowHandle; import android.view.MotionEvent; +import android.view.SurfaceControl; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; @@ -302,7 +303,8 @@ class TaskPositioner implements IBinder.DeathRecipient { mDisplayContent.getDisplayRotation().pause(); // Notify InputMonitor to take mDragWindowHandle. - mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/); + mDisplayContent.getInputMonitor().updateInputWindowsImmediately(); + new SurfaceControl.Transaction().syncInputWindows().apply(true); mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics); mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics); diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java index 2441954012e59..56b3bba2a4311 100644 --- a/services/core/java/com/android/server/wm/TaskPositioningController.java +++ b/services/core/java/com/android/server/wm/TaskPositioningController.java @@ -24,7 +24,6 @@ import android.app.IActivityTaskManager; import android.graphics.Point; import android.graphics.Rect; import android.os.Handler; -import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Slog; @@ -51,7 +50,6 @@ class TaskPositioningController { private @Nullable TaskPositioner mTaskPositioner; private final Rect mTmpClipRect = new Rect(); - private IBinder mTransferTouchFromToken; boolean isPositioningLocked() { return mTaskPositioner != null; @@ -104,8 +102,6 @@ class TaskPositioningController { mTmpClipRect.set(0, 0, p.x, p.y); t.setWindowCrop(mInputSurface, mTmpClipRect); - t.transferTouchFocus(mTransferTouchFromToken, h.token); - mTransferTouchFromToken = null; } boolean startMovingTask(IWindow window, float startX, float startY) { @@ -168,6 +164,7 @@ class TaskPositioningController { mPositioningDisplay = displayContent; mTaskPositioner = TaskPositioner.create(mService); + mTaskPositioner.register(displayContent); // We need to grab the touch focus so that the touch events during the // resizing/scrolling are not sent to the app. 'win' is the main window @@ -178,8 +175,12 @@ class TaskPositioningController { && displayContent.mCurrentFocus.mAppToken == win.mAppToken) { transferFocusFromWin = displayContent.mCurrentFocus; } - mTransferTouchFromToken = transferFocusFromWin.mInputChannel.getToken(); - mTaskPositioner.register(displayContent); + if (!mInputManager.transferTouchFocus( + transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) { + Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus"); + cleanUpTaskPositioner(); + return false; + } mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY); return true; diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index aa2a96497b996..abbd1abff614a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -161,9 +161,8 @@ public abstract class WindowManagerInternal { default boolean registerInputChannel( DragState state, Display display, InputManagerService service, InputChannel source) { - state.mTransferTouchFromToken = source.getToken(); state.register(display); - return true; + return service.transferTouchFocus(source, state.getInputChannel()); } /** diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 0e9da83d4d1f4..fb2fdab19a548 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -1570,6 +1570,27 @@ static void nativeSetSystemUiVisibility(JNIEnv* /* env */, im->setSystemUiVisibility(visibility); } +static jboolean nativeTransferTouchFocus(JNIEnv* env, + jclass /* clazz */, jlong ptr, jobject fromChannelObj, jobject toChannelObj) { + NativeInputManager* im = reinterpret_cast(ptr); + + sp fromChannel = + android_view_InputChannel_getInputChannel(env, fromChannelObj); + sp toChannel = + android_view_InputChannel_getInputChannel(env, toChannelObj); + + if (fromChannel == nullptr || toChannel == nullptr) { + return JNI_FALSE; + } + + if (im->getInputManager()->getDispatcher()-> + transferTouchFocus(fromChannel->getToken(), toChannel->getToken())) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } +} + static void nativeSetPointerSpeed(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint speed) { NativeInputManager* im = reinterpret_cast(ptr); @@ -1763,6 +1784,8 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*) nativeSetInputDispatchMode }, { "nativeSetSystemUiVisibility", "(JI)V", (void*) nativeSetSystemUiVisibility }, + { "nativeTransferTouchFocus", "(JLandroid/view/InputChannel;Landroid/view/InputChannel;)Z", + (void*) nativeTransferTouchFocus }, { "nativeSetPointerSpeed", "(JI)V", (void*) nativeSetPointerSpeed }, { "nativeSetShowTouches", "(JZ)V", diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java index 0110e94eb1cd1..bb80e5e4ddde6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java @@ -20,9 +20,11 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -124,6 +126,7 @@ public class DragDropControllerTests extends WindowTestsBase { mDisplayContent = spy(mDisplayContent); mWindow = createDropTargetWindow("Drag test window", 0); doReturn(mWindow).when(mDisplayContent).getTouchableWinAtPointLocked(0, 0); + when(mWm.mInputManager.transferTouchFocus(any(), any())).thenReturn(true); synchronized (mWm.mGlobalLock) { mWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow); @@ -177,6 +180,7 @@ public class DragDropControllerTests extends WindowTestsBase { .setFormat(PixelFormat.TRANSLUCENT) .build(); + assertTrue(mWm.mInputManager.transferTouchFocus(null, null)); mToken = mTarget.performDrag( new SurfaceSession(), 0, 0, mWindow.mClient, flag, surface, 0, 0, 0, 0, 0, data); diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java index 8d2a79b6b5db9..2ad40f2dc5776 100644 --- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java +++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java @@ -96,11 +96,6 @@ public class StubTransaction extends SurfaceControl.Transaction { return this; } - @Override - public SurfaceControl.Transaction transferTouchFocus(IBinder fromToken, IBinder toToken) { - return this; - } - @Override public SurfaceControl.Transaction setGeometry(SurfaceControl sc, Rect sourceCrop, Rect destFrame, @Surface.Rotation int orientation) { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java index 714d2f2f94a12..eb351b63a469a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; @@ -57,6 +58,10 @@ public class TaskPositioningControllerTests extends WindowTestsBase { assertNotNull(mWm.mTaskPositioningController); mTarget = mWm.mTaskPositioningController; + when(mWm.mInputManager.transferTouchFocus( + any(InputChannel.class), + any(InputChannel.class))).thenReturn(true); + mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window"); mWindow.mInputChannel = new InputChannel(); synchronized (mWm.mGlobalLock) {