diff options
author | 2019-11-07 15:33:20 -0800 | |
---|---|---|
committer | 2019-11-07 15:54:27 -0800 | |
commit | 5cf25319775616f88d59768bd9dd0753afd0359f (patch) | |
tree | 68482078dd710dab7c5f07a6ec9d9c56cabb8f74 | |
parent | f8a289110576dcff9c7486d8e4f80a85d9786f23 (diff) |
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
13 files changed, 259 insertions, 59 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 466320ba4403..5e2d4a54d27a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4415,6 +4415,10 @@ package android.view { 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 @@ package android.view { } 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 6ce5ac4197ea..eaf6fca1b91f 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -314,5 +314,6 @@ interface IWindowSession { * 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 5f6bc2352131..3d05e2a0b9f6 100644 --- a/core/java/android/view/InputApplicationHandle.java +++ b/core/java/android/view/InputApplicationHandle.java @@ -36,7 +36,7 @@ public final class InputApplicationHandle { // Dispatching timeout. public long dispatchingTimeoutNanos; - public IBinder token; + public final IBinder token; private native void nativeDispose(); @@ -44,6 +44,12 @@ public final class InputApplicationHandle { 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 ed8492e482c7..3080b42e81ce 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 @@ public abstract class InputEventReceiver { 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 59e9ed1512ee..0b5af2d01349 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_OVERLA 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.Region; 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 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } /** + * @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 85bf19f855bb..97adaf57f9b4 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -69,6 +69,7 @@ import android.os.Build; 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 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, 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 @@ public final class ViewRootImpl implements ViewParent, } /** + * @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 c2500b89073e..addf8e242e3d 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 @@ import android.annotation.TestApi; */ @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 @@ public class WindowlessViewRoot { t.apply(); }); } + + public void dispose() { + mViewRoot.dispatchDetachedFromWindow(); + } } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 6c6046f1876f..403bfda78292 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -24,8 +24,6 @@ import android.os.RemoteException; 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 @@ class WindowlessWindowManager implements IWindowSession { 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 @@ class WindowlessWindowManager implements IWindowSession { /** * 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 @@ class WindowlessWindowManager implements IWindowSession { 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 @@ class WindowlessWindowManager implements IWindowSession { } @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 @@ class WindowlessWindowManager implements IWindowSession { } @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 000000000000..24948a254a26 --- /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 1ebbb0294204..2a6fb4af86ab 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 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal 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 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal // 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 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal 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 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal 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 06e7d665bb42..96be7cc416bd 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 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { 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 2c56b1124f9f..56d36e0769f8 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.IWindowId; 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 @@ public class WindowManagerService extends IWindowManager.Stub boolean mHardKeyboardAvailable; WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; SettingsObserver mSettingsObserver; + final EmbeddedWindowController mEmbeddedWindowController; @VisibleForTesting final class SettingsObserver extends ContentObserver { @@ -1283,6 +1285,7 @@ public class WindowManagerService extends IWindowManager.Stub new HandlerExecutor(mH), mPropertiesChangedListener); LocalServices.addService(WindowManagerInternal.class, new LocalService()); + mEmbeddedWindowController = new EmbeddedWindowController(mGlobalLock); } /** @@ -1868,10 +1871,13 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } // 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 @@ public class WindowManagerService extends IWindowManager.Stub } 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 @@ public class WindowManagerService extends IWindowManager.Stub * 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 @@ public class WindowManagerService extends IWindowManager.Stub // 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 5a146da1a3f2..5c1e830e1382 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 @@ public class WindowlessWmTest extends Activity implements SurfaceHolder.Callback @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() { |