Add transferHostTouchGestureToEmbedded API
Allow the host to transfer touch gesture to the embedded window.
Renamed focusGrantToken to inputTransferToken so it can be used to
transfer focus and gesture from host to embedded.
Test: SurfaceControlViewHostTests#testTransferHostTouchGestureToEmbedded
Bug: 303254234
Change-Id: Ie09121eccce46237d96b1a3233792bd3f3f3fd23
diff --git a/core/api/current.txt b/core/api/current.txt
index 7e3da22..d1eb1d6 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -49810,6 +49810,7 @@
method public default void removeOnBufferTransformHintChangedListener(@NonNull android.view.AttachedSurfaceControl.OnBufferTransformHintChangedListener);
method public default void setChildBoundingInsets(@NonNull android.graphics.Rect);
method public default void setTouchableRegion(@Nullable android.graphics.Region);
+ method @FlaggedApi("com.android.window.flags.transfer_gesture_to_embedded") public default boolean transferHostTouchGestureToEmbedded(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
}
@UiThread public static interface AttachedSurfaceControl.OnBufferTransformHintChangedListener {
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index d545751..fd5517d 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -231,4 +231,19 @@
default void removeTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
@NonNull Consumer<Boolean> listener) {
}
+
+ /**
+ * Transfer the currently in progress touch gesture from the host to the requested
+ * {@link SurfaceControlViewHost.SurfacePackage}. This requires that the
+ * SurfaceControlViewHost was created with the current host's inputToken.
+ *
+ * @param surfacePackage The SurfacePackage to transfer the gesture to.
+ * @return Whether the touch stream was transferred.
+ */
+ @FlaggedApi(Flags.FLAG_TRANSFER_GESTURE_TO_EMBEDDED)
+ default boolean transferHostTouchGestureToEmbedded(
+ @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
+ throw new UnsupportedOperationException(
+ "transferHostTouchGestureToEmbedded is unimplemented");
+ }
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7acf2f8..02e97da 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -357,4 +357,6 @@
boolean cancelDraw(IWindow window);
boolean transferEmbeddedTouchFocusToHost(IWindow embeddedWindow);
+
+ boolean transferHostTouchGestureToEmbedded(IWindow hostWindow, IBinder transferTouchToken);
}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 57b19a8..4056531 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -287,7 +287,8 @@
}
/**
- * Returns an input token used which can be used to request focus on the embedded surface.
+ * Returns an input token used which can be used to request focus on the embedded surface
+ * or to transfer touch gesture to the embedded surface.
*
* @hide
*/
@@ -526,7 +527,8 @@
}
/**
- * Returns an input token used which can be used to request focus on the embedded surface.
+ * Returns an input token used which can be used to request focus on the embedded surface
+ * or to transfer touch gesture to the embedded surface.
*
* @hide
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2422369..1ee303c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -11893,4 +11893,17 @@
}
Log.d(mTag, msg);
}
+
+ @Override
+ public boolean transferHostTouchGestureToEmbedded(
+ @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
+ final IWindowSession realWm = WindowManagerGlobal.getWindowSession();
+ try {
+ return realWm.transferHostTouchGestureToEmbedded(mWindow,
+ surfacePackage.getInputToken());
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ return false;
+ }
}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 7c3b6ae..652fe24 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -656,6 +656,14 @@
return false;
}
+ @Override
+ public boolean transferHostTouchGestureToEmbedded(IWindow hostWindow,
+ IBinder embeddedInputToken) {
+ Log.e(TAG, "Received request to transferHostTouchGestureToEmbedded on"
+ + " WindowlessWindowManager. We shouldn't get here!");
+ return false;
+ }
+
void setParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) {
IBinder oldInterface = mParentInterface == null ? null : mParentInterface.asBinder();
IBinder newInterface = parentInterface == null ? null : parentInterface.asBinder();
diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig
index 5ad5c79..68eddff 100644
--- a/core/java/android/window/flags/window_surfaces.aconfig
+++ b/core/java/android/window/flags/window_surfaces.aconfig
@@ -25,3 +25,10 @@
is_fixed_read_only: true
bug: "304508760"
}
+
+flag {
+ namespace: "window_surfaces"
+ name: "transfer_gesture_to_embedded"
+ description: "Enable public API for Window Surfaces"
+ bug: "287076178"
+}
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 275396f..1462878 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -150,8 +150,8 @@
/**
* A unique token associated with the embedded window that can be used by the host window
- * to request focus transfer to the embedded. This is not the input token since we don't
- * want to give clients access to each others input token.
+ * to request focus transfer and gesture transfer to the embedded. This is not the input
+ * token since we don't want to give clients access to each others input token.
*/
private final IBinder mInputTransferToken;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index a756847..0c55d8a 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -964,6 +964,23 @@
}
@Override
+ public boolean transferHostTouchGestureToEmbedded(IWindow hostWindow,
+ IBinder inputTransferToken) {
+ if (hostWindow == null) {
+ return false;
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ boolean didTransfer;
+ try {
+ didTransfer = mService.transferHostTouchGestureToEmbedded(this, hostWindow,
+ inputTransferToken);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return didTransfer;
+ }
+ @Override
public void generateDisplayHash(IWindow window, Rect boundsInWindow, String hashAlgorithm,
RemoteCallback callback) {
final long origId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9fb7e8d..c2958e4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8960,6 +8960,43 @@
}
}
+ boolean transferHostTouchGestureToEmbedded(Session session, IWindow hostWindow,
+ IBinder inputTransferToken) {
+ final IBinder hostInputChannel, embeddedInputChannel;
+ synchronized (mGlobalLock) {
+ final WindowState hostWindowState = windowForClientLocked(session, hostWindow, false);
+ if (hostWindowState == null) {
+ Slog.w(TAG, "Attempt to transfer touch gesture with invalid host window");
+ return false;
+ }
+
+ final EmbeddedWindowController.EmbeddedWindow ew =
+ mEmbeddedWindowController.getByInputTransferToken(inputTransferToken);
+ if (ew == null || ew.mHostWindowState == null) {
+ Slog.w(TAG, "Attempt to transfer touch gesture to non-existent embedded window");
+ return false;
+ }
+ if (ew.mHostWindowState.mClient.asBinder() != hostWindow.asBinder()) {
+ Slog.w(TAG, "Attempt to transfer touch gesture to embedded window not associated"
+ + " with host window");
+ return false;
+ }
+ embeddedInputChannel = ew.getInputChannelToken();
+ if (embeddedInputChannel == null) {
+ Slog.w(TAG, "Attempt to transfer touch focus from embedded window with no input"
+ + " channel");
+ return false;
+ }
+ hostInputChannel = hostWindowState.mInputChannelToken;
+ if (hostInputChannel == null) {
+ Slog.w(TAG,
+ "Attempt to transfer touch focus to a host window with no input channel");
+ return false;
+ }
+ return mInputManager.transferTouchFocus(hostInputChannel, embeddedInputChannel);
+ }
+ }
+
private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
int displayId, SurfaceControl surface, String name,
InputApplicationHandle applicationHandle, int flags,