summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml2
-rw-r--r--core/java/android/view/KeyCharacterMap.java12
-rwxr-xr-xcore/java/android/view/KeyEvent.java74
-rw-r--r--core/java/android/view/MotionEvent.java12
-rw-r--r--core/java/android/view/WindowManagerPolicy.java29
-rw-r--r--core/jni/android_app_NativeActivity.cpp33
-rw-r--r--core/jni/android_view_KeyEvent.cpp43
-rw-r--r--core/jni/android_view_KeyEvent.h16
-rw-r--r--core/jni/android_view_MotionEvent.cpp28
-rw-r--r--core/jni/android_view_MotionEvent.h14
-rw-r--r--include/ui/Input.h4
-rw-r--r--include/ui/InputDispatcher.h7
-rw-r--r--libs/ui/EventHub.cpp4
-rw-r--r--libs/ui/InputDispatcher.cpp49
-rw-r--r--libs/ui/InputReader.cpp2
-rw-r--r--libs/ui/tests/InputDispatcher_test.cpp4
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java40
-rw-r--r--policy/src/com/android/internal/policy/impl/ShortcutManager.java14
-rw-r--r--services/java/com/android/server/InputManager.java24
-rw-r--r--services/java/com/android/server/WindowManagerService.java23
-rw-r--r--services/jni/com_android_server_InputManager.cpp113
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");