Update input policy to handle embedded windows
ANR - If embedded windows are slow in handling inputs the system should blame the embedded app.
PointerDownOutsideFocus - if a user taps outside the currently focused window onto an
embedded window, treat it as if the host window was tapped.
Rename blessInputSurface -> grantInputChannel and add a name to embedded windows.
Bug: 134365580
Test: b WindowlessWmTest
Test: atest CtsWindowManagerDeviceTestCases:WindowlessWmTests
Change-Id: If88970cf6ce17669b41fec995535151a492fab12
diff --git a/api/test-current.txt b/api/test-current.txt
index 466320b..5e2d4a5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4415,6 +4415,10 @@
method public abstract String asyncImpl() default "";
}
+ public class SurfaceView extends android.view.View {
+ method @Nullable public android.os.IBinder getInputToken();
+ }
+
@UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
method public android.view.View getTooltipView();
method public boolean isAutofilled();
@@ -4462,8 +4466,9 @@
}
public class WindowlessViewRoot {
- ctor public WindowlessViewRoot(android.content.Context, android.view.Display, android.view.SurfaceControl);
+ ctor public WindowlessViewRoot(@NonNull android.content.Context, @NonNull android.view.Display, @NonNull android.view.SurfaceControl, @Nullable android.os.IBinder);
method public void addView(android.view.View, android.view.WindowManager.LayoutParams);
+ method public void dispose();
method public void relayout(android.view.WindowManager.LayoutParams);
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 6ce5ac4..eaf6fca 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -314,5 +314,6 @@
* Request the server to call setInputWindowInfo on a given Surface, and return
* an input channel where the client can receive input.
*/
- void blessInputSurface(int displayId, in SurfaceControl surface, out InputChannel outInputChannel);
+ void grantInputChannel(int displayId, in SurfaceControl surface, in IWindow window,
+ in IBinder hostInputToken, out InputChannel outInputChannel);
}
diff --git a/core/java/android/view/InputApplicationHandle.java b/core/java/android/view/InputApplicationHandle.java
index 5f6bc23..3d05e2a 100644
--- a/core/java/android/view/InputApplicationHandle.java
+++ b/core/java/android/view/InputApplicationHandle.java
@@ -36,7 +36,7 @@
// Dispatching timeout.
public long dispatchingTimeoutNanos;
- public IBinder token;
+ public final IBinder token;
private native void nativeDispose();
@@ -44,6 +44,12 @@
this.token = token;
}
+ public InputApplicationHandle(InputApplicationHandle handle) {
+ this.token = handle.token;
+ this.dispatchingTimeoutNanos = handle.dispatchingTimeoutNanos;
+ this.name = handle.name;
+ }
+
@Override
protected void finalize() throws Throwable {
try {
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index ed8492e..3080b42 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.UnsupportedAppUsage;
+import android.os.IBinder;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
@@ -184,6 +185,16 @@
return false;
}
+ /**
+ * @return Returns a token to identify the input channel.
+ */
+ public IBinder getToken() {
+ if (mInputChannel == null) {
+ return null;
+ }
+ return mInputChannel.getToken();
+ }
+
// Called from native code.
@SuppressWarnings("unused")
@UnsupportedAppUsage
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 59e9ed1..0b5af2d 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -20,6 +20,8 @@
import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.CompatibilityInfo.Translator;
@@ -34,6 +36,7 @@
import android.graphics.RenderNode;
import android.os.Build;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -1444,6 +1447,19 @@
}
/**
+ * @return The token used to identify the windows input channel.
+ * @hide
+ */
+ @TestApi
+ public @Nullable IBinder getInputToken() {
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot == null) {
+ return null;
+ }
+ return viewRoot.getInputToken();
+ }
+
+ /**
* Set window stopped to false and update surface visibility when ViewRootImpl surface is
* created.
* @hide
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 85bf19f..97adaf5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -69,6 +69,7 @@
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -1661,7 +1662,7 @@
return mBlastBufferQueue.getSurface();
}
-
+
private void setBoundsLayerCrop() {
// mWinFrame is already adjusted for surface insets. So offset it and use it as
// the cropping bounds.
@@ -7179,7 +7180,7 @@
if (mSurfaceControl.isValid()) {
if (USE_BLAST_BUFFERQUEUE == false) {
mSurface.copyFrom(mSurfaceControl);
- } else {
+ } else {
mSurface.transferFrom(getOrCreateBLASTSurface(
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f)));
@@ -8932,6 +8933,16 @@
}
/**
+ * @return Returns a token used to identify the windows input channel.
+ */
+ public IBinder getInputToken() {
+ if (mInputEventReceiver == null) {
+ return null;
+ }
+ return mInputEventReceiver.getToken();
+ }
+
+ /**
* Class for managing the accessibility interaction connection
* based on the global accessibility state.
*/
diff --git a/core/java/android/view/WindowlessViewRoot.java b/core/java/android/view/WindowlessViewRoot.java
index c2500b8..addf8e2 100644
--- a/core/java/android/view/WindowlessViewRoot.java
+++ b/core/java/android/view/WindowlessViewRoot.java
@@ -16,12 +16,11 @@
package android.view;
-import android.content.res.Resources;
-import android.content.Context;
-import android.view.SurfaceControl;
-import android.view.View;
-
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.content.Context;
+import android.os.IBinder;
/**
* Utility class for adding a view hierarchy to a SurfaceControl.
@@ -31,10 +30,13 @@
*/
@TestApi
public class WindowlessViewRoot {
- ViewRootImpl mViewRoot;
- WindowlessWindowManager mWm;
- public WindowlessViewRoot(Context c, Display d, SurfaceControl rootSurface) {
- mWm = new WindowlessWindowManager(c.getResources().getConfiguration(), rootSurface);
+ private ViewRootImpl mViewRoot;
+ private WindowlessWindowManager mWm;
+ public WindowlessViewRoot(@NonNull Context c, @NonNull Display d,
+ @NonNull SurfaceControl rootSurface,
+ @Nullable IBinder hostInputToken) {
+ mWm = new WindowlessWindowManager(c.getResources().getConfiguration(), rootSurface,
+ hostInputToken);
mViewRoot = new ViewRootImpl(c, d, mWm);
}
@@ -49,4 +51,8 @@
t.apply();
});
}
+
+ public void dispose() {
+ mViewRoot.dispatchDetachedFromWindow();
+ }
}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 6c6046f..403bfda 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -24,8 +24,6 @@
import android.util.Log;
import android.util.MergedConfiguration;
import android.view.IWindowSession;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import java.util.HashMap;
@@ -60,18 +58,20 @@
final HashMap<IBinder, ResizeCompleteCallback> mResizeCompletionForWindow =
new HashMap<IBinder, ResizeCompleteCallback>();
- final SurfaceSession mSurfaceSession = new SurfaceSession();
- final SurfaceControl mRootSurface;
- final Configuration mConfiguration;
- IWindowSession mRealWm;
+ private final SurfaceSession mSurfaceSession = new SurfaceSession();
+ private final SurfaceControl mRootSurface;
+ private final Configuration mConfiguration;
+ private final IWindowSession mRealWm;
+ private final IBinder mHostInputToken;
private int mForceHeight = -1;
private int mForceWidth = -1;
- WindowlessWindowManager(Configuration c, SurfaceControl rootSurface) {
+ WindowlessWindowManager(Configuration c, SurfaceControl rootSurface, IBinder hostInputToken) {
mRootSurface = rootSurface;
mConfiguration = new Configuration(c);
mRealWm = WindowManagerGlobal.getWindowSession();
+ mHostInputToken = hostInputToken;
}
/**
@@ -87,6 +87,7 @@
/**
* IWindowSession implementation.
*/
+ @Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
@@ -101,10 +102,11 @@
mStateForWindow.put(window.asBinder(), new State(sc, attrs));
}
- if ((attrs.inputFeatures &
- WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
+ if (((attrs.inputFeatures &
+ WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) &&
+ (mHostInputToken != null)) {
try {
- mRealWm.blessInputSurface(displayId, sc, outInputChannel);
+ mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, outInputChannel);
} catch (RemoteException e) {
Log.e(TAG, "Failed to bless surface: " + e);
}
@@ -122,10 +124,12 @@
}
@Override
- public void remove(android.view.IWindow window) {}
+ public void remove(android.view.IWindow window) throws RemoteException {
+ mRealWm.remove(window);
+ }
private boolean isOpaque(WindowManager.LayoutParams attrs) {
- if (attrs.surfaceInsets != null && attrs.surfaceInsets.left != 0 ||
+ if (attrs.surfaceInsets != null && attrs.surfaceInsets.left != 0 ||
attrs.surfaceInsets.top != 0 || attrs.surfaceInsets.right != 0 ||
attrs.surfaceInsets.bottom != 0) {
return false;
@@ -326,8 +330,8 @@
}
@Override
- public void blessInputSurface(int displayId, SurfaceControl surface,
- InputChannel outInputChannel) {
+ public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window,
+ IBinder hostInputToken, InputChannel outInputChannel) {
}
@Override
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
new file mode 100644
index 0000000..24948a2
--- /dev/null
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.ActivityRecord.INVALID_PID;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.view.IWindow;
+
+/**
+ * Keeps track of embedded windows.
+ *
+ * If the embedded window does not receive input then Window Manager does not keep track of it.
+ * But if they do receive input, we keep track of the calling PID to blame the right app and
+ * the host window to send pointerDownOutsideFocus.
+ */
+class EmbeddedWindowController {
+ /* maps input token to an embedded window */
+ private ArrayMap<IBinder /*input token */, EmbeddedWindow> mWindows = new ArrayMap<>();
+ private final Object mWmLock;
+
+ EmbeddedWindowController(Object wmLock) {
+ mWmLock = wmLock;
+ }
+
+ void add(IBinder inputToken, IWindow window, WindowState hostWindowState, int ownerUid,
+ int ownerPid) {
+ EmbeddedWindow embeddedWindow = new EmbeddedWindow(window, hostWindowState, ownerUid,
+ ownerPid);
+ try {
+ mWindows.put(inputToken, embeddedWindow);
+ window.asBinder().linkToDeath(()-> {
+ synchronized (mWmLock) {
+ mWindows.remove(inputToken);
+ }
+ }, 0);
+ } catch (RemoteException e) {
+ // The caller has died, remove from the map
+ mWindows.remove(inputToken);
+ }
+ }
+
+ WindowState getHostWindow(IBinder inputToken) {
+ EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
+ return embeddedWindow != null ? embeddedWindow.mHostWindowState : null;
+ }
+
+ int getOwnerPid(IBinder inputToken) {
+ EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
+ return embeddedWindow != null ? embeddedWindow.mOwnerPid : INVALID_PID;
+ }
+
+ void remove(IWindow client) {
+ for (ArrayMap.Entry<IBinder, EmbeddedWindow> entry: mWindows.entrySet()) {
+ if (entry.getValue().mClient.asBinder() == client.asBinder()) {
+ mWindows.remove(entry.getKey());
+ return;
+ }
+ }
+ }
+
+ void removeWindowsWithHost(WindowState host) {
+ for (ArrayMap.Entry<IBinder, EmbeddedWindow> entry: mWindows.entrySet()) {
+ if (entry.getValue().mHostWindowState == host) {
+ mWindows.remove(entry.getKey());
+ }
+ }
+ }
+
+ private static class EmbeddedWindow {
+ final IWindow mClient;
+ final WindowState mHostWindowState;
+ final int mOwnerUid;
+ final int mOwnerPid;
+
+ EmbeddedWindow(IWindow clientToken, WindowState hostWindowState, int ownerUid,
+ int ownerPid) {
+ mClient = clientToken;
+ mHostWindowState = hostWindowState;
+ mOwnerUid = ownerUid;
+ mOwnerPid = ownerPid;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 1ebbb02..2a6fb4a 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -87,12 +87,20 @@
ActivityRecord activity = null;
WindowState windowState = null;
boolean aboveSystem = false;
+ int windowPid = INVALID_PID;
//TODO(b/141764879) Limit scope of wm lock when input calls notifyANR
synchronized (mService.mGlobalLock) {
if (token != null) {
windowState = mService.mInputToWindowMap.get(token);
if (windowState != null) {
activity = windowState.mActivityRecord;
+ windowPid = windowState.mSession.mPid;
+ } else {
+ // Check if this is an embedded window and if so get the embedded app pid
+ windowPid = mService.mEmbeddedWindowController.getOwnerPid(token);
+ WindowState hostWindowState =
+ mService.mEmbeddedWindowController.getHostWindow(token);
+ aboveSystem = isWindowAboveSystem(hostWindowState);
}
}
@@ -107,9 +115,7 @@
// Figure out whether this window is layered above system windows.
// We need to do this here to help the activity manager know how to
// layer its ANR dialog.
- int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
- TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
- aboveSystem = windowState.mBaseLayer > systemAlertLayer;
+ aboveSystem = isWindowAboveSystem(windowState);
} else if (activity != null) {
Slog.i(TAG_WM, "Input event dispatching timed out "
+ "sending to application " + activity.stringName
@@ -128,18 +134,17 @@
if (activity != null && activity.appToken != null) {
// Notify the activity manager about the timeout and let it decide whether
// to abort dispatching or keep waiting.
- final boolean abort = activity.keyDispatchingTimedOut(reason,
- (windowState != null) ? windowState.mSession.mPid : INVALID_PID);
+ final boolean abort = activity.keyDispatchingTimedOut(reason, windowPid);
if (!abort) {
// The activity manager declined to abort dispatching.
// Wait a bit longer and timeout again later.
return activity.mInputDispatchingTimeoutNanos;
}
- } else if (windowState != null) {
+ } else if (windowState != null || windowPid != INVALID_PID) {
// Notify the activity manager about the timeout and let it decide whether
// to abort dispatching or keep waiting.
- long timeout = mService.mAmInternal.inputDispatchingTimedOut(
- windowState.mSession.mPid, aboveSystem, reason);
+ long timeout = mService.mAmInternal.inputDispatchingTimedOut(windowPid, aboveSystem,
+ reason);
if (timeout >= 0) {
// The activity manager declined to abort dispatching.
// Wait a bit longer and timeout again later.
@@ -149,6 +154,12 @@
return 0; // abort dispatching
}
+ private boolean isWindowAboveSystem(WindowState windowState) {
+ int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
+ TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
+ return windowState.mBaseLayer > systemAlertLayer;
+ }
+
/** Notifies that the input device configuration has changed. */
@Override
public void notifyConfigurationChanged() {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 06e7d66..96be7cc 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -623,13 +623,14 @@
return false;
}
- public void blessInputSurface(int displayId, SurfaceControl surface,
- InputChannel outInputChannel) {
+ public void grantInputChannel(int displayId, SurfaceControl surface,
+ IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
final int callerUid = Binder.getCallingUid();
final int callerPid = Binder.getCallingPid();
final long identity = Binder.clearCallingIdentity();
try {
- mService.blessInputSurface(callerUid, callerPid, displayId, surface, outInputChannel);
+ mService.grantInputChannel(callerUid, callerPid, displayId, surface, window,
+ hostInputToken, outInputChannel);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2c56b11..56d36e0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -224,6 +224,7 @@
import android.view.IWindowManager;
import android.view.IWindowSession;
import android.view.IWindowSessionCallback;
+import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -698,6 +699,7 @@
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
SettingsObserver mSettingsObserver;
+ final EmbeddedWindowController mEmbeddedWindowController;
@VisibleForTesting
final class SettingsObserver extends ContentObserver {
@@ -1283,6 +1285,7 @@
new HandlerExecutor(mH), mPropertiesChangedListener);
LocalServices.addService(WindowManagerInternal.class, new LocalService());
+ mEmbeddedWindowController = new EmbeddedWindowController(mGlobalLock);
}
/**
@@ -1868,10 +1871,13 @@
void removeWindow(Session session, IWindow client) {
synchronized (mGlobalLock) {
WindowState win = windowForClientLocked(session, client, false);
- if (win == null) {
+ if (win != null) {
+ win.removeIfPossible();
return;
}
- win.removeIfPossible();
+
+ // Remove embedded window map if the token belongs to an embedded window
+ mEmbeddedWindowController.remove(client);
}
}
@@ -1894,6 +1900,7 @@
if (dc.mCurrentFocus == null) {
dc.mWinRemovedSinceNullFocus.add(win);
}
+ mEmbeddedWindowController.removeWindowsWithHost(win);
mPendingRemove.remove(win);
mResizingWindows.remove(win);
updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
@@ -4574,7 +4581,7 @@
}
// First notify the accessibility manager for the change so it has
- // the windows before the newly focused one starts firing eventgs.
+ // the windows before the newly focused one starts firing events.
if (accessibilityController != null) {
accessibilityController.onWindowFocusChangedNotLocked(
displayContent.getDisplayId());
@@ -7643,7 +7650,12 @@
}
private void onPointerDownOutsideFocusLocked(IBinder touchedToken) {
- final WindowState touchedWindow = mInputToWindowMap.get(touchedToken);
+ WindowState touchedWindow = mInputToWindowMap.get(touchedToken);
+ if (touchedWindow == null) {
+ // if a user taps outside the currently focused window onto an embedded window, treat
+ // it as if the host window was tapped.
+ touchedWindow = mEmbeddedWindowController.getHostWindow(touchedToken);
+ }
if (touchedWindow == null || !touchedWindow.canReceiveKeys()) {
return;
}
@@ -7706,20 +7718,37 @@
* Used by WindowlessWindowManager to enable input on SurfaceControl embedded
* views.
*/
- void blessInputSurface(int callingUid, int callingPid, int displayId, SurfaceControl surface,
- InputChannel outInputChannel) {
- String name = "Blessed Surface";
- InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
- InputChannel inputChannel = inputChannels[0];
- InputChannel clientChannel = inputChannels[1];
+ void grantInputChannel(int callingUid, int callingPid, int displayId, SurfaceControl surface,
+ IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
+ final InputApplicationHandle applicationHandle;
+ final String name;
+ final InputChannel[] inputChannels;
+ final InputChannel clientChannel;
+ final InputChannel serverChannel;
+ synchronized (mGlobalLock) {
+ final WindowState hostWindow = mInputToWindowMap.get(hostInputToken);
+ if (hostWindow == null) {
+ Slog.e(TAG, "Failed to grant input channel");
+ return;
+ }
+ name = "EmbeddedWindow{ u" + UserHandle.getUserId(callingUid)
+ + " " + hostWindow.getWindowTag() + "}";
+
+ inputChannels = InputChannel.openInputChannelPair(name);
+ serverChannel = inputChannels[0];
+ clientChannel = inputChannels[1];
+ mInputManager.registerInputChannel(serverChannel);
+ mEmbeddedWindowController.add(serverChannel.getToken(), window, hostWindow, callingUid,
+ callingPid);
+ applicationHandle = new InputApplicationHandle(
+ hostWindow.mInputWindowHandle.inputApplicationHandle);
+ }
clientChannel.transferTo(outInputChannel);
clientChannel.dispose();
- mInputManager.registerInputChannel(inputChannel);
-
- InputWindowHandle h = new InputWindowHandle(null, displayId);
- h.token = inputChannel.getToken();
+ InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
+ h.token = serverChannel.getToken();
h.name = name;
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
h.layoutParamsType = 0;
@@ -7744,7 +7773,7 @@
// Prevent the java finalizer from breaking the input channel. But we won't
// do any further management so we just release the java ref and let the
// InputDispatcher hold the last ref.
- inputChannel.release();
+ serverChannel.release();
}
/** Return whether layer tracing is enabled */
diff --git a/tests/WindowlessWmTest/src/com/android/test/viewembed/WindowlessWmTest.java b/tests/WindowlessWmTest/src/com/android/test/viewembed/WindowlessWmTest.java
index 5a146da..5c1e830 100644
--- a/tests/WindowlessWmTest/src/com/android/test/viewembed/WindowlessWmTest.java
+++ b/tests/WindowlessWmTest/src/com/android/test/viewembed/WindowlessWmTest.java
@@ -17,17 +17,16 @@
package com.android.test.viewembed;
import android.app.Activity;
-import android.os.Bundle;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
+import android.os.Bundle;
import android.view.Gravity;
-import android.view.WindowlessViewRoot;
import android.view.SurfaceHolder;
-import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowlessViewRoot;
import android.widget.Button;
import android.widget.FrameLayout;
@@ -50,8 +49,8 @@
@Override
public void surfaceCreated(SurfaceHolder holder) {
- mVr = new WindowlessViewRoot(this, this.getDisplay(),
- mView.getSurfaceControl());
+ mVr = new WindowlessViewRoot(this, this.getDisplay(), mView.getSurfaceControl(),
+ mView.getInputToken());
Button v = new Button(this);
v.setBackgroundColor(Color.BLUE);
v.setOnClickListener(new View.OnClickListener() {