summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2011-08-30 20:34:48 -0700
committerJeff Brown <jeffbrown@google.com>2011-08-30 21:40:28 -0700
commitcc4f7db698f88b633a286d8ab1105b28a474cd09 (patch)
tree02ec7d914ab182e912af5c147ebc7483a719c6de
parentad4d2c99ed3a08a5090c38e9dd906df8fb894614 (diff)
downloadframeworks_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
-rw-r--r--core/java/android/view/ViewRootImpl.java32
-rw-r--r--core/java/android/view/WindowManager.java9
-rw-r--r--core/jni/android_view_InputChannel.cpp27
-rw-r--r--core/jni/android_view_InputQueue.cpp15
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java1
-rw-r--r--services/input/Android.mk1
-rw-r--r--services/input/InputApplication.cpp42
-rw-r--r--services/input/InputApplication.h36
-rw-r--r--services/input/InputDispatcher.cpp365
-rw-r--r--services/input/InputDispatcher.h11
-rw-r--r--services/input/InputWindow.cpp28
-rw-r--r--services/input/InputWindow.h54
-rw-r--r--services/java/com/android/server/wm/DragState.java3
-rw-r--r--services/java/com/android/server/wm/InputApplicationHandle.java7
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java16
-rw-r--r--services/java/com/android/server/wm/InputWindowHandle.java7
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java5
-rw-r--r--services/java/com/android/server/wm/WindowState.java16
-rw-r--r--services/jni/com_android_server_InputApplicationHandle.cpp13
-rw-r--r--services/jni/com_android_server_InputApplicationHandle.h2
-rw-r--r--services/jni/com_android_server_InputManager.cpp17
-rw-r--r--services/jni/com_android_server_InputWindowHandle.cpp53
-rw-r--r--services/jni/com_android_server_InputWindowHandle.h2
23 files changed, 518 insertions, 244 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;
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 0c2801c..5fcf8fa 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -111,7 +111,9 @@ static jobject android_view_InputChannel_createInputChannel(JNIEnv* env,
NativeInputChannel* nativeInputChannel) {
jobject inputChannelObj = env->NewObject(gInputChannelClassInfo.clazz,
gInputChannelClassInfo.ctor);
- android_view_InputChannel_setNativeInputChannel(env, inputChannelObj, nativeInputChannel);
+ if (inputChannelObj) {
+ android_view_InputChannel_setNativeInputChannel(env, inputChannelObj, nativeInputChannel);
+ }
return inputChannelObj;
}
@@ -126,18 +128,29 @@ static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv*
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
if (result) {
- LOGE("Could not open input channel pair. status=%d", result);
- jniThrowRuntimeException(env, "Could not open input channel pair.");
+ String8 message;
+ message.appendFormat("Could not open input channel pair. status=%d", result);
+ jniThrowRuntimeException(env, message.string());
+ return NULL;
+ }
+
+ jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
+ if (env->ExceptionCheck()) {
return NULL;
}
- // TODO more robust error checking
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(serverChannel));
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(clientChannel));
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
- jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
return channelPair;
@@ -161,7 +174,7 @@ static void android_view_InputChannel_nativeDispose(JNIEnv* env, jobject obj, jb
static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,
jobject otherObj) {
- if (android_view_InputChannel_getInputChannel(env, otherObj) != NULL) {
+ if (android_view_InputChannel_getNativeInputChannel(env, otherObj) != NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Other object already has a native input channel.");
return;
@@ -175,7 +188,7 @@ static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,
static void android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject obj,
jobject parcelObj) {
- if (android_view_InputChannel_getInputChannel(env, obj) != NULL) {
+ if (android_view_InputChannel_getNativeInputChannel(env, obj) != NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"This object already has a native input channel.");
return;
diff --git a/core/jni/android_view_InputQueue.cpp b/core/jni/android_view_InputQueue.cpp
index 80c4871..300c04a 100644
--- a/core/jni/android_view_InputQueue.cpp
+++ b/core/jni/android_view_InputQueue.cpp
@@ -455,8 +455,9 @@ static void android_view_InputQueue_nativeRegisterInputChannel(JNIEnv* env, jcla
env, inputChannelObj, inputHandlerObj, messageQueueObj);
if (status) {
- jniThrowRuntimeException(env, "Failed to register input channel. "
- "Check logs for details.");
+ String8 message;
+ message.appendFormat("Failed to register input channel. status=%d", status);
+ jniThrowRuntimeException(env, message.string());
}
}
@@ -465,8 +466,9 @@ static void android_view_InputQueue_nativeUnregisterInputChannel(JNIEnv* env, jc
status_t status = gNativeInputQueue.unregisterInputChannel(env, inputChannelObj);
if (status) {
- jniThrowRuntimeException(env, "Failed to unregister input channel. "
- "Check logs for details.");
+ String8 message;
+ message.appendFormat("Failed to unregister input channel. status=%d", status);
+ jniThrowRuntimeException(env, message.string());
}
}
@@ -479,8 +481,9 @@ static void android_view_InputQueue_nativeFinished(JNIEnv* env, jclass clazz,
// was no longer registered (DEAD_OBJECT) since it is a common race that can occur
// during application shutdown. The input dispatcher recovers gracefully anyways.
if (status != OK && status != DEAD_OBJECT) {
- jniThrowRuntimeException(env, "Failed to finish input event. "
- "Check logs for details.");
+ String8 message;
+ message.appendFormat("Failed to finish input event. status=%d", status);
+ jniThrowRuntimeException(env, message.string());
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index dfd1b00..c988846 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -900,6 +900,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
lp.setTitle("PointerLocation");
WindowManager wm = (WindowManager)
mContext.getSystemService(Context.WINDOW_SERVICE);
+ lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
wm.addView(addView, lp);
if (mPointerLocationInputChannel == null) {
diff --git a/services/input/Android.mk b/services/input/Android.mk
index afbe546..86c6c8a 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -18,6 +18,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
EventHub.cpp \
+ InputApplication.cpp \
InputDispatcher.cpp \
InputListener.cpp \
InputManager.cpp \
diff --git a/services/input/InputApplication.cpp b/services/input/InputApplication.cpp
new file mode 100644
index 0000000..a99e637
--- /dev/null
+++ b/services/input/InputApplication.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "InputApplication"
+
+#include "InputApplication.h"
+
+#include <cutils/log.h>
+
+namespace android {
+
+// --- InputApplicationHandle ---
+
+InputApplicationHandle::InputApplicationHandle() :
+ mInfo(NULL) {
+}
+
+InputApplicationHandle::~InputApplicationHandle() {
+ delete mInfo;
+}
+
+void InputApplicationHandle::releaseInfo() {
+ if (mInfo) {
+ delete mInfo;
+ mInfo = NULL;
+ }
+}
+
+} // namespace android
diff --git a/services/input/InputApplication.h b/services/input/InputApplication.h
index 8902f7a..67ae94b 100644
--- a/services/input/InputApplication.h
+++ b/services/input/InputApplication.h
@@ -27,14 +27,32 @@ namespace android {
/*
* Describes the properties of an application that can receive input.
+ */
+struct InputApplicationInfo {
+ String8 name;
+ nsecs_t dispatchingTimeout;
+};
+
+
+/*
+ * Handle for an application that can receive input.
*
* Used by the native input dispatcher as a handle for the window manager objects
* that describe an application.
*/
class InputApplicationHandle : public RefBase {
public:
- String8 name;
- nsecs_t dispatchingTimeout;
+ inline const InputApplicationInfo* getInfo() const {
+ return mInfo;
+ }
+
+ inline String8 getName() const {
+ return mInfo ? mInfo->name : String8("<invalid>");
+ }
+
+ inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
+ return mInfo ? mInfo->dispatchingTimeout : defaultValue;
+ }
/**
* Requests that the state of this object be updated to reflect
@@ -45,11 +63,19 @@ public:
*
* Returns true on success, or false if the handle is no longer valid.
*/
- virtual bool update() = 0;
+ virtual bool updateInfo() = 0;
+
+ /**
+ * Releases the storage used by the associated information when it is
+ * no longer needed.
+ */
+ void releaseInfo();
protected:
- InputApplicationHandle() { }
- virtual ~InputApplicationHandle() { }
+ InputApplicationHandle();
+ virtual ~InputApplicationHandle();
+
+ InputApplicationInfo* mInfo;
};
} // namespace android
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index cf167ae..1eb5f0e 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -306,7 +306,12 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
}
}
}
+
+ // Nothing to do if there is no pending event.
if (! mPendingEvent) {
+ if (mActiveConnections.isEmpty()) {
+ dispatchIdleLocked();
+ }
return;
}
} else {
@@ -462,6 +467,16 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
}
}
+void InputDispatcher::dispatchIdleLocked() {
+#if DEBUG_FOCUS
+ LOGD("Dispatcher idle. There are no pending events or active connections.");
+#endif
+
+ // Reset targets when idle, to release input channels and other resources
+ // they are holding onto.
+ resetTargetsLocked();
+}
+
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
bool needWake = mInboundQueue.isEmpty();
mInboundQueue.enqueueAtTail(entry);
@@ -525,20 +540,21 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int3
size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- int32_t flags = windowHandle->layoutParamsFlags;
-
- if (windowHandle->visible) {
- if (!(flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) {
- bool isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE
- | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) {
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ int32_t flags = windowInfo->layoutParamsFlags;
+
+ if (windowInfo->visible) {
+ if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
+ bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
+ | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
+ if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
// Found window.
return windowHandle;
}
}
}
- if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
+ if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
// Error window is on top but not visible, so touch is dropped.
return NULL;
}
@@ -1051,9 +1067,15 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
LOGD("Waiting for application to become ready for input: %s",
getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
#endif
- nsecs_t timeout = windowHandle != NULL ? windowHandle->dispatchingTimeout :
- applicationHandle != NULL ?
- applicationHandle->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
+ nsecs_t timeout;
+ if (windowHandle != NULL) {
+ timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
+ } else if (applicationHandle != NULL) {
+ timeout = applicationHandle->getDispatchingTimeout(
+ DEFAULT_INPUT_DISPATCHING_TIMEOUT);
+ } else {
+ timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
+ }
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
mInputTargetWaitStartTime = currentTime;
@@ -1168,7 +1190,7 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
}
// If the currently focused window is paused then keep waiting.
- if (mFocusedWindowHandle->paused) {
+ if (mFocusedWindowHandle->getInfo()->paused) {
#if DEBUG_FOCUS
LOGD("Waiting because focused window is paused.");
#endif
@@ -1302,21 +1324,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- int32_t flags = windowHandle->layoutParamsFlags;
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ int32_t flags = windowInfo->layoutParamsFlags;
- if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
+ if (flags & InputWindowInfo::FLAG_SYSTEM_ERROR) {
if (topErrorWindowHandle == NULL) {
topErrorWindowHandle = windowHandle;
}
}
- if (windowHandle->visible) {
- if (! (flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) {
- isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE
- | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) {
+ if (windowInfo->visible) {
+ if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
+ isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
+ | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
+ if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
if (! screenWasOff
- || (flags & InputWindowHandle::FLAG_TOUCHABLE_WHEN_WAKING)) {
+ || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) {
newTouchedWindowHandle = windowHandle;
}
break; // found touched window, exit window loop
@@ -1324,7 +1347,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
}
if (maskedAction == AMOTION_EVENT_ACTION_DOWN
- && (flags & InputWindowHandle::FLAG_WATCH_OUTSIDE_TOUCH)) {
+ && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
@@ -1350,7 +1373,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
}
// Figure out whether splitting will be allowed for this window.
- if (newTouchedWindowHandle != NULL && newTouchedWindowHandle->supportsSplitTouch()) {
+ if (newTouchedWindowHandle != NULL
+ && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
// New window supports splitting.
isSplit = true;
} else if (isSplit) {
@@ -1396,7 +1420,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// within the touched window.
if (!isTouchModal) {
while (sample->next) {
- if (!newHoverWindowHandle->touchableRegionContainsPoint(
+ if (!newHoverWindowHandle->getInfo()->touchableRegionContainsPoint(
sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y))) {
*outSplitBatchAfterSample = sample;
@@ -1444,15 +1468,15 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
&& newTouchedWindowHandle != NULL) {
#if DEBUG_FOCUS
LOGD("Touch is slipping out of window %s into window %s.",
- oldTouchedWindowHandle->name.string(),
- newTouchedWindowHandle->name.string());
+ oldTouchedWindowHandle->getName().string(),
+ newTouchedWindowHandle->getName().string());
#endif
// Make a slippery exit from the old window.
mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
// Make a slippery entrance into the new window.
- if (newTouchedWindowHandle->supportsSplitTouch()) {
+ if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
isSplit = true;
}
@@ -1484,7 +1508,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// Let the previous window know that the hover sequence is over.
if (mLastHoverWindowHandle != NULL) {
#if DEBUG_HOVER
- LOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->name.string());
+ LOGD("Sending hover exit event to window %s.",
+ mLastHoverWindowHandle->getName().string());
#endif
mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
@@ -1493,7 +1518,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// Let the new window know that the hover sequence is starting.
if (newHoverWindowHandle != NULL) {
#if DEBUG_HOVER
- LOGD("Sending hover enter event to window %s.", newHoverWindowHandle->name.string());
+ LOGD("Sending hover enter event to window %s.",
+ newHoverWindowHandle->getName().string());
#endif
mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
@@ -1533,12 +1559,12 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
sp<InputWindowHandle> foregroundWindowHandle =
mTempTouchState.getFirstForegroundWindowHandle();
- const int32_t foregroundWindowUid = foregroundWindowHandle->ownerUid;
+ const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
- if (inputWindowHandle->ownerUid != foregroundWindowUid) {
+ if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
mTempTouchState.addOrUpdateWindow(inputWindowHandle,
InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
}
@@ -1551,7 +1577,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
// If the touched window is paused then keep waiting.
- if (touchedWindow.windowHandle->paused) {
+ if (touchedWindow.windowHandle->getInfo()->paused) {
#if DEBUG_FOCUS
LOGD("Waiting because touched window is paused.");
#endif
@@ -1581,10 +1607,11 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
sp<InputWindowHandle> foregroundWindowHandle =
mTempTouchState.getFirstForegroundWindowHandle();
- if (foregroundWindowHandle->hasWallpaper) {
+ if (foregroundWindowHandle->getInfo()->hasWallpaper) {
for (size_t i = 0; i < mWindowHandles.size(); i++) {
sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- if (windowHandle->layoutParamsType == InputWindowHandle::TYPE_WALLPAPER) {
+ if (windowHandle->getInfo()->layoutParamsType
+ == InputWindowInfo::TYPE_WALLPAPER) {
mTempTouchState.addOrUpdateWindow(windowHandle,
InputTarget::FLAG_WINDOW_IS_OBSCURED
| InputTarget::FLAG_DISPATCH_AS_IS,
@@ -1708,12 +1735,13 @@ void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowH
int32_t targetFlags, BitSet32 pointerIds) {
mCurrentInputTargets.push();
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
InputTarget& target = mCurrentInputTargets.editTop();
- target.inputChannel = windowHandle->inputChannel;
+ target.inputChannel = windowInfo->inputChannel;
target.flags = targetFlags;
- target.xOffset = - windowHandle->frameLeft;
- target.yOffset = - windowHandle->frameTop;
- target.scaleFactor = windowHandle->scaleFactor;
+ target.xOffset = - windowInfo->frameLeft;
+ target.yOffset = - windowInfo->frameTop;
+ target.scaleFactor = windowInfo->scaleFactor;
target.pointerIds = pointerIds;
}
@@ -1734,14 +1762,15 @@ void InputDispatcher::addMonitoringTargetsLocked() {
bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
const InjectionState* injectionState) {
if (injectionState
- && (windowHandle == NULL || windowHandle->ownerUid != injectionState->injectorUid)
+ && (windowHandle == NULL
+ || windowHandle->getInfo()->ownerUid != injectionState->injectorUid)
&& !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
if (windowHandle != NULL) {
LOGW("Permission denied: injecting event from pid %d uid %d to window %s "
"owned by uid %d",
injectionState->injectorPid, injectionState->injectorUid,
- windowHandle->name.string(),
- windowHandle->ownerUid);
+ windowHandle->getName().string(),
+ windowHandle->getInfo()->ownerUid);
} else {
LOGW("Permission denied: injecting event from pid %d uid %d",
injectionState->injectorPid, injectionState->injectorUid);
@@ -1759,8 +1788,10 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(
if (otherHandle == windowHandle) {
break;
}
- if (otherHandle->visible && ! otherHandle->isTrustedOverlay()
- && otherHandle->frameContainsPoint(x, y)) {
+
+ const InputWindowInfo* otherInfo = otherHandle->getInfo();
+ if (otherInfo->visible && ! otherInfo->isTrustedOverlay()
+ && otherInfo->frameContainsPoint(x, y)) {
return true;
}
}
@@ -1769,7 +1800,7 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(
bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(
const sp<InputWindowHandle>& windowHandle) {
- ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->inputChannel);
+ ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel());
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
return connection->outboundQueue.isEmpty();
@@ -1783,15 +1814,15 @@ String8 InputDispatcher::getApplicationWindowLabelLocked(
const sp<InputWindowHandle>& windowHandle) {
if (applicationHandle != NULL) {
if (windowHandle != NULL) {
- String8 label(applicationHandle->name);
+ String8 label(applicationHandle->getName());
label.append(" - ");
- label.append(windowHandle->name);
+ label.append(windowHandle->getName());
return label;
} else {
- return applicationHandle->name;
+ return applicationHandle->getName();
}
} else if (windowHandle != NULL) {
- return windowHandle->name;
+ return windowHandle->getName();
} else {
return String8("<unknown application or window>");
}
@@ -2127,7 +2158,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
if (status) {
LOGE("channel '%s' ~ Could not publish key event, "
"status=%d", connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
+ abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
return;
}
break;
@@ -2190,7 +2221,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
if (status) {
LOGE("channel '%s' ~ Could not publish motion event, "
"status=%d", connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
+ abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
return;
}
@@ -2223,7 +2254,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
LOGE("channel '%s' ~ Could not append motion sample "
"for a reason other than out of memory, status=%d",
connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
+ abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
return;
}
}
@@ -2245,7 +2276,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
if (status) {
LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
+ abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
return;
}
@@ -2280,7 +2311,7 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
if (status) {
LOGE("channel '%s' ~ Could not reset publisher, status=%d",
connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection);
+ abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
return;
}
@@ -2324,10 +2355,10 @@ void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
}
void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
+ const sp<Connection>& connection, bool notify) {
#if DEBUG_DISPATCH_CYCLE
- LOGD("channel '%s' ~ abortBrokenDispatchCycle",
- connection->getInputChannelName());
+ LOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
+ connection->getInputChannelName(), toString(notify));
#endif
// Clear the outbound queue.
@@ -2338,8 +2369,10 @@ void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
if (connection->status == Connection::STATUS_NORMAL) {
connection->status = Connection::STATUS_BROKEN;
- // Notify other system components.
- onDispatchCycleBrokenLocked(currentTime, connection);
+ if (notify) {
+ // Notify other system components.
+ onDispatchCycleBrokenLocked(currentTime, connection);
+ }
}
}
@@ -2368,36 +2401,41 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
return 0; // remove the callback
}
- nsecs_t currentTime = now();
-
+ bool notify;
sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
- if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
- LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
- "events=0x%x", connection->getInputChannelName(), events);
- d->abortBrokenDispatchCycleLocked(currentTime, connection);
- d->runCommandsLockedInterruptible();
- return 0; // remove the callback
- }
+ if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
+ if (!(events & ALOOPER_EVENT_INPUT)) {
+ LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
+ "events=0x%x", connection->getInputChannelName(), events);
+ return 1;
+ }
- if (! (events & ALOOPER_EVENT_INPUT)) {
- LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
- "events=0x%x", connection->getInputChannelName(), events);
- return 1;
- }
+ bool handled = false;
+ status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
+ if (!status) {
+ nsecs_t currentTime = now();
+ d->finishDispatchCycleLocked(currentTime, connection, handled);
+ d->runCommandsLockedInterruptible();
+ return 1;
+ }
- bool handled = false;
- status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
- if (status) {
LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
connection->getInputChannelName(), status);
- d->abortBrokenDispatchCycleLocked(currentTime, connection);
- d->runCommandsLockedInterruptible();
- return 0; // remove the callback
+ notify = true;
+ } else {
+ // Monitor channels are never explicitly unregistered.
+ // We do it automatically when the remote endpoint is closed so don't warn
+ // about them.
+ notify = !connection->monitor;
+ if (notify) {
+ LOGW("channel '%s' ~ Consumer closed input channel or an error occurred. "
+ "events=0x%x", connection->getInputChannelName(), events);
+ }
}
- d->finishDispatchCycleLocked(currentTime, connection, handled);
- d->runCommandsLockedInterruptible();
- return 1;
+ // Unregister the channel.
+ d->unregisterInputChannelLocked(connection->inputChannel, notify);
+ return 0; // remove the callback
} // release lock
}
@@ -2450,9 +2488,10 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
InputTarget target;
sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
if (windowHandle != NULL) {
- target.xOffset = -windowHandle->frameLeft;
- target.yOffset = -windowHandle->frameTop;
- target.scaleFactor = windowHandle->scaleFactor;
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ target.xOffset = -windowInfo->frameLeft;
+ target.yOffset = -windowInfo->frameTop;
+ target.scaleFactor = windowInfo->scaleFactor;
} else {
target.xOffset = 0;
target.yOffset = 0;
@@ -2854,9 +2893,9 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
#if DEBUG_BATCHING
LOGD("Not streaming hover move because the last hovered window "
"is '%s' but the currently hovered window is '%s'.",
- mLastHoverWindowHandle->name.string(),
+ mLastHoverWindowHandle->getName().string(),
hoverWindowHandle != NULL
- ? hoverWindowHandle->name.string() : "<null>");
+ ? hoverWindowHandle->getName().string() : "<null>");
#endif
goto NoBatchingOrStreaming;
}
@@ -3183,7 +3222,7 @@ sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (windowHandle->inputChannel == inputChannel) {
+ if (windowHandle->getInputChannel() == inputChannel) {
return windowHandle;
}
}
@@ -3208,17 +3247,18 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu
{ // acquire lock
AutoMutex _l(mLock);
+ Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
mWindowHandles = inputWindowHandles;
sp<InputWindowHandle> newFocusedWindowHandle;
bool foundHoveredWindow = false;
for (size_t i = 0; i < mWindowHandles.size(); i++) {
const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (!windowHandle->update() || windowHandle->inputChannel == NULL) {
+ if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) {
mWindowHandles.removeAt(i--);
continue;
}
- if (windowHandle->hasFocus) {
+ if (windowHandle->getInfo()->hasFocus) {
newFocusedWindowHandle = windowHandle;
}
if (windowHandle == mLastHoverWindowHandle) {
@@ -3234,19 +3274,20 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu
if (mFocusedWindowHandle != NULL) {
#if DEBUG_FOCUS
LOGD("Focus left window: %s",
- mFocusedWindowHandle->name.string());
+ mFocusedWindowHandle->getName().string());
#endif
- if (mFocusedWindowHandle->inputChannel != NULL) {
+ sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
+ if (focusedInputChannel != NULL) {
CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
"focus left window");
synthesizeCancelationEventsForInputChannelLocked(
- mFocusedWindowHandle->inputChannel, options);
+ focusedInputChannel, options);
}
}
if (newFocusedWindowHandle != NULL) {
#if DEBUG_FOCUS
LOGD("Focus entered window: %s",
- newFocusedWindowHandle->name.string());
+ newFocusedWindowHandle->getName().string());
#endif
}
mFocusedWindowHandle = newFocusedWindowHandle;
@@ -3256,17 +3297,34 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu
TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
#if DEBUG_FOCUS
- LOGD("Touched window was removed: %s", touchedWindow.windowHandle->name.string());
+ LOGD("Touched window was removed: %s",
+ touchedWindow.windowHandle->getName().string());
#endif
- if (touchedWindow.windowHandle->inputChannel != NULL) {
+ sp<InputChannel> touchedInputChannel =
+ touchedWindow.windowHandle->getInputChannel();
+ if (touchedInputChannel != NULL) {
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
"touched window was removed");
synthesizeCancelationEventsForInputChannelLocked(
- touchedWindow.windowHandle->inputChannel, options);
+ touchedInputChannel, options);
}
mTouchState.windows.removeAt(i--);
}
}
+
+ // Release information for windows that are no longer present.
+ // This ensures that unused input channels are released promptly.
+ // Otherwise, they might stick around until the window handle is destroyed
+ // which might not happen until the next GC.
+ for (size_t i = 0; i < oldWindowHandles.size(); i++) {
+ const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
+ if (!hasWindowHandleLocked(oldWindowHandle)) {
+#if DEBUG_FOCUS
+ LOGD("Window went away: %s", oldWindowHandle->getName().string());
+#endif
+ oldWindowHandle->releaseInfo();
+ }
+ }
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
@@ -3281,15 +3339,17 @@ void InputDispatcher::setFocusedApplication(
{ // acquire lock
AutoMutex _l(mLock);
- if (inputApplicationHandle != NULL && inputApplicationHandle->update()) {
+ if (inputApplicationHandle != NULL && inputApplicationHandle->updateInfo()) {
if (mFocusedApplicationHandle != inputApplicationHandle) {
if (mFocusedApplicationHandle != NULL) {
resetTargetsLocked();
+ mFocusedApplicationHandle->releaseInfo();
}
mFocusedApplicationHandle = inputApplicationHandle;
}
} else if (mFocusedApplicationHandle != NULL) {
resetTargetsLocked();
+ mFocusedApplicationHandle->releaseInfo();
mFocusedApplicationHandle.clear();
}
@@ -3469,13 +3529,14 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
if (mFocusedApplicationHandle != NULL) {
dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
- mFocusedApplicationHandle->name.string(),
- mFocusedApplicationHandle->dispatchingTimeout / 1000000.0);
+ mFocusedApplicationHandle->getName().string(),
+ mFocusedApplicationHandle->getDispatchingTimeout(
+ DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
} else {
dump.append(INDENT "FocusedApplication: <null>\n");
}
dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
- mFocusedWindowHandle != NULL ? mFocusedWindowHandle->name.string() : "<null>");
+ mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>");
dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
@@ -3486,7 +3547,8 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTouchState.windows[i];
dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
- i, touchedWindow.windowHandle->name.string(), touchedWindow.pointerIds.value,
+ i, touchedWindow.windowHandle->getName().string(),
+ touchedWindow.pointerIds.value,
touchedWindow.targetFlags);
}
} else {
@@ -3497,26 +3559,28 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
dump.append(INDENT "Windows:\n");
for (size_t i = 0; i < mWindowHandles.size(); i++) {
const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+
dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
"visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
"frame=[%d,%d][%d,%d], scale=%f, "
"touchableRegion=",
- i, windowHandle->name.string(),
- toString(windowHandle->paused),
- toString(windowHandle->hasFocus),
- toString(windowHandle->hasWallpaper),
- toString(windowHandle->visible),
- toString(windowHandle->canReceiveKeys),
- windowHandle->layoutParamsFlags, windowHandle->layoutParamsType,
- windowHandle->layer,
- windowHandle->frameLeft, windowHandle->frameTop,
- windowHandle->frameRight, windowHandle->frameBottom,
- windowHandle->scaleFactor);
- dumpRegion(dump, windowHandle->touchableRegion);
- dump.appendFormat(", inputFeatures=0x%08x", windowHandle->inputFeatures);
+ i, windowInfo->name.string(),
+ toString(windowInfo->paused),
+ toString(windowInfo->hasFocus),
+ toString(windowInfo->hasWallpaper),
+ toString(windowInfo->visible),
+ toString(windowInfo->canReceiveKeys),
+ windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
+ windowInfo->layer,
+ windowInfo->frameLeft, windowInfo->frameTop,
+ windowInfo->frameRight, windowInfo->frameBottom,
+ windowInfo->scaleFactor);
+ dumpRegion(dump, windowInfo->touchableRegion);
+ dump.appendFormat(", inputFeatures=0x%08x", windowInfo->inputFeatures);
dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- windowHandle->ownerPid, windowHandle->ownerUid,
- windowHandle->dispatchingTimeout / 1000000.0);
+ windowInfo->ownerPid, windowInfo->ownerUid,
+ windowInfo->dispatchingTimeout / 1000000.0);
}
} else {
dump.append(INDENT "Windows: <none>\n");
@@ -3572,7 +3636,7 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
return BAD_VALUE;
}
- sp<Connection> connection = new Connection(inputChannel, inputWindowHandle);
+ sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
status_t status = connection->initialize();
if (status) {
LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
@@ -3602,39 +3666,54 @@ status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputCh
{ // acquire lock
AutoMutex _l(mLock);
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- if (connectionIndex < 0) {
- LOGW("Attempted to unregister already unregistered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
+ status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/);
+ if (status) {
+ return status;
}
+ } // release lock
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
+ // Wake the poll loop because removing the connection may have changed the current
+ // synchronization state.
+ mLooper->wake();
+ return OK;
+}
- connection->status = Connection::STATUS_ZOMBIE;
+status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
+ bool notify) {
+ ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
+ if (connectionIndex < 0) {
+ LOGW("Attempted to unregister already unregistered input channel '%s'",
+ inputChannel->getName().string());
+ return BAD_VALUE;
+ }
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- if (mMonitoringChannels[i] == inputChannel) {
- mMonitoringChannels.removeAt(i);
- break;
- }
- }
+ sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+ mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
- mLooper->removeFd(inputChannel->getReceivePipeFd());
+ if (connection->monitor) {
+ removeMonitorChannelLocked(inputChannel);
+ }
- nsecs_t currentTime = now();
- abortBrokenDispatchCycleLocked(currentTime, connection);
+ mLooper->removeFd(inputChannel->getReceivePipeFd());
- runCommandsLockedInterruptible();
- } // release lock
+ nsecs_t currentTime = now();
+ abortBrokenDispatchCycleLocked(currentTime, connection, notify);
- // Wake the poll loop because removing the connection may have changed the current
- // synchronization state.
- mLooper->wake();
+ runCommandsLockedInterruptible();
+
+ connection->status = Connection::STATUS_ZOMBIE;
return OK;
}
+void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
+ for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+ if (mMonitoringChannels[i] == inputChannel) {
+ mMonitoringChannels.removeAt(i);
+ break;
+ }
+ }
+}
+
ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
if (connectionIndex >= 0) {
@@ -3736,7 +3815,7 @@ void InputDispatcher::doNotifyANRLockedInterruptible(
resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
commandEntry->inputWindowHandle != NULL
- ? commandEntry->inputWindowHandle->inputChannel : NULL);
+ ? commandEntry->inputWindowHandle->getInputChannel() : NULL);
}
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -4495,8 +4574,9 @@ bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& mement
// --- InputDispatcher::Connection ---
InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle) :
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+ monitor(monitor),
inputPublisher(inputChannel),
lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
}
@@ -4627,8 +4707,9 @@ bool InputDispatcher::TouchState::isSlippery() const {
for (size_t i = 0; i < windows.size(); i++) {
const TouchedWindow& window = windows.itemAt(i);
if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- if (haveSlipperyForegroundWindow || !(window.windowHandle->layoutParamsFlags
- & InputWindowHandle::FLAG_SLIPPERY)) {
+ if (haveSlipperyForegroundWindow
+ || !(window.windowHandle->getInfo()->layoutParamsFlags
+ & InputWindowInfo::FLAG_SLIPPERY)) {
return false;
}
haveSlipperyForegroundWindow = true;
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 3c83691..e78f7bd 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -814,6 +814,7 @@ private:
Status status;
sp<InputChannel> inputChannel; // never null
sp<InputWindowHandle> inputWindowHandle; // may be null
+ bool monitor;
InputPublisher inputPublisher;
InputState inputState;
Queue<DispatchEntry> outboundQueue;
@@ -822,7 +823,7 @@ private:
nsecs_t lastDispatchTime; // the time when the last event was dispatched
explicit Connection(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle);
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
@@ -868,6 +869,7 @@ private:
Vector<EventEntry*> mTempCancelationEvents;
void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime);
+ void dispatchIdleLocked();
// Batches a new sample onto a motion entry.
// Assumes that the we have already checked that we can append samples.
@@ -1073,7 +1075,8 @@ private:
void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
bool handled);
void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
- void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
+ void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+ bool notify);
void drainOutboundQueueLocked(Connection* connection);
static int handleReceiveCallback(int receiveFd, int events, void* data);
@@ -1094,6 +1097,10 @@ private:
void dumpDispatchStateLocked(String8& dump);
void logDispatchStateLocked();
+ // Registration.
+ void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel);
+ status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify);
+
// Add or remove a connection to the mActiveConnections vector.
void activateConnectionLocked(Connection* connection);
void deactivateConnectionLocked(Connection* connection);
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
index 0ce8867..fe61918 100644
--- a/services/input/InputWindow.cpp
+++ b/services/input/InputWindow.cpp
@@ -22,25 +22,43 @@
namespace android {
-// --- InputWindowHandle ---
+// --- InputWindowInfo ---
-bool InputWindowHandle::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
return touchableRegion.contains(x, y);
}
-bool InputWindowHandle::frameContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
return x >= frameLeft && x <= frameRight
&& y >= frameTop && y <= frameBottom;
}
-bool InputWindowHandle::isTrustedOverlay() const {
+bool InputWindowInfo::isTrustedOverlay() const {
return layoutParamsType == TYPE_INPUT_METHOD
|| layoutParamsType == TYPE_INPUT_METHOD_DIALOG
|| layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
}
-bool InputWindowHandle::supportsSplitTouch() const {
+bool InputWindowInfo::supportsSplitTouch() const {
return layoutParamsFlags & FLAG_SPLIT_TOUCH;
}
+
+// --- InputWindowHandle ---
+
+InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+ inputApplicationHandle(inputApplicationHandle), mInfo(NULL) {
+}
+
+InputWindowHandle::~InputWindowHandle() {
+ delete mInfo;
+}
+
+void InputWindowHandle::releaseInfo() {
+ if (mInfo) {
+ delete mInfo;
+ mInfo = NULL;
+ }
+}
+
} // namespace android
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index 272081c..8861bee 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -30,15 +30,9 @@
namespace android {
/*
- * A handle to a window that can receive input.
- *
- * Used by the native input dispatcher to indirectly refer to the window manager objects
- * that describe a window.
+ * Describes the properties of a window that can receive input.
*/
-class InputWindowHandle : public RefBase {
-public:
- const sp<InputApplicationHandle> inputApplicationHandle;
-
+struct InputWindowInfo {
// Window flags from WindowManager.LayoutParams
enum {
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
@@ -116,7 +110,6 @@ public:
INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
};
- sp<InputWindowHandle> inputWindowHandle;
sp<InputChannel> inputChannel;
String8 name;
int32_t layoutParamsFlags;
@@ -149,6 +142,34 @@ public:
bool isTrustedOverlay() const;
bool supportsSplitTouch() const;
+};
+
+
+/*
+ * Handle for a window that can receive input.
+ *
+ * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * that describe a window.
+ */
+class InputWindowHandle : public RefBase {
+public:
+ const sp<InputApplicationHandle> inputApplicationHandle;
+
+ inline const InputWindowInfo* getInfo() const {
+ return mInfo;
+ }
+
+ inline sp<InputChannel> getInputChannel() const {
+ return mInfo ? mInfo->inputChannel : NULL;
+ }
+
+ inline String8 getName() const {
+ return mInfo ? mInfo->name : String8("<invalid>");
+ }
+
+ inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
+ return mInfo ? mInfo->dispatchingTimeout : defaultValue;
+ }
/**
* Requests that the state of this object be updated to reflect
@@ -159,12 +180,19 @@ public:
*
* Returns true on success, or false if the handle is no longer valid.
*/
- virtual bool update() = 0;
+ virtual bool updateInfo() = 0;
+
+ /**
+ * Releases the storage used by the associated information when it is
+ * no longer needed.
+ */
+ void releaseInfo();
protected:
- InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
- inputApplicationHandle(inputApplicationHandle) { }
- virtual ~InputWindowHandle() { }
+ InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle);
+ virtual ~InputWindowHandle();
+
+ InputWindowInfo* mInfo;
};
} // namespace android
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index b37d1c2..e622503 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -139,6 +139,9 @@ class DragState {
mServerChannel.dispose();
mClientChannel = null;
mServerChannel = null;
+
+ mDragWindowHandle = null;
+ mDragApplicationHandle = null;
}
}
diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/wm/InputApplicationHandle.java
index d78b1d9..1812f11 100644
--- a/services/java/com/android/server/wm/InputApplicationHandle.java
+++ b/services/java/com/android/server/wm/InputApplicationHandle.java
@@ -46,7 +46,10 @@ public final class InputApplicationHandle {
@Override
protected void finalize() throws Throwable {
- nativeDispose();
- super.finalize();
+ try {
+ nativeDispose();
+ } finally {
+ super.finalize();
+ }
}
}
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 12ef238..573a7d4 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -17,10 +17,10 @@
package com.android.server.wm;
import android.graphics.Rect;
-import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;
+import android.view.InputChannel;
import android.view.KeyEvent;
import android.view.WindowManager;
@@ -160,13 +160,21 @@ final class InputMonitor {
if (WindowManagerService.DEBUG_DRAG) {
Log.d(WindowManagerService.TAG, "Inserting drag window");
}
- addInputWindowHandleLw(mService.mDragState.mDragWindowHandle);
+ final InputWindowHandle dragWindowHandle = mService.mDragState.mDragWindowHandle;
+ if (dragWindowHandle != null) {
+ addInputWindowHandleLw(dragWindowHandle);
+ } else {
+ Slog.w(WindowManagerService.TAG, "Drag is in progress but there is no "
+ + "drag window handle.");
+ }
}
final int N = windows.size();
for (int i = N - 1; i >= 0; i--) {
final WindowState child = windows.get(i);
- if (child.mInputChannel == null || child.mRemoved) {
+ final InputChannel inputChannel = child.mInputChannel;
+ final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
+ if (inputChannel == null || inputWindowHandle == null || child.mRemoved) {
// Skip this window because it cannot possibly receive input.
continue;
}
@@ -186,8 +194,6 @@ final class InputMonitor {
}
// Add a window to our list of input windows.
- final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
- inputWindowHandle.inputChannel = child.mInputChannel;
inputWindowHandle.name = child.toString();
inputWindowHandle.layoutParamsFlags = flags;
inputWindowHandle.layoutParamsType = type;
diff --git a/services/java/com/android/server/wm/InputWindowHandle.java b/services/java/com/android/server/wm/InputWindowHandle.java
index abf68d9..264877c 100644
--- a/services/java/com/android/server/wm/InputWindowHandle.java
+++ b/services/java/com/android/server/wm/InputWindowHandle.java
@@ -98,7 +98,10 @@ public final class InputWindowHandle {
@Override
protected void finalize() throws Throwable {
- nativeDispose();
- super.finalize();
+ try {
+ nativeDispose();
+ } finally {
+ super.finalize();
+ }
}
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 192d32b..8bc4f81 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2051,10 +2051,11 @@ public class WindowManagerService extends IWindowManager.Stub
return res;
}
- if (outInputChannel != null) {
+ if (outInputChannel != null && (attrs.inputFeatures
+ & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
String name = win.makeInputChannelName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
- win.mInputChannel = inputChannels[0];
+ win.setInputChannel(inputChannels[0]);
inputChannels[1].transferTo(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index cdd0047..a384b03 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -1236,7 +1236,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
* Input Manager uses when discarding windows from input consideration.
*/
boolean isPotentialDragTarget() {
- return isVisibleNow() && (mInputChannel != null) && !mRemoved;
+ return isVisibleNow() && !mRemoved
+ && mInputChannel != null && mInputWindowHandle != null;
}
/**
@@ -1372,7 +1373,16 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// we are doing this as part of processing a death note.)
}
}
-
+
+ void setInputChannel(InputChannel inputChannel) {
+ if (mInputChannel != null) {
+ throw new IllegalStateException("Window already has an input channel.");
+ }
+
+ mInputChannel = inputChannel;
+ mInputWindowHandle.inputChannel = inputChannel;
+ }
+
void disposeInputChannel() {
if (mInputChannel != null) {
mService.mInputManager.unregisterInputChannel(mInputChannel);
@@ -1380,6 +1390,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mInputChannel.dispose();
mInputChannel = null;
}
+
+ mInputWindowHandle.inputChannel = null;
}
private class DeathRecipient implements IBinder.DeathRecipient {
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
index 7de67d9..c76ab53 100644
--- a/services/jni/com_android_server_InputApplicationHandle.cpp
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -49,25 +49,30 @@ jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEn
return env->NewLocalRef(mObjWeak);
}
-bool NativeInputApplicationHandle::update() {
+bool NativeInputApplicationHandle::updateInfo() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject obj = env->NewLocalRef(mObjWeak);
if (!obj) {
+ releaseInfo();
return false;
}
+ if (!mInfo) {
+ mInfo = new InputApplicationInfo();
+ }
+
jstring nameObj = jstring(env->GetObjectField(obj,
gInputApplicationHandleClassInfo.name));
if (nameObj) {
const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
- name.setTo(nameStr);
+ mInfo->name.setTo(nameStr);
env->ReleaseStringUTFChars(nameObj, nameStr);
env->DeleteLocalRef(nameObj);
} else {
- name.setTo("<null>");
+ mInfo->name.setTo("<null>");
}
- dispatchingTimeout = env->GetLongField(obj,
+ mInfo->dispatchingTimeout = env->GetLongField(obj,
gInputApplicationHandleClassInfo.dispatchingTimeoutNanos);
env->DeleteLocalRef(obj);
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
index 04cd9d6..89d48c6 100644
--- a/services/jni/com_android_server_InputApplicationHandle.h
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -31,7 +31,7 @@ public:
jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
- virtual bool update();
+ virtual bool updateInfo();
private:
jweak mObjWeak;
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 0a723e8..f976301 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -618,8 +618,9 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleO
size_t numWindows = windowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
- if (windowHandle->hasFocus && (windowHandle->inputFeatures
- & InputWindowHandle::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures
+ & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
newPointerGesturesEnabled = false;
}
}
@@ -1086,8 +1087,9 @@ static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env,
status_t status = gNativeInputManager->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);
if (status) {
- jniThrowRuntimeException(env, "Failed to register input channel. "
- "Check logs for details.");
+ String8 message;
+ message.appendFormat("Failed to register input channel. status=%d", status);
+ jniThrowRuntimeException(env, message.string());
return;
}
@@ -1113,9 +1115,10 @@ static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env
android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
- if (status) {
- jniThrowRuntimeException(env, "Failed to unregister input channel. "
- "Check logs for details.");
+ if (status && status != BAD_VALUE) { // ignore already unregistered channel
+ String8 message;
+ message.appendFormat("Failed to unregister input channel. status=%d", status);
+ jniThrowRuntimeException(env, message.string());
}
}
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
index 09be881..0607eee 100644
--- a/services/jni/com_android_server_InputWindowHandle.cpp
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -74,77 +74,82 @@ jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
return env->NewLocalRef(mObjWeak);
}
-bool NativeInputWindowHandle::update() {
+bool NativeInputWindowHandle::updateInfo() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject obj = env->NewLocalRef(mObjWeak);
if (!obj) {
+ releaseInfo();
return false;
}
+ if (!mInfo) {
+ mInfo = new InputWindowInfo();
+ }
+
jobject inputChannelObj = env->GetObjectField(obj,
gInputWindowHandleClassInfo.inputChannel);
if (inputChannelObj) {
- inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
+ mInfo->inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
env->DeleteLocalRef(inputChannelObj);
} else {
- inputChannel = NULL;
+ mInfo->inputChannel.clear();
}
jstring nameObj = jstring(env->GetObjectField(obj,
gInputWindowHandleClassInfo.name));
if (nameObj) {
const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
- name.setTo(nameStr);
+ mInfo->name.setTo(nameStr);
env->ReleaseStringUTFChars(nameObj, nameStr);
env->DeleteLocalRef(nameObj);
} else {
- name.setTo("<null>");
+ mInfo->name.setTo("<null>");
}
- layoutParamsFlags = env->GetIntField(obj,
+ mInfo->layoutParamsFlags = env->GetIntField(obj,
gInputWindowHandleClassInfo.layoutParamsFlags);
- layoutParamsType = env->GetIntField(obj,
+ mInfo->layoutParamsType = env->GetIntField(obj,
gInputWindowHandleClassInfo.layoutParamsType);
- dispatchingTimeout = env->GetLongField(obj,
+ mInfo->dispatchingTimeout = env->GetLongField(obj,
gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
- frameLeft = env->GetIntField(obj,
+ mInfo->frameLeft = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameLeft);
- frameTop = env->GetIntField(obj,
+ mInfo->frameTop = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameTop);
- frameRight = env->GetIntField(obj,
+ mInfo->frameRight = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameRight);
- frameBottom = env->GetIntField(obj,
+ mInfo->frameBottom = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameBottom);
- scaleFactor = env->GetFloatField(obj,
+ mInfo->scaleFactor = env->GetFloatField(obj,
gInputWindowHandleClassInfo.scaleFactor);
jobject regionObj = env->GetObjectField(obj,
gInputWindowHandleClassInfo.touchableRegion);
if (regionObj) {
SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
- touchableRegion.set(*region);
+ mInfo->touchableRegion.set(*region);
env->DeleteLocalRef(regionObj);
} else {
- touchableRegion.setEmpty();
+ mInfo->touchableRegion.setEmpty();
}
- visible = env->GetBooleanField(obj,
+ mInfo->visible = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.visible);
- canReceiveKeys = env->GetBooleanField(obj,
+ mInfo->canReceiveKeys = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.canReceiveKeys);
- hasFocus = env->GetBooleanField(obj,
+ mInfo->hasFocus = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.hasFocus);
- hasWallpaper = env->GetBooleanField(obj,
+ mInfo->hasWallpaper = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.hasWallpaper);
- paused = env->GetBooleanField(obj,
+ mInfo->paused = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.paused);
- layer = env->GetIntField(obj,
+ mInfo->layer = env->GetIntField(obj,
gInputWindowHandleClassInfo.layer);
- ownerPid = env->GetIntField(obj,
+ mInfo->ownerPid = env->GetIntField(obj,
gInputWindowHandleClassInfo.ownerPid);
- ownerUid = env->GetIntField(obj,
+ mInfo->ownerUid = env->GetIntField(obj,
gInputWindowHandleClassInfo.ownerUid);
- inputFeatures = env->GetIntField(obj,
+ mInfo->inputFeatures = env->GetIntField(obj,
gInputWindowHandleClassInfo.inputFeatures);
env->DeleteLocalRef(obj);
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
index 913c3b1..2cfa17d3 100644
--- a/services/jni/com_android_server_InputWindowHandle.h
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -32,7 +32,7 @@ public:
jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
- virtual bool update();
+ virtual bool updateInfo();
private:
jweak mObjWeak;