Merge changes from topic "dispatcher-policy-cleanup" into udc-dev

* changes:
  Clean up KeyEvent JNI APIs
  Clean up JNI methods of InputDispatcherPolicy
  Clean up InputDispatcherPolicyInterface
This commit is contained in:
Prabir Pradhan
2023-05-03 14:45:40 +00:00
committed by Android (Google) Code Review
8 changed files with 155 additions and 179 deletions

View File

@@ -374,7 +374,7 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
}
inputEventObj =
android_view_KeyEvent_fromNative(env,
static_cast<KeyEvent*>(inputEvent));
static_cast<KeyEvent&>(*inputEvent));
break;
case InputEventType::MOTION: {

View File

@@ -353,8 +353,7 @@ static jboolean nativeSendKeyEvent(JNIEnv* env, jclass clazz, jlong senderPtr,
jint seq, jobject eventObj) {
sp<NativeInputEventSender> sender =
reinterpret_cast<NativeInputEventSender*>(senderPtr);
KeyEvent event;
android_view_KeyEvent_toNative(env, eventObj, &event);
const KeyEvent event = android_view_KeyEvent_toNative(env, eventObj);
status_t status = sender->sendKeyEvent(seq, &event);
return !status;
}

View File

@@ -221,12 +221,7 @@ static jlong nativeSendKeyEvent(JNIEnv* env, jobject clazz, jlong ptr, jobject e
jboolean predispatch) {
InputQueue* queue = reinterpret_cast<InputQueue*>(ptr);
KeyEvent* event = queue->createKeyEvent();
status_t status = android_view_KeyEvent_toNative(env, eventObj, event);
if (status) {
queue->recycleInputEvent(event);
jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
return -1;
}
*event = android_view_KeyEvent_toNative(env, eventObj);
if (predispatch) {
event->setFlags(event->getFlags() | AKEY_EVENT_FLAG_PREDISPATCH);

View File

@@ -217,7 +217,7 @@ static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jlong ptr,
result = env->NewObjectArray(jsize(events.size()), gKeyEventClassInfo.clazz, NULL);
if (result) {
for (size_t i = 0; i < events.size(); i++) {
jobject keyEventObj = android_view_KeyEvent_fromNative(env, &events.itemAt(i));
jobject keyEventObj = android_view_KeyEvent_fromNative(env, events.itemAt(i));
if (!keyEventObj) break; // threw OOM exception
env->SetObjectArrayElement(result, jsize(i), keyEventObj);
env->DeleteLocalRef(keyEventObj);

View File

@@ -94,16 +94,16 @@ static struct {
// ----------------------------------------------------------------------------
jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
ScopedLocalRef<jbyteArray> hmac = toJbyteArray(env, event->getHmac());
jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent& event) {
ScopedLocalRef<jbyteArray> hmac = toJbyteArray(env, event.getHmac());
jobject eventObj =
env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, gKeyEventClassInfo.obtain,
event->getId(), event->getDownTime(), event->getEventTime(),
event->getAction(), event->getKeyCode(),
event->getRepeatCount(), event->getMetaState(),
event->getDeviceId(), event->getScanCode(),
event->getFlags(), event->getSource(),
event->getDisplayId(), hmac.get(), nullptr);
event.getId(), event.getDownTime(), event.getEventTime(),
event.getAction(), event.getKeyCode(),
event.getRepeatCount(), event.getMetaState(),
event.getDeviceId(), event.getScanCode(), event.getFlags(),
event.getSource(), event.getDisplayId(), hmac.get(),
nullptr);
if (env->ExceptionCheck()) {
ALOGE("An exception occurred while obtaining a key event.");
LOGE_EX(env);
@@ -113,8 +113,7 @@ jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
return eventObj;
}
status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
KeyEvent* event) {
KeyEvent android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj) {
jint id = env->GetIntField(eventObj, gKeyEventClassInfo.mId);
jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
@@ -133,9 +132,10 @@ status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
event->initialize(id, deviceId, source, displayId, *hmac, action, flags, keyCode, scanCode,
metaState, repeatCount, downTime, eventTime);
return OK;
KeyEvent event;
event.initialize(id, deviceId, source, displayId, *hmac, action, flags, keyCode, scanCode,
metaState, repeatCount, downTime, eventTime);
return event;
}
status_t android_view_KeyEvent_recycle(JNIEnv* env, jobject eventObj) {

View File

@@ -27,12 +27,11 @@ class KeyEvent;
/* 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);
extern jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent& event);
/* 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);
extern KeyEvent android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj);
/* Recycles a DVM KeyEvent object.
* Key events should only be recycled if they are owned by the system since user

View File

@@ -87,11 +87,8 @@ int64_t AKeyEvent_getDownTime(const AInputEvent* key_event) {
const AInputEvent* AKeyEvent_fromJava(JNIEnv* env, jobject keyEvent) {
std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
android::status_t ret = android::android_view_KeyEvent_toNative(env, keyEvent, event.get());
if (ret == android::OK) {
return event.release();
}
return nullptr;
*event = android::android_view_KeyEvent_toNative(env, keyEvent);
return event.release();
}
int64_t AKeyEvent_getEventTime(const AInputEvent* key_event) {

View File

@@ -342,15 +342,15 @@ public:
void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy) override;
void notifyVibratorState(int32_t deviceId, bool isOn) override;
bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override;
void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override;
void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) override;
void interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override;
InputDispatcherConfiguration getDispatcherConfiguration() override;
void interceptKeyBeforeQueueing(const KeyEvent& keyEvent, uint32_t& policyFlags) override;
void interceptMotionBeforeQueueing(int32_t displayId, nsecs_t when,
uint32_t& policyFlags) override;
nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token, const KeyEvent* keyEvent,
nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token, const KeyEvent& keyEvent,
uint32_t policyFlags) override;
bool dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent* keyEvent,
uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) override;
std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent& keyEvent,
uint32_t policyFlags) override;
void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override;
void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
void setPointerCapture(const PointerCaptureRequest& request) override;
@@ -450,7 +450,7 @@ NativeInputManager::NativeInputManager(jobject serviceObj, const sp<Looper>& loo
mServiceObj = env->NewGlobalRef(serviceObj);
InputManager* im = new InputManager(this, this);
InputManager* im = new InputManager(this, *this);
mInputManager = im;
defaultServiceManager()->addService(String16("inputflinger"), im);
}
@@ -1007,21 +1007,22 @@ void NativeInputManager::notifyVibratorState(int32_t deviceId, bool isOn) {
checkAndClearExceptionFromCallback(env, "notifyVibratorState");
}
void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
InputDispatcherConfiguration NativeInputManager::getDispatcherConfiguration() {
ATRACE_CALL();
InputDispatcherConfiguration config;
JNIEnv* env = jniEnv();
jint keyRepeatTimeout = env->CallIntMethod(mServiceObj,
gServiceClassInfo.getKeyRepeatTimeout);
jint keyRepeatTimeout = env->CallIntMethod(mServiceObj, gServiceClassInfo.getKeyRepeatTimeout);
if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
config.keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
}
jint keyRepeatDelay = env->CallIntMethod(mServiceObj,
gServiceClassInfo.getKeyRepeatDelay);
jint keyRepeatDelay = env->CallIntMethod(mServiceObj, gServiceClassInfo.getKeyRepeatDelay);
if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
config.keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
}
return config;
}
void NativeInputManager::displayRemoved(JNIEnv* env, int32_t displayId) {
@@ -1294,110 +1295,112 @@ void NativeInputManager::notifyStylusGestureStarted(int32_t deviceId, nsecs_t ev
checkAndClearExceptionFromCallback(env, "notifyStylusGestureStarted");
}
bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
bool NativeInputManager::filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) {
ATRACE_CALL();
jobject inputEventObj;
JNIEnv* env = jniEnv();
switch (inputEvent->getType()) {
ScopedLocalRef<jobject> inputEventObj(env);
switch (inputEvent.getType()) {
case InputEventType::KEY:
inputEventObj =
android_view_KeyEvent_fromNative(env, static_cast<const KeyEvent*>(inputEvent));
inputEventObj.reset(
android_view_KeyEvent_fromNative(env,
static_cast<const KeyEvent&>(inputEvent)));
break;
case InputEventType::MOTION:
inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
static_cast<const MotionEvent&>(
*inputEvent));
inputEventObj.reset(
android_view_MotionEvent_obtainAsCopy(env,
static_cast<const MotionEvent&>(
inputEvent)));
break;
default:
return true; // dispatch the event normally
}
if (!inputEventObj) {
if (!inputEventObj.get()) {
ALOGE("Failed to obtain input event object for filterInputEvent.");
return true; // dispatch the event normally
}
// The callee is responsible for recycling the event.
jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
inputEventObj, policyFlags);
const jboolean continueEventDispatch =
env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
inputEventObj.get(), policyFlags);
if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
pass = true;
return true; // dispatch the event normally
}
env->DeleteLocalRef(inputEventObj);
return pass;
return continueEventDispatch;
}
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
uint32_t& policyFlags) {
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent& keyEvent,
uint32_t& policyFlags) {
ATRACE_CALL();
// Policy:
// - Ignore untrusted events and pass them along.
// - Ask the window manager what to do with normal events and trusted injected events.
// - For normal events wake and brighten the screen if currently off or dim.
bool interactive = mInteractive.load();
const bool interactive = mInteractive.load();
if (interactive) {
policyFlags |= POLICY_FLAG_INTERACTIVE;
}
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
nsecs_t when = keyEvent->getEventTime();
JNIEnv* env = jniEnv();
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
jint wmActions;
if (keyEventObj) {
wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
wmActions = 0;
}
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
} else {
ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
wmActions = 0;
}
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
if ((policyFlags & POLICY_FLAG_TRUSTED) == 0) {
if (interactive) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
return;
}
const nsecs_t when = keyEvent.getEventTime();
JNIEnv* env = jniEnv();
ScopedLocalRef<jobject> keyEventObj(env, android_view_KeyEvent_fromNative(env, keyEvent));
if (!keyEventObj.get()) {
ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
return;
}
jint wmActions = env->CallIntMethod(mServiceObj, gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj.get(), policyFlags);
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
wmActions = 0;
}
android_view_KeyEvent_recycle(env, keyEventObj.get());
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
void NativeInputManager::interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,
uint32_t& policyFlags) {
void NativeInputManager::interceptMotionBeforeQueueing(int32_t displayId, nsecs_t when,
uint32_t& policyFlags) {
ATRACE_CALL();
// Policy:
// - Ignore untrusted events and pass them along.
// - No special filtering for injected events required at this time.
// - Filter normal events based on screen state.
// - For normal events brighten (but do not wake) the screen if currently dim.
bool interactive = mInteractive.load();
const bool interactive = mInteractive.load();
if (interactive) {
policyFlags |= POLICY_FLAG_INTERACTIVE;
}
if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
if (policyFlags & POLICY_FLAG_INTERACTIVE) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
} else {
JNIEnv* env = jniEnv();
jint wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
displayId, when, policyFlags);
if (checkAndClearExceptionFromCallback(env,
"interceptMotionBeforeQueueingNonInteractive")) {
wmActions = 0;
}
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
} else {
if ((policyFlags & POLICY_FLAG_TRUSTED) == 0 || (policyFlags & POLICY_FLAG_INJECTED)) {
if (interactive) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
return;
}
if (policyFlags & POLICY_FLAG_INTERACTIVE) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
return;
}
JNIEnv* env = jniEnv();
const jint wmActions =
env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
displayId, when, policyFlags);
if (checkAndClearExceptionFromCallback(env, "interceptMotionBeforeQueueingNonInteractive")) {
return;
}
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
@@ -1411,81 +1414,76 @@ void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
}
}
nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags) {
nsecs_t NativeInputManager::interceptKeyBeforeDispatching(const sp<IBinder>& token,
const KeyEvent& keyEvent,
uint32_t policyFlags) {
ATRACE_CALL();
// Policy:
// - 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.
nsecs_t result = 0;
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
ScopedLocalFrame localFrame(env);
// Token may be null
jobject tokenObj = javaObjectForIBinder(env, token);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jlong delayMillis = env->CallLongMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeDispatching,
tokenObj, keyEventObj, policyFlags);
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
if (!error) {
if (delayMillis < 0) {
result = -1;
} else if (delayMillis > 0) {
result = milliseconds_to_nanoseconds(delayMillis);
}
}
} else {
ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
}
if ((policyFlags & POLICY_FLAG_TRUSTED) == 0) {
return 0;
}
return result;
JNIEnv* env = jniEnv();
ScopedLocalFrame localFrame(env);
// Token may be null
ScopedLocalRef<jobject> tokenObj(env, javaObjectForIBinder(env, token));
ScopedLocalRef<jobject> keyEventObj(env, android_view_KeyEvent_fromNative(env, keyEvent));
if (!keyEventObj.get()) {
ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
return 0;
}
const jlong delayMillis =
env->CallLongMethod(mServiceObj, gServiceClassInfo.interceptKeyBeforeDispatching,
tokenObj.get(), keyEventObj.get(), policyFlags);
android_view_KeyEvent_recycle(env, keyEventObj.get());
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching")) {
return 0;
}
return delayMillis < 0 ? -1 : milliseconds_to_nanoseconds(delayMillis);
}
bool NativeInputManager::dispatchUnhandledKey(const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
std::optional<KeyEvent> NativeInputManager::dispatchUnhandledKey(const sp<IBinder>& token,
const KeyEvent& keyEvent,
uint32_t policyFlags) {
ATRACE_CALL();
// Policy:
// - Ignore untrusted events and do not perform default handling.
bool result = false;
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
ScopedLocalFrame localFrame(env);
// Note: tokenObj may be null.
jobject tokenObj = javaObjectForIBinder(env, token);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj,
gServiceClassInfo.dispatchUnhandledKey,
tokenObj, keyEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
fallbackKeyEventObj = nullptr;
}
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
if (fallbackKeyEventObj) {
// Note: outFallbackKeyEvent may be the same object as keyEvent.
if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj,
outFallbackKeyEvent)) {
result = true;
}
android_view_KeyEvent_recycle(env, fallbackKeyEventObj);
env->DeleteLocalRef(fallbackKeyEventObj);
}
} else {
ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
}
if ((policyFlags & POLICY_FLAG_TRUSTED) == 0) {
return {};
}
return result;
JNIEnv* env = jniEnv();
ScopedLocalFrame localFrame(env);
// Note: tokenObj may be null.
ScopedLocalRef<jobject> tokenObj(env, javaObjectForIBinder(env, token));
ScopedLocalRef<jobject> keyEventObj(env, android_view_KeyEvent_fromNative(env, keyEvent));
if (!keyEventObj.get()) {
ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
return {};
}
ScopedLocalRef<jobject>
fallbackKeyEventObj(env,
env->CallObjectMethod(mServiceObj,
gServiceClassInfo.dispatchUnhandledKey,
tokenObj.get(), keyEventObj.get(),
policyFlags));
android_view_KeyEvent_recycle(env, keyEventObj.get());
if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey") ||
!fallbackKeyEventObj.get()) {
return {};
}
const KeyEvent fallbackEvent = android_view_KeyEvent_toNative(env, fallbackKeyEventObj.get());
android_view_KeyEvent_recycle(env, fallbackKeyEventObj.get());
return fallbackEvent;
}
void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) {
@@ -1876,13 +1874,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject i
InputEventInjectionSync mode = static_cast<InputEventInjectionSync>(syncMode);
if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
KeyEvent keyEvent;
status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
if (status) {
jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
return static_cast<jint>(InputEventInjectionResult::FAILED);
}
const KeyEvent keyEvent = android_view_KeyEvent_toNative(env, inputEventObj);
const InputEventInjectionResult result =
im->getInputManager()->getDispatcher().injectInputEvent(&keyEvent, targetUid, mode,
std::chrono::milliseconds(
@@ -1913,13 +1905,7 @@ static jobject nativeVerifyInputEvent(JNIEnv* env, jobject nativeImplObj, jobjec
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
KeyEvent keyEvent;
status_t status = android_view_KeyEvent_toNative(env, inputEventObj, &keyEvent);
if (status) {
jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
return nullptr;
}
const KeyEvent keyEvent = android_view_KeyEvent_toNative(env, inputEventObj);
std::unique_ptr<VerifiedInputEvent> verifiedEvent =
im->getInputManager()->getDispatcher().verifyInputEvent(keyEvent);
if (verifiedEvent == nullptr) {