1.interceptKeyBeforeQueueing
顾名思义在加入队列之前拦截事件,调用过程如下分析
inputDispatch.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
...
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
...
}
此处的mPolicy对应的就是com_android_server_input_InputManagerService.cpp的this.即是此类
详细见这个方法
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp
mLooper(looper), mInteractive(true) {
...
sp
mInputManager = new InputManager(eventHub, this, this);
}
调用mPolicy->interceptKeyBeforeQueueing也就是调用com_android_server_input_InputManagerService.cpp的interceptKeyBeforeQueueing
代码如下:
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.
// - For normal events wake and brighten the screen if currently off or dim.
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) {
//此处表示调用InputManagerService.java层的interceptKeyBeforeQueueing
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 (interactive) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
}
wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj, policyFlags);
此为jni的调用方式,表示调用java层的interceptKeyBeforeQueueing方法
handleInterceptActions这个方法会把返回值wmActions转换为policyFlags的值,policyFlags会封装成KeyEntry类型给inputDispatch.后面会根据这个值表示要不要传递给应用
到了InputManagerService.java层的interceptKeyBeforeQueueing方法
// Native callback.
private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
whenNanos, policyFlags);
}
此处mWindowManagerCallbacks对应的是InputMonitor(在systemServer.java里设置inputManager.setWindowManagerCallbacks(wm.getInputMonitor());)
InputMonitor.cpp
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
if(mService.mTestFlag)//for POWER_KEY
return 0x00000001;
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
此处mPolicy对应的就是PhoneWindowManager.java
InputDispatcher::notifyKey是在inputReader.cpp里面通过方法processKey调用
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
int32_t usageCode) {
...
getListener()->notifyKey(&args);
}
此处见博客Android输入InputManagerService的启动和事件读取过程中有说明
到此interceptKeyBeforeQueueing结束
2.interceptKeyBeforeDispatching
顾名思义在分发之前拦截
在inputDispatch.cpp里面的方法dispatchKeyLocked处理.
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
...
// Give the policy a chance to intercept the key.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
if (mFocusedWindowHandle != NULL) {
commandEntry->inputWindowHandle = mFocusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
return false; // wait for the command to run
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
}
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
if (*dropReason == DROP_REASON_NOT_DROPPED) {
*dropReason = DROP_REASON_POLICY;
}
}
...
}
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
CommandEntry* commandEntry) {
KeyEntry* entry = commandEntry->keyEntry;
KeyEvent event;
initializeKeyEvent(&event, entry);
mLock.unlock();
nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
&event, entry->policyFlags);
mLock.lock();
if (delay < 0) {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
} else if (!delay) {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
entry->interceptKeyWakeupTime = now() + delay;
}
entry->release();
}
doInterceptKeyBeforeDispatchingLockedInterruptible调用mPolicy->interceptKeyBeforeDispatching,
mPolicy同上,对应的是com_android_server_input_InputManagerService.cpp
代码如下
nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
const sp
const KeyEvent* keyEvent, uint32_t policyFlags) {
// 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();
// Note: inputWindowHandle may be null.
jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jlong delayMillis = env->CallLongMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeDispatching,
inputWindowHandleObj, 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.");
}
env->DeleteLocalRef(inputWindowHandleObj);
}
return result;
}
interceptKeyBeforeDispatching调用的是InputManagerService.java层的interceptKeyBeforeQueueing.其它同上调用过程,最后到PhoneWindowManager.java的interceptKeyBeforeDispatching