Android事件传递流程
##启动服务
在系统启动时候,会启动多个服务,其中包括InputManagerService
inputManager = new InputManagerService(context);
看看InputManagerService构造方法
public InputManagerService(Context context) { this.mContext = context; this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); .... mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); //mPtr是NativeInputManager的实例....}
构造方法中比较重要的是nativeInit,对应在com_android_server_input_InputManagerService.cpp中执行
static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); if (messageQueue == NULL) { jniThrowRuntimeException(env, "MessageQueue is not initialized."); return 0; } NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); im->incStrong(0); return reinterpret_cast(im);}
上述主要完成NativeInputManager初始化,并返回NativeInputManager实例对象,继续分析NativeInputManager构造函数,同样在com_android_server_input_InputManagerService.cpp文件中
NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp& looper) : mLooper(looper), mInteractive(true) { JNIEnv* env = jniEnv(); mContextObj = env->NewGlobalRef(contextObj); mServiceObj = env->NewGlobalRef(serviceObj); { AutoMutex _l(mLock); mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE; mLocked.pointerSpeed = 0; mLocked.pointerGesturesEnabled = true; mLocked.showTouches = false; mLocked.pointerCapture = false; } mInteractive = true; sp eventHub = new EventHub(); // A. 构造EventHub,EventHub用来监听/dev/input目录下文件节点的变化 mInputManager = new InputManager(eventHub, this, this); // B. 构造InputManager对象}
上面分为两个主要步骤,A和B
##构造EventHub
static const char *DEVICE_PATH = "/dev/input";EventHub::EventHub(void) : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(), mOpeningDevices(0), mClosingDevices(0), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); mEpollFd = epoll_create(EPOLL_SIZE_HINT); // ...... LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); mINotifyFd = inotify_init(); // ...... int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE); // ...... LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d", DEVICE_PATH, errno); struct epoll_event eventItem; memset(&eventItem, 0, sizeof(eventItem)); eventItem.events = EPOLLIN; eventItem.data.u32 = EPOLL_ID_INOTIFY; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem); // ...... LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno); int wakeFds[2]; result = pipe(wakeFds); LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); mWakeReadPipeFd = wakeFds[0]; mWakeWritePipeFd = wakeFds[1]; result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", errno); result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", errno); eventItem.data.u32 = EPOLL_ID_WAKE; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", errno); int major, minor; getLinuxRelease(&major, &minor); // EPOLLWAKEUP was introduced in kernel 3.5 mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);}
EventHub中有一个比较重要的方法,getEvents(),该方法会不断读取/dev/input目录下的文件节点的变化,如果没有发生变化,则该方法一直处于阻塞状态
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { ALOG_ASSERT(bufferSize >= 1); AutoMutex _l(mLock); struct input_event readBuffer[bufferSize]; RawEvent* event = buffer; size_t capacity = bufferSize; bool awoken = false; for (;;) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); // Reopen input devices if needed. if (mNeedToReopenDevices) { mNeedToReopenDevices = false; ALOGI("Reopening all input devices due to a configuration change."); closeAllDevicesLocked(); mNeedToScanDevices = true; break; // return to the caller before we actually rescan } // Report any devices that had last been added/removed. while (mClosingDevices) { Device* device = mClosingDevices; ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.string()); mClosingDevices = device->next; event->when = now; event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id; event->type = DEVICE_REMOVED; event += 1; delete device; mNeedToSendFinishedDeviceScan = true; if (--capacity == 0) { break; } } if (mNeedToScanDevices) { mNeedToScanDevices = false; scanDevicesLocked(); mNeedToSendFinishedDeviceScan = true; } while (mOpeningDevices != NULL) { Device* device = mOpeningDevices; ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.string()); mOpeningDevices = device->next; event->when = now; event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; event->type = DEVICE_ADDED; event += 1; mNeedToSendFinishedDeviceScan = true; if (--capacity == 0) { break; } } if (mNeedToSendFinishedDeviceScan) { mNeedToSendFinishedDeviceScan = false; event->when = now; event->type = FINISHED_DEVICE_SCAN; event += 1; if (--capacity == 0) { break; } } // Grab the next input event. bool deviceChanged = false; while (mPendingEventIndex < mPendingEventCount) { const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++]; if (eventItem.data.u32 == EPOLL_ID_INOTIFY) { if (eventItem.events & EPOLLIN) { mPendingINotify = true; } else { ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events); } continue; } if (eventItem.data.u32 == EPOLL_ID_WAKE) { if (eventItem.events & EPOLLIN) { ALOGV("awoken after wake()"); awoken = true; char buffer[16]; ssize_t nRead; do { nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); } else { ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.", eventItem.events); } continue; } ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32); if (deviceIndex < 0) { ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.", eventItem.events, eventItem.data.u32); continue; } Device* device = mDevices.valueAt(deviceIndex); if (eventItem.events & EPOLLIN) { int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); //......... if (readSize == 0 || (readSize < 0 && errno == ENODEV)) { // Device was removed before INotify noticed. ALOGW("could not get event, removed? (fd: %d size: %" PRId32 " bufferSize: %zu capacity: %zu errno: %d)\n", device->fd, readSize, bufferSize, capacity, errno); deviceChanged = true; closeDeviceLocked(device); } else if (readSize < 0) { if (errno != EAGAIN && errno != EINTR) { ALOGW("could not get event (errno=%d)", errno); } } else if ((readSize % sizeof(struct input_event)) != 0) { ALOGE("could not get event (wrong size: %d)", readSize); } else { int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; size_t count = size_t(readSize) / sizeof(struct input_event); for (size_t i = 0; i < count; i++) { struct input_event& iev = readBuffer[i]; ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d", device->path.string(), (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value); // Some input devices may have a better concept of the time // when an input event was actually generated than the kernel // which simply timestamps all events on entry to evdev. // This is a custom Android extension of the input protocol // mainly intended for use with uinput based device drivers. if (iev.type == EV_MSC) { if (iev.code == MSC_ANDROID_TIME_SEC) { device->timestampOverrideSec = iev.value; continue; } else if (iev.code == MSC_ANDROID_TIME_USEC) { device->timestampOverrideUsec = iev.value; continue; } } if (device->timestampOverrideSec || device->timestampOverrideUsec) { iev.time.tv_sec = device->timestampOverrideSec; iev.time.tv_usec = device->timestampOverrideUsec; if (iev.type == EV_SYN && iev.code == SYN_REPORT) { device->timestampOverrideSec = 0; device->timestampOverrideUsec = 0; } ALOGV("applied override time %d.%06d", int(iev.time.tv_sec), int(iev.time.tv_usec)); } // Use the time specified in the event instead of the current time // so that downstream code can get more accurate estimates of // event dispatch latency from the time the event is enqueued onto // the evdev client buffer. // // The event's timestamp fortuitously uses the same monotonic clock // time base as the rest of Android. The kernel event device driver // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts(). // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a // system call that also queries ktime_get_ts(). event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL + nsecs_t(iev.time.tv_usec) * 1000LL; ALOGV("event time %" PRId64 ", now %" PRId64, event->when, now); // Bug 7291243: Add a guard in case the kernel generates timestamps // that appear to be far into the future because they were generated // using the wrong clock source. // // This can happen because when the input device is initially opened // it has a default clock source of CLOCK_REALTIME. Any input events // enqueued right after the device is opened will have timestamps // generated using CLOCK_REALTIME. We later set the clock source // to CLOCK_MONOTONIC but it is already too late. // // Invalid input event timestamps can result in ANRs, crashes and // and other issues that are hard to track down. We must not let them // propagate through the system. // // Log a warning so that we notice the problem and recover gracefully. if (event->when >= now + 10 * 1000000000LL) { // Double-check. Time may have moved on. nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC); if (event->when > time) { ALOGW("An input event from %s has a timestamp that appears to " "have been generated using the wrong clock source " "(expected CLOCK_MONOTONIC): " "event time %" PRId64 ", current time %" PRId64 ", call time %" PRId64 ". " "Using current time instead.", device->path.string(), event->when, time, now); event->when = time; } else { ALOGV("Event time is ok but failed the fast path and required " "an extra call to systemTime: " "event time %" PRId64 ", current time %" PRId64 ", call time %" PRId64 ".", event->when, time, now); } }//......... event->deviceId = deviceId; event->type = iev.type; event->code = iev.code; event->value = iev.value; event += 1; capacity -= 1; } if (capacity == 0) { // The result buffer is full. Reset the pending event index // so we will try to read the device again on the next iteration. mPendingEventIndex -= 1; break; } } } else if (eventItem.events & EPOLLHUP) { ALOGI("Removing device %s due to epoll hang-up event.", device->identifier.name.string()); deviceChanged = true; closeDeviceLocked(device); } else { ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events, device->identifier.name.string()); } } // readNotify() will modify the list of devices so this must be done after // processing all other events to ensure that we read all remaining events // before closing the devices. if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) { mPendingINotify = false; readNotifyLocked(); //......... deviceChanged = true; } // Report added or removed devices immediately. if (deviceChanged) { continue; } // Return now if we have collected any events or if we were explicitly awoken. if (event != buffer || awoken) { break; } // Poll for events. Mind the wake lock dance! // We hold a wake lock at all times except during epoll_wait(). This works due to some // subtle choreography. When a device driver has pending (unread) events, it acquires // a kernel wake lock. However, once the last pending event has been read, the device // driver will release the kernel wake lock. To prevent the system from going to sleep // when this happens, the EventHub holds onto its own user wake lock while the client // is processing events. Thus the system can only sleep if there are no events // pending or currently being processed. // // The timeout is advisory only. If the device is asleep, it will not wake just to // service the timeout. mPendingEventIndex = 0; mLock.unlock(); // release lock before poll, must be before release_wake_lock release_wake_lock(WAKE_LOCK_ID); int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis); // 将会一直处于阻塞状态,直到/dev/input目录下有节点发生变化 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock if (pollResult == 0) { // Timed out. mPendingEventCount = 0; break; } if (pollResult < 0) { // An error occurred. mPendingEventCount = 0; // Sleep after errors to avoid locking up the system. // Hopefully the error is transient. if (errno != EINTR) { ALOGW("poll failed (errno=%d)\n", errno); usleep(100000); } } else { // Some events occurred. mPendingEventCount = size_t(pollResult); } } // All done, return the number of events we read. return event - buffer;}
##InputReader和InputDispatcher读取和分发
InputReader类负责从上述EventHub的getEvent读取节点变化,并由InputDispatcher分发给上层,这里主要涉及到以下几个类:
InputDispatcher
InputReader
InputDispatcherThread
InputReaderThread
InputListener
###InputReader和InputDispatcher的启动
继续回到 InputManager.cpp 的构造方法
InputManager::InputManager( const sp& eventHub, const sp& readerPolicy, const sp& dispatcherPolicy) { mDispatcher = new InputDispatcher(dispatcherPolicy); mReader = new InputReader(eventHub, readerPolicy, mDispatcher); initialize();}void InputManager::initialize() { mReaderThread = new InputReaderThread(mReader); mDispatcherThread = new InputDispatcherThread(mDispatcher);}
上述初始化完成之后,回到SystemServer,此时程序会一直往下走
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());inputManager.start();public void start() { Slog.i(TAG, "Starting input manager"); nativeStart(mPtr); // 上述构造方法中,已经直到mPtr是NativeInputManager的实例 ....}
上述nativeStart是com_android_server_input_InputManagerService.cpp中方法
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) { NativeInputManager* im = reinterpret_cast(ptr); status_t result = im->getInputManager()->start(); // InputManager.cpp start方法 if (result) { jniThrowRuntimeException(env, "Input manager could not be started."); }}
InputManager.cpp#start
status_t InputManager::start() { status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); if (result) { ALOGE("Could not start InputDispatcher thread due to error %d.", result); return result; } result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); if (result) { ALOGE("Could not start InputReader thread due to error %d.", result); mDispatcherThread->requestExit(); return result; } return OK;}
上述mDispatcherThread->run和mReaderThread->run会分别执行对应的threadLoop方法,这里涉及到android中的threadLoop知识点,后续做详细介绍
InputReader.cpp
bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true;}
loopOnce
void InputReader::loopOnce() { int32_t oldGeneration; int32_t timeoutMillis; bool inputDevicesChanged = false; Vector inputDevices; { // acquire lock AutoMutex _l(mLock); oldGeneration = mGeneration; timeoutMillis = -1; uint32_t changes = mConfigurationChangesToRefresh; if (changes) { mConfigurationChangesToRefresh = 0; timeoutMillis = 0; refreshConfigurationLocked(changes); } else if (mNextTimeout != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); } } // release lock size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); // getEvent获取节点的变化 { // acquire lock AutoMutex _l(mLock); mReaderIsAliveCondition.broadcast(); if (count) { processEventsLocked(mEventBuffer, count); // 到这里 } if (mNextTimeout != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); if (now >= mNextTimeout) {#if DEBUG_RAW_EVENTS ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);#endif mNextTimeout = LLONG_MAX; timeoutExpiredLocked(now); } } if (oldGeneration != mGeneration) { inputDevicesChanged = true; getInputDevicesLocked(inputDevices); } } // release lock // Send out a message that the describes the changed input devices. if (inputDevicesChanged) { mPolicy->notifyInputDevicesChanged(inputDevices); } // Flush queued events out to the listener. // This must happen outside of the lock because the listener could potentially call // back into the InputReader's methods, such as getScanCodeState, or become blocked // on another thread similarly waiting to acquire the InputReader lock thereby // resulting in a deadlock. This situation is actually quite plausible because the // listener is actually the input dispatcher, which calls into the window manager, // which occasionally calls into the input reader. mQueuedListener->flush();}
processEventsLocked
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) { for (const RawEvent* rawEvent = rawEvents; count;) { int32_t type = rawEvent->type; size_t batchSize = 1; if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { int32_t deviceId = rawEvent->deviceId; while (batchSize < count) { if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT || rawEvent[batchSize].deviceId != deviceId) { break; } batchSize += 1; }#if DEBUG_RAW_EVENTS ALOGD("BatchSize: %d Count: %d", batchSize, count);#endif processEventsForDeviceLocked(deviceId, rawEvent, batchSize); // 到这里 } else { switch (rawEvent->type) { case EventHubInterface::DEVICE_ADDED: addDeviceLocked(rawEvent->when, rawEvent->deviceId); // 增加节点 break; case EventHubInterface::DEVICE_REMOVED: removeDeviceLocked(rawEvent->when, rawEvent->deviceId); // 删除节点 break; case EventHubInterface::FINISHED_DEVICE_SCAN: handleConfigurationChangedLocked(rawEvent->when); // 节点发生变化 break; default: ALOG_ASSERT(false); // can't happen break; } } count -= batchSize; rawEvent += batchSize; }}
processEventsForDeviceLocked
void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count) { ssize_t deviceIndex = mDevices.indexOfKey(deviceId); if (deviceIndex < 0) { ALOGW("Discarding event for unknown deviceId %d.", deviceId); return; } InputDevice* device = mDevices.valueAt(deviceIndex); if (device->isIgnored()) { //ALOGD("Discarding event for ignored deviceId %d.", deviceId); return; } device->process(rawEvents, count); // 到这里
InputDevice#process
void InputDevice::process(const RawEvent* rawEvents, size_t count) { // Process all of the events in order for each mapper. // We cannot simply ask each mapper to process them in bulk because mappers may // have side-effects that must be interleaved. For example, joystick movement events and // gamepad button presses are handled by different mappers but they should be dispatched // in the order received. size_t numMappers = mMappers.size(); for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {#if DEBUG_RAW_EVENTS ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld", rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);#endif if (mDropUntilNextSync) { if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { mDropUntilNextSync = false;#if DEBUG_RAW_EVENTS ALOGD("Recovered from input event buffer overrun.");#endif } else {#if DEBUG_RAW_EVENTS ALOGD("Dropped input event while waiting for next input sync.");#endif } } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) { ALOGI("Detected input event buffer overrun for device %s.", getName().string()); mDropUntilNextSync = true; reset(rawEvent->when); } else { for (size_t i = 0; i < numMappers; i++) { InputMapper* mapper = mMappers[i]; mapper->process(rawEvent); // 到这里 } } --count; }}InputMapper根据具体的按键类型,会调用不同的InputMapper ,比如:SwitchInputMapper耳机拔插的switch类型,KeyboardInputMapper物理按键,电源键,音量键等void KeyboardInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { case EV_KEY: { int32_t scanCode = rawEvent->code; int32_t usageCode = mCurrentHidUsage; mCurrentHidUsage = 0; if (isKeyboardOrGamepadKey(scanCode)) { processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode); // 到这里,调用到processKey } break; } case EV_MSC: { if (rawEvent->code == MSC_SCAN) { mCurrentHidUsage = rawEvent->value; } break; } case EV_SYN: { if (rawEvent->code == SYN_REPORT) { mCurrentHidUsage = 0; } } }}
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) { int32_t keyCode; int32_t keyMetaState; uint32_t policyFlags; if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState, &keyCode, &keyMetaState, &policyFlags)) { keyCode = AKEYCODE_UNKNOWN; keyMetaState = mMetaState; policyFlags = 0; } if (down) { // Rotate key codes according to orientation if needed. if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { keyCode = rotateKeyCode(keyCode, mOrientation); } // Add key down. ssize_t keyDownIndex = findKeyDown(scanCode); if (keyDownIndex >= 0) { // key repeat, be sure to use same keycode as before in case of rotation keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode; } else { // key down if ((policyFlags & POLICY_FLAG_VIRTUAL) && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) { return; } if (policyFlags & POLICY_FLAG_GESTURE) { mDevice->cancelTouch(when); } mKeyDowns.push(); KeyDown& keyDown = mKeyDowns.editTop(); keyDown.keyCode = keyCode; keyDown.scanCode = scanCode; } mDownTime = when; } else { // Remove key down. ssize_t keyDownIndex = findKeyDown(scanCode); if (keyDownIndex >= 0) { // key up, be sure to use same keycode as before in case of rotation keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode; mKeyDowns.removeAt(size_t(keyDownIndex)); } else { // key was not actually down ALOGI("Dropping key up from device %s because the key was not down. " "keyCode=%d, scanCode=%d", getDeviceName().string(), keyCode, scanCode); return; } } if (updateMetaStateIfNeeded(keyCode, down)) { // If global meta state changed send it along with the key. // If it has not changed then we'll use what keymap gave us, // since key replacement logic might temporarily reset a few // meta bits for given key. keyMetaState = mMetaState; } nsecs_t downTime = mDownTime; // Key down on external an keyboard should wake the device. // We don't do this for internal keyboards to prevent them from waking up in your pocket. // For internal keyboards, the key layout file should specify the policy flags for // each wake key individually. // TODO: Use the input device configuration to control this behavior more finely. if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) { policyFlags |= POLICY_FLAG_WAKE; } if (mParameters.handlesKeyRepeat) { policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; } NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime); getListener()->notifyKey(&args); //最终将获取到的事件传递到getListener()->notifyKey方法中}
上面getListener()会返回InputListener.cpp类型对象,所以就到了InputListener.cpp#notifyKey方法中
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
mArgsQueue.push(new NotifyKeyArgs(*args));
}
可以看到,最终只是添加到了mArgsQueue集合中
Vector
mQueuedListener->flush(); 这个就会将mArgsQueue集合中保存的事件传递给InputDispatcher.cpp中InputListener.cpp#flushvoid QueuedInputListener::flush() { size_t count = mArgsQueue.size(); for (size_t i = 0; i < count; i++) { NotifyArgs* args = mArgsQueue[i]; args->notify(mInnerListener); delete args; } mArgsQueue.clear();}
void NotifyKeyArgs::notify(const sp& listener) const { listener->notifyKey(this);}
这里的listener是什么? 重新看下InputReader.cpp的构造函数
InputReader::InputReader(const sp& eventHub, const sp& policy, const sp& listener) : mContext(this), mEventHub(eventHub), mPolicy(policy), mGlobalMetaState(0), mGeneration(1), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), mConfigurationChangesToRefresh(0) { mQueuedListener = new QueuedInputListener(listener); { // acquire lock AutoMutex _l(mLock); refreshConfigurationLocked(0); updateGlobalMetaStateLocked(); } // release lock}
上述构造InputReader是在InputManager.cpp中构造的
InputManager::InputManager( const sp& eventHub, const sp& readerPolicy, const sp& dispatcherPolicy) { mDispatcher = new InputDispatcher(dispatcherPolicy); mReader = new InputReader(eventHub, readerPolicy, mDispatcher); initialize();}
所以上述listener就是InputDispatcher.cpp实例对象
回到InputDispatcher.cpp中
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 | AMETA_META_LEFT_ON | AMETA_META_RIGHT_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 | AMETA_META_LEFT_ON | AMETA_META_RIGHT_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); // 此处会回调到InputMonitor中 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(); }}
InputMonitor#interceptKeyBeforeQueueing
@Override public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags); }
这里就到了PhoneWindowManager#interceptKeyBeforeQueueing中
专注技术分享,包括Java,python,AI人工智能,Android分享,不定期更新学习视频,欢迎关注
更多相关文章
- Android使用SDK方法详解
- Android 发送普通的post请求的方法
- android之通过URL来获取网络资源并下载资源简单实例
- 实例:在Android调用WCF服务
- Android中View绘制流程以及invalidate()等相关方法分析
- Android 获取Gmail邮箱地址方法
- ubuntu的android studio调试小米手机的方法
- android 布局之滑动探究 scrollTo 和 scrollBy 方法使用说明
- Android 自定义view 和 onMeasure方法介绍