summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/input/Android.mk1
-rw-r--r--services/input/InputApplication.h51
-rw-r--r--services/input/InputDispatcher.cpp156
-rw-r--r--services/input/InputDispatcher.h167
-rw-r--r--services/input/InputWindow.cpp47
-rw-r--r--services/input/InputWindow.h164
-rw-r--r--services/input/tests/InputDispatcher_test.cpp8
-rw-r--r--services/input/tests/InputReader_test.cpp3
-rw-r--r--services/java/com/android/server/InputApplication.java13
-rw-r--r--services/java/com/android/server/InputApplicationHandle.java45
-rw-r--r--services/java/com/android/server/InputManager.java25
-rw-r--r--services/java/com/android/server/InputWindow.java33
-rw-r--r--services/java/com/android/server/InputWindowHandle.java51
-rw-r--r--services/java/com/android/server/WindowManagerService.java69
-rw-r--r--services/jni/Android.mk4
-rw-r--r--services/jni/com_android_server_InputApplication.cpp95
-rw-r--r--services/jni/com_android_server_InputApplication.h32
-rw-r--r--services/jni/com_android_server_InputApplicationHandle.cpp121
-rw-r--r--services/jni/com_android_server_InputApplicationHandle.h44
-rw-r--r--services/jni/com_android_server_InputManager.cpp495
-rw-r--r--services/jni/com_android_server_InputWindow.cpp240
-rw-r--r--services/jni/com_android_server_InputWindow.h32
-rw-r--r--services/jni/com_android_server_InputWindowHandle.cpp135
-rw-r--r--services/jni/com_android_server_InputWindowHandle.h45
-rw-r--r--services/jni/onload.cpp8
25 files changed, 1426 insertions, 658 deletions
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 37804ff66d31..d7b61fc9592e 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -21,6 +21,7 @@ LOCAL_SRC_FILES:= \
InputDispatcher.cpp \
InputManager.cpp \
InputReader.cpp \
+ InputWindow.cpp \
PointerController.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/services/input/InputApplication.h b/services/input/InputApplication.h
new file mode 100644
index 000000000000..cc8006217c11
--- /dev/null
+++ b/services/input/InputApplication.h
@@ -0,0 +1,51 @@
+/*
+ * 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 _UI_INPUT_APPLICATION_H
+#define _UI_INPUT_APPLICATION_H
+
+#include <ui/Input.h>
+
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+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
+ * that describe an application.
+ */
+class InputApplicationHandle : public RefBase {
+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
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 89a7751a35fd..b5a4bd2da0c7 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -72,6 +72,10 @@ const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
// when an application takes too long to respond and the user has pressed an app switch key.
const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
+// Amount of time to allow for an event to be dispatched (measured since its eventTime)
+// before considering it stale and dropping it.
+const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
+
static inline nsecs_t now() {
return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -151,34 +155,12 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount,
}
-// --- InputWindow ---
-
-bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
- return x >= touchableAreaLeft && x <= touchableAreaRight
- && y >= touchableAreaTop && y <= touchableAreaBottom;
-}
-
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x <= frameRight
- && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindow::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;
-}
-
-
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
mPolicy(policy),
- mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
+ mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
+ mNextUnblockedEvent(NULL),
mDispatchEnabled(true), mDispatchFrozen(false),
mFocusedWindow(NULL),
mFocusedApplication(NULL),
@@ -368,6 +350,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
}
// Now we have an event to dispatch.
+ // All events are eventually dequeued and processed this way, even if we intend to drop them.
assert(mPendingEvent != NULL);
bool done = false;
DropReason dropReason = DROP_REASON_NOT_DROPPED;
@@ -376,6 +359,11 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
} else if (!mDispatchEnabled) {
dropReason = DROP_REASON_DISABLED;
}
+
+ if (mNextUnblockedEvent == mPendingEvent) {
+ mNextUnblockedEvent = NULL;
+ }
+
switch (mPendingEvent->type) {
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
@@ -395,6 +383,13 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
dropReason = DROP_REASON_APP_SWITCH;
}
}
+ if (dropReason == DROP_REASON_NOT_DROPPED
+ && isStaleEventLocked(currentTime, typedEntry)) {
+ dropReason = DROP_REASON_STALE;
+ }
+ if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+ dropReason = DROP_REASON_BLOCKED;
+ }
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
&dropReason, nextWakeupTime);
break;
@@ -405,6 +400,13 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
+ if (dropReason == DROP_REASON_NOT_DROPPED
+ && isStaleEventLocked(currentTime, typedEntry)) {
+ dropReason = DROP_REASON_STALE;
+ }
+ if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+ dropReason = DROP_REASON_BLOCKED;
+ }
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
@@ -431,6 +433,9 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
switch (entry->type) {
case EventEntry::TYPE_KEY: {
+ // Optimize app switch latency.
+ // If the application takes too long to catch up then we drop all events preceding
+ // the app switch key.
KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
if (isAppSwitchKeyEventLocked(keyEntry)) {
if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
@@ -448,11 +453,63 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
}
break;
}
+
+ case EventEntry::TYPE_MOTION: {
+ // Optimize case where the current application is unresponsive and the user
+ // decides to touch a window in a different application.
+ // If the application takes too long to catch up then we drop all events preceding
+ // the touch into the other window.
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+ if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
+ && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+ && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
+ && mInputTargetWaitApplication != NULL) {
+ int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].x);
+ int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].y);
+ const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
+ if (touchedWindow
+ && touchedWindow->inputWindowHandle != NULL
+ && touchedWindow->inputWindowHandle->getInputApplicationHandle()
+ != mInputTargetWaitApplication) {
+ // User touched a different application than the one we are waiting on.
+ // Flag the event, and start pruning the input queue.
+ mNextUnblockedEvent = motionEntry;
+ needWake = true;
+ }
+ }
+ break;
+ }
}
return needWake;
}
+const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+ // Traverse windows from front to back to find touched window.
+ size_t numWindows = mWindows.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->touchableAreaContainsPoint(x, y)) {
+ // Found window.
+ return window;
+ }
+ }
+ }
+
+ if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+ // Error window is on top but not visible, so touch is dropped.
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
const char* reason;
switch (dropReason) {
@@ -470,6 +527,16 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR
LOGI("Dropped event because of pending overdue app switch.");
reason = "inbound event was dropped because of pending overdue app switch";
break;
+ case DROP_REASON_BLOCKED:
+ LOGI("Dropped event because the current application is not responding and the user "
+ "has started interating with a different application.");
+ reason = "inbound event was dropped because the current application is not responding "
+ "and the user has started interating with a different application";
+ break;
+ case DROP_REASON_STALE:
+ LOGI("Dropped event because it is stale.");
+ reason = "inbound event was dropped because it is stale";
+ break;
default:
assert(false);
return;
@@ -521,6 +588,10 @@ void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
#endif
}
+bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
+ return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
+}
+
bool InputDispatcher::runCommandsLockedInterruptible() {
if (mCommandQueue.isEmpty()) {
return false;
@@ -670,7 +741,7 @@ bool InputDispatcher::dispatchKeyLocked(
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
if (mFocusedWindow) {
- commandEntry->inputChannel = mFocusedWindow->inputChannel;
+ commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
@@ -848,6 +919,7 @@ void InputDispatcher::resetTargetsLocked() {
mCurrentInputTargetsValid = false;
mCurrentInputTargets.clear();
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+ mInputTargetWaitApplication.clear();
}
void InputDispatcher::commitTargetsLocked() {
@@ -866,6 +938,7 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
mInputTargetWaitTimeoutExpired = false;
+ mInputTargetWaitApplication.clear();
}
} else {
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
@@ -880,6 +953,15 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = currentTime + timeout;
mInputTargetWaitTimeoutExpired = false;
+ mInputTargetWaitApplication.clear();
+
+ if (window && window->inputWindowHandle != NULL) {
+ mInputTargetWaitApplication =
+ window->inputWindowHandle->getInputApplicationHandle();
+ }
+ if (mInputTargetWaitApplication == NULL && application) {
+ mInputTargetWaitApplication = application->inputApplicationHandle;
+ }
}
}
@@ -2624,7 +2706,7 @@ void InputDispatcher::setFocusedApplication(const InputApplication* inputApplica
void InputDispatcher::releaseFocusedApplicationLocked() {
if (mFocusedApplication) {
mFocusedApplication = NULL;
- mFocusedApplicationStorage.handle.clear();
+ mFocusedApplicationStorage.inputApplicationHandle.clear();
}
}
@@ -2860,7 +2942,8 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
}
}
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
#if DEBUG_REGISTRATION
LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
toString(monitor));
@@ -2875,7 +2958,7 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
return BAD_VALUE;
}
- sp<Connection> connection = new Connection(inputChannel);
+ sp<Connection> connection = new Connection(inputChannel, inputWindowHandle);
status_t status = connection->initialize();
if (status) {
LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
@@ -3002,9 +3085,10 @@ void InputDispatcher::onANRLocked(
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doNotifyANRLockedInterruptible);
if (application) {
- commandEntry->inputApplicationHandle = application->handle;
+ commandEntry->inputApplicationHandle = application->inputApplicationHandle;
}
if (window) {
+ commandEntry->inputWindowHandle = window->inputWindowHandle;
commandEntry->inputChannel = window->inputChannel;
}
}
@@ -3025,7 +3109,7 @@ void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
if (connection->status != Connection::STATUS_ZOMBIE) {
mLock.unlock();
- mPolicy->notifyInputChannelBroken(connection->inputChannel);
+ mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
mLock.lock();
}
@@ -3036,7 +3120,7 @@ void InputDispatcher::doNotifyANRLockedInterruptible(
mLock.unlock();
nsecs_t newTimeout = mPolicy->notifyANR(
- commandEntry->inputApplicationHandle, commandEntry->inputChannel);
+ commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
mLock.lock();
@@ -3052,7 +3136,7 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
mLock.unlock();
- bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
+ bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
&event, entry->policyFlags);
mLock.lock();
@@ -3095,7 +3179,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
mLock.unlock();
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
+ bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
&event, keyEntry->policyFlags, &event);
mLock.lock();
@@ -3604,8 +3688,10 @@ bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& mement
// --- InputDispatcher::Connection ---
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
- status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle) :
+ status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+ inputPublisher(inputChannel),
lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
}
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index c8beab2aabae..11e511732061 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -33,6 +33,9 @@
#include <unistd.h>
#include <limits.h>
+#include "InputWindow.h"
+#include "InputApplication.h"
+
namespace android {
@@ -116,137 +119,6 @@ struct InputTarget {
/*
- * 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,
- FLAG_DIM_BEHIND = 0x00000002,
- FLAG_BLUR_BEHIND = 0x00000004,
- FLAG_NOT_FOCUSABLE = 0x00000008,
- FLAG_NOT_TOUCHABLE = 0x00000010,
- FLAG_NOT_TOUCH_MODAL = 0x00000020,
- FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
- FLAG_KEEP_SCREEN_ON = 0x00000080,
- FLAG_LAYOUT_IN_SCREEN = 0x00000100,
- FLAG_LAYOUT_NO_LIMITS = 0x00000200,
- FLAG_FULLSCREEN = 0x00000400,
- FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
- FLAG_DITHER = 0x00001000,
- FLAG_SECURE = 0x00002000,
- FLAG_SCALED = 0x00004000,
- FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
- FLAG_LAYOUT_INSET_DECOR = 0x00010000,
- FLAG_ALT_FOCUSABLE_IM = 0x00020000,
- FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
- FLAG_SHOW_WHEN_LOCKED = 0x00080000,
- FLAG_SHOW_WALLPAPER = 0x00100000,
- FLAG_TURN_SCREEN_ON = 0x00200000,
- FLAG_DISMISS_KEYGUARD = 0x00400000,
- FLAG_SPLIT_TOUCH = 0x00800000,
- FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
- FLAG_COMPATIBLE_WINDOW = 0x20000000,
- FLAG_SYSTEM_ERROR = 0x40000000,
- };
-
- // Window types from WindowManager.LayoutParams
- enum {
- FIRST_APPLICATION_WINDOW = 1,
- TYPE_BASE_APPLICATION = 1,
- TYPE_APPLICATION = 2,
- TYPE_APPLICATION_STARTING = 3,
- LAST_APPLICATION_WINDOW = 99,
- FIRST_SUB_WINDOW = 1000,
- TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
- TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
- TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
- TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
- TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
- LAST_SUB_WINDOW = 1999,
- FIRST_SYSTEM_WINDOW = 2000,
- TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
- TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
- TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
- TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
- TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
- TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
- TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
- TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
- TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
- TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
- TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
- TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
- TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
- TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
- TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+14,
- TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
- TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
- TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+17,
- LAST_SYSTEM_WINDOW = 2999,
- };
-
- sp<InputChannel> inputChannel;
- String8 name;
- int32_t layoutParamsFlags;
- int32_t layoutParamsType;
- nsecs_t dispatchingTimeout;
- int32_t frameLeft;
- int32_t frameTop;
- int32_t frameRight;
- int32_t frameBottom;
- int32_t visibleFrameLeft;
- int32_t visibleFrameTop;
- int32_t visibleFrameRight;
- int32_t visibleFrameBottom;
- int32_t touchableAreaLeft;
- int32_t touchableAreaTop;
- int32_t touchableAreaRight;
- int32_t touchableAreaBottom;
- bool visible;
- bool canReceiveKeys;
- bool hasFocus;
- bool hasWallpaper;
- bool paused;
- int32_t layer;
- int32_t ownerPid;
- int32_t ownerUid;
-
- bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
- bool frameContainsPoint(int32_t x, int32_t y) const;
-
- /* Returns true if the window is of a trusted type that is allowed to silently
- * overlay other windows for the purpose of implementing the secure views feature.
- * Trusted overlays, such as IME windows, can partly obscure other windows without causing
- * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
- */
- bool isTrustedOverlay() const;
-
- bool supportsSplitTouch() const;
-};
-
-
-/*
- * A private handle type used by the input manager to track the window.
- */
-class InputApplicationHandle : public RefBase {
-protected:
- InputApplicationHandle() { }
- virtual ~InputApplicationHandle() { }
-};
-
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
- String8 name;
- nsecs_t dispatchingTimeout;
- sp<InputApplicationHandle> handle;
-};
-
-
-/*
* Input dispatcher policy interface.
*
* The input reader policy is used by the input reader to interact with the Window Manager
@@ -267,10 +139,10 @@ public:
/* Notifies the system that an application is not responding.
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel) = 0;
+ const sp<InputWindowHandle>& inputWindowHandle) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */
- virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
+ virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
/* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
virtual nsecs_t getKeyRepeatTimeout() = 0;
@@ -303,12 +175,12 @@ public:
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
- virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+ virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
/* Allows the policy a chance to perform default processing for an unhandled key.
* Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
- virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+ virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
/* Notifies the policy about switch events.
@@ -407,7 +279,8 @@ public:
*
* These methods may be called on any thread (usually by the input manager).
*/
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) = 0;
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
};
@@ -461,7 +334,8 @@ public:
virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel);
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
private:
@@ -615,6 +489,7 @@ private:
KeyEntry* keyEntry;
sp<InputChannel> inputChannel;
sp<InputApplicationHandle> inputApplicationHandle;
+ sp<InputWindowHandle> inputWindowHandle;
int32_t userActivityEventType;
bool handled;
};
@@ -815,7 +690,8 @@ private:
};
Status status;
- sp<InputChannel> inputChannel;
+ sp<InputChannel> inputChannel; // never null
+ sp<InputWindowHandle> inputWindowHandle; // may be null
InputPublisher inputPublisher;
InputState inputState;
Queue<DispatchEntry> outboundQueue;
@@ -823,7 +699,8 @@ private:
nsecs_t lastEventTime; // the time when the event was originally captured
nsecs_t lastDispatchTime; // the time when the last event was dispatched
- explicit Connection(const sp<InputChannel>& inputChannel);
+ explicit Connection(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle);
inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
@@ -851,6 +728,8 @@ private:
DROP_REASON_POLICY = 1,
DROP_REASON_APP_SWITCH = 2,
DROP_REASON_DISABLED = 3,
+ DROP_REASON_BLOCKED = 4,
+ DROP_REASON_STALE = 5,
};
sp<InputDispatcherPolicyInterface> mPolicy;
@@ -884,6 +763,15 @@ private:
bool isAppSwitchPendingLocked();
void resetPendingAppSwitchLocked(bool handled);
+ // Stale event latency optimization.
+ static bool isStaleEventLocked(nsecs_t currentTime, EventEntry* entry);
+
+ // Blocked event latency optimization. Drops old events when the user intends
+ // to transfer focus to a new application.
+ EventEntry* mNextUnblockedEvent;
+
+ const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);
+
// All registered connections mapped by receive pipe file descriptor.
KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
@@ -1006,6 +894,7 @@ private:
nsecs_t mInputTargetWaitStartTime;
nsecs_t mInputTargetWaitTimeoutTime;
bool mInputTargetWaitTimeoutExpired;
+ sp<InputApplicationHandle> mInputTargetWaitApplication;
// Finding targets for input events.
void resetTargetsLocked();
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
new file mode 100644
index 000000000000..9ce45f50513c
--- /dev/null
+++ b/services/input/InputWindow.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "InputWindow.h"
+
+#include <cutils/log.h>
+
+namespace android {
+
+// --- InputWindow ---
+
+bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
+ return x >= touchableAreaLeft && x <= touchableAreaRight
+ && y >= touchableAreaTop && y <= touchableAreaBottom;
+}
+
+bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
+ return x >= frameLeft && x <= frameRight
+ && y >= frameTop && y <= frameBottom;
+}
+
+bool InputWindow::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;
+}
+
+} // namespace android
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
new file mode 100644
index 000000000000..b3d5a651ba75
--- /dev/null
+++ b/services/input/InputWindow.h
@@ -0,0 +1,164 @@
+/*
+ * 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 _UI_INPUT_WINDOW_H
+#define _UI_INPUT_WINDOW_H
+
+#include <ui/Input.h>
+#include <ui/InputTransport.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+#include "InputApplication.h"
+
+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;
+};
+
+
+/*
+ * 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,
+ FLAG_DIM_BEHIND = 0x00000002,
+ FLAG_BLUR_BEHIND = 0x00000004,
+ FLAG_NOT_FOCUSABLE = 0x00000008,
+ FLAG_NOT_TOUCHABLE = 0x00000010,
+ FLAG_NOT_TOUCH_MODAL = 0x00000020,
+ FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
+ FLAG_KEEP_SCREEN_ON = 0x00000080,
+ FLAG_LAYOUT_IN_SCREEN = 0x00000100,
+ FLAG_LAYOUT_NO_LIMITS = 0x00000200,
+ FLAG_FULLSCREEN = 0x00000400,
+ FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
+ FLAG_DITHER = 0x00001000,
+ FLAG_SECURE = 0x00002000,
+ FLAG_SCALED = 0x00004000,
+ FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
+ FLAG_LAYOUT_INSET_DECOR = 0x00010000,
+ FLAG_ALT_FOCUSABLE_IM = 0x00020000,
+ FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
+ FLAG_SHOW_WHEN_LOCKED = 0x00080000,
+ FLAG_SHOW_WALLPAPER = 0x00100000,
+ FLAG_TURN_SCREEN_ON = 0x00200000,
+ FLAG_DISMISS_KEYGUARD = 0x00400000,
+ FLAG_SPLIT_TOUCH = 0x00800000,
+ FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
+ FLAG_COMPATIBLE_WINDOW = 0x20000000,
+ FLAG_SYSTEM_ERROR = 0x40000000,
+ };
+
+ // Window types from WindowManager.LayoutParams
+ enum {
+ FIRST_APPLICATION_WINDOW = 1,
+ TYPE_BASE_APPLICATION = 1,
+ TYPE_APPLICATION = 2,
+ TYPE_APPLICATION_STARTING = 3,
+ LAST_APPLICATION_WINDOW = 99,
+ FIRST_SUB_WINDOW = 1000,
+ TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
+ TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
+ TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
+ TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
+ TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
+ LAST_SUB_WINDOW = 1999,
+ FIRST_SYSTEM_WINDOW = 2000,
+ TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
+ TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
+ TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
+ TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
+ TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
+ TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
+ TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
+ TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
+ TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
+ TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
+ TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
+ TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
+ TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
+ TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
+ TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+14,
+ TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
+ TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
+ TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+17,
+ LAST_SYSTEM_WINDOW = 2999,
+ };
+
+ sp<InputWindowHandle> inputWindowHandle;
+ sp<InputChannel> inputChannel;
+ String8 name;
+ int32_t layoutParamsFlags;
+ int32_t layoutParamsType;
+ nsecs_t dispatchingTimeout;
+ int32_t frameLeft;
+ int32_t frameTop;
+ int32_t frameRight;
+ int32_t frameBottom;
+ int32_t visibleFrameLeft;
+ int32_t visibleFrameTop;
+ int32_t visibleFrameRight;
+ int32_t visibleFrameBottom;
+ int32_t touchableAreaLeft;
+ int32_t touchableAreaTop;
+ int32_t touchableAreaRight;
+ int32_t touchableAreaBottom;
+ bool visible;
+ bool canReceiveKeys;
+ bool hasFocus;
+ bool hasWallpaper;
+ bool paused;
+ int32_t layer;
+ int32_t ownerPid;
+ int32_t ownerUid;
+
+ bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
+ bool frameContainsPoint(int32_t x, int32_t y) const;
+
+ /* Returns true if the window is of a trusted type that is allowed to silently
+ * overlay other windows for the purpose of implementing the secure views feature.
+ * Trusted overlays, such as IME windows, can partly obscure other windows without causing
+ * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
+ */
+ bool isTrustedOverlay() const;
+
+ bool supportsSplitTouch() const;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_WINDOW_H
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index b79633ad5afe..5ba18671441e 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -36,11 +36,11 @@ private:
}
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel) {
+ const sp<InputWindowHandle>& inputWindowHandle) {
return 0;
}
- virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+ virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
}
virtual nsecs_t getKeyRepeatTimeout() {
@@ -61,12 +61,12 @@ private:
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
}
- virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+ virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
return false;
}
- virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+ virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
return false;
}
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 9d2c52f07809..8ec6f534274d 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -368,7 +368,8 @@ private:
return 0;
}
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
ADD_FAILURE() << "Should never be called by input reader.";
return 0;
}
diff --git a/services/java/com/android/server/InputApplication.java b/services/java/com/android/server/InputApplication.java
index 38420d4f899f..ae0948441757 100644
--- a/services/java/com/android/server/InputApplication.java
+++ b/services/java/com/android/server/InputApplication.java
@@ -18,16 +18,19 @@ package com.android.server;
/**
* 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;
-
- // The application window token.
- public Object token;
+
+ public void recycle() {
+ inputApplicationHandle = null;
+ }
}
diff --git a/services/java/com/android/server/InputApplicationHandle.java b/services/java/com/android/server/InputApplicationHandle.java
new file mode 100644
index 000000000000..d396d11caa41
--- /dev/null
+++ b/services/java/com/android/server/InputApplicationHandle.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+/**
+ * Functions as a handle for an application that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's
+ * application window token.
+ * @hide
+ */
+public final class InputApplicationHandle {
+ // Pointer to the native input application handle.
+ // This field is lazily initialized via JNI.
+ @SuppressWarnings("unused")
+ private int ptr;
+
+ // The window manager's application window token.
+ public final WindowManagerService.AppWindowToken appWindowToken;
+
+ private native void nativeDispose();
+
+ public InputApplicationHandle(WindowManagerService.AppWindowToken appWindowToken) {
+ this.appWindowToken = appWindowToken;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ nativeDispose();
+ super.finalize();
+ }
+}
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 410b8c259b00..5c2048bd81f4 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -77,7 +77,7 @@ public class InputManager {
private static native boolean nativeHasKeys(int deviceId, int sourceMask,
int[] keyCodes, boolean[] keyExists);
private static native void nativeRegisterInputChannel(InputChannel inputChannel,
- boolean monitor);
+ InputWindowHandle inputWindowHandle, boolean monitor);
private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
private static native int nativeInjectInputEvent(InputEvent event,
int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
@@ -240,7 +240,7 @@ public class InputManager {
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
- nativeRegisterInputChannel(inputChannels[0], true);
+ nativeRegisterInputChannel(inputChannels[0], null, true);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
}
@@ -248,13 +248,16 @@ public class InputManager {
/**
* Registers an input channel so that it can be used as an input event target.
* @param inputChannel The input channel to register.
+ * @param inputWindowHandle The handle of the input window associated with the
+ * input channel, or null if none.
*/
- public void registerInputChannel(InputChannel inputChannel) {
+ public void registerInputChannel(InputChannel inputChannel,
+ InputWindowHandle inputWindowHandle) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
- nativeRegisterInputChannel(inputChannel, false);
+ nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
}
/**
@@ -429,13 +432,15 @@ public class InputManager {
}
@SuppressWarnings("unused")
- public void notifyInputChannelBroken(InputChannel inputChannel) {
- mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputChannel);
+ public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+ mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
}
@SuppressWarnings("unused")
- public long notifyANR(Object token, InputChannel inputChannel) {
- return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel);
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle) {
+ return mWindowManagerService.mInputMonitor.notifyANR(
+ inputApplicationHandle, inputWindowHandle);
}
@SuppressWarnings("unused")
@@ -445,14 +450,14 @@ public class InputManager {
}
@SuppressWarnings("unused")
- public boolean interceptKeyBeforeDispatching(InputChannel focus,
+ public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags) {
return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
focus, event, policyFlags);
}
@SuppressWarnings("unused")
- public KeyEvent dispatchUnhandledKey(InputChannel focus,
+ public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
KeyEvent event, int policyFlags) {
return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
focus, event, policyFlags);
diff --git a/services/java/com/android/server/InputWindow.java b/services/java/com/android/server/InputWindow.java
index befc770b4136..1515290145d8 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -20,64 +20,67 @@ 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 area.
public int frameLeft;
public int frameTop;
public int frameRight;
public int frameBottom;
-
+
// Window visible frame area.
public int visibleFrameLeft;
public int visibleFrameTop;
public int visibleFrameRight;
public int visibleFrameBottom;
-
+
// Window touchable area.
public int touchableAreaLeft;
public int touchableAreaTop;
public int touchableAreaRight;
public int touchableAreaBottom;
-
+
// 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;
-
+
public void recycle() {
+ inputWindowHandle = null;
inputChannel = null;
}
}
diff --git a/services/java/com/android/server/InputWindowHandle.java b/services/java/com/android/server/InputWindowHandle.java
new file mode 100644
index 000000000000..4b9293918031
--- /dev/null
+++ b/services/java/com/android/server/InputWindowHandle.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+import android.view.WindowManagerPolicy;
+
+/**
+ * Functions as a handle for a window that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's window state.
+ * @hide
+ */
+public final class InputWindowHandle {
+ // Pointer to the native input window handle.
+ // This field is lazily initialized via JNI.
+ @SuppressWarnings("unused")
+ private int ptr;
+
+ // The input application handle.
+ public final InputApplicationHandle inputApplicationHandle;
+
+ // The window manager's window state.
+ public final WindowManagerPolicy.WindowState windowState;
+
+ private native void nativeDispose();
+
+ public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
+ WindowManagerPolicy.WindowState windowState) {
+ this.inputApplicationHandle = inputApplicationHandle;
+ this.windowState = windowState;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ nativeDispose();
+ super.finalize();
+ }
+}
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index c33d19d706a7..5c823bae8aa4 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -536,7 +536,7 @@ public class WindowManagerService extends IWindowManager.Stub
InputChannel[] channels = InputChannel.openInputChannelPair("drag");
mServerChannel = channels[0];
mClientChannel = channels[1];
- mInputManager.registerInputChannel(mServerChannel);
+ mInputManager.registerInputChannel(mServerChannel, null);
InputQueue.registerInputChannel(mClientChannel, mDragInputHandler,
mH.getLooper().getQueue());
}
@@ -2311,7 +2311,7 @@ public class WindowManagerService extends IWindowManager.Stub
win.mInputChannel = inputChannels[0];
inputChannels[1].transferToBinderOutParameter(outInputChannel);
- mInputManager.registerInputChannel(win.mInputChannel);
+ mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
}
// From now on, no exceptions or errors allowed!
@@ -5711,13 +5711,13 @@ public class WindowManagerService extends IWindowManager.Stub
*
* Called by the InputManager.
*/
- public void notifyInputChannelBroken(InputChannel inputChannel) {
+ public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+ if (inputWindowHandle == null) {
+ return;
+ }
+
synchronized (mWindowMap) {
- WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
- if (windowState == null) {
- return; // irrelevant
- }
-
+ WindowState windowState = (WindowState) inputWindowHandle.windowState;
Slog.i(TAG, "WINDOW DIED " + windowState);
removeWindowLocked(windowState.mSession, windowState);
}
@@ -5728,11 +5728,12 @@ public class WindowManagerService extends IWindowManager.Stub
*
* Called by the InputManager.
*/
- public long notifyANR(Object token, InputChannel inputChannel) {
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle) {
AppWindowToken appWindowToken = null;
- if (inputChannel != null) {
+ if (inputWindowHandle != null) {
synchronized (mWindowMap) {
- WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
+ WindowState windowState = (WindowState) inputWindowHandle.windowState;
if (windowState != null) {
Slog.i(TAG, "Input event dispatching timed out sending to "
+ windowState.mAttrs.getTitle());
@@ -5741,8 +5742,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (appWindowToken == null && token != null) {
- appWindowToken = (AppWindowToken) token;
+ if (appWindowToken == null && inputApplicationHandle != null) {
+ appWindowToken = inputApplicationHandle.appWindowToken;
Slog.i(TAG, "Input event dispatching timed out sending to application "
+ appWindowToken.stringName);
}
@@ -5762,24 +5763,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
return 0; // abort dispatching
}
-
- private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
- synchronized (mWindowMap) {
- return getWindowStateForInputChannelLocked(inputChannel);
- }
- }
-
- private WindowState getWindowStateForInputChannelLocked(InputChannel inputChannel) {
- int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- WindowState windowState = mWindows.get(i);
- if (windowState.mInputChannel == inputChannel) {
- return windowState;
- }
- }
-
- return null;
- }
private void addDragInputWindowLw(InputWindowList windowList) {
final InputWindow inputWindow = windowList.add();
@@ -5856,6 +5839,7 @@ public class WindowManagerService extends IWindowManager.Stub
// 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;
@@ -5934,16 +5918,16 @@ public class WindowManagerService extends IWindowManager.Stub
/* Provides an opportunity for the window manager policy to process a key before
* ordinary dispatch. */
public boolean interceptKeyBeforeDispatching(
- InputChannel focus, KeyEvent event, int policyFlags) {
- WindowState windowState = getWindowStateForInputChannel(focus);
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = (WindowState) focus.windowState;
return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
}
/* Provides an opportunity for the window manager policy to process a key that
* the application did not handle. */
public KeyEvent dispatchUnhandledKey(
- InputChannel focus, KeyEvent event, int policyFlags) {
- WindowState windowState = getWindowStateForInputChannel(focus);
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = (WindowState) focus.windowState;
return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
}
@@ -5973,12 +5957,14 @@ public class WindowManagerService extends IWindowManager.Stub
if (newApp == null) {
mInputManager.setFocusedApplication(null);
} else {
+ mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
mTempInputApplication.name = newApp.toString();
mTempInputApplication.dispatchingTimeoutNanos =
newApp.inputDispatchingTimeoutNanos;
- mTempInputApplication.token = newApp;
-
+
mInputManager.setFocusedApplication(mTempInputApplication);
+
+ mTempInputApplication.recycle();
}
}
@@ -6823,7 +6809,8 @@ public class WindowManagerService extends IWindowManager.Stub
int mSurfaceLayer;
float mSurfaceAlpha;
- // Input channel
+ // Input channel and input window handle used by the input dispatcher.
+ InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
// Used to improve performance of toString()
@@ -6915,6 +6902,8 @@ public class WindowManagerService extends IWindowManager.Stub
mLayer = 0;
mAnimLayer = 0;
mLastLayer = 0;
+ mInputWindowHandle = new InputWindowHandle(
+ mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
}
void attach() {
@@ -8304,11 +8293,15 @@ public class WindowManagerService extends IWindowManager.Stub
boolean startingMoved;
boolean firstWindowDrawn;
+ // Input application handle used by the input dispatcher.
+ InputApplicationHandle mInputApplicationHandle;
+
AppWindowToken(IApplicationToken _token) {
super(_token.asBinder(),
WindowManager.LayoutParams.TYPE_APPLICATION, true);
appWindowToken = this;
appToken = _token;
+ mInputApplicationHandle = new InputApplicationHandle(this);
}
public void setAnimation(Animation anim) {
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index ec85e54b52c2..f5a5b4da5e80 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,7 +4,11 @@ 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 \
com_android_server_SystemServer.cpp \
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
new file mode 100644
index 000000000000..a46a162071e8
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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 {
+ jclass clazz;
+
+ 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); \
+ var = jclass(env->NewGlobalRef(var));
+
+#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) {
+ FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
+
+ GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
+ gInputApplicationClassInfo.clazz,
+ "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+ GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
+ "name", "Ljava/lang/String;");
+
+ GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
+ gInputApplicationClassInfo.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
new file mode 100644
index 000000000000..85fb891cfd2b
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.h
@@ -0,0 +1,32 @@
+/*
+ * 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
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
new file mode 100644
index 000000000000..ab82635595d8
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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 "InputApplicationHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jfieldID ptr;
+} gInputApplicationHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputApplicationHandle ---
+
+NativeInputApplicationHandle::NativeInputApplicationHandle(jweak objWeak) :
+ mObjWeak(objWeak) {
+}
+
+NativeInputApplicationHandle::~NativeInputApplicationHandle() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEnv* env) {
+ return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+ JNIEnv* env, jobject inputApplicationHandleObj) {
+ if (!inputApplicationHandleObj) {
+ return NULL;
+ }
+
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr);
+ NativeInputApplicationHandle* handle;
+ if (ptr) {
+ handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+ } else {
+ jweak objWeak = env->NewWeakGlobalRef(inputApplicationHandleObj);
+ handle = new NativeInputApplicationHandle(objWeak);
+ handle->incStrong(inputApplicationHandleObj);
+ env->SetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr,
+ reinterpret_cast<int>(handle));
+ }
+ return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputApplicationHandle_nativeDispose(JNIEnv* env, jobject obj) {
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(obj, gInputApplicationHandleClassInfo.ptr);
+ if (ptr) {
+ env->SetIntField(obj, gInputApplicationHandleClassInfo.ptr, 0);
+
+ NativeInputApplicationHandle* handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+ handle->decStrong(obj);
+ }
+}
+
+
+static JNINativeMethod gInputApplicationHandleMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeDispose", "()V",
+ (void*) android_server_InputApplicationHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#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_InputApplicationHandle(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "com/android/server/InputApplicationHandle",
+ gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
+ LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ FIND_CLASS(gInputApplicationHandleClassInfo.clazz, "com/android/server/InputApplicationHandle");
+
+ GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, gInputApplicationHandleClassInfo.clazz,
+ "ptr", "I");
+
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
new file mode 100644
index 000000000000..9d187219b2ec
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -0,0 +1,44 @@
+/*
+ * 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_HANDLE_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputApplicationHandle : public InputApplicationHandle {
+public:
+ NativeInputApplicationHandle(jweak objWeak);
+ virtual ~NativeInputApplicationHandle();
+
+ jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
+
+private:
+ jweak mObjWeak;
+};
+
+
+extern sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+ JNIEnv* env, jobject inputApplicationHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 5ed63f0b14dc..e04e4c3324f3 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -42,11 +42,13 @@
#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 {
-// ----------------------------------------------------------------------------
-
static struct {
jclass clazz;
@@ -68,44 +70,6 @@ static struct {
static struct {
jclass clazz;
-
- jfieldID inputChannel;
- jfieldID name;
- jfieldID layoutParamsFlags;
- jfieldID layoutParamsType;
- jfieldID dispatchingTimeoutNanos;
- jfieldID frameLeft;
- jfieldID frameTop;
- jfieldID frameRight;
- jfieldID frameBottom;
- jfieldID visibleFrameLeft;
- jfieldID visibleFrameTop;
- jfieldID visibleFrameRight;
- jfieldID visibleFrameBottom;
- jfieldID touchableAreaLeft;
- jfieldID touchableAreaTop;
- jfieldID touchableAreaRight;
- jfieldID touchableAreaBottom;
- jfieldID visible;
- jfieldID canReceiveKeys;
- jfieldID hasFocus;
- jfieldID hasWallpaper;
- jfieldID paused;
- jfieldID layer;
- jfieldID ownerPid;
- jfieldID ownerUid;
-} gInputWindowClassInfo;
-
-static struct {
- jclass clazz;
-
- jfieldID name;
- jfieldID dispatchingTimeoutNanos;
- jfieldID token;
-} gInputApplicationClassInfo;
-
-static struct {
- jclass clazz;
} gKeyEventClassInfo;
static struct {
@@ -141,7 +105,29 @@ static struct {
jfieldID hotSpotY;
} gPointerIconClassInfo;
-// ----------------------------------------------------------------------------
+
+// --- Global functions ---
+
+static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
+ const sp<InputApplicationHandle>& inputApplicationHandle) {
+ if (inputApplicationHandle == NULL) {
+ return NULL;
+ }
+ return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
+ getInputApplicationHandleObjLocalRef(env);
+}
+
+static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
+ const sp<InputWindowHandle>& inputWindowHandle) {
+ if (inputWindowHandle == NULL) {
+ return NULL;
+ }
+ return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
+ getInputWindowHandleObjLocalRef(env);
+}
+
+
+// --- NativeInputManager ---
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
@@ -160,7 +146,7 @@ public:
void setDisplayOrientation(int32_t displayId, int32_t orientation);
status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
- jweak inputChannelObjWeak, bool monitor);
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
@@ -182,37 +168,22 @@ public:
uint32_t policyFlags);
virtual void notifyConfigurationChanged(nsecs_t when);
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel);
- virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
+ const sp<InputWindowHandle>& inputWindowHandle);
+ virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
virtual nsecs_t getKeyRepeatTimeout();
virtual nsecs_t getKeyRepeatDelay();
virtual int32_t getMaxEventsPerSecond();
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
- virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+ virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags);
- virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+ virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
virtual bool checkInjectEventsPermissionNonReentrant(
int32_t injectorPid, int32_t injectorUid);
private:
- class ApplicationToken : public InputApplicationHandle {
- jweak mTokenObjWeak;
-
- public:
- ApplicationToken(jweak tokenObjWeak) :
- mTokenObjWeak(tokenObjWeak) { }
-
- virtual ~ApplicationToken() {
- JNIEnv* env = NativeInputManager::jniEnv();
- env->DeleteWeakGlobalRef(mTokenObjWeak);
- }
-
- inline jweak getTokenObj() { return mTokenObjWeak; }
- };
-
sp<InputManager> mInputManager;
jobject mCallbacksObj;
@@ -232,19 +203,12 @@ private:
// Pointer controller singleton, created and destroyed as needed.
wp<PointerController> pointerController;
-
- // Weak references to all currently registered input channels by connection pointer.
- KeyedVector<InputChannel*, jweak> inputChannelObjWeakTable;
} mLocked;
// Power manager interactions.
bool isScreenOn();
bool isScreenBright();
- jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
-
- static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
-
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
static inline JNIEnv* jniEnv() {
@@ -252,7 +216,7 @@ private:
}
};
-// ----------------------------------------------------------------------------
+
NativeInputManager::NativeInputManager(jobject callbacksObj) :
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
@@ -328,88 +292,17 @@ void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orient
}
status_t NativeInputManager::registerInputChannel(JNIEnv* env,
- const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
- jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
- if (! inputChannelObjWeak) {
- LOGE("Could not create weak reference for input channel.");
- LOGE_EX(env);
- return NO_MEMORY;
- }
-
- status_t status;
- {
- AutoMutex _l(mLock);
-
- ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
- if (index >= 0) {
- LOGE("Input channel object '%s' has already been registered",
- inputChannel->getName().string());
- status = INVALID_OPERATION;
- goto DeleteWeakRef;
- }
-
- mLocked.inputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
- }
-
- status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor);
- if (! status) {
- // Success.
- return OK;
- }
-
- // Failed!
- {
- AutoMutex _l(mLock);
- mLocked.inputChannelObjWeakTable.removeItem(inputChannel.get());
- }
-
-DeleteWeakRef:
- env->DeleteWeakGlobalRef(inputChannelObjWeak);
- return status;
+ const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+ return mInputManager->getDispatcher()->registerInputChannel(
+ inputChannel, inputWindowHandle, monitor);
}
status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
const sp<InputChannel>& inputChannel) {
- jweak inputChannelObjWeak;
- {
- AutoMutex _l(mLock);
-
- ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
- if (index < 0) {
- LOGE("Input channel object '%s' is not currently registered",
- inputChannel->getName().string());
- return INVALID_OPERATION;
- }
-
- inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
- mLocked.inputChannelObjWeakTable.removeItemsAt(index);
- }
-
- env->DeleteWeakGlobalRef(inputChannelObjWeak);
-
return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
}
-jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
- const sp<InputChannel>& inputChannel) {
- InputChannel* inputChannelPtr = inputChannel.get();
- if (! inputChannelPtr) {
- return NULL;
- }
-
- {
- AutoMutex _l(mLock);
-
- ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannelPtr);
- if (index < 0) {
- return NULL;
- }
-
- jweak inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
- return env->NewLocalRef(inputChannelObjWeak);
- }
-}
-
bool NativeInputManager::getDisplayInfo(int32_t displayId,
int32_t* width, int32_t* height, int32_t* orientation) {
bool result = false;
@@ -549,50 +442,46 @@ void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
}
nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel) {
+ const sp<InputWindowHandle>& inputWindowHandle) {
#if DEBUG_INPUT_DISPATCHER_POLICY
LOGD("notifyANR");
#endif
JNIEnv* env = jniEnv();
- jobject tokenObjLocal;
- if (inputApplicationHandle.get()) {
- ApplicationToken* token = static_cast<ApplicationToken*>(inputApplicationHandle.get());
- jweak tokenObjWeak = token->getTokenObj();
- tokenObjLocal = env->NewLocalRef(tokenObjWeak);
- } else {
- tokenObjLocal = NULL;
- }
+ jobject inputApplicationHandleObj =
+ getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
+ jobject inputWindowHandleObj =
+ getInputWindowHandleObjLocalRef(env, inputWindowHandle);
- jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
jlong newTimeout = env->CallLongMethod(mCallbacksObj,
- gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal);
+ gCallbacksClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
newTimeout = 0; // abort dispatch
} else {
assert(newTimeout >= 0);
}
- env->DeleteLocalRef(tokenObjLocal);
- env->DeleteLocalRef(inputChannelObjLocal);
+ env->DeleteLocalRef(inputWindowHandleObj);
+ env->DeleteLocalRef(inputApplicationHandleObj);
return newTimeout;
}
-void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
#if DEBUG_INPUT_DISPATCHER_POLICY
- LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
+ LOGD("notifyInputChannelBroken");
#endif
JNIEnv* env = jniEnv();
- jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
- if (inputChannelObjLocal) {
+ jobject inputWindowHandleObj =
+ getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+ if (inputWindowHandleObj) {
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
- inputChannelObjLocal);
+ inputWindowHandleObj);
checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
- env->DeleteLocalRef(inputChannelObjLocal);
+ env->DeleteLocalRef(inputWindowHandleObj);
}
}
@@ -630,160 +519,32 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArra
jsize length = env->GetArrayLength(windowObjArray);
for (jsize i = 0; i < length; i++) {
- jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
- if (! inputTargetObj) {
+ jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
+ if (! windowObj) {
break; // found null element indicating end of used portion of the array
}
windows.push();
InputWindow& window = windows.editTop();
- bool valid = populateWindow(env, inputTargetObj, window);
- if (! valid) {
+ android_server_InputWindow_toNative(env, windowObj, &window);
+ if (window.inputChannel == NULL) {
windows.pop();
}
-
- env->DeleteLocalRef(inputTargetObj);
+ env->DeleteLocalRef(windowObj);
}
mInputManager->getDispatcher()->setInputWindows(windows);
}
-bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
- InputWindow& outWindow) {
- bool valid = false;
-
- jobject inputChannelObj = env->GetObjectField(windowObj,
- gInputWindowClassInfo.inputChannel);
- if (inputChannelObj) {
- sp<InputChannel> inputChannel =
- android_view_InputChannel_getInputChannel(env, inputChannelObj);
- if (inputChannel != NULL) {
- jstring name = jstring(env->GetObjectField(windowObj,
- gInputWindowClassInfo.name));
- jint layoutParamsFlags = env->GetIntField(windowObj,
- gInputWindowClassInfo.layoutParamsFlags);
- jint layoutParamsType = env->GetIntField(windowObj,
- gInputWindowClassInfo.layoutParamsType);
- jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
- gInputWindowClassInfo.dispatchingTimeoutNanos);
- jint frameLeft = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameLeft);
- jint frameTop = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameTop);
- jint frameRight = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameRight);
- jint frameBottom = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameBottom);
- jint visibleFrameLeft = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameLeft);
- jint visibleFrameTop = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameTop);
- jint visibleFrameRight = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameRight);
- jint visibleFrameBottom = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameBottom);
- jint touchableAreaLeft = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaLeft);
- jint touchableAreaTop = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaTop);
- jint touchableAreaRight = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaRight);
- jint touchableAreaBottom = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaBottom);
- jboolean visible = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.visible);
- jboolean canReceiveKeys = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.canReceiveKeys);
- jboolean hasFocus = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.hasFocus);
- jboolean hasWallpaper = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.hasWallpaper);
- jboolean paused = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.paused);
- jint layer = env->GetIntField(windowObj,
- gInputWindowClassInfo.layer);
- jint ownerPid = env->GetIntField(windowObj,
- gInputWindowClassInfo.ownerPid);
- jint ownerUid = env->GetIntField(windowObj,
- gInputWindowClassInfo.ownerUid);
-
- const char* nameStr = env->GetStringUTFChars(name, NULL);
-
- outWindow.inputChannel = inputChannel;
- outWindow.name.setTo(nameStr);
- outWindow.layoutParamsFlags = layoutParamsFlags;
- outWindow.layoutParamsType = layoutParamsType;
- outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
- outWindow.frameLeft = frameLeft;
- outWindow.frameTop = frameTop;
- outWindow.frameRight = frameRight;
- outWindow.frameBottom = frameBottom;
- outWindow.visibleFrameLeft = visibleFrameLeft;
- outWindow.visibleFrameTop = visibleFrameTop;
- outWindow.visibleFrameRight = visibleFrameRight;
- outWindow.visibleFrameBottom = visibleFrameBottom;
- outWindow.touchableAreaLeft = touchableAreaLeft;
- outWindow.touchableAreaTop = touchableAreaTop;
- outWindow.touchableAreaRight = touchableAreaRight;
- outWindow.touchableAreaBottom = touchableAreaBottom;
- outWindow.visible = visible;
- outWindow.canReceiveKeys = canReceiveKeys;
- outWindow.hasFocus = hasFocus;
- outWindow.hasWallpaper = hasWallpaper;
- outWindow.paused = paused;
- outWindow.layer = layer;
- outWindow.ownerPid = ownerPid;
- outWindow.ownerUid = ownerUid;
-
- env->ReleaseStringUTFChars(name, nameStr);
- env->DeleteLocalRef(name);
- valid = true;
- } else {
- LOGW("Dropping input target because its input channel is not initialized.");
- }
-
- env->DeleteLocalRef(inputChannelObj);
- } else {
- LOGW("Dropping input target because the input channel object was null.");
- }
- return valid;
-}
-
void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
if (applicationObj) {
- jstring nameObj = jstring(env->GetObjectField(applicationObj,
- gInputApplicationClassInfo.name));
- jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
- gInputApplicationClassInfo.dispatchingTimeoutNanos);
- jobject tokenObj = env->GetObjectField(applicationObj,
- gInputApplicationClassInfo.token);
- jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
- if (! tokenObjWeak) {
- LOGE("Could not create weak reference for application token.");
- LOGE_EX(env);
- env->ExceptionClear();
- }
- env->DeleteLocalRef(tokenObj);
-
- String8 name;
- if (nameObj) {
- const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
- name.setTo(nameStr);
- env->ReleaseStringUTFChars(nameObj, nameStr);
- env->DeleteLocalRef(nameObj);
- } else {
- LOGE("InputApplication.name should not be null.");
- name.setTo("unknown");
- }
-
InputApplication application;
- application.name = name;
- application.dispatchingTimeout = dispatchingTimeoutNanos;
- application.handle = new ApplicationToken(tokenObjWeak);
- mInputManager->getDispatcher()->setFocusedApplication(& application);
- } else {
- mInputManager->getDispatcher()->setFocusedApplication(NULL);
+ android_server_InputApplication_toNative(env, applicationObj, &application);
+ if (application.inputApplicationHandle != NULL) {
+ mInputManager->getDispatcher()->setFocusedApplication(&application);
+ }
}
+ mInputManager->getDispatcher()->setFocusedApplication(NULL);
}
void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -875,7 +636,8 @@ void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t&
}
}
-bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::interceptKeyBeforeDispatching(
+ const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
// Policy:
// - Ignore untrusted events and pass them along.
@@ -885,13 +647,13 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& i
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
- // Note: inputChannel may be null.
- jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+ // Note: inputWindowHandle may be null.
+ jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
gCallbacksClassInfo.interceptKeyBeforeDispatching,
- inputChannelObj, keyEventObj, policyFlags);
+ inputWindowHandleObj, keyEventObj, policyFlags);
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
@@ -899,12 +661,12 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& i
} else {
LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
}
- env->DeleteLocalRef(inputChannelObj);
+ env->DeleteLocalRef(inputWindowHandleObj);
}
return result;
}
-bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
// Policy:
// - Ignore untrusted events and do not perform default handling.
@@ -912,13 +674,13 @@ bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChann
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
- // Note: inputChannel may be null.
- jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+ // Note: inputWindowHandle may be null.
+ jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
gCallbacksClassInfo.dispatchUnhandledKey,
- inputChannelObj, keyEventObj, policyFlags);
+ inputWindowHandleObj, keyEventObj, policyFlags);
checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
@@ -935,7 +697,7 @@ bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChann
} else {
LOGE("Failed to obtain key event object for dispatchUnhandledKey.");
}
- env->DeleteLocalRef(inputChannelObj);
+ env->DeleteLocalRef(inputWindowHandleObj);
}
return result;
}
@@ -1079,7 +841,7 @@ static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
}
static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
- jobject inputChannelObj, jboolean monitor) {
+ jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
if (checkInputManagerUnitialized(env)) {
return;
}
@@ -1091,9 +853,11 @@ static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env,
return;
}
+ sp<InputWindowHandle> inputWindowHandle =
+ android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
status_t status = gNativeInputManager->registerInputChannel(
- env, inputChannel, inputChannelObj, monitor);
+ env, inputChannel, inputWindowHandle, monitor);
if (status) {
jniThrowRuntimeException(env, "Failed to register input channel. "
"Check logs for details.");
@@ -1311,7 +1075,8 @@ static JNINativeMethod gInputManagerMethods[] = {
(void*) android_server_InputManager_nativeGetSwitchState },
{ "nativeHasKeys", "(II[I[Z)Z",
(void*) android_server_InputManager_nativeHasKeys },
- { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
+ { "nativeRegisterInputChannel",
+ "(Landroid/view/InputChannel;Lcom/android/server/InputWindowHandle;Z)V",
(void*) android_server_InputManager_nativeRegisterInputChannel },
{ "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
(void*) android_server_InputManager_nativeUnregisterInputChannel },
@@ -1364,21 +1129,22 @@ int register_android_server_InputManager(JNIEnv* env) {
"notifyLidSwitchChanged", "(JZ)V");
GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
- "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
+ "notifyInputChannelBroken", "(Lcom/android/server/InputWindowHandle;)V");
GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
- "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
+ "notifyANR",
+ "(Lcom/android/server/InputApplicationHandle;Lcom/android/server/InputWindowHandle;)J");
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
"interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
"interceptKeyBeforeDispatching",
- "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
+ "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
"dispatchUnhandledKey",
- "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+ "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
"checkInjectEventsPermission", "(II)Z");
@@ -1401,99 +1167,6 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
"getPointerIcon", "()Lcom/android/server/InputManager$PointerIcon;");
- // InputWindow
-
- FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
-
- GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
- "inputChannel", "Landroid/view/InputChannel;");
-
- GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
- "name", "Ljava/lang/String;");
-
- GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
- "layoutParamsFlags", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
- "layoutParamsType", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
- "dispatchingTimeoutNanos", "J");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
- "frameLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
- "frameTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
- "frameRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
- "frameBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
- "visibleFrameLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
- "visibleFrameTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
- "visibleFrameRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
- "visibleFrameBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
- "touchableAreaLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
- "touchableAreaTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
- "touchableAreaRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
- "touchableAreaBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
- "visible", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
- "canReceiveKeys", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
- "hasFocus", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
- "hasWallpaper", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
- "paused", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
- "layer", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
- "ownerPid", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
- "ownerUid", "I");
-
- // InputApplication
-
- FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
-
- GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
- "name", "Ljava/lang/String;");
-
- GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
- gInputApplicationClassInfo.clazz,
- "dispatchingTimeoutNanos", "J");
-
- GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
- "token", "Ljava/lang/Object;");
-
// KeyEvent
FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
new file mode 100644
index 000000000000..a4609a0f9b85
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.cpp
@@ -0,0 +1,240 @@
+/*
+ * 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 "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jfieldID inputWindowHandle;
+ jfieldID inputChannel;
+ jfieldID name;
+ jfieldID layoutParamsFlags;
+ jfieldID layoutParamsType;
+ jfieldID dispatchingTimeoutNanos;
+ jfieldID frameLeft;
+ jfieldID frameTop;
+ jfieldID frameRight;
+ jfieldID frameBottom;
+ jfieldID visibleFrameLeft;
+ jfieldID visibleFrameTop;
+ jfieldID visibleFrameRight;
+ jfieldID visibleFrameBottom;
+ jfieldID touchableAreaLeft;
+ jfieldID touchableAreaTop;
+ jfieldID touchableAreaRight;
+ jfieldID touchableAreaBottom;
+ jfieldID visible;
+ jfieldID canReceiveKeys;
+ jfieldID hasFocus;
+ jfieldID hasWallpaper;
+ jfieldID paused;
+ jfieldID layer;
+ jfieldID ownerPid;
+ jfieldID ownerUid;
+} 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->visibleFrameLeft = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameLeft);
+ outInputWindow->visibleFrameTop = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameTop);
+ outInputWindow->visibleFrameRight = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameRight);
+ outInputWindow->visibleFrameBottom = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameBottom);
+ outInputWindow->touchableAreaLeft = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaLeft);
+ outInputWindow->touchableAreaTop = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaTop);
+ outInputWindow->touchableAreaRight = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaRight);
+ outInputWindow->touchableAreaBottom = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaBottom);
+ 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);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#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) {
+ FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
+
+ GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, gInputWindowClassInfo.clazz,
+ "inputWindowHandle", "Lcom/android/server/InputWindowHandle;");
+
+ GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
+ "inputChannel", "Landroid/view/InputChannel;");
+
+ GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
+ "name", "Ljava/lang/String;");
+
+ GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
+ "layoutParamsFlags", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
+ "layoutParamsType", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
+ "dispatchingTimeoutNanos", "J");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
+ "frameLeft", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
+ "frameTop", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+ "frameRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+ "frameBottom", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
+ "visibleFrameLeft", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
+ "visibleFrameTop", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
+ "visibleFrameRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
+ "visibleFrameBottom", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
+ "touchableAreaLeft", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
+ "touchableAreaTop", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
+ "touchableAreaRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
+ "touchableAreaBottom", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
+ "visible", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
+ "canReceiveKeys", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
+ "hasFocus", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
+ "hasWallpaper", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
+ "paused", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
+ "layer", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
+ "ownerPid", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
+ "ownerUid", "I");
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h
new file mode 100644
index 000000000000..eaf7bdedbd7c
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.h
@@ -0,0 +1,32 @@
+/*
+ * 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
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
new file mode 100644
index 000000000000..4d66212087ca
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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 "InputWindowHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputWindowHandle.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jfieldID ptr;
+ jfieldID inputApplicationHandle;
+} gInputWindowHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputWindowHandle ---
+
+NativeInputWindowHandle::NativeInputWindowHandle(
+ const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) :
+ InputWindowHandle(inputApplicationHandle),
+ mObjWeak(objWeak) {
+}
+
+NativeInputWindowHandle::~NativeInputWindowHandle() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
+ return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+ JNIEnv* env, jobject inputWindowHandleObj) {
+ if (!inputWindowHandleObj) {
+ return NULL;
+ }
+
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr);
+ NativeInputWindowHandle* handle;
+ if (ptr) {
+ handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+ } else {
+ jobject inputApplicationHandleObj = env->GetObjectField(inputWindowHandleObj,
+ gInputWindowHandleClassInfo.inputApplicationHandle);
+ sp<InputApplicationHandle> inputApplicationHandle =
+ android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+ env->DeleteLocalRef(inputApplicationHandleObj);
+
+ jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
+ handle = new NativeInputWindowHandle(inputApplicationHandle, objWeak);
+ handle->incStrong(inputWindowHandleObj);
+ env->SetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
+ reinterpret_cast<int>(handle));
+ }
+ return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputWindowHandle_nativeDispose(JNIEnv* env, jobject obj) {
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(obj, gInputWindowHandleClassInfo.ptr);
+ if (ptr) {
+ env->SetIntField(obj, gInputWindowHandleClassInfo.ptr, 0);
+
+ NativeInputWindowHandle* handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+ handle->decStrong(obj);
+ }
+}
+
+
+static JNINativeMethod gInputWindowHandleMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeDispose", "()V",
+ (void*) android_server_InputWindowHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#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_InputWindowHandle(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "com/android/server/InputWindowHandle",
+ gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
+ LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ FIND_CLASS(gInputWindowHandleClassInfo.clazz, "com/android/server/InputWindowHandle");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, gInputWindowHandleClassInfo.clazz,
+ "ptr", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
+ gInputWindowHandleClassInfo.clazz,
+ "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
new file mode 100644
index 000000000000..43f2a6ba9536
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -0,0 +1,45 @@
+/*
+ * 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_HANDLE_H
+#define _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputWindowHandle : public InputWindowHandle {
+public:
+ NativeInputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+ jweak objWeak);
+ virtual ~NativeInputWindowHandle();
+
+ jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
+
+private:
+ jweak mObjWeak;
+};
+
+
+extern sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+ JNIEnv* env, jobject inputWindowHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index cd4f0a46c517..bdd6d808ac42 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -6,6 +6,10 @@
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);
int register_android_server_PowerManagerService(JNIEnv* env);
@@ -28,6 +32,10 @@ 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);
register_android_server_AlarmManagerService(env);