diff options
21 files changed, 351 insertions, 196 deletions
diff --git a/api/current.xml b/api/current.xml index a98c8b6..87394ce 100644 --- a/api/current.xml +++ b/api/current.xml @@ -196675,7 +196675,7 @@ value="0" static="true" final="true" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > </field> diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index fbd9eac..d330cca 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -31,7 +31,19 @@ import java.lang.Character; public class KeyCharacterMap { /** * The id of the device's primary built in keyboard is always 0. + * + * @deprecated This constant should no longer be used because there is no + * guarantee that a device has a built-in keyboard that can be used for + * typing text. There might not be a built-in keyboard, the built-in keyboard + * might be a {@link #NUMERIC} or {@link #SPECIAL_FUNCTION} keyboard, or there + * might be multiple keyboards installed including external keyboards. + * When interpreting key presses received from the framework, applications should + * use the device id specified in the {@link #KeyEvent} received. + * When synthesizing key presses for delivery elsewhere or when translating key presses + * from unknown keyboards, applications should use the special {@link #VIRTUAL_KEYBOARD} + * device id. */ + @Deprecated public static final int BUILT_IN_KEYBOARD = 0; /** diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index b3277e4..03407a3 100755 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1081,7 +1081,15 @@ public class KeyEvent extends InputEvent implements Parcelable { static final boolean DEBUG = false; static final String TAG = "KeyEvent"; - + + private static final int MAX_RECYCLED = 10; + private static final Object gRecyclerLock = new Object(); + private static int gRecyclerUsed; + private static KeyEvent gRecyclerTop; + + private KeyEvent mNext; + private boolean mRecycled; + private int mMetaState; private int mAction; private int mKeyCode; @@ -1160,6 +1168,9 @@ public class KeyEvent extends InputEvent implements Parcelable { } } + private KeyEvent() { + } + /** * Create a new key event. * @@ -1382,6 +1393,67 @@ public class KeyEvent extends InputEvent implements Parcelable { mCharacters = origEvent.mCharacters; } + private static KeyEvent obtain() { + final KeyEvent ev; + synchronized (gRecyclerLock) { + ev = gRecyclerTop; + if (ev == null) { + return new KeyEvent(); + } + gRecyclerTop = ev.mNext; + gRecyclerUsed -= 1; + } + ev.mRecycled = false; + ev.mNext = null; + return ev; + } + + /** + * Obtains a (potentially recycled) key event. + * + * @hide + */ + public static KeyEvent obtain(long downTime, long eventTime, int action, + int code, int repeat, int metaState, + int deviceId, int scancode, int flags, int source, String characters) { + KeyEvent ev = obtain(); + ev.mDownTime = downTime; + ev.mEventTime = eventTime; + ev.mAction = action; + ev.mKeyCode = code; + ev.mRepeatCount = repeat; + ev.mMetaState = metaState; + ev.mDeviceId = deviceId; + ev.mScanCode = scancode; + ev.mFlags = flags; + ev.mSource = source; + ev.mCharacters = characters; + return ev; + } + + /** + * Recycles a key event. + * Key events should only be recycled if they are owned by the system since user + * code expects them to be essentially immutable, "tracking" notwithstanding. + * + * @hide + */ + public final void recycle() { + if (mRecycled) { + throw new RuntimeException(toString() + " recycled twice!"); + } + mRecycled = true; + mCharacters = null; + + synchronized (gRecyclerLock) { + if (gRecyclerUsed < MAX_RECYCLED) { + gRecyclerUsed++; + mNext = gRecyclerTop; + gRecyclerTop = this; + } + } + } + /** * Create a new key event that is the same as the given one, but whose * event time and repeat count are replaced with the given value. diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 195d689..e81aa98 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -314,10 +314,10 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ static private final int BASE_AVAIL_SAMPLES = 8; - static private final int MAX_RECYCLED = 10; - static private Object gRecyclerLock = new Object(); - static private int gRecyclerUsed = 0; - static private MotionEvent gRecyclerTop = null; + private static final int MAX_RECYCLED = 10; + private static final Object gRecyclerLock = new Object(); + private static int gRecyclerUsed; + private static MotionEvent gRecyclerTop; private long mDownTimeNano; private int mAction; @@ -361,7 +361,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { static private MotionEvent obtain(int pointerCount, int sampleCount) { final MotionEvent ev; synchronized (gRecyclerLock) { - if (gRecyclerTop == null) { + ev = gRecyclerTop; + if (ev == null) { if (pointerCount < BASE_AVAIL_POINTERS) { pointerCount = BASE_AVAIL_POINTERS; } @@ -370,7 +371,6 @@ public final class MotionEvent extends InputEvent implements Parcelable { } return new MotionEvent(pointerCount, sampleCount); } - ev = gRecyclerTop; gRecyclerTop = ev.mNext; gRecyclerUsed -= 1; } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 5a9cd97..af36d80 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -551,19 +551,14 @@ public interface WindowManagerPolicy { * affect the power state of the device, for example, the power keys. * Generally, it's best to keep as little as possible in the queue thread * because it's the most fragile. - * @param whenNanos The event time in uptime nanoseconds. - * @param action The key event action. - * @param flags The key event flags. - * @param keyCode The key code. - * @param scanCode The key's scan code. + * @param event The key event. * @param policyFlags The policy flags associated with the key. * @param isScreenOn True if the screen is already on * * @return The bitwise or of the {@link #ACTION_PASS_TO_USER}, * {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags. */ - public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, - int keyCode, int scanCode, int policyFlags, boolean isScreenOn); + public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn); /** * Called from the input dispatcher thread before a key is dispatched to a window. @@ -574,18 +569,12 @@ public interface WindowManagerPolicy { * * @param win The window that currently has focus. This is where the key * event will normally go. - * @param action The key event action. - * @param flags The key event flags. - * @param keyCode The key code. - * @param scanCode The key's scan code. - * @param metaState bit mask of meta keys that are held. - * @param repeatCount Number of times a key down has repeated. + * @param event The key event. * @param policyFlags The policy flags associated with the key. * @return Returns true if the policy consumed the event and it should * not be further dispatched. */ - public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, - int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags); + public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags); /** * Called from the input dispatcher thread when an application did not handle @@ -596,17 +585,11 @@ public interface WindowManagerPolicy { * * @param win The window that currently has focus. This is where the key * event will normally go. - * @param action The key event action. - * @param flags The key event flags. - * @param keyCode The key code. - * @param scanCode The key's scan code. - * @param metaState bit mask of meta keys that are held. - * @param repeatCount Number of times a key down has repeated. + * @param event The key event. * @param policyFlags The policy flags associated with the key. * @return Returns true if the policy consumed the event. */ - public boolean dispatchUnhandledKey(WindowState win, int action, int flags, - int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags); + public boolean dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags); /** * Called when layout of the windows is about to start. diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp index 695d50a4..b033878 100644 --- a/core/jni/android_app_NativeActivity.cpp +++ b/core/jni/android_app_NativeActivity.cpp @@ -579,20 +579,30 @@ static int mainWorkCallback(int fd, int events, void* data) { while ((keyEvent=code->nativeInputQueue->consumeUnhandledEvent()) != NULL) { jobject inputEventObj = android_view_KeyEvent_fromNative( code->env, keyEvent); - jboolean handled = code->env->CallBooleanMethod(code->clazz, - gNativeActivityClassInfo.dispatchUnhandledKeyEvent, inputEventObj); - checkAndClearExceptionFromCallback(code->env, "dispatchUnhandledKeyEvent"); - code->env->DeleteLocalRef(inputEventObj); + jboolean handled; + if (inputEventObj) { + handled = code->env->CallBooleanMethod(code->clazz, + gNativeActivityClassInfo.dispatchUnhandledKeyEvent, inputEventObj); + checkAndClearExceptionFromCallback(code->env, "dispatchUnhandledKeyEvent"); + code->env->DeleteLocalRef(inputEventObj); + } else { + LOGE("Failed to obtain key event for dispatchUnhandledKeyEvent."); + handled = false; + } code->nativeInputQueue->finishEvent(keyEvent, handled, true); } int seq; while ((keyEvent=code->nativeInputQueue->consumePreDispatchingEvent(&seq)) != NULL) { jobject inputEventObj = android_view_KeyEvent_fromNative( code->env, keyEvent); - code->env->CallVoidMethod(code->clazz, - gNativeActivityClassInfo.preDispatchKeyEvent, inputEventObj, seq); - checkAndClearExceptionFromCallback(code->env, "preDispatchKeyEvent"); - code->env->DeleteLocalRef(inputEventObj); + if (inputEventObj) { + code->env->CallVoidMethod(code->clazz, + gNativeActivityClassInfo.preDispatchKeyEvent, inputEventObj, seq); + checkAndClearExceptionFromCallback(code->env, "preDispatchKeyEvent"); + code->env->DeleteLocalRef(inputEventObj); + } else { + LOGE("Failed to obtain key event for preDispatchKeyEvent."); + } } } break; case CMD_FINISH: { @@ -987,7 +997,12 @@ dispatchKeyEvent_native(JNIEnv* env, jobject clazz, jint handle, jobject eventOb NativeCode* code = (NativeCode*)handle; if (code->nativeInputQueue != NULL) { KeyEvent* event = code->nativeInputQueue->createKeyEvent(); - android_view_KeyEvent_toNative(env, eventObj, event); + status_t status = android_view_KeyEvent_toNative(env, eventObj, event); + if (status) { + delete event; + jniThrowRuntimeException(env, "Could not read contents of KeyEvent object."); + return; + } code->nativeInputQueue->dispatchEvent(event); } } diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp index 7e7583c..4b04b8b 100644 --- a/core/jni/android_view_KeyEvent.cpp +++ b/core/jni/android_view_KeyEvent.cpp @@ -30,7 +30,8 @@ namespace android { static struct { jclass clazz; - jmethodID ctor; + jmethodID obtain; + jmethodID recycle; jfieldID mDeviceId; jfieldID mSource; @@ -48,7 +49,8 @@ static struct { // ---------------------------------------------------------------------------- jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) { - return env->NewObject(gKeyEventClassInfo.clazz, gKeyEventClassInfo.ctor, + jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, + gKeyEventClassInfo.obtain, nanoseconds_to_milliseconds(event->getDownTime()), nanoseconds_to_milliseconds(event->getEventTime()), event->getAction(), @@ -58,10 +60,18 @@ jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) { event->getDeviceId(), event->getScanCode(), event->getFlags(), - event->getSource()); + event->getSource(), + NULL); + if (env->ExceptionCheck()) { + LOGE("An exception occurred while obtaining a key event."); + LOGE_EX(env); + env->ExceptionClear(); + return NULL; + } + return eventObj; } -void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, +status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, KeyEvent* event) { jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId); jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource); @@ -77,6 +87,18 @@ void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, event->initialize(deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount, milliseconds_to_nanoseconds(downTime), milliseconds_to_nanoseconds(eventTime)); + return OK; +} + +status_t android_view_KeyEvent_recycle(JNIEnv* env, jobject eventObj) { + env->CallVoidMethod(eventObj, gKeyEventClassInfo.recycle); + if (env->ExceptionCheck()) { + LOGW("An exception occurred while recycling a key event."); + LOGW_EX(env); + env->ExceptionClear(); + return UNKNOWN_ERROR; + } + return OK; } static jboolean native_isSystemKey(JNIEnv* env, jobject clazz, jint keyCode) { @@ -87,6 +109,7 @@ static jboolean native_hasDefaultAction(JNIEnv* env, jobject clazz, jint keyCode return KeyEvent::hasDefaultAction(keyCode); } + // ---------------------------------------------------------------------------- static const JNINativeMethod g_methods[] = { @@ -99,6 +122,10 @@ static const JNINativeMethod g_methods[] = { LOG_FATAL_IF(! var, "Unable to find class " className); \ var = jclass(env->NewGlobalRef(var)); +#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ + var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find static method" methodName); + #define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ var = env->GetMethodID(clazz, methodName, fieldDescriptor); \ LOG_FATAL_IF(! var, "Unable to find method" methodName); @@ -109,9 +136,11 @@ static const JNINativeMethod g_methods[] = { int register_android_view_KeyEvent(JNIEnv* env) { FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); - - GET_METHOD_ID(gKeyEventClassInfo.ctor, gKeyEventClassInfo.clazz, - "<init>", "(JJIIIIIIII)V"); + + GET_STATIC_METHOD_ID(gKeyEventClassInfo.obtain, gKeyEventClassInfo.clazz, + "obtain", "(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;"); + GET_METHOD_ID(gKeyEventClassInfo.recycle, gKeyEventClassInfo.clazz, + "recycle", "()V"); GET_FIELD_ID(gKeyEventClassInfo.mDeviceId, gKeyEventClassInfo.clazz, "mDeviceId", "I"); diff --git a/core/jni/android_view_KeyEvent.h b/core/jni/android_view_KeyEvent.h index 0bd410c..586eb2f 100644 --- a/core/jni/android_view_KeyEvent.h +++ b/core/jni/android_view_KeyEvent.h @@ -18,18 +18,28 @@ #define _ANDROID_VIEW_KEYEVENT_H #include "jni.h" +#include <utils/Errors.h> +#include <utils/threads.h> namespace android { class KeyEvent; -/* Obtains an instance of a DVM KeyEvent object as a copy of a native KeyEvent instance. */ +/* Obtains an instance of a DVM KeyEvent object as a copy of a native KeyEvent instance. + * Returns NULL on error. */ extern jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event); -/* Copies the contents of a DVM KeyEvent object to a native KeyEvent instance. */ -extern void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, +/* Copies the contents of a DVM KeyEvent object to a native KeyEvent instance. + * Returns non-zero on error. */ +extern status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, KeyEvent* event); +/* Recycles a DVM KeyEvent object. + * Key events should only be recycled if they are owned by the system since user + * code expects them to be essentially immutable, "tracking" notwithstanding. + * Returns non-zero on error. */ +extern status_t android_view_KeyEvent_recycle(JNIEnv* env, jobject eventObj); + } // namespace android #endif // _ANDROID_OS_KEYEVENT_H diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp index 537ac72..f32f0ff 100644 --- a/core/jni/android_view_MotionEvent.cpp +++ b/core/jni/android_view_MotionEvent.cpp @@ -169,7 +169,7 @@ jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* even return eventObj; } -void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, +status_t android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, MotionEvent* event) { jint deviceId = env->GetIntField(eventObj, gMotionEventClassInfo.mDeviceId); jint source = env->GetIntField(eventObj, gMotionEventClassInfo.mSource); @@ -184,6 +184,16 @@ void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, jint flags = env->GetIntField(eventObj, gMotionEventClassInfo.mFlags); jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers); jint numSamples = env->GetIntField(eventObj, gMotionEventClassInfo.mNumSamples); + + if (numPointers == 0) { + LOGE("Malformed MotionEvent: mNumPointers was zero"); + return BAD_VALUE; + } + if (numSamples == 0) { + LOGE("Malformed MotionEvent: mNumSamples was zero"); + return BAD_VALUE; + } + jintArray pointerIdentifierArray = jintArray(env->GetObjectField(eventObj, gMotionEventClassInfo.mPointerIdentifiers)); jfloatArray dataSampleArray = jfloatArray(env->GetObjectField(eventObj, @@ -191,9 +201,6 @@ void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, jlongArray eventTimeNanoSampleArray = jlongArray(env->GetObjectField(eventObj, gMotionEventClassInfo.mEventTimeNanoSamples)); - LOG_FATAL_IF(numPointers == 0, "numPointers was zero"); - LOG_FATAL_IF(numSamples == 0, "numSamples was zero"); - jint* pointerIdentifiers = (jint*)env->GetPrimitiveArrayCritical(pointerIdentifierArray, NULL); jfloat* dataSamples = (jfloat*)env->GetPrimitiveArrayCritical(dataSampleArray, NULL); jlong* eventTimeNanoSamples = (jlong*)env->GetPrimitiveArrayCritical( @@ -236,22 +243,25 @@ void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, event->addSample(sampleEventTime, samplePointerCoords); } - env->ReleasePrimitiveArrayCritical(pointerIdentifierArray, pointerIdentifiers, JNI_ABORT); - env->ReleasePrimitiveArrayCritical(dataSampleArray, dataSamples, JNI_ABORT); env->ReleasePrimitiveArrayCritical(eventTimeNanoSampleArray, eventTimeNanoSamples, JNI_ABORT); + env->ReleasePrimitiveArrayCritical(dataSampleArray, dataSamples, JNI_ABORT); + env->ReleasePrimitiveArrayCritical(pointerIdentifierArray, pointerIdentifiers, JNI_ABORT); - env->DeleteLocalRef(pointerIdentifierArray); - env->DeleteLocalRef(dataSampleArray); env->DeleteLocalRef(eventTimeNanoSampleArray); + env->DeleteLocalRef(dataSampleArray); + env->DeleteLocalRef(pointerIdentifierArray); + return OK; } -void android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) { +status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) { env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle); if (env->ExceptionCheck()) { LOGW("An exception occurred while recycling a motion event."); LOGW_EX(env); env->ExceptionClear(); + return UNKNOWN_ERROR; } + return OK; } static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { diff --git a/core/jni/android_view_MotionEvent.h b/core/jni/android_view_MotionEvent.h index 86e4bde..80dc861 100644 --- a/core/jni/android_view_MotionEvent.h +++ b/core/jni/android_view_MotionEvent.h @@ -18,20 +18,24 @@ #define _ANDROID_VIEW_MOTIONEVENT_H #include "jni.h" +#include <utils/Errors.h> namespace android { class MotionEvent; -/* Obtains an instance of a DVM MotionEvent object as a copy of a native MotionEvent instance. */ +/* Obtains an instance of a DVM MotionEvent object as a copy of a native MotionEvent instance. + * Returns NULL on error. */ extern jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* event); -/* Copies the contents of a DVM MotionEvent object to a native MotionEvent instance. */ -extern void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, +/* Copies the contents of a DVM MotionEvent object to a native MotionEvent instance. + * Returns non-zero on error. */ +extern status_t android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, MotionEvent* event); -/* Recycles a DVM MotionEvent object. */ -extern void android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj); +/* Recycles a DVM MotionEvent object. + * Returns non-zero on error. */ +extern status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj); } // namespace android diff --git a/include/ui/Input.h b/include/ui/Input.h index 11b798f..4dc8f2a 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -507,10 +507,8 @@ enum InputDeviceConfigurationFileType { /* * Get the path of an input device configuration file, if one is available. * Spaces in the name are replaced with underscores. + * Considers both system provided and user installed configuration files. * - * Looks in: <system-root>/usr/<type-specific-directory>/<name><extension>. - * - * TODO Also look in a user installable location. * Returns an empty string if not found. */ extern String8 getInputDeviceConfigurationFilePath( diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h index d0812de..b621680 100644 --- a/include/ui/InputDispatcher.h +++ b/include/ui/InputDispatcher.h @@ -291,9 +291,7 @@ public: * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event * should be dispatched to applications. */ - virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId, - int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode, - uint32_t& policyFlags) = 0; + virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0; /* Intercepts a generic touch, trackball or other event before queueing it. * The policy can use this method as an opportunity to perform power management functions @@ -894,9 +892,6 @@ private: // Input channels that will receive a copy of all input events. Vector<sp<InputChannel> > mMonitoringChannels; - // Preallocated key event object used for policy inquiries. - KeyEvent mReusableKeyEvent; - // Event injection and synchronization. Condition mInjectionResultAvailableCondition; bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid); diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index f831086..b312cda 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -146,12 +146,12 @@ uint32_t EventHub::getDeviceClasses(int32_t deviceId) const } void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const { - outConfiguration->clear(); - AutoMutex _l(mLock); device_t* device = getDeviceLocked(deviceId); if (device && device->configuration) { *outConfiguration = *device->configuration; + } else { + outConfiguration->clear(); } } diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index db7d448..0708223 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -2081,9 +2081,22 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou return; } + if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { + policyFlags |= POLICY_FLAG_VIRTUAL; + flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; + } + policyFlags |= POLICY_FLAG_TRUSTED; - mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags, - keyCode, scanCode, /*byref*/ policyFlags); + + KeyEvent event; + event.initialize(deviceId, source, action, flags, keyCode, scanCode, + metaState, 0, downTime, eventTime); + + mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); + + if (policyFlags & POLICY_FLAG_WOKE_HERE) { + flags |= AKEY_EVENT_FLAG_WOKE_HERE; + } bool needWake; { // acquire lock @@ -2289,17 +2302,22 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, return INPUT_EVENT_INJECTION_FAILED; } - nsecs_t eventTime = keyEvent->getEventTime(); - int32_t deviceId = keyEvent->getDeviceId(); int32_t flags = keyEvent->getFlags(); - int32_t keyCode = keyEvent->getKeyCode(); - int32_t scanCode = keyEvent->getScanCode(); - mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags, - keyCode, scanCode, /*byref*/ policyFlags); + if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) { + policyFlags |= POLICY_FLAG_VIRTUAL; + } + + mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags); + + if (policyFlags & POLICY_FLAG_WOKE_HERE) { + flags |= AKEY_EVENT_FLAG_WOKE_HERE; + } mLock.lock(); - injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(), - policyFlags, action, flags, keyCode, scanCode, keyEvent->getMetaState(), + injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(), + keyEvent->getDeviceId(), keyEvent->getSource(), + policyFlags, action, flags, + keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), keyEvent->getRepeatCount(), keyEvent->getDownTime()); break; } @@ -2999,12 +3017,14 @@ void InputDispatcher::doNotifyANRLockedInterruptible( void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( CommandEntry* commandEntry) { KeyEntry* entry = commandEntry->keyEntry; - initializeKeyEvent(&mReusableKeyEvent, entry); + + KeyEvent event; + initializeKeyEvent(&event, entry); mLock.unlock(); bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel, - & mReusableKeyEvent, entry->policyFlags); + &event, entry->policyFlags); mLock.lock(); @@ -3025,12 +3045,13 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( && dispatchEntry->hasForegroundTarget() && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) { KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry); - initializeKeyEvent(&mReusableKeyEvent, keyEntry); + KeyEvent event; + initializeKeyEvent(&event, keyEntry); mLock.unlock(); mPolicy->dispatchUnhandledKey(connection->inputChannel, - & mReusableKeyEvent, keyEntry->policyFlags); + &event, keyEntry->policyFlags); mLock.lock(); } diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp index dc9085b..aa690e5 100644 --- a/libs/ui/InputReader.cpp +++ b/libs/ui/InputReader.cpp @@ -2007,7 +2007,7 @@ void TouchInputMapper::dumpCalibration(String8& dump) { } if (mCalibration.haveToolSizeIsSummed) { - dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %d\n", + dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n", toString(mCalibration.toolSizeIsSummed)); } diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp index f352dbf..68f9037 100644 --- a/libs/ui/tests/InputDispatcher_test.cpp +++ b/libs/ui/tests/InputDispatcher_test.cpp @@ -54,9 +54,7 @@ private: return 60; } - virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId, - int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode, - uint32_t& policyFlags) { + virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) { } virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 1373627..c528745 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -1215,11 +1215,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, - int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) { + public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { final boolean keyguardOn = keyguardOn(); - final boolean down = (action == KeyEvent.ACTION_DOWN); - final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0); + final int keyCode = event.getKeyCode(); + final int repeatCount = event.getRepeatCount(); + final int metaState = event.getMetaState(); + final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; + final boolean canceled = event.isCanceled(); if (false) { Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" @@ -1348,7 +1350,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Shortcuts are invoked through Search+key, so intercept those here if (mSearchKeyPressed) { if (down && repeatCount == 0 && !keyguardOn) { - Intent shortcutIntent = mShortcutManager.getIntent(keyCode, metaState); + Intent shortcutIntent = mShortcutManager.getIntent(event); if (shortcutIntent != null) { shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(shortcutIntent); @@ -1368,13 +1370,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public boolean dispatchUnhandledKey(WindowState win, int action, int flags, - int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) { + public boolean dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { if (false) { - Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + action - + ", flags=" + flags + ", keyCode=" + keyCode - + ", scanCode=" + scanCode + ", metaState=" + metaState - + ", repeatCount=" + repeatCount + ", policyFlags=" + policyFlags); + Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() + + ", flags=" + event.getFlags() + + ", keyCode=" + event.getKeyCode() + + ", scanCode=" + event.getScanCode() + + ", metaState=" + event.getMetaState() + + ", repeatCount=" + event.getRepeatCount() + + ", policyFlags=" + policyFlags); } return false; } @@ -1970,10 +1974,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, - int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { - final boolean down = action == KeyEvent.ACTION_DOWN; - final boolean canceled = (flags & KeyEvent.FLAG_CANCELED) != 0; + public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { + final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; + final boolean canceled = event.isCanceled(); + final int keyCode = event.getKeyCode(); final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; @@ -2164,12 +2168,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Only do this if we would otherwise not pass it to the user. In that // case, the PhoneWindow class will do the same thing, except it will // only do it if the showing app doesn't process the key on its own. - long when = whenNanos / 1000000; - KeyEvent keyEvent = new KeyEvent(when, when, action, keyCode, 0, 0, - KeyCharacterMap.VIRTUAL_KEYBOARD, scanCode, flags, - InputDevice.SOURCE_KEYBOARD); mBroadcastWakeLock.acquire(); - mHandler.post(new PassHeadsetKey(keyEvent)); + mHandler.post(new PassHeadsetKey(new KeyEvent(event))); } break; } diff --git a/policy/src/com/android/internal/policy/impl/ShortcutManager.java b/policy/src/com/android/internal/policy/impl/ShortcutManager.java index 51377d8..fc66a20 100644 --- a/policy/src/com/android/internal/policy/impl/ShortcutManager.java +++ b/policy/src/com/android/internal/policy/impl/ShortcutManager.java @@ -25,6 +25,7 @@ import android.provider.Settings; import android.util.Log; import android.util.SparseArray; import android.view.KeyCharacterMap; +import android.view.KeyEvent; import java.net.URISyntaxException; @@ -100,20 +101,17 @@ class ShortcutManager extends ContentObserver { * This will first try an exact match (with modifiers), and then try a * match without modifiers (primary character on a key). * - * @param keyCode The keycode of the key pushed. - * @param modifiers The modifiers without any that are used for chording - * to invoke a shortcut. + * @param event The key event of the key that was pressed. * @return The intent that matches the shortcut, or null if not found. */ - public Intent getIntent(int keyCode, int modifiers) { - KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); + public Intent getIntent(KeyEvent event) { // First try the exact keycode (with modifiers) - int shortcut = kcm.get(keyCode, modifiers); + int shortcut = event.getUnicodeChar(); Intent intent = shortcut != 0 ? mShortcutIntents.get(shortcut) : null; if (intent != null) return intent; - + // Next try the keycode without modifiers (the primary character on that key) - shortcut = Character.toLowerCase(kcm.get(keyCode, 0)); + shortcut = Character.toLowerCase(event.getUnicodeChar(0)); return shortcut != 0 ? mShortcutIntents.get(shortcut) : null; } diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index 30b49d3..9078811 100644 --- a/services/java/com/android/server/InputManager.java +++ b/services/java/com/android/server/InputManager.java @@ -30,6 +30,7 @@ import android.util.Xml; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; +import android.view.KeyEvent; import android.view.Surface; import java.io.BufferedReader; @@ -398,26 +399,23 @@ public class InputManager { } @SuppressWarnings("unused") - public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, - int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { + public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing( - whenNanos, action, flags, keyCode, scanCode, policyFlags, isScreenOn); + event, policyFlags, isScreenOn); } @SuppressWarnings("unused") - public boolean interceptKeyBeforeDispatching(InputChannel focus, int action, - int flags, int keyCode, int scanCode, int metaState, int repeatCount, - int policyFlags) { - return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus, - action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags); + public boolean interceptKeyBeforeDispatching(InputChannel focus, + KeyEvent event, int policyFlags) { + return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching( + focus, event, policyFlags); } @SuppressWarnings("unused") - public boolean dispatchUnhandledKey(InputChannel focus, int action, - int flags, int keyCode, int scanCode, int metaState, int repeatCount, - int policyFlags) { - return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(focus, - action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags); + public boolean dispatchUnhandledKey(InputChannel focus, + KeyEvent event, int policyFlags) { + return mWindowManagerService.mInputMonitor.dispatchUnhandledKey( + focus, event, policyFlags); } @SuppressWarnings("unused") diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index cbb35c6..5e49404 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5829,30 +5829,25 @@ public class WindowManagerService extends IWindowManager.Stub /* Provides an opportunity for the window manager policy to intercept early key * processing as soon as the key has been read from the device. */ - public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, - int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { - return mPolicy.interceptKeyBeforeQueueing(whenNanos, action, flags, - keyCode, scanCode, policyFlags, isScreenOn); + public int interceptKeyBeforeQueueing( + KeyEvent event, int policyFlags, boolean isScreenOn) { + return mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn); } /* Provides an opportunity for the window manager policy to process a key before * ordinary dispatch. */ - public boolean interceptKeyBeforeDispatching(InputChannel focus, - int action, int flags, int keyCode, int scanCode, int metaState, int repeatCount, - int policyFlags) { + public boolean interceptKeyBeforeDispatching( + InputChannel focus, KeyEvent event, int policyFlags) { WindowState windowState = getWindowStateForInputChannel(focus); - return mPolicy.interceptKeyBeforeDispatching(windowState, action, flags, - keyCode, scanCode, metaState, repeatCount, policyFlags); + 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 boolean dispatchUnhandledKey(InputChannel focus, - int action, int flags, int keyCode, int scanCode, int metaState, int repeatCount, - int policyFlags) { + public boolean dispatchUnhandledKey( + InputChannel focus, KeyEvent event, int policyFlags) { WindowState windowState = getWindowStateForInputChannel(focus); - return mPolicy.dispatchUnhandledKey(windowState, action, flags, - keyCode, scanCode, metaState, repeatCount, policyFlags); + return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags); } /* Called when the current input focus changes. diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index d0760c0..aa84db5 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -191,9 +191,7 @@ public: virtual nsecs_t getKeyRepeatTimeout(); virtual nsecs_t getKeyRepeatDelay(); virtual int32_t getMaxEventsPerSecond(); - virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId, - int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode, - uint32_t& policyFlags); + 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, const KeyEvent* keyEvent, uint32_t policyFlags); @@ -718,6 +716,7 @@ bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj, outWindow.ownerUid = ownerUid; env->ReleaseStringUTFChars(name, nameStr); + env->DeleteLocalRef(name); valid = true; } else { LOGW("Dropping input target because its input channel is not initialized."); @@ -779,20 +778,8 @@ bool NativeInputManager::isScreenBright() { return android_server_PowerManagerService_isScreenBright(); } -void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, - int32_t deviceId, int32_t action, int32_t &flags, - int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) { -#if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, " - "keyCode=%d, scanCode=%d, policyFlags=0x%x", - when, deviceId, action, flags, keyCode, scanCode, policyFlags); -#endif - - if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { - policyFlags |= POLICY_FLAG_VIRTUAL; - flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; - } - +void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, + uint32_t& policyFlags) { // Policy: // - Ignore untrusted events and pass them along. // - Ask the window manager what to do with normal events and trusted injected events. @@ -802,21 +789,30 @@ void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2; const int32_t WM_ACTION_GO_TO_SLEEP = 4; + nsecs_t when = keyEvent->getEventTime(); bool isScreenOn = this->isScreenOn(); bool isScreenBright = this->isScreenBright(); JNIEnv* env = jniEnv(); - jint wmActions = env->CallIntMethod(mCallbacksObj, - gCallbacksClassInfo.interceptKeyBeforeQueueing, - when, action, flags, keyCode, scanCode, policyFlags, isScreenOn); - if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { + jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); + jint wmActions; + if (keyEventObj) { + wmActions = env->CallIntMethod(mCallbacksObj, + gCallbacksClassInfo.interceptKeyBeforeQueueing, + keyEventObj, policyFlags, isScreenOn); + if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { + wmActions = 0; + } + android_view_KeyEvent_recycle(env, keyEventObj); + env->DeleteLocalRef(keyEventObj); + } else { + LOGE("Failed to obtain key event object for interceptKeyBeforeQueueing."); wmActions = 0; } - if (!(flags & POLICY_FLAG_INJECTED)) { + if (!(policyFlags & POLICY_FLAG_INJECTED)) { if (!isScreenOn) { policyFlags |= POLICY_FLAG_WOKE_HERE; - flags |= AKEY_EVENT_FLAG_WOKE_HERE; } if (!isScreenBright) { @@ -841,10 +837,6 @@ void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, } void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { -#if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags); -#endif - // Policy: // - Ignore untrusted events and pass them along. // - No special filtering for injected events required at this time. @@ -869,46 +861,62 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& i // - Ignore untrusted events and pass them along. // - Filter normal events and trusted injected events through the window manager policy to // handle the HOME key and the like. + bool result; if (policyFlags & POLICY_FLAG_TRUSTED) { JNIEnv* env = jniEnv(); // Note: inputChannel may be null. jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel); - jboolean consumed = env->CallBooleanMethod(mCallbacksObj, - gCallbacksClassInfo.interceptKeyBeforeDispatching, - inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), - keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), - keyEvent->getRepeatCount(), policyFlags); - bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); + jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); + if (keyEventObj) { + jboolean consumed = env->CallBooleanMethod(mCallbacksObj, + gCallbacksClassInfo.interceptKeyBeforeDispatching, + inputChannelObj, keyEventObj, policyFlags); + bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); + android_view_KeyEvent_recycle(env, keyEventObj); + env->DeleteLocalRef(keyEventObj); + result = consumed && !error; + } else { + LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching."); + result = false; + } env->DeleteLocalRef(inputChannelObj); - return consumed && ! error; } else { - return false; + result = false; } + return result; } bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel, const KeyEvent* keyEvent, uint32_t policyFlags) { // Policy: // - Ignore untrusted events and do not perform default handling. + bool result; if (policyFlags & POLICY_FLAG_TRUSTED) { JNIEnv* env = jniEnv(); // Note: inputChannel may be null. jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel); - jboolean handled = env->CallBooleanMethod(mCallbacksObj, - gCallbacksClassInfo.dispatchUnhandledKey, - inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), - keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), - keyEvent->getRepeatCount(), policyFlags); - bool error = checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey"); + jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); + if (keyEventObj) { + jboolean handled = env->CallBooleanMethod(mCallbacksObj, + gCallbacksClassInfo.dispatchUnhandledKey, + inputChannelObj, keyEventObj, policyFlags); + bool error = checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey"); + android_view_KeyEvent_recycle(env, keyEventObj); + env->DeleteLocalRef(keyEventObj); + result = handled && !error; + } else { + LOGE("Failed to obtain key event object for dispatchUnhandledKey."); + result = false; + } env->DeleteLocalRef(inputChannelObj); - return handled && ! error; } else { - return false; + result = false; } + return result; } void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) { @@ -1107,13 +1115,21 @@ static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jcla if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) { KeyEvent keyEvent; - android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent); + status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent); + if (status) { + jniThrowRuntimeException(env, "Could not read contents of KeyEvent object."); + return INPUT_EVENT_INJECTION_FAILED; + } return gNativeInputManager->getInputManager()->getDispatcher()->injectInputEvent( & keyEvent, injectorPid, injectorUid, syncMode, timeoutMillis); } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) { MotionEvent motionEvent; - android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent); + status_t status = android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent); + if (status) { + jniThrowRuntimeException(env, "Could not read contents of MotionEvent object."); + return INPUT_EVENT_INJECTION_FAILED; + } return gNativeInputManager->getInputManager()->getDispatcher()->injectInputEvent( & motionEvent, injectorPid, injectorUid, syncMode, timeoutMillis); @@ -1332,13 +1348,14 @@ int register_android_server_InputManager(JNIEnv* env) { "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J"); GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz, - "interceptKeyBeforeQueueing", "(JIIIIIZ)I"); + "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I"); GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz, - "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIIII)Z"); + "interceptKeyBeforeDispatching", + "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z"); GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz, - "dispatchUnhandledKey", "(Landroid/view/InputChannel;IIIIIII)Z"); + "dispatchUnhandledKey", "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z"); GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz, "checkInjectEventsPermission", "(II)Z"); |