前面的事件派发过程就跳过了,从PhoneWindowManager开始说起
安全模式简述
android平台,在长按power / menu键时会快速进入一个模式选择,部分定制的平台是直接进入安装模式,也可以定制成公司需要的一些特定功能模式,比如报警 ...
power 也属于全局的特殊按键,同样在PhoneWindowManager.java中被捕获处理。
Power键(long)监听流程
InputDispatcher.cpp 中InputDispatcher::notifyKey分发按键
[cpp] view plain copy
- void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
- #if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
- "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
- args->eventTime, args->deviceId, args->source, args->policyFlags,
- args->action, args->flags, args->keyCode, args->scanCode,
- args->metaState, args->downTime);
- #endif
- if (!validateKeyEvent(args->action)) {
- return;
- }
- uint32_t policyFlags = args->policyFlags;
- int32_t flags = args->flags;
- int32_t metaState = args->metaState;
- if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
- }
- if (policyFlags & POLICY_FLAG_FUNCTION) {
- metaState |= AMETA_FUNCTION_ON;
- }
- policyFlags |= POLICY_FLAG_TRUSTED;
- int32_t keyCode = args->keyCode;
- if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {
- int32_t newKeyCode = AKEYCODE_UNKNOWN;
- if (keyCode == AKEYCODE_DEL) {
- newKeyCode = AKEYCODE_BACK;
- } else if (keyCode == AKEYCODE_ENTER) {
- newKeyCode = AKEYCODE_HOME;
- }
- if (newKeyCode != AKEYCODE_UNKNOWN) {
- AutoMutex _l(mLock);
- struct KeyReplacement replacement = {keyCode, args->deviceId};
- mReplacedKeys.add(replacement, newKeyCode);
- keyCode = newKeyCode;
- metaState &= ~AMETA_META_ON;
- }
- } else if (args->action == AKEY_EVENT_ACTION_UP) {
- // In order to maintain a consistent stream of up and down events, check to see if the key
- // going up is one we've replaced in a down event and haven't yet replaced in an up event,
- // even if the modifier was released between the down and the up events.
- AutoMutex _l(mLock);
- struct KeyReplacement replacement = {keyCode, args->deviceId};
- ssize_t index = mReplacedKeys.indexOfKey(replacement);
- if (index >= 0) {
- keyCode = mReplacedKeys.valueAt(index);
- mReplacedKeys.removeItemsAt(index);
- metaState &= ~AMETA_META_ON;
- }
- }
- KeyEvent event;
- event.initialize(args->deviceId, args->source, args->action,
- flags, keyCode, args->scanCode, metaState, 0,
- args->downTime, args->eventTime);
- mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
- bool needWake;
- { // acquire lock
- mLock.lock();
- if (shouldSendKeyToInputFilterLocked(args)) {
- mLock.unlock();
- policyFlags |= POLICY_FLAG_FILTERED;
- if (!mPolicy->filterInputEvent(&event, policyFlags)) {
- return; // event was consumed by the filter
- }
- mLock.lock();
- }
- int32_t repeatCount = 0;
- KeyEntry* newEntry = new KeyEntry(args->eventTime,
- args->deviceId, args->source, policyFlags,
- args->action, flags, keyCode, args->scanCode,
- metaState, repeatCount, args->downTime);
- needWake = enqueueInboundEventLocked(newEntry);
- mLock.unlock();
- } // release lock
- if (needWake) {
- mLooper->wake();
- }
- }
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); 截获按键并处理,也即NativeInputManager::interceptKeyBeforeQueueing
[cpp] view plain copy
- 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.
- if (mInteractive) {
- 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 (mInteractive) {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
- }
- }
- }
wmActions = env->CallIntMethod(mServiceObj,gServiceClassInfo.interceptKeyBeforeQueueing,keyEventObj, policyFlags);则会call 到
InputManagerService.java中的interceptKeyBeforeQueueing
[cpp] view plain copy
- private long interceptKeyBeforeQueueing(InputWindowHandle focus,
- KeyEvent event, int policyFlags) {
- return mWindowManagerCallbacks.interceptKeyBeforeQueueing(focus, event, policyFlags);
- }
mWindowManagerCallbacks实际为InputMonitor
SystemServer.java 文件中startOtherServices调用inputManager.setWindowManagerCallbacks(wm.getInputMonitor()),给mWindowManagerCallbacks
赋值,而wm.getInputMonitor()获取的是InputMonitor, 所以mWindowManagerCallbacks.interceptKeyBeforeQueueing最后调用到InputMonitor:interceptKeyBeforeQueueing
InputMonitor.java文件中:
[cpp] v