OSDN Git Service

Refactor input dispatcher use of window/app handles.
authorJeff Brown <jeffbrown@google.com>
Thu, 14 Jul 2011 05:51:29 +0000 (22:51 -0700)
committerJeff Brown <jeffbrown@google.com>
Thu, 14 Jul 2011 11:11:21 +0000 (04:11 -0700)
This change moves the cached window and application input state
into the handle objects themselves.  It simplifies the dispatcher
somewhat because it no longer needs to fix up references to
transient InputWindow objects each time the window list is updated.

This change will also make it easier to optimize setInputWindows
to avoid doing a lot of redundant data copying.  In principle, only
the modified fields need to be updated.  However, for now we
continue to update all fields in unison as before.

It turns out that the input dispatcher was inappropriately retaining
pointers to InputWindow objects within the mWindows InputWindow
vector.  This vector is copy-on-write so it is possible and the
item pointers to change if an editing operation is performed on
the vector when it does not exclusively own the underlying
SharedBuffer.  This bug was uncovered by a previous change that
replaced calls to clear() and appendVector() with a simple use
of operator= which caused the buffer to be shared.  Consequently
after editItemAt was called (which it shouldn't have, actually)
the buffer was copied and the cached InputWindow pointers became
invalid.  Oops.  This change fixes the problem.

Change-Id: I0a259339a6015fcf9113dc4081a6875e047fd425

26 files changed:
services/input/InputApplication.h
services/input/InputDispatcher.cpp
services/input/InputDispatcher.h
services/input/InputWindow.cpp
services/input/InputWindow.h
services/input/tests/InputReader_test.cpp
services/java/com/android/server/wm/AppWindowToken.java
services/java/com/android/server/wm/InputApplication.java [deleted file]
services/java/com/android/server/wm/InputApplicationHandle.java
services/java/com/android/server/wm/InputManager.java
services/java/com/android/server/wm/InputMonitor.java
services/java/com/android/server/wm/InputWindow.java [deleted file]
services/java/com/android/server/wm/InputWindowHandle.java
services/java/com/android/server/wm/InputWindowList.java [deleted file]
services/java/com/android/server/wm/WindowState.java
services/jni/Android.mk
services/jni/com_android_server_InputApplication.cpp [deleted file]
services/jni/com_android_server_InputApplication.h [deleted file]
services/jni/com_android_server_InputApplicationHandle.cpp
services/jni/com_android_server_InputApplicationHandle.h
services/jni/com_android_server_InputManager.cpp
services/jni/com_android_server_InputWindow.cpp [deleted file]
services/jni/com_android_server_InputWindow.h [deleted file]
services/jni/com_android_server_InputWindowHandle.cpp
services/jni/com_android_server_InputWindowHandle.h
services/jni/onload.cpp

index cc80062..8902f7a 100644 (file)
 namespace android {
 
 /*
- * A handle to an application that can receive input.
- * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * Describes the properties of 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;
+
+    /**
+     * Requests that the state of this object be updated to reflect
+     * the most current available information about the application.
+     *
+     * This method should only be called from within the input dispatcher's
+     * critical section.
+     *
+     * Returns true on success, or false if the handle is no longer valid.
+     */
+    virtual bool update() = 0;
+
 protected:
     InputApplicationHandle() { }
     virtual ~InputApplicationHandle() { }
 };
 
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
-    sp<InputApplicationHandle> inputApplicationHandle;
-    String8 name;
-    nsecs_t dispatchingTimeout;
-};
-
 } // namespace android
 
 #endif // _UI_INPUT_APPLICATION_H
index 10b9083..1cac502 100644 (file)
@@ -211,11 +211,8 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
     mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
     mNextUnblockedEvent(NULL),
     mDispatchEnabled(true), mDispatchFrozen(false), mInputFilterEnabled(false),
-    mFocusedWindow(NULL),
-    mFocusedApplication(NULL),
     mCurrentInputTargetsValid(false),
-    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE),
-    mLastHoverWindow(NULL) {
+    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
     mLooper = new Looper(false);
 
     mInboundQueue.headSentinel.refCount = -1;
@@ -501,16 +498,15 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
         if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
                 && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                 && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
-                && mInputTargetWaitApplication != NULL) {
+                && mInputTargetWaitApplicationHandle != NULL) {
             int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].
                     getAxisValue(AMOTION_EVENT_AXIS_X));
             int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].
                     getAxisValue(AMOTION_EVENT_AXIS_Y));
-            const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
-            if (touchedWindow
-                    && touchedWindow->inputWindowHandle != NULL
-                    && touchedWindow->inputWindowHandle->getInputApplicationHandle()
-                            != mInputTargetWaitApplication) {
+            sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y);
+            if (touchedWindowHandle != NULL
+                    && touchedWindowHandle->inputApplicationHandle
+                            != mInputTargetWaitApplicationHandle) {
                 // User touched a different application than the one we are waiting on.
                 // Flag the event, and start pruning the input queue.
                 mNextUnblockedEvent = motionEntry;
@@ -524,25 +520,25 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
     return needWake;
 }
 
-const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
     // Traverse windows from front to back to find touched window.
-    size_t numWindows = mWindows.size();
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        const InputWindow* window = & mWindows.editItemAt(i);
-        int32_t flags = window->layoutParamsFlags;
-
-        if (window->visible) {
-            if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
-                bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
-                        | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
-                if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
+        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)) {
                     // Found window.
-                    return window;
+                    return windowHandle;
                 }
             }
         }
 
-        if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+        if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
             // Error window is on top but not visible, so touch is dropped.
             return NULL;
         }
@@ -781,8 +777,8 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
         if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
             CommandEntry* commandEntry = postCommandLocked(
                     & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-            if (mFocusedWindow) {
-                commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
+            if (mFocusedWindowHandle != NULL) {
+                commandEntry->inputWindowHandle = mFocusedWindowHandle;
             }
             commandEntry->keyEntry = entry;
             entry->refCount += 1;
@@ -1011,7 +1007,7 @@ void InputDispatcher::resetTargetsLocked() {
     mCurrentInputTargetsValid = false;
     mCurrentInputTargets.clear();
     mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-    mInputTargetWaitApplication.clear();
+    mInputTargetWaitApplicationHandle.clear();
 }
 
 void InputDispatcher::commitTargetsLocked() {
@@ -1019,9 +1015,11 @@ void InputDispatcher::commitTargetsLocked() {
 }
 
 int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
-        const EventEntry* entry, const InputApplication* application, const InputWindow* window,
+        const EventEntry* entry,
+        const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle,
         nsecs_t* nextWakeupTime) {
-    if (application == NULL && window == NULL) {
+    if (applicationHandle == NULL && windowHandle == NULL) {
         if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
 #if DEBUG_FOCUS
             LOGD("Waiting for system to become ready for input.");
@@ -1030,29 +1028,29 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
             mInputTargetWaitStartTime = currentTime;
             mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
             mInputTargetWaitTimeoutExpired = false;
-            mInputTargetWaitApplication.clear();
+            mInputTargetWaitApplicationHandle.clear();
         }
     } else {
         if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
 #if DEBUG_FOCUS
             LOGD("Waiting for application to become ready for input: %s",
-                    getApplicationWindowLabelLocked(application, window).string());
+                    getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
 #endif
-            nsecs_t timeout = window ? window->dispatchingTimeout :
-                application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
+            nsecs_t timeout = windowHandle != NULL ? windowHandle->dispatchingTimeout :
+                applicationHandle != NULL ?
+                        applicationHandle->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
 
             mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
             mInputTargetWaitStartTime = currentTime;
             mInputTargetWaitTimeoutTime = currentTime + timeout;
             mInputTargetWaitTimeoutExpired = false;
-            mInputTargetWaitApplication.clear();
+            mInputTargetWaitApplicationHandle.clear();
 
-            if (window && window->inputWindowHandle != NULL) {
-                mInputTargetWaitApplication =
-                        window->inputWindowHandle->getInputApplicationHandle();
+            if (windowHandle != NULL) {
+                mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
             }
-            if (mInputTargetWaitApplication == NULL && application) {
-                mInputTargetWaitApplication = application->inputApplicationHandle;
+            if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
+                mInputTargetWaitApplicationHandle = applicationHandle;
             }
         }
     }
@@ -1062,7 +1060,8 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
     }
 
     if (currentTime >= mInputTargetWaitTimeoutTime) {
-        onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
+        onANRLocked(currentTime, applicationHandle, windowHandle,
+                entry->eventTime, mInputTargetWaitStartTime);
 
         // Force poll loop to wake up immediately on next iteration once we get the
         // ANR response back from the policy.
@@ -1129,15 +1128,15 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
 
     // If there is no currently focused window and no focused application
     // then drop the event.
-    if (! mFocusedWindow) {
-        if (mFocusedApplication) {
+    if (mFocusedWindowHandle == NULL) {
+        if (mFocusedApplicationHandle != NULL) {
 #if DEBUG_FOCUS
             LOGD("Waiting because there is no focused window but there is a "
                     "focused application that may eventually add a window: %s.",
-                    getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+                    getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
 #endif
             injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    mFocusedApplication, NULL, nextWakeupTime);
+                    mFocusedApplicationHandle, NULL, nextWakeupTime);
             goto Unresponsive;
         }
 
@@ -1147,34 +1146,34 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
     }
 
     // Check permissions.
-    if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
+    if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
         injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
         goto Failed;
     }
 
     // If the currently focused window is paused then keep waiting.
-    if (mFocusedWindow->paused) {
+    if (mFocusedWindowHandle->paused) {
 #if DEBUG_FOCUS
         LOGD("Waiting because focused window is paused.");
 #endif
         injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
+                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
         goto Unresponsive;
     }
 
     // If the currently focused window is still working on previous events then keep waiting.
-    if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
+    if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindowHandle)) {
 #if DEBUG_FOCUS
         LOGD("Waiting because focused window still processing previous input.");
 #endif
         injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
+                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
         goto Unresponsive;
     }
 
     // Success!  Output targets.
     injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-    addWindowTargetLocked(mFocusedWindow,
+    addWindowTargetLocked(mFocusedWindowHandle,
             InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0));
 
     // Done.
@@ -1236,7 +1235,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
     // Update the touch state as needed based on the properties of the touch event.
     int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
     InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
-    const InputWindow* newHoverWindow = NULL;
+    sp<InputWindowHandle> newHoverWindowHandle;
 
     bool isSplit = mTouchState.split;
     bool switchedDevice = mTouchState.deviceId >= 0
@@ -1279,42 +1278,44 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
                 getAxisValue(AMOTION_EVENT_AXIS_X));
         int32_t y = int32_t(sample->pointerCoords[pointerIndex].
                 getAxisValue(AMOTION_EVENT_AXIS_Y));
-        const InputWindow* newTouchedWindow = NULL;
-        const InputWindow* topErrorWindow = NULL;
+        sp<InputWindowHandle> newTouchedWindowHandle;
+        sp<InputWindowHandle> topErrorWindowHandle;
         bool isTouchModal = false;
 
         // Traverse windows from front to back to find touched window and outside targets.
-        size_t numWindows = mWindows.size();
+        size_t numWindows = mWindowHandles.size();
         for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.editItemAt(i);
-            int32_t flags = window->layoutParamsFlags;
+            sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+            int32_t flags = windowHandle->layoutParamsFlags;
 
-            if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
-                if (! topErrorWindow) {
-                    topErrorWindow = window;
+            if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
+                if (topErrorWindowHandle == NULL) {
+                    topErrorWindowHandle = windowHandle;
                 }
             }
 
-            if (window->visible) {
-                if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
-                    isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
-                            | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
-                    if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
-                        if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
-                            newTouchedWindow = window;
+            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 (! screenWasOff
+                                || (flags & InputWindowHandle::FLAG_TOUCHABLE_WHEN_WAKING)) {
+                            newTouchedWindowHandle = windowHandle;
                         }
                         break; // found touched window, exit window loop
                     }
                 }
 
                 if (maskedAction == AMOTION_EVENT_ACTION_DOWN
-                        && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
+                        && (flags & InputWindowHandle::FLAG_WATCH_OUTSIDE_TOUCH)) {
                     int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
-                    if (isWindowObscuredAtPointLocked(window, x, y)) {
+                    if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
                         outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
                     }
 
-                    mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
+                    mTempTouchState.addOrUpdateWindow(
+                            windowHandle, outsideTargetFlags, BitSet32(0));
                 }
             }
         }
@@ -1322,7 +1323,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
         // If there is an error window but it is not taking focus (typically because
         // it is invisible) then wait for it.  Any other focused window may in
         // fact be in ANR state.
-        if (topErrorWindow && newTouchedWindow != topErrorWindow) {
+        if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
 #if DEBUG_FOCUS
             LOGD("Waiting because system error window is pending.");
 #endif
@@ -1333,26 +1334,26 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
         }
 
         // Figure out whether splitting will be allowed for this window.
-        if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
+        if (newTouchedWindowHandle != NULL && newTouchedWindowHandle->supportsSplitTouch()) {
             // New window supports splitting.
             isSplit = true;
         } else if (isSplit) {
             // New window does not support splitting but we have already split events.
             // Assign the pointer to the first foreground window we find.
             // (May be NULL which is why we put this code block before the next check.)
-            newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
+            newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
         }
 
         // If we did not find a touched window then fail.
-        if (! newTouchedWindow) {
-            if (mFocusedApplication) {
+        if (newTouchedWindowHandle == NULL) {
+            if (mFocusedApplicationHandle != NULL) {
 #if DEBUG_FOCUS
                 LOGD("Waiting because there is no touched window but there is a "
                         "focused application that may eventually add a new window: %s.",
-                        getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+                        getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
 #endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        mFocusedApplication, NULL, nextWakeupTime);
+                        mFocusedApplicationHandle, NULL, nextWakeupTime);
                 goto Unresponsive;
             }
 
@@ -1366,20 +1367,20 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
         if (isSplit) {
             targetFlags |= InputTarget::FLAG_SPLIT;
         }
-        if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+        if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
             targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
         }
 
         // Update hover state.
         if (isHoverAction) {
-            newHoverWindow = newTouchedWindow;
+            newHoverWindowHandle = newTouchedWindowHandle;
 
             // Ensure all subsequent motion samples are also within the touched window.
             // Set *outSplitBatchAfterSample to the sample before the first one that is not
             // within the touched window.
             if (!isTouchModal) {
                 while (sample->next) {
-                    if (!newHoverWindow->touchableRegionContainsPoint(
+                    if (!newHoverWindowHandle->touchableRegionContainsPoint(
                             sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
                             sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y))) {
                         *outSplitBatchAfterSample = sample;
@@ -1389,7 +1390,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
                 }
             }
         } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
-            newHoverWindow = mLastHoverWindow;
+            newHoverWindowHandle = mLastHoverWindowHandle;
         }
 
         // Update the temporary touch state.
@@ -1398,7 +1399,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
             uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
             pointerIds.markBit(pointerId);
         }
-        mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+        mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
     } else {
         /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
 
@@ -1420,19 +1421,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
             int32_t x = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
             int32_t y = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
 
-            const InputWindow* oldTouchedWindow = mTempTouchState.getFirstForegroundWindow();
-            const InputWindow* newTouchedWindow = findTouchedWindowAtLocked(x, y);
-            if (oldTouchedWindow != newTouchedWindow && newTouchedWindow) {
+            sp<InputWindowHandle> oldTouchedWindowHandle =
+                    mTempTouchState.getFirstForegroundWindowHandle();
+            sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(x, y);
+            if (oldTouchedWindowHandle != newTouchedWindowHandle
+                    && newTouchedWindowHandle != NULL) {
 #if DEBUG_FOCUS
                 LOGD("Touch is slipping out of window %s into window %s.",
-                        oldTouchedWindow->name.string(), newTouchedWindow->name.string());
+                        oldTouchedWindowHandle->name.string(),
+                        newTouchedWindowHandle->name.string());
 #endif
                 // Make a slippery exit from the old window.
-                mTempTouchState.addOrUpdateWindow(oldTouchedWindow,
+                mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
                         InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
 
                 // Make a slippery entrance into the new window.
-                if (newTouchedWindow->supportsSplitTouch()) {
+                if (newTouchedWindowHandle->supportsSplitTouch()) {
                     isSplit = true;
                 }
 
@@ -1441,7 +1445,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
                 if (isSplit) {
                     targetFlags |= InputTarget::FLAG_SPLIT;
                 }
-                if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+                if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
                     targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
                 }
 
@@ -1449,7 +1453,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
                 if (isSplit) {
                     pointerIds.markBit(entry->pointerProperties[0].id);
                 }
-                mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+                mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
 
                 // Split the batch here so we send exactly one sample.
                 *outSplitBatchAfterSample = &entry->firstSample;
@@ -1457,25 +1461,25 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
         }
     }
 
-    if (newHoverWindow != mLastHoverWindow) {
+    if (newHoverWindowHandle != mLastHoverWindowHandle) {
         // Split the batch here so we send exactly one sample as part of ENTER or EXIT.
         *outSplitBatchAfterSample = &entry->firstSample;
 
         // Let the previous window know that the hover sequence is over.
-        if (mLastHoverWindow) {
+        if (mLastHoverWindowHandle != NULL) {
 #if DEBUG_HOVER
-            LOGD("Sending hover exit event to window %s.", mLastHoverWindow->name.string());
+            LOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->name.string());
 #endif
-            mTempTouchState.addOrUpdateWindow(mLastHoverWindow,
+            mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
                     InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
         }
 
         // Let the new window know that the hover sequence is starting.
-        if (newHoverWindow) {
+        if (newHoverWindowHandle != NULL) {
 #if DEBUG_HOVER
-            LOGD("Sending hover enter event to window %s.", newHoverWindow->name.string());
+            LOGD("Sending hover enter event to window %s.", newHoverWindowHandle->name.string());
 #endif
-            mTempTouchState.addOrUpdateWindow(newHoverWindow,
+            mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
                     InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
         }
     }
@@ -1488,7 +1492,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
             const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
             if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
                 haveForegroundWindow = true;
-                if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
+                if (! checkInjectionPermission(touchedWindow.windowHandle,
+                        entry->injectionState)) {
                     injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
                     injectionPermission = INJECTION_PERMISSION_DENIED;
                     goto Failed;
@@ -1510,14 +1515,15 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
     // Check whether windows listening for outside touches are owned by the same UID. If it is
     // set the policy flag that we will not reveal coordinate information to this window.
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
-        const int32_t foregroundWindowUid = foregroundWindow->ownerUid;
+        sp<InputWindowHandle> foregroundWindowHandle =
+                mTempTouchState.getFirstForegroundWindowHandle();
+        const int32_t foregroundWindowUid = foregroundWindowHandle->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) {
-                const InputWindow* inputWindow = touchedWindow.window;
-                if (inputWindow->ownerUid != foregroundWindowUid) {
-                    mTempTouchState.addOrUpdateWindow(inputWindow,
+                sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
+                if (inputWindowHandle->ownerUid != foregroundWindowUid) {
+                    mTempTouchState.addOrUpdateWindow(inputWindowHandle,
                             InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
                 }
             }
@@ -1529,22 +1535,22 @@ 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.window->paused) {
+            if (touchedWindow.windowHandle->paused) {
 #if DEBUG_FOCUS
                 LOGD("Waiting because touched window is paused.");
 #endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
+                        NULL, touchedWindow.windowHandle, nextWakeupTime);
                 goto Unresponsive;
             }
 
             // If the touched window is still working on previous events then keep waiting.
-            if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
+            if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
                 LOGD("Waiting because touched window still processing previous input.");
 #endif
                 injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
+                        NULL, touchedWindow.windowHandle, nextWakeupTime);
                 goto Unresponsive;
             }
         }
@@ -1557,12 +1563,13 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
     // engine only supports touch events.  We would need to add a mechanism similar
     // to View.onGenericMotionEvent to enable wallpapers to handle these events.
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
-        if (foregroundWindow->hasWallpaper) {
-            for (size_t i = 0; i < mWindows.size(); i++) {
-                const InputWindow* window = & mWindows[i];
-                if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
-                    mTempTouchState.addOrUpdateWindow(window,
+        sp<InputWindowHandle> foregroundWindowHandle =
+                mTempTouchState.getFirstForegroundWindowHandle();
+        if (foregroundWindowHandle->hasWallpaper) {
+            for (size_t i = 0; i < mWindowHandles.size(); i++) {
+                sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+                if (windowHandle->layoutParamsType == InputWindowHandle::TYPE_WALLPAPER) {
+                    mTempTouchState.addOrUpdateWindow(windowHandle,
                             InputTarget::FLAG_WINDOW_IS_OBSCURED
                                     | InputTarget::FLAG_DISPATCH_AS_IS,
                             BitSet32(0));
@@ -1576,7 +1583,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
 
     for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
         const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
-        addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
+        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                 touchedWindow.pointerIds);
     }
 
@@ -1658,7 +1665,7 @@ Failed:
             }
 
             // Update hover state.
-            mLastHoverWindow = newHoverWindow;
+            mLastHoverWindowHandle = newHoverWindowHandle;
         }
     } else {
 #if DEBUG_FOCUS
@@ -1681,16 +1688,16 @@ Unresponsive:
     return injectionResult;
 }
 
-void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-        BitSet32 pointerIds) {
+void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+        int32_t targetFlags, BitSet32 pointerIds) {
     mCurrentInputTargets.push();
 
     InputTarget& target = mCurrentInputTargets.editTop();
-    target.inputChannel = window->inputChannel;
+    target.inputChannel = windowHandle->inputChannel;
     target.flags = targetFlags;
-    target.xOffset = - window->frameLeft;
-    target.yOffset = - window->frameTop;
-    target.scaleFactor = window->scaleFactor;
+    target.xOffset = - windowHandle->frameLeft;
+    target.yOffset = - windowHandle->frameTop;
+    target.scaleFactor = windowHandle->scaleFactor;
     target.pointerIds = pointerIds;
 }
 
@@ -1708,17 +1715,17 @@ void InputDispatcher::addMonitoringTargetsLocked() {
     }
 }
 
-bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
+bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
         const InjectionState* injectionState) {
     if (injectionState
-            && (window == NULL || window->ownerUid != injectionState->injectorUid)
+            && (windowHandle == NULL || windowHandle->ownerUid != injectionState->injectorUid)
             && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
-        if (window) {
-            LOGW("Permission denied: injecting event from pid %d uid %d to window "
-                    "with input channel %s owned by uid %d",
+        if (windowHandle != NULL) {
+            LOGW("Permission denied: injecting event from pid %d uid %d to window %s "
+                    "owned by uid %d",
                     injectionState->injectorPid, injectionState->injectorUid,
-                    window->inputChannel->getName().string(),
-                    window->ownerUid);
+                    windowHandle->name.string(),
+                    windowHandle->ownerUid);
         } else {
             LOGW("Permission denied: injecting event from pid %d uid %d",
                     injectionState->injectorPid, injectionState->injectorUid);
@@ -1729,22 +1736,24 @@ bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
 }
 
 bool InputDispatcher::isWindowObscuredAtPointLocked(
-        const InputWindow* window, int32_t x, int32_t y) const {
-    size_t numWindows = mWindows.size();
+        const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        const InputWindow* other = & mWindows.itemAt(i);
-        if (other == window) {
+        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
+        if (otherHandle == windowHandle) {
             break;
         }
-        if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
+        if (otherHandle->visible && ! otherHandle->isTrustedOverlay()
+                && otherHandle->frameContainsPoint(x, y)) {
             return true;
         }
     }
     return false;
 }
 
-bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
-    ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
+bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(
+        const sp<InputWindowHandle>& windowHandle) {
+    ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->inputChannel);
     if (connectionIndex >= 0) {
         sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
         return connection->outboundQueue.isEmpty();
@@ -1753,19 +1762,20 @@ bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow*
     }
 }
 
-String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
-        const InputWindow* window) {
-    if (application) {
-        if (window) {
-            String8 label(application->name);
+String8 InputDispatcher::getApplicationWindowLabelLocked(
+        const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle) {
+    if (applicationHandle != NULL) {
+        if (windowHandle != NULL) {
+            String8 label(applicationHandle->name);
             label.append(" - ");
-            label.append(window->name);
+            label.append(windowHandle->name);
             return label;
         } else {
-            return application->name;
+            return applicationHandle->name;
         }
-    } else if (window) {
-        return window->name;
+    } else if (windowHandle != NULL) {
+        return windowHandle->name;
     } else {
         return String8("<unknown application or window>");
     }
@@ -2422,11 +2432,11 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
             }
 
             InputTarget target;
-            const InputWindow* window = getWindowLocked(connection->inputChannel);
-            if (window) {
-                target.xOffset = -window->frameLeft;
-                target.yOffset = -window->frameTop;
-                target.scaleFactor = window->scaleFactor;
+            sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
+            if (windowHandle != NULL) {
+                target.xOffset = -windowHandle->frameLeft;
+                target.yOffset = -windowHandle->frameTop;
+                target.scaleFactor = windowHandle->scaleFactor;
             } else {
                 target.xOffset = 0;
                 target.yOffset = 0;
@@ -2809,7 +2819,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
                     }
 
                     if (action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
-                        if (!mLastHoverWindow) {
+                        if (mLastHoverWindowHandle == NULL) {
 #if DEBUG_BATCHING
                             LOGD("Not streaming hover move because there is no "
                                     "last hovered window.");
@@ -2817,15 +2827,16 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
                             goto NoBatchingOrStreaming;
                         }
 
-                        const InputWindow* hoverWindow = findTouchedWindowAtLocked(
+                        sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(
                                 pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
                                 pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
-                        if (mLastHoverWindow != hoverWindow) {
+                        if (mLastHoverWindowHandle != hoverWindowHandle) {
 #if DEBUG_BATCHING
                             LOGD("Not streaming hover move because the last hovered window "
                                     "is '%s' but the currently hovered window is '%s'.",
-                                    mLastHoverWindow->name.string(),
-                                    hoverWindow ? hoverWindow->name.string() : "<null>");
+                                    mLastHoverWindowHandle->name.string(),
+                                    hoverWindowHandle != NULL
+                                            ? hoverWindowHandle->name.string() : "<null>");
 #endif
                             goto NoBatchingOrStreaming;
                         }
@@ -3125,113 +3136,109 @@ void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* ent
     }
 }
 
-const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
-    for (size_t i = 0; i < mWindows.size(); i++) {
-        const InputWindow* window = & mWindows[i];
-        if (window->inputChannel == inputChannel) {
-            return window;
+sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
+        const sp<InputChannel>& inputChannel) const {
+    size_t numWindows = mWindowHandles.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+        if (windowHandle->inputChannel == inputChannel) {
+            return windowHandle;
         }
     }
     return NULL;
 }
 
-void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
+bool InputDispatcher::hasWindowHandleLocked(
+        const sp<InputWindowHandle>& windowHandle) const {
+    size_t numWindows = mWindowHandles.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        if (mWindowHandles.itemAt(i) == windowHandle) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
 #if DEBUG_FOCUS
     LOGD("setInputWindows");
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
 
-        // Clear old window pointers.
-        sp<InputChannel> oldFocusedWindowChannel;
-        if (mFocusedWindow) {
-            oldFocusedWindowChannel = mFocusedWindow->inputChannel;
-            mFocusedWindow = NULL;
-        }
-        sp<InputChannel> oldLastHoverWindowChannel;
-        if (mLastHoverWindow) {
-            oldLastHoverWindowChannel = mLastHoverWindow->inputChannel;
-            mLastHoverWindow = NULL;
-        }
-
-        mWindows.clear();
-
-        // Loop over new windows and rebuild the necessary window pointers for
-        // tracking focus and touch.
-        mWindows.appendVector(inputWindows);
+        mWindowHandles = inputWindowHandles;
 
-        size_t numWindows = mWindows.size();
-        for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.itemAt(i);
-            if (window->hasFocus) {
-                mFocusedWindow = window;
-                break;
+        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) {
+                mWindowHandles.removeAt(i--);
+                continue;
             }
+            if (windowHandle->hasFocus) {
+                newFocusedWindowHandle = windowHandle;
+            }
+            if (windowHandle == mLastHoverWindowHandle) {
+                foundHoveredWindow = true;
+            }
+        }
+
+        if (!foundHoveredWindow) {
+            mLastHoverWindowHandle = NULL;
         }
 
-        if (oldFocusedWindowChannel != NULL) {
-            if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
+        if (mFocusedWindowHandle != newFocusedWindowHandle) {
+            if (mFocusedWindowHandle != NULL) {
 #if DEBUG_FOCUS
                 LOGD("Focus left window: %s",
-                        oldFocusedWindowChannel->getName().string());
+                        mFocusedWindowHandle->name.string());
 #endif
                 CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                         "focus left window");
-                synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel, options);
-                oldFocusedWindowChannel.clear();
+                synthesizeCancelationEventsForInputChannelLocked(
+                        mFocusedWindowHandle->inputChannel, options);
             }
-        }
-        if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
+            if (newFocusedWindowHandle != NULL) {
 #if DEBUG_FOCUS
-            LOGD("Focus entered window: %s",
-                    mFocusedWindow->inputChannel->getName().string());
+                LOGD("Focus entered window: %s",
+                        newFocusedWindowHandle->name.string());
 #endif
+            }
+            mFocusedWindowHandle = newFocusedWindowHandle;
         }
 
-        for (size_t i = 0; i < mTouchState.windows.size(); ) {
+        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
             TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
-            const InputWindow* window = getWindowLocked(touchedWindow.channel);
-            if (window) {
-                touchedWindow.window = window;
-                i += 1;
-            } else {
+            if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
-                LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
+                LOGD("Touched window was removed: %s", touchedWindow.windowHandle->name.string());
 #endif
                 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
                         "touched window was removed");
-                synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel, options);
-                mTouchState.windows.removeAt(i);
+                synthesizeCancelationEventsForInputChannelLocked(
+                        touchedWindow.windowHandle->inputChannel, options);
+                mTouchState.windows.removeAt(i--);
             }
         }
-
-        // Recover the last hovered window.
-        if (oldLastHoverWindowChannel != NULL) {
-            mLastHoverWindow = getWindowLocked(oldLastHoverWindowChannel);
-            oldLastHoverWindowChannel.clear();
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
     } // release lock
 
     // Wake up poll loop since it may need to make new input dispatching choices.
     mLooper->wake();
 }
 
-void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
+void InputDispatcher::setFocusedApplication(
+        const sp<InputApplicationHandle>& inputApplicationHandle) {
 #if DEBUG_FOCUS
     LOGD("setFocusedApplication");
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
 
-        releaseFocusedApplicationLocked();
-
-        if (inputApplication) {
-            mFocusedApplicationStorage = *inputApplication;
-            mFocusedApplication = & mFocusedApplicationStorage;
+        if (inputApplicationHandle != NULL && inputApplicationHandle->update()) {
+            mFocusedApplicationHandle = inputApplicationHandle;
+        } else {
+            mFocusedApplicationHandle.clear();
         }
 
 #if DEBUG_FOCUS
@@ -3243,13 +3250,6 @@ void InputDispatcher::setFocusedApplication(const InputApplication* inputApplica
     mLooper->wake();
 }
 
-void InputDispatcher::releaseFocusedApplicationLocked() {
-    if (mFocusedApplication) {
-        mFocusedApplication = NULL;
-        mFocusedApplicationStorage.inputApplicationHandle.clear();
-    }
-}
-
 void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
 #if DEBUG_FOCUS
     LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
@@ -3315,15 +3315,15 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
     { // acquire lock
         AutoMutex _l(mLock);
 
-        const InputWindow* fromWindow = getWindowLocked(fromChannel);
-        const InputWindow* toWindow = getWindowLocked(toChannel);
-        if (! fromWindow || ! toWindow) {
+        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
+        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
+        if (fromWindowHandle == NULL || toWindowHandle == NULL) {
 #if DEBUG_FOCUS
             LOGD("Cannot transfer focus because from or to window not found.");
 #endif
             return false;
         }
-        if (fromWindow == toWindow) {
+        if (fromWindowHandle == toWindowHandle) {
 #if DEBUG_FOCUS
             LOGD("Trivial transfer to same window.");
 #endif
@@ -3333,7 +3333,7 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
         bool found = false;
         for (size_t i = 0; i < mTouchState.windows.size(); i++) {
             const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            if (touchedWindow.window == fromWindow) {
+            if (touchedWindow.windowHandle == fromWindowHandle) {
                 int32_t oldTargetFlags = touchedWindow.targetFlags;
                 BitSet32 pointerIds = touchedWindow.pointerIds;
 
@@ -3342,7 +3342,7 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
                 int32_t newTargetFlags = oldTargetFlags
                         & (InputTarget::FLAG_FOREGROUND
                                 | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
-                mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
+                mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
 
                 found = true;
                 break;
@@ -3392,7 +3392,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
     resetTargetsLocked();
 
     mTouchState.reset();
-    mLastHoverWindow = NULL;
+    mLastHoverWindowHandle.clear();
 }
 
 void InputDispatcher::logDispatchStateLocked() {
@@ -3415,15 +3415,15 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
     dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
     dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
 
-    if (mFocusedApplication) {
+    if (mFocusedApplicationHandle != NULL) {
         dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
-                mFocusedApplication->name.string(),
-                mFocusedApplication->dispatchingTimeout / 1000000.0);
+                mFocusedApplicationHandle->name.string(),
+                mFocusedApplicationHandle->dispatchingTimeout / 1000000.0);
     } else {
         dump.append(INDENT "FocusedApplication: <null>\n");
     }
     dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
-            mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
+            mFocusedWindowHandle != NULL ? mFocusedWindowHandle->name.string() : "<null>");
 
     dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
     dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
@@ -3434,37 +3434,37 @@ 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.window->name.string(), touchedWindow.pointerIds.value,
+                    i, touchedWindow.windowHandle->name.string(), touchedWindow.pointerIds.value,
                     touchedWindow.targetFlags);
         }
     } else {
         dump.append(INDENT "TouchedWindows: <none>\n");
     }
 
-    if (!mWindows.isEmpty()) {
+    if (!mWindowHandles.isEmpty()) {
         dump.append(INDENT "Windows:\n");
-        for (size_t i = 0; i < mWindows.size(); i++) {
-            const InputWindow& window = mWindows[i];
+        for (size_t i = 0; i < mWindowHandles.size(); i++) {
+            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
             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, window.name.string(),
-                    toString(window.paused),
-                    toString(window.hasFocus),
-                    toString(window.hasWallpaper),
-                    toString(window.visible),
-                    toString(window.canReceiveKeys),
-                    window.layoutParamsFlags, window.layoutParamsType,
-                    window.layer,
-                    window.frameLeft, window.frameTop,
-                    window.frameRight, window.frameBottom,
-                    window.scaleFactor);
-            dumpRegion(dump, window.touchableRegion);
-            dump.appendFormat(", inputFeatures=0x%08x", window.inputFeatures);
+                    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);
             dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
-                    window.ownerPid, window.ownerUid,
-                    window.dispatchingTimeout / 1000000.0);
+                    windowHandle->ownerPid, windowHandle->ownerUid,
+                    windowHandle->dispatchingTimeout / 1000000.0);
         }
     } else {
         dump.append(INDENT "Windows: <none>\n");
@@ -3636,23 +3636,19 @@ void InputDispatcher::onDispatchCycleBrokenLocked(
 }
 
 void InputDispatcher::onANRLocked(
-        nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+        nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+        const sp<InputWindowHandle>& windowHandle,
         nsecs_t eventTime, nsecs_t waitStartTime) {
     LOGI("Application is not responding: %s.  "
             "%01.1fms since event, %01.1fms since wait started",
-            getApplicationWindowLabelLocked(application, window).string(),
+            getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
             (currentTime - eventTime) / 1000000.0,
             (currentTime - waitStartTime) / 1000000.0);
 
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyANRLockedInterruptible);
-    if (application) {
-        commandEntry->inputApplicationHandle = application->inputApplicationHandle;
-    }
-    if (window) {
-        commandEntry->inputWindowHandle = window->inputWindowHandle;
-        commandEntry->inputChannel = window->inputChannel;
-    }
+    commandEntry->inputApplicationHandle = applicationHandle;
+    commandEntry->inputWindowHandle = windowHandle;
 }
 
 void InputDispatcher::doNotifyConfigurationChangedInterruptible(
@@ -3686,7 +3682,9 @@ void InputDispatcher::doNotifyANRLockedInterruptible(
 
     mLock.lock();
 
-    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
+    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
+            commandEntry->inputWindowHandle != NULL
+                    ? commandEntry->inputWindowHandle->inputChannel : NULL);
 }
 
 void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -4560,11 +4558,10 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
     split = other.split;
     deviceId = other.deviceId;
     source = other.source;
-    windows.clear();
-    windows.appendVector(other.windows);
+    windows = other.windows;
 }
 
-void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
+void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
         int32_t targetFlags, BitSet32 pointerIds) {
     if (targetFlags & InputTarget::FLAG_SPLIT) {
         split = true;
@@ -4572,7 +4569,7 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
 
     for (size_t i = 0; i < windows.size(); i++) {
         TouchedWindow& touchedWindow = windows.editItemAt(i);
-        if (touchedWindow.window == window) {
+        if (touchedWindow.windowHandle == windowHandle) {
             touchedWindow.targetFlags |= targetFlags;
             if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
                 touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
@@ -4585,10 +4582,9 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
     windows.push();
 
     TouchedWindow& touchedWindow = windows.editTop();
-    touchedWindow.window = window;
+    touchedWindow.windowHandle = windowHandle;
     touchedWindow.targetFlags = targetFlags;
     touchedWindow.pointerIds = pointerIds;
-    touchedWindow.channel = window->inputChannel;
 }
 
 void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
@@ -4605,11 +4601,11 @@ void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
     }
 }
 
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() const {
+sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
     for (size_t i = 0; i < windows.size(); i++) {
         const TouchedWindow& window = windows.itemAt(i);
         if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            return window.window;
+            return window.windowHandle;
         }
     }
     return NULL;
@@ -4621,8 +4617,8 @@ 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.window->layoutParamsFlags & InputWindow::FLAG_SLIPPERY)) {
+            if (haveSlipperyForegroundWindow || !(window.windowHandle->layoutParamsFlags
+                    & InputWindowHandle::FLAG_SLIPPERY)) {
                 return false;
             }
             haveSlipperyForegroundWindow = true;
index bdd1922..15fd274 100644 (file)
@@ -321,13 +321,14 @@ public:
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) = 0;
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
 
     /* Sets the focused application.
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual void setFocusedApplication(const InputApplication* inputApplication) = 0;
+    virtual void setFocusedApplication(
+            const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
 
     /* Sets the input dispatching mode.
      *
@@ -406,8 +407,8 @@ public:
             int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
             uint32_t policyFlags);
 
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
-    virtual void setFocusedApplication(const InputApplication* inputApplication);
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
+    virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
     virtual void setInputDispatchMode(bool enabled, bool frozen);
     virtual void setInputFilterEnabled(bool enabled);
 
@@ -578,7 +579,6 @@ private:
         sp<Connection> connection;
         nsecs_t eventTime;
         KeyEntry* keyEntry;
-        sp<InputChannel> inputChannel;
         sp<InputApplicationHandle> inputApplicationHandle;
         sp<InputWindowHandle> inputWindowHandle;
         int32_t userActivityEventType;
@@ -894,7 +894,7 @@ private:
     // to transfer focus to a new application.
     EventEntry* mNextUnblockedEvent;
 
-    const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);
+    sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t x, int32_t y);
 
     // All registered connections mapped by receive pipe file descriptor.
     KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
@@ -953,19 +953,19 @@ private:
     bool mDispatchFrozen;
     bool mInputFilterEnabled;
 
-    Vector<InputWindow> mWindows;
+    Vector<sp<InputWindowHandle> > mWindowHandles;
 
-    const InputWindow* getWindowLocked(const sp<InputChannel>& inputChannel);
+    sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
+    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
 
     // Focus tracking for keys, trackball, etc.
-    const InputWindow* mFocusedWindow;
+    sp<InputWindowHandle> mFocusedWindowHandle;
 
     // Focus tracking for touch.
     struct TouchedWindow {
-        const InputWindow* window;
+        sp<InputWindowHandle> windowHandle;
         int32_t targetFlags;
         BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
-        sp<InputChannel> channel;
     };
     struct TouchState {
         bool down;
@@ -978,9 +978,10 @@ private:
         ~TouchState();
         void reset();
         void copyFrom(const TouchState& other);
-        void addOrUpdateWindow(const InputWindow* window,int32_t targetFlags, BitSet32 pointerIds);
+        void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
+                int32_t targetFlags, BitSet32 pointerIds);
         void filterNonAsIsTouchWindows();
-        const InputWindow* getFirstForegroundWindow() const;
+        sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
         bool isSlippery() const;
     };
 
@@ -988,9 +989,7 @@ private:
     TouchState mTempTouchState;
 
     // Focused application.
-    InputApplication* mFocusedApplication;
-    InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
-    void releaseFocusedApplicationLocked();
+    sp<InputApplicationHandle> mFocusedApplicationHandle;
 
     // Dispatch inbound events.
     bool dispatchConfigurationChangedLocked(
@@ -1021,16 +1020,17 @@ private:
     nsecs_t mInputTargetWaitStartTime;
     nsecs_t mInputTargetWaitTimeoutTime;
     bool mInputTargetWaitTimeoutExpired;
-    sp<InputApplicationHandle> mInputTargetWaitApplication;
+    sp<InputApplicationHandle> mInputTargetWaitApplicationHandle;
 
     // Contains the last window which received a hover event.
-    const InputWindow* mLastHoverWindow;
+    sp<InputWindowHandle> mLastHoverWindowHandle;
 
     // Finding targets for input events.
     void resetTargetsLocked();
     void commitTargetsLocked();
     int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
-            const InputApplication* application, const InputWindow* window,
+            const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle,
             nsecs_t* nextWakeupTime);
     void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
             const sp<InputChannel>& inputChannel);
@@ -1043,15 +1043,17 @@ private:
             nsecs_t* nextWakeupTime, bool* outConflictingPointerActions,
             const MotionSample** outSplitBatchAfterSample);
 
-    void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-            BitSet32 pointerIds);
+    void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+            int32_t targetFlags, BitSet32 pointerIds);
     void addMonitoringTargetsLocked();
     void pokeUserActivityLocked(const EventEntry* eventEntry);
-    bool checkInjectionPermission(const InputWindow* window, const InjectionState* injectionState);
-    bool isWindowObscuredAtPointLocked(const InputWindow* window, int32_t x, int32_t y) const;
-    bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window);
-    String8 getApplicationWindowLabelLocked(const InputApplication* application,
-            const InputWindow* window);
+    bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
+            const InjectionState* injectionState);
+    bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
+            int32_t x, int32_t y) const;
+    bool isWindowFinishedWithPreviousInputLocked(const sp<InputWindowHandle>& windowHandle);
+    String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle);
 
     // Manage the dispatch cycle for a single connection.
     // These methods are deliberately not Interruptible because doing all of the work
@@ -1100,7 +1102,8 @@ private:
     void onDispatchCycleBrokenLocked(
             nsecs_t currentTime, const sp<Connection>& connection);
     void onANRLocked(
-            nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+            nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+            const sp<InputWindowHandle>& windowHandle,
             nsecs_t eventTime, nsecs_t waitStartTime);
 
     // Outbound policy interactions.
index b552f6d..0ce8867 100644 (file)
 
 namespace android {
 
-// --- InputWindow ---
+// --- InputWindowHandle ---
 
-bool InputWindow::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowHandle::touchableRegionContainsPoint(int32_t x, int32_t y) const {
     return touchableRegion.contains(x, y);
 }
 
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowHandle::frameContainsPoint(int32_t x, int32_t y) const {
     return x >= frameLeft && x <= frameRight
             && y >= frameTop && y <= frameBottom;
 }
 
-bool InputWindow::isTrustedOverlay() const {
+bool InputWindowHandle::isTrustedOverlay() const {
     return layoutParamsType == TYPE_INPUT_METHOD
             || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
             || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
 }
 
-bool InputWindow::supportsSplitTouch() const {
-    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+bool InputWindowHandle::supportsSplitTouch() const {
+    return layoutParamsFlags & FLAG_SPLIT_TOUCH;
 }
 
 } // namespace android
index d166ad4..272081c 100644 (file)
@@ -31,29 +31,14 @@ 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.
  */
 class InputWindowHandle : public RefBase {
-protected:
-    InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
-            mInputApplicationHandle(inputApplicationHandle) { }
-    virtual ~InputWindowHandle() { }
-
 public:
-    inline sp<InputApplicationHandle> getInputApplicationHandle() {
-        return mInputApplicationHandle;
-    }
-
-private:
-    sp<InputApplicationHandle> mInputApplicationHandle;
-};
-
+    const sp<InputApplicationHandle> inputApplicationHandle;
 
-/*
- * An input window describes the bounds of a window that can receive input.
- */
-struct InputWindow {
     // Window flags from WindowManager.LayoutParams
     enum {
         FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
@@ -164,6 +149,22 @@ struct InputWindow {
     bool isTrustedOverlay() const;
 
     bool supportsSplitTouch() const;
+
+    /**
+     * Requests that the state of this object be updated to reflect
+     * the most current available information about the application.
+     *
+     * This method should only be called from within the input dispatcher's
+     * critical section.
+     *
+     * Returns true on success, or false if the handle is no longer valid.
+     */
+    virtual bool update() = 0;
+
+protected:
+    InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+            inputApplicationHandle(inputApplicationHandle) { }
+    virtual ~InputWindowHandle() { }
 };
 
 } // namespace android
index 67067de..131894a 100644 (file)
@@ -369,11 +369,12 @@ private:
         return INPUT_EVENT_INJECTION_FAILED;
     }
 
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
         ADD_FAILURE() << "Should never be called by input reader.";
     }
 
-    virtual void setFocusedApplication(const InputApplication* inputApplication) {
+    virtual void setFocusedApplication(
+            const sp<InputApplicationHandle>& inputApplicationHandle) {
         ADD_FAILURE() << "Should never be called by input reader.";
     }
 
index d3d9df4..bfa2b39 100644 (file)
@@ -101,7 +101,7 @@ class AppWindowToken extends WindowToken {
     boolean firstWindowDrawn;
 
     // Input application handle used by the input dispatcher.
-    InputApplicationHandle mInputApplicationHandle;
+    final InputApplicationHandle mInputApplicationHandle;
 
     AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
         super(_service, _token.asBinder(),
diff --git a/services/java/com/android/server/wm/InputApplication.java b/services/java/com/android/server/wm/InputApplication.java
deleted file mode 100644 (file)
index e04fd31..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2010 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;
-
-
-/**
- * Describes input-related application properties for use by the input dispatcher.
- * @hide
- */
-public final class InputApplication {
-    // Application handle.
-    public InputApplicationHandle inputApplicationHandle;
-
-    // Application name.
-    public String name;
-
-    // Dispatching timeout.
-    public long dispatchingTimeoutNanos;
-
-    public void recycle() {
-        inputApplicationHandle = null;
-    }
-}
index 64c8e7e..d78b1d9 100644 (file)
@@ -32,6 +32,12 @@ public final class InputApplicationHandle {
     // The window manager's application window token.
     public final AppWindowToken appWindowToken;
 
+    // Application name.
+    public String name;
+
+    // Dispatching timeout.
+    public long dispatchingTimeoutNanos;
+
     private native void nativeDispose();
 
     public InputApplicationHandle(AppWindowToken appWindowToken) {
index 65007f9..3133a19 100644 (file)
@@ -25,7 +25,6 @@ import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.os.Environment;
-import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.SystemProperties;
@@ -83,10 +82,10 @@ public class InputManager {
     private static native int nativeInjectInputEvent(InputEvent event,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
             int policyFlags);
-    private static native void nativeSetInputWindows(InputWindow[] windows);
+    private static native void nativeSetInputWindows(InputWindowHandle[] windowHandles);
     private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
     private static native void nativeSetSystemUiVisibility(int visibility);
-    private static native void nativeSetFocusedApplication(InputApplication application);
+    private static native void nativeSetFocusedApplication(InputApplicationHandle application);
     private static native InputDevice nativeGetInputDevice(int deviceId);
     private static native void nativeGetInputConfiguration(Configuration configuration);
     private static native int[] nativeGetInputDeviceIds();
@@ -372,11 +371,11 @@ public class InputManager {
         return nativeGetInputDeviceIds();
     }
     
-    public void setInputWindows(InputWindow[] windows) {
-        nativeSetInputWindows(windows);
+    public void setInputWindows(InputWindowHandle[] windowHandles) {
+        nativeSetInputWindows(windowHandles);
     }
     
-    public void setFocusedApplication(InputApplication application) {
+    public void setFocusedApplication(InputApplicationHandle application) {
         nativeSetFocusedApplication(application);
     }
     
index 6806634..08a3560 100644 (file)
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import android.graphics.Rect;
-import android.os.Binder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
@@ -26,6 +25,7 @@ import android.view.KeyEvent;
 import android.view.WindowManager;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 
 final class InputMonitor {
     private final WindowManagerService mService;
@@ -42,12 +42,14 @@ final class InputMonitor {
     // When true, need to call updateInputWindowsLw().
     private boolean mUpdateInputWindowsNeeded = true;
 
-    // Temporary list of windows information to provide to the input dispatcher.
-    private InputWindowList mTempInputWindows = new InputWindowList();
-    
-    // Temporary input application object to provide to the input dispatcher.
-    private InputApplication mTempInputApplication = new InputApplication();
-    
+    // Fake handles for the drag surface, lazily initialized.
+    private InputApplicationHandle mDragApplicationHandle;
+    private InputWindowHandle mDragWindowHandle;
+
+    // Array of window handles to provide to the input dispatcher.
+    private InputWindowHandle[] mInputWindowHandles;
+    private int mInputWindowHandleCount;
+
     // Set to true when the first input device configuration change notification
     // is received to indicate that the input devices are ready.
     private final Object mInputDevicesReadyMonitor = new Object();
@@ -68,8 +70,10 @@ final class InputMonitor {
 
         synchronized (mService.mWindowMap) {
             WindowState windowState = (WindowState) inputWindowHandle.windowState;
-            Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
-            mService.removeWindowLocked(windowState.mSession, windowState);
+            if (windowState != null) {
+                Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
+                mService.removeWindowLocked(windowState.mSession, windowState);
+            }
         }
     }
     
@@ -94,8 +98,11 @@ final class InputMonitor {
         
         if (appWindowToken == null && inputApplicationHandle != null) {
             appWindowToken = inputApplicationHandle.appWindowToken;
-            Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to application "
-                    + appWindowToken.stringName);
+            if (appWindowToken != null) {
+                Slog.i(WindowManagerService.TAG,
+                        "Input event dispatching timed out sending to application "
+                                + appWindowToken.stringName);
+            }
         }
 
         if (appWindowToken != null && appWindowToken.appToken != null) {
@@ -114,32 +121,59 @@ final class InputMonitor {
         return 0; // abort dispatching
     }
 
-    private void addDragInputWindowLw(InputWindowList windowList) {
-        final InputWindow inputWindow = windowList.add();
-        inputWindow.inputChannel = mService.mDragState.mServerChannel;
-        inputWindow.name = "drag";
-        inputWindow.layoutParamsFlags = 0;
-        inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
-        inputWindow.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
-        inputWindow.visible = true;
-        inputWindow.canReceiveKeys = false;
-        inputWindow.hasFocus = true;
-        inputWindow.hasWallpaper = false;
-        inputWindow.paused = false;
-        inputWindow.layer = mService.mDragState.getDragLayerLw();
-        inputWindow.ownerPid = Process.myPid();
-        inputWindow.ownerUid = Process.myUid();
-        inputWindow.inputFeatures = 0;
-        inputWindow.scaleFactor = 1.0f;
+    private void addDragInputWindowLw() {
+        if (mDragWindowHandle == null) {
+            mDragApplicationHandle = new InputApplicationHandle(null);
+            mDragApplicationHandle.name = "drag";
+            mDragApplicationHandle.dispatchingTimeoutNanos =
+                    WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null);
+            mDragWindowHandle.name = "drag";
+            mDragWindowHandle.layoutParamsFlags = 0;
+            mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
+            mDragWindowHandle.dispatchingTimeoutNanos =
+                    WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+            mDragWindowHandle.visible = true;
+            mDragWindowHandle.canReceiveKeys = false;
+            mDragWindowHandle.hasFocus = true;
+            mDragWindowHandle.hasWallpaper = false;
+            mDragWindowHandle.paused = false;
+            mDragWindowHandle.ownerPid = Process.myPid();
+            mDragWindowHandle.ownerUid = Process.myUid();
+            mDragWindowHandle.inputFeatures = 0;
+            mDragWindowHandle.scaleFactor = 1.0f;
+
+            // The drag window cannot receive new touches.
+            mDragWindowHandle.touchableRegion.setEmpty();
+        }
+
+        mDragWindowHandle.layer = mService.mDragState.getDragLayerLw();
 
         // The drag window covers the entire display
-        inputWindow.frameLeft = 0;
-        inputWindow.frameTop = 0;
-        inputWindow.frameRight = mService.mDisplay.getRealWidth();
-        inputWindow.frameBottom = mService.mDisplay.getRealHeight();
+        mDragWindowHandle.frameLeft = 0;
+        mDragWindowHandle.frameTop = 0;
+        mDragWindowHandle.frameRight = mService.mDisplay.getRealWidth();
+        mDragWindowHandle.frameBottom = mService.mDisplay.getRealHeight();
+
+        addInputWindowHandleLw(mDragWindowHandle);
+    }
 
-        // The drag window cannot receive new touches.
-        inputWindow.touchableRegion.setEmpty();
+    private void addInputWindowHandleLw(InputWindowHandle windowHandle) {
+        if (mInputWindowHandles == null) {
+            mInputWindowHandles = new InputWindowHandle[16];
+        }
+        if (mInputWindowHandleCount >= mInputWindowHandles.length) {
+            mInputWindowHandles = Arrays.copyOf(mInputWindowHandles,
+                    mInputWindowHandleCount * 2);
+        }
+        mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
+    }
+
+    private void clearInputWindowHandlesLw() {
+        while (mInputWindowHandleCount != 0) {
+            mInputWindowHandles[--mInputWindowHandleCount] = null;
+        }
     }
 
     public void setUpdateInputWindowsNeededLw() {
@@ -154,7 +188,7 @@ final class InputMonitor {
         mUpdateInputWindowsNeeded = false;
 
         if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED updateInputWindowsLw");
-        
+
         // Populate the input window list with information about all of the windows that
         // could potentially receive input.
         // As an optimization, we could try to prune the list of windows but this turns
@@ -168,7 +202,7 @@ final class InputMonitor {
             if (WindowManagerService.DEBUG_DRAG) {
                 Log.d(WindowManagerService.TAG, "Inserting drag window");
             }
-            addDragInputWindowLw(mTempInputWindows);
+            addDragInputWindowLw();
         }
 
         final int N = windows.size();
@@ -194,48 +228,48 @@ final class InputMonitor {
             }
 
             // Add a window to our list of input windows.
-            final InputWindow inputWindow = mTempInputWindows.add();
-            inputWindow.inputWindowHandle = child.mInputWindowHandle;
-            inputWindow.inputChannel = child.mInputChannel;
-            inputWindow.name = child.toString();
-            inputWindow.layoutParamsFlags = flags;
-            inputWindow.layoutParamsType = type;
-            inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
-            inputWindow.visible = isVisible;
-            inputWindow.canReceiveKeys = child.canReceiveKeys();
-            inputWindow.hasFocus = hasFocus;
-            inputWindow.hasWallpaper = hasWallpaper;
-            inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
-            inputWindow.layer = child.mLayer;
-            inputWindow.ownerPid = child.mSession.mPid;
-            inputWindow.ownerUid = child.mSession.mUid;
-            inputWindow.inputFeatures = child.mAttrs.inputFeatures;
+            final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
+            inputWindowHandle.inputChannel = child.mInputChannel;
+            inputWindowHandle.name = child.toString();
+            inputWindowHandle.layoutParamsFlags = flags;
+            inputWindowHandle.layoutParamsType = type;
+            inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
+            inputWindowHandle.visible = isVisible;
+            inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
+            inputWindowHandle.hasFocus = hasFocus;
+            inputWindowHandle.hasWallpaper = hasWallpaper;
+            inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+            inputWindowHandle.layer = child.mLayer;
+            inputWindowHandle.ownerPid = child.mSession.mPid;
+            inputWindowHandle.ownerUid = child.mSession.mUid;
+            inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
 
             final Rect frame = child.mFrame;
-            inputWindow.frameLeft = frame.left;
-            inputWindow.frameTop = frame.top;
-            inputWindow.frameRight = frame.right;
-            inputWindow.frameBottom = frame.bottom;
+            inputWindowHandle.frameLeft = frame.left;
+            inputWindowHandle.frameTop = frame.top;
+            inputWindowHandle.frameRight = frame.right;
+            inputWindowHandle.frameBottom = frame.bottom;
 
             if (child.mGlobalScale != 1) {
                 // If we are scaling the window, input coordinates need
                 // to be inversely scaled to map from what is on screen
                 // to what is actually being touched in the UI.
-                inputWindow.scaleFactor = 1.0f/child.mGlobalScale;
+                inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
             } else {
-                inputWindow.scaleFactor = 1;
+                inputWindowHandle.scaleFactor = 1;
             }
 
-            child.getTouchableRegion(inputWindow.touchableRegion);
+            child.getTouchableRegion(inputWindowHandle.touchableRegion);
+
+            addInputWindowHandleLw(inputWindowHandle);
         }
 
         // Send windows to native code.
-        mService.mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
-        
+        mService.mInputManager.setInputWindows(mInputWindowHandles);
+
         // Clear the list in preparation for the next round.
-        // Also avoids keeping InputChannel objects referenced unnecessarily.
-        mTempInputWindows.clear();
-        
+        clearInputWindowHandlesLw();
+
         if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
     }
 
@@ -329,14 +363,11 @@ final class InputMonitor {
         if (newApp == null) {
             mService.mInputManager.setFocusedApplication(null);
         } else {
-            mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
-            mTempInputApplication.name = newApp.toString();
-            mTempInputApplication.dispatchingTimeoutNanos =
-                    newApp.inputDispatchingTimeoutNanos;
-
-            mService.mInputManager.setFocusedApplication(mTempInputApplication);
+            final InputApplicationHandle handle = newApp.mInputApplicationHandle;
+            handle.name = newApp.toString();
+            handle.dispatchingTimeoutNanos = newApp.inputDispatchingTimeoutNanos;
 
-            mTempInputApplication.recycle();
+            mService.mInputManager.setFocusedApplication(handle);
         }
     }
     
diff --git a/services/java/com/android/server/wm/InputWindow.java b/services/java/com/android/server/wm/InputWindow.java
deleted file mode 100644 (file)
index 655d734..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2010 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 android.graphics.Region;
-import android.view.InputChannel;
-
-/**
- * Describes input-related window properties for use by the input dispatcher.
- * @hide
- */
-public final class InputWindow {
-    // The window handle.
-    public InputWindowHandle inputWindowHandle;
-
-    // The input channel associated with the window.
-    public InputChannel inputChannel;
-
-    // The window name.
-    public String name;
-
-    // Window layout params attributes.  (WindowManager.LayoutParams)
-    public int layoutParamsFlags;
-    public int layoutParamsType;
-
-    // Dispatching timeout.
-    public long dispatchingTimeoutNanos;
-
-    // Window frame.
-    public int frameLeft;
-    public int frameTop;
-    public int frameRight;
-    public int frameBottom;
-
-    // Global scaling factor applied to touch events when they are dispatched
-    // to the window
-    public float scaleFactor;
-
-    // Window touchable region.
-    public final Region touchableRegion = new Region();
-
-    // Window is visible.
-    public boolean visible;
-
-    // Window can receive keys.
-    public boolean canReceiveKeys;
-
-    // Window has focus.
-    public boolean hasFocus;
-
-    // Window has wallpaper.  (window is the current wallpaper target)
-    public boolean hasWallpaper;
-
-    // Input event dispatching is paused.
-    public boolean paused;
-
-    // Window layer.
-    public int layer;
-
-    // Id of process and user that owns the window.
-    public int ownerPid;
-    public int ownerUid;
-
-    // Window input features.
-    public int inputFeatures;
-
-    public void recycle() {
-        inputWindowHandle = null;
-        inputChannel = null;
-    }
-}
index cc508c6..abf68d9 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import android.graphics.Region;
+import android.view.InputChannel;
 import android.view.WindowManagerPolicy;
 
 /**
@@ -35,6 +37,57 @@ public final class InputWindowHandle {
     // The window manager's window state.
     public final WindowManagerPolicy.WindowState windowState;
 
+    // The input channel associated with the window.
+    public InputChannel inputChannel;
+
+    // The window name.
+    public String name;
+
+    // Window layout params attributes.  (WindowManager.LayoutParams)
+    public int layoutParamsFlags;
+    public int layoutParamsType;
+
+    // Dispatching timeout.
+    public long dispatchingTimeoutNanos;
+
+    // Window frame.
+    public int frameLeft;
+    public int frameTop;
+    public int frameRight;
+    public int frameBottom;
+
+    // Global scaling factor applied to touch events when they are dispatched
+    // to the window
+    public float scaleFactor;
+
+    // Window touchable region.
+    public final Region touchableRegion = new Region();
+
+    // Window is visible.
+    public boolean visible;
+
+    // Window can receive keys.
+    public boolean canReceiveKeys;
+
+    // Window has focus.
+    public boolean hasFocus;
+
+    // Window has wallpaper.  (window is the current wallpaper target)
+    public boolean hasWallpaper;
+
+    // Input event dispatching is paused.
+    public boolean paused;
+
+    // Window layer.
+    public int layer;
+
+    // Id of process and user that owns the window.
+    public int ownerPid;
+    public int ownerUid;
+
+    // Window input features.
+    public int inputFeatures;
+
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
diff --git a/services/java/com/android/server/wm/InputWindowList.java b/services/java/com/android/server/wm/InputWindowList.java
deleted file mode 100644 (file)
index 6077337..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2010 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;
-
-
-/**
- * A specialized list of window information objects backed by an array.
- * 
- * This class is part of an InputManager optimization to avoid allocating objects and arrays
- * unnecessarily.  Internally, it keeps an array full of demand-allocated objects that it
- * recycles each time the list is cleared.  The used portion of the array is padded with a null.
- * 
- * The contents of the list are intended to be Z-ordered from top to bottom.
- * 
- * @hide
- */
-public final class InputWindowList {
-    private InputWindow[] mArray;
-    private int mCount;
-    
-    /**
-     * Creates an empty list.
-     */
-    public InputWindowList() {
-        mArray = new InputWindow[8];
-    }
-    
-    /**
-     * Clears the list.
-     */
-    public void clear() {
-        if (mCount == 0) {
-            return;
-        }
-        
-        int count = mCount;
-        mCount = 0;
-        mArray[count] = mArray[0];
-        while (count > 0) {
-            count -= 1;
-            mArray[count].recycle();
-        }
-        mArray[0] = null;
-    }
-    
-    /**
-     * Adds an uninitialized input window object to the list and returns it.
-     */
-    public InputWindow add() {
-        if (mCount + 1 == mArray.length) {
-            InputWindow[] oldArray = mArray;
-            mArray = new InputWindow[oldArray.length * 2];
-            System.arraycopy(oldArray, 0, mArray, 0, mCount);
-        }
-        
-        // Grab object from tail (after used section) if available.
-        InputWindow item = mArray[mCount + 1];
-        if (item == null) {
-            item = new InputWindow();
-        }
-        
-        mArray[mCount] = item;
-        mCount += 1;
-        mArray[mCount] = null;
-        return item;
-    }
-    
-    /**
-     * Gets the input window objects as a null-terminated array.
-     * @return The input window array.
-     */
-    public InputWindow[] toNullTerminatedArray() {
-        return mArray;
-    }
-}
\ No newline at end of file
index b370ec9..d298ff7 100644 (file)
@@ -272,7 +272,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
     float mSurfaceAlpha;
     
     // Input channel and input window handle used by the input dispatcher.
-    InputWindowHandle mInputWindowHandle;
+    final InputWindowHandle mInputWindowHandle;
     InputChannel mInputChannel;
     
     // Used to improve performance of toString()
@@ -306,6 +306,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
             mIsFloatingLayer = false;
             mBaseLayer = 0;
             mSubLayer = 0;
+            mInputWindowHandle = null;
             return;
         }
         mDeathRecipient = deathRecipient;
index e1c7305..6fa5dfa 100644 (file)
@@ -4,10 +4,8 @@ include $(CLEAR_VARS)
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_BatteryService.cpp \
-    com_android_server_InputApplication.cpp \
     com_android_server_InputApplicationHandle.cpp \
     com_android_server_InputManager.cpp \
-    com_android_server_InputWindow.cpp \
     com_android_server_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
     com_android_server_PowerManagerService.cpp \
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
deleted file mode 100644 (file)
index 1f80242..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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 "JNIHelp.h"
-#include "jni.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "com_android_server_InputApplication.h"
-#include "com_android_server_InputApplicationHandle.h"
-
-namespace android {
-
-static struct {
-    jfieldID inputApplicationHandle;
-    jfieldID name;
-    jfieldID dispatchingTimeoutNanos;
-} gInputApplicationClassInfo;
-
-
-// --- Global functions ---
-
-void android_server_InputApplication_toNative(
-        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) {
-    jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj,
-            gInputApplicationClassInfo.inputApplicationHandle);
-    if (inputApplicationHandleObj) {
-        outInputApplication->inputApplicationHandle =
-                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
-        env->DeleteLocalRef(inputApplicationHandleObj);
-    } else {
-        outInputApplication->inputApplicationHandle = NULL;
-    }
-
-    jstring nameObj = jstring(env->GetObjectField(inputApplicationObj,
-            gInputApplicationClassInfo.name));
-    if (nameObj) {
-        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-        outInputApplication->name.setTo(nameStr);
-        env->ReleaseStringUTFChars(nameObj, nameStr);
-        env->DeleteLocalRef(nameObj);
-    } else {
-        LOGE("InputApplication.name should not be null.");
-        outInputApplication->name.setTo("unknown");
-    }
-
-    outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj,
-            gInputApplicationClassInfo.dispatchingTimeoutNanos);
-}
-
-
-// --- JNI ---
-
-#define FIND_CLASS(var, className) \
-        var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_InputApplication(JNIEnv* env) {
-    jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/wm/InputApplication");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
-            clazz,
-            "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.name, clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
-            clazz,
-            "dispatchingTimeoutNanos", "J");
-    return 0;
-}
-
-} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h
deleted file mode 100644 (file)
index 85fb891..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H
-#define _ANDROID_SERVER_INPUT_APPLICATION_H
-
-#include <input/InputApplication.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputApplication_toNative(
-        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_APPLICATION_H
index 9516964..7de67d9 100644 (file)
@@ -27,6 +27,8 @@ namespace android {
 
 static struct {
     jfieldID ptr;
+    jfieldID name;
+    jfieldID dispatchingTimeoutNanos;
 } gInputApplicationHandleClassInfo;
 
 static Mutex gHandleMutex;
@@ -47,6 +49,31 @@ jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEn
     return env->NewLocalRef(mObjWeak);
 }
 
+bool NativeInputApplicationHandle::update() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject obj = env->NewLocalRef(mObjWeak);
+    if (!obj) {
+        return false;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(obj,
+            gInputApplicationHandleClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        name.setTo("<null>");
+    }
+
+    dispatchingTimeout = env->GetLongField(obj,
+            gInputApplicationHandleClassInfo.dispatchingTimeoutNanos);
+
+    env->DeleteLocalRef(obj);
+    return true;
+}
+
 
 // --- Global functions ---
 
@@ -113,6 +140,13 @@ int register_android_server_InputApplicationHandle(JNIEnv* env) {
     GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
             "ptr", "I");
 
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.name, clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.dispatchingTimeoutNanos,
+            clazz,
+            "dispatchingTimeoutNanos", "J");
+
     return 0;
 }
 
index 9d18721..04cd9d6 100644 (file)
@@ -31,6 +31,8 @@ public:
 
     jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
 
+    virtual bool update();
+
 private:
     jweak mObjWeak;
 };
index 14a4109..de9c9d0 100644 (file)
@@ -46,9 +46,7 @@
 #include <android/graphics/GraphicsJNI.h>
 
 #include "com_android_server_PowerManagerService.h"
-#include "com_android_server_InputApplication.h"
 #include "com_android_server_InputApplicationHandle.h"
-#include "com_android_server_InputWindow.h"
 #include "com_android_server_InputWindowHandle.h"
 
 namespace android {
@@ -175,8 +173,8 @@ public:
             const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
-    void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
-    void setFocusedApplication(JNIEnv* env, jobject applicationObj);
+    void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray);
+    void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj);
     void setInputDispatchMode(bool enabled, bool frozen);
     void setSystemUiVisibility(int32_t visibility);
     void setPointerSpeed(int32_t speed);
@@ -582,31 +580,38 @@ bool NativeInputManager::isKeyRepeatEnabled() {
     return isScreenOn();
 }
 
-void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
-    Vector<InputWindow> windows;
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
+    Vector<sp<InputWindowHandle> > windowHandles;
 
-    bool newPointerGesturesEnabled = true;
-    jsize length = env->GetArrayLength(windowObjArray);
-    for (jsize i = 0; i < length; i++) {
-        jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
-        if (! windowObj) {
-            break; // found null element indicating end of used portion of the array
-        }
+    if (windowHandleObjArray) {
+        jsize length = env->GetArrayLength(windowHandleObjArray);
+        for (jsize i = 0; i < length; i++) {
+            jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
+            if (! windowHandleObj) {
+                break; // found null element indicating end of used portion of the array
+            }
 
-        windows.push();
-        InputWindow& window = windows.editTop();
-        android_server_InputWindow_toNative(env, windowObj, &window);
-        if (window.inputChannel == NULL) {
-            windows.pop();
-        } else if (window.hasFocus) {
-            if (window.inputFeatures & InputWindow::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES) {
-                newPointerGesturesEnabled = false;
+            sp<InputWindowHandle> windowHandle =
+                    android_server_InputWindowHandle_getHandle(env, windowHandleObj);
+            if (windowHandle != NULL) {
+                windowHandles.push(windowHandle);
             }
+            env->DeleteLocalRef(windowHandleObj);
         }
-        env->DeleteLocalRef(windowObj);
     }
 
-    mInputManager->getDispatcher()->setInputWindows(windows);
+    mInputManager->getDispatcher()->setInputWindows(windowHandles);
+
+    // Do this after the dispatcher has updated the window handle state.
+    bool newPointerGesturesEnabled = true;
+    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)) {
+            newPointerGesturesEnabled = false;
+        }
+    }
 
     uint32_t changes = 0;
     { // acquire lock
@@ -623,16 +628,10 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArra
     }
 }
 
-void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
-    if (applicationObj) {
-        InputApplication application;
-        android_server_InputApplication_toNative(env, applicationObj, &application);
-        if (application.inputApplicationHandle != NULL) {
-            mInputManager->getDispatcher()->setFocusedApplication(&application);
-            return;
-        }
-    }
-    mInputManager->getDispatcher()->setFocusedApplication(NULL);
+void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) {
+    sp<InputApplicationHandle> applicationHandle =
+            android_server_InputApplicationHandle_getHandle(env, applicationHandleObj);
+    mInputManager->getDispatcher()->setFocusedApplication(applicationHandle);
 }
 
 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -1137,21 +1136,21 @@ static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jcla
 }
 
 static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
-        jobjectArray windowObjArray) {
+        jobjectArray windowHandleObjArray) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
 
-    gNativeInputManager->setInputWindows(env, windowObjArray);
+    gNativeInputManager->setInputWindows(env, windowHandleObjArray);
 }
 
 static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
-        jobject applicationObj) {
+        jobject applicationHandleObj) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
 
-    gNativeInputManager->setFocusedApplication(env, applicationObj);
+    gNativeInputManager->setFocusedApplication(env, applicationHandleObj);
 }
 
 static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
@@ -1313,9 +1312,9 @@ static JNINativeMethod gInputManagerMethods[] = {
             (void*) android_server_InputManager_nativeSetInputFilterEnabled },
     { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIIII)I",
             (void*) android_server_InputManager_nativeInjectInputEvent },
-    { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindow;)V",
+    { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindowHandle;)V",
             (void*) android_server_InputManager_nativeSetInputWindows },
-    { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplication;)V",
+    { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplicationHandle;)V",
             (void*) android_server_InputManager_nativeSetFocusedApplication },
     { "nativeSetInputDispatchMode", "(ZZ)V",
             (void*) android_server_InputManager_nativeSetInputDispatchMode },
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
deleted file mode 100644 (file)
index 0426f63..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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 "InputWindow"
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include <android_view_InputChannel.h>
-#include <android/graphics/Region.h>
-#include "com_android_server_InputWindow.h"
-#include "com_android_server_InputWindowHandle.h"
-
-namespace android {
-
-static struct {
-    jfieldID inputWindowHandle;
-    jfieldID inputChannel;
-    jfieldID name;
-    jfieldID layoutParamsFlags;
-    jfieldID layoutParamsType;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID frameLeft;
-    jfieldID frameTop;
-    jfieldID frameRight;
-    jfieldID frameBottom;
-    jfieldID scaleFactor;
-    jfieldID touchableRegion;
-    jfieldID visible;
-    jfieldID canReceiveKeys;
-    jfieldID hasFocus;
-    jfieldID hasWallpaper;
-    jfieldID paused;
-    jfieldID layer;
-    jfieldID ownerPid;
-    jfieldID ownerUid;
-    jfieldID inputFeatures;
-} gInputWindowClassInfo;
-
-
-// --- Global functions ---
-
-void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) {
-    jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.inputWindowHandle);
-    if (inputWindowHandleObj) {
-        outInputWindow->inputWindowHandle =
-                android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
-        env->DeleteLocalRef(inputWindowHandleObj);
-    } else {
-        outInputWindow->inputWindowHandle = NULL;
-    }
-
-    jobject inputChannelObj = env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.inputChannel);
-    if (inputChannelObj) {
-        outInputWindow->inputChannel =
-                android_view_InputChannel_getInputChannel(env, inputChannelObj);
-        env->DeleteLocalRef(inputChannelObj);
-    } else {
-        outInputWindow->inputChannel = NULL;
-    }
-
-    jstring nameObj = jstring(env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.name));
-    if (nameObj) {
-        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-        outInputWindow->name.setTo(nameStr);
-        env->ReleaseStringUTFChars(nameObj, nameStr);
-        env->DeleteLocalRef(nameObj);
-    } else {
-        LOGE("InputWindow.name should not be null.");
-        outInputWindow->name.setTo("unknown");
-    }
-
-    outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.layoutParamsFlags);
-    outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.layoutParamsType);
-    outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj,
-            gInputWindowClassInfo.dispatchingTimeoutNanos);
-    outInputWindow->frameLeft = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameLeft);
-    outInputWindow->frameTop = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameTop);
-    outInputWindow->frameRight = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameRight);
-    outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.frameBottom);
-    outInputWindow->scaleFactor = env->GetFloatField(inputWindowObj,
-            gInputWindowClassInfo.scaleFactor);
-
-    jobject regionObj = env->GetObjectField(inputWindowObj,
-            gInputWindowClassInfo.touchableRegion);
-    if (regionObj) {
-        SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
-        outInputWindow->touchableRegion.set(*region);
-        env->DeleteLocalRef(regionObj);
-    } else {
-        outInputWindow->touchableRegion.setEmpty();
-    }
-
-    outInputWindow->visible = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.visible);
-    outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.canReceiveKeys);
-    outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.hasFocus);
-    outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.hasWallpaper);
-    outInputWindow->paused = env->GetBooleanField(inputWindowObj,
-            gInputWindowClassInfo.paused);
-    outInputWindow->layer = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.layer);
-    outInputWindow->ownerPid = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.ownerPid);
-    outInputWindow->ownerUid = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.ownerUid);
-    outInputWindow->inputFeatures = env->GetIntField(inputWindowObj,
-            gInputWindowClassInfo.inputFeatures);
-}
-
-
-// --- JNI ---
-
-#define FIND_CLASS(var, className) \
-        var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_InputWindow(JNIEnv* env) {
-    jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/wm/InputWindow");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, clazz,
-            "inputWindowHandle", "Lcom/android/server/wm/InputWindowHandle;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, clazz,
-            "inputChannel", "Landroid/view/InputChannel;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.name, clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, clazz,
-            "layoutParamsFlags", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, clazz,
-            "layoutParamsType", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, clazz,
-            "frameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameTop, clazz,
-            "frameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameRight, clazz,
-            "frameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, clazz,
-            "frameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.scaleFactor, clazz,
-            "scaleFactor", "F");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableRegion, clazz,
-            "touchableRegion", "Landroid/graphics/Region;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visible, clazz,
-            "visible", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, clazz,
-            "canReceiveKeys", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, clazz,
-            "hasFocus", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, clazz,
-            "hasWallpaper", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.paused, clazz,
-            "paused", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layer, clazz,
-            "layer", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, clazz,
-            "ownerPid", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, clazz,
-            "ownerUid", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputFeatures, clazz,
-            "inputFeatures", "I");
-    return 0;
-}
-
-} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h
deleted file mode 100644 (file)
index eaf7bde..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
-
-#include <input/InputWindow.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
-        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
index aaf679c..09be881 100644 (file)
@@ -21,6 +21,9 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/threads.h>
 
+#include <android_view_InputChannel.h>
+#include <android/graphics/Region.h>
+
 #include "com_android_server_InputWindowHandle.h"
 #include "com_android_server_InputApplicationHandle.h"
 
@@ -29,6 +32,26 @@ namespace android {
 static struct {
     jfieldID ptr;
     jfieldID inputApplicationHandle;
+    jfieldID inputChannel;
+    jfieldID name;
+    jfieldID layoutParamsFlags;
+    jfieldID layoutParamsType;
+    jfieldID dispatchingTimeoutNanos;
+    jfieldID frameLeft;
+    jfieldID frameTop;
+    jfieldID frameRight;
+    jfieldID frameBottom;
+    jfieldID scaleFactor;
+    jfieldID touchableRegion;
+    jfieldID visible;
+    jfieldID canReceiveKeys;
+    jfieldID hasFocus;
+    jfieldID hasWallpaper;
+    jfieldID paused;
+    jfieldID layer;
+    jfieldID ownerPid;
+    jfieldID ownerUid;
+    jfieldID inputFeatures;
 } gInputWindowHandleClassInfo;
 
 static Mutex gHandleMutex;
@@ -51,6 +74,83 @@ jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
     return env->NewLocalRef(mObjWeak);
 }
 
+bool NativeInputWindowHandle::update() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject obj = env->NewLocalRef(mObjWeak);
+    if (!obj) {
+        return false;
+    }
+
+    jobject inputChannelObj = env->GetObjectField(obj,
+            gInputWindowHandleClassInfo.inputChannel);
+    if (inputChannelObj) {
+        inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
+        env->DeleteLocalRef(inputChannelObj);
+    } else {
+        inputChannel = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(obj,
+            gInputWindowHandleClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        name.setTo("<null>");
+    }
+
+    layoutParamsFlags = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.layoutParamsFlags);
+    layoutParamsType = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.layoutParamsType);
+    dispatchingTimeout = env->GetLongField(obj,
+            gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
+    frameLeft = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameLeft);
+    frameTop = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameTop);
+    frameRight = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameRight);
+    frameBottom = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.frameBottom);
+    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);
+        env->DeleteLocalRef(regionObj);
+    } else {
+        touchableRegion.setEmpty();
+    }
+
+    visible = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.visible);
+    canReceiveKeys = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.canReceiveKeys);
+    hasFocus = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.hasFocus);
+    hasWallpaper = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.hasWallpaper);
+    paused = env->GetBooleanField(obj,
+            gInputWindowHandleClassInfo.paused);
+    layer = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.layer);
+    ownerPid = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.ownerPid);
+    ownerUid = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.ownerUid);
+    inputFeatures = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.inputFeatures);
+
+    env->DeleteLocalRef(obj);
+    return true;
+}
+
 
 // --- Global functions ---
 
@@ -127,6 +227,65 @@ int register_android_server_InputWindowHandle(JNIEnv* env) {
             clazz,
             "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
 
+    GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
+            "inputChannel", "Landroid/view/InputChannel;");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz,
+            "layoutParamsFlags", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz,
+            "layoutParamsType", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz,
+            "dispatchingTimeoutNanos", "J");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameLeft, clazz,
+            "frameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameTop, clazz,
+            "frameTop", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameRight, clazz,
+            "frameRight", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz,
+            "frameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz,
+            "scaleFactor", "F");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz,
+            "touchableRegion", "Landroid/graphics/Region;");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz,
+            "visible", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz,
+            "canReceiveKeys", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz,
+            "hasFocus", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz,
+            "hasWallpaper", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
+            "paused", "Z");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz,
+            "layer", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
+            "ownerPid", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ownerUid, clazz,
+            "ownerUid", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz,
+            "inputFeatures", "I");
     return 0;
 }
 
index 43f2a6b..913c3b1 100644 (file)
@@ -32,6 +32,8 @@ public:
 
     jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
 
+    virtual bool update();
+
 private:
     jweak mObjWeak;
 };
index 9dff48b..4178039 100644 (file)
@@ -22,9 +22,7 @@
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryService(JNIEnv* env);
-int register_android_server_InputApplication(JNIEnv* env);
 int register_android_server_InputApplicationHandle(JNIEnv* env);
-int register_android_server_InputWindow(JNIEnv* env);
 int register_android_server_InputWindowHandle(JNIEnv* env);
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
@@ -51,9 +49,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
     LOG_ASSERT(env, "Could not retrieve the env!");
 
     register_android_server_PowerManagerService(env);
-    register_android_server_InputApplication(env);
     register_android_server_InputApplicationHandle(env);
-    register_android_server_InputWindow(env);
     register_android_server_InputWindowHandle(env);
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);