diff options
author | Jeff Brown <jeffbrown@google.com> | 2011-08-30 20:34:48 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2011-08-30 21:40:28 -0700 |
commit | cc4f7db698f88b633a286d8ab1105b28a474cd09 (patch) | |
tree | 02ec7d914ab182e912af5c147ebc7483a719c6de /core/java/android/view | |
parent | ad4d2c99ed3a08a5090c38e9dd906df8fb894614 (diff) | |
download | frameworks_base-cc4f7db698f88b633a286d8ab1105b28a474cd09.zip frameworks_base-cc4f7db698f88b633a286d8ab1105b28a474cd09.tar.gz frameworks_base-cc4f7db698f88b633a286d8ab1105b28a474cd09.tar.bz2 |
Fix input channel leak.
Bug: 5156144
Input channels could leak or simply live longer than they should
in some cases.
1. Monitor channels (used by the pointer location overlay) are never
unregistered, so they would leak.
Added code to handle failures in the receive callback by closing
the input channel.
2. The DragState held onto its input window and application handles
even after the input channel was disposed.
Added code to null these handles out when they are no longer needed.
3. Input channels previously used as input event targets would stick
around until the targets were cleared (usually on the next
event).
Added code to detect when the input dispatcher is in
an idle state and to proactively clear the targets then
to ensure that resources are released promptly.
4. Native input window handles held onto the input channel even
after the input window was removed from the input dispatcher.
Consequently, the input channel would not be disposed until
the input window handle itself was freed. Since the input
window handle is held from managed code, this meant that the
window's input channel could stick around until the next GC.
Refactored the input window handle to separate the properties
(info) and identify (handle) state into different objects.
Then modified the dispatcher to release the properties (info)
when no longer needed, including the input channel.
7. The pointer location overlay does not actually use its
standard input channel, only the monitor input channel.
Added INPUT_FEATURE_NO_INPUT_CHANNEL to allow windows to
request that they not be provided with an input channel
at all.
Improved some of the error handling logic to emit the status
code as part of the exception message.
Change-Id: I01988d4391a70c6678c8b0e936ca051af680b1a5
Diffstat (limited to 'core/java/android/view')
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 32 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 9 |
2 files changed, 27 insertions, 14 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a0cc287..5c045bb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -454,7 +454,10 @@ public final class ViewRootImpl extends Handler implements ViewParent, // manager, to make sure we do the relayout before receiving // any other events from the system. requestLayout(); - mInputChannel = new InputChannel(); + if ((mWindowAttributes.inputFeatures + & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { + mInputChannel = new InputChannel(); + } try { res = sWindowSession.add(mWindow, mWindowAttributes, getHostVisibility(), mAttachInfo.mContentInsets, @@ -524,12 +527,14 @@ public final class ViewRootImpl extends Handler implements ViewParent, mInputQueueCallback = ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue(); } - if (mInputQueueCallback != null) { - mInputQueue = new InputQueue(mInputChannel); - mInputQueueCallback.onInputQueueCreated(mInputQueue); - } else { - InputQueue.registerInputChannel(mInputChannel, mInputHandler, - Looper.myQueue()); + if (mInputChannel != null) { + if (mInputQueueCallback != null) { + mInputQueue = new InputQueue(mInputChannel); + mInputQueueCallback.onInputQueueCreated(mInputQueue); + } else { + InputQueue.registerInputChannel(mInputChannel, mInputHandler, + Looper.myQueue()); + } } view.assignParent(this); @@ -2152,13 +2157,12 @@ public final class ViewRootImpl extends Handler implements ViewParent, mSurface.release(); - if (mInputChannel != null) { - if (mInputQueueCallback != null) { - mInputQueueCallback.onInputQueueDestroyed(mInputQueue); - mInputQueueCallback = null; - } else { - InputQueue.unregisterInputChannel(mInputChannel); - } + if (mInputQueueCallback != null && mInputQueue != null) { + mInputQueueCallback.onInputQueueDestroyed(mInputQueue); + mInputQueueCallback = null; + mInputQueue = null; + } else if (mInputChannel != null) { + InputQueue.unregisterInputChannel(mInputChannel); } try { sWindowSession.remove(mWindow); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index fdd9b2c..52d25d9 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1029,9 +1029,18 @@ public interface WindowManager extends ViewManager { public static final int INPUT_FEATURE_DISABLE_POINTER_GESTURES = 0x00000001; /** + * Does not construct an input channel for this window. The channel will therefore + * be incapable of receiving input. + * + * @hide + */ + public static final int INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002; + + /** * Control special features of the input subsystem. * * @see #INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES + * @see #INPUT_FEATURE_NO_INPUT_CHANNEL * @hide */ public int inputFeatures; |