本篇涉及到的主要代碼:
frameworks/native/services/inputflinger/
上一篇我們介紹了InputChannel以及InputConnection的創建以及它們在事件分發流程中的作用,至此輸入事件從native層的InputDispatcher傳遞到了位于應用行程空間的ViewRootImpl,但是InputDispatcher的輸入事件又從何而來呢?本篇將會為大家解答第三篇中留下的這個疑問,
1.1 InputReader的創建
[-> InputManager.cpp]
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = createInputDispatcher(dispatcherPolicy);
mClassifier = new InputClassifier(mDispatcher);
// 將NativeInputManager作為InputReaderPolicyInterface傳遞給InputReader
// 將InputClassfier作為InputListenerInterface傳遞給InputReader
mReader = createInputReader(readerPolicy, mClassifier);
}
[-> InputReaderFactory.cpp]
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener) {
// 創建InputReader[見1.2小節
// 創建EventHub[見1.5小節]
return new InputReader(std::make_unique<EventHub>(), policy, listener);
}
回顧一下第二篇提到的InputDispatcher和InputReader的創建程序:NativeInputManager繼承于InputReaderPolicyInterface和InputDispatcherPolicyInterface,它會被傳遞為InputReader建構式的第二個引數;InputClassfier繼承于InputClassifierInterface,而InputClassifierInterface又繼承于InputListenerInterface,所以它會被傳遞為InputReader建構式的第三個引數;
1.2 InputReader建構式
[-> InputReader.cpp]
// --- InputReader ---
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
: mContext(this),
// 初始化EventHub
mEventHub(eventHub),
// 初始化mPolicy
mPolicy(policy),
mGlobalMetaState(0),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
// 創建QueuedInputListener
mQueuedListener = new QueuedInputListener(listener);
{ // acquire lock
AutoMutex _l(mLock);
// 通過mPolicy即NativeManager呼叫JNI方法getReaderConfiguration獲取配置,
// 而它最侄訓調到Java層IMS的一些方法獲取保存在檔案中的一些系統配置項
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
[-> InputListener.cpp]
QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
// 初始化mInnerListener
mInnerListener(innerListener) {
}
InputReader建構式中,創建了一個非常重要的物件mQueuedListener,它將在InputReader執行緒啟動后將讀取到的輸入事件傳遞給InputDispatcher;
1.3 InputReader執行緒啟動
[-> InputReader.cpp]
status_t InputReader::start() {
// 只能啟動一次
if (mThread) {
return ALREADY_EXISTS;
}
mEventHub->wake
// 創建名為"InputReader"的執行緒,其loop方法和wake方法分別為loopOnce()[見1.4小節]和mEventHub->wake()
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
在第三篇中我們分析過"InputThread只是對InputThreadImpl的封裝,InputThreadImpl才是一個真正的執行緒",同InputDispatcher一樣:在呼叫InputThreadImpl.run方法之后,執行緒就開始運行起來并呼叫threadLoop方法開始訊息佇列的回圈處理,這樣也就回到了InputReader.loopOnce()方法;
1.4 訊息回圈loopOnce()
[-> InputReader.cpp]
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
// 通過EventHub獲取輸入事件[見1.6小節]
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
// 處理輸入事件[見1.7小節]
processEventsLocked(mEventBuffer, count);
}
} // release lock
......
// 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.
// 將輸入事件傳遞給InputDispatcher[見1.13小節]
mQueuedListener->flush();
}
loopOnce()方法通過EventHub.getEvents源源不斷的獲取RawEvent事件,然后交由processEventsLocked作預處理,最后通過QueuedListener->flush方法將輸入事件傳遞給InputDispatcher,在這之前我們首先要看看EventHub是什么,它在建構式中又做了些什么;
1.5 EventHub建構式
[-> EventHub.cpp]
EventHub::EventHub(void)
: mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
mNextDeviceId(1),
mControllerNumbers(),
mOpeningDevices(nullptr),
mClosingDevices(nullptr),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false),
mNeedToScanDevices(true),
mPendingEventCount(0),
mPendingEventIndex(0),
mPendingINotify(false) {
ensureProcessCanBlockSuspend();
// 創建epoll并保存生成的檔案描述符mEpollFd
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
// 創建inotify并保存生成的檔案描述符mINotifyFd
mINotifyFd = inotify_init();
// 此處DEVICE_PATH為"/dev/input",利用mINotifyFd監聽該設備結點
mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
struct epoll_event eventItem = {};
eventItem.events = EPOLLIN | EPOLLWAKEUP;
eventItem.data.fd = mINotifyFd;
//添加iNotify到epoll實體
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
int wakeFds[2];
// 創建管道
result = pipe(wakeFds);
// 讀管道
mWakeReadPipeFd = wakeFds[0];
// 寫管道
mWakeWritePipeFd = wakeFds[1];
//將pipe的讀和寫都設定為非阻塞方式
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
//添加管道的讀端到epoll實體
eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}
EventHub在建構式中主要完成了以下幾項作業:創建epoll實體;初始化iNotify監聽/dev/input設備結點,并添加到epoll實體;創建非阻塞模式的管道,并將管道的讀端添加到epoll;
1.6 EventHub.getEvents
[-> EventHub.cpp]
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
AutoMutex _l(mLock);
// 讀取到的input_event
struct input_event readBuffer[bufferSize];
// 原始事件,容量大小為256
RawEvent* event = buffer;
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
......
// 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.c_str());
mClosingDevices = device->next;
event->when = now;
event->deviceId = (device->id == mBuiltInKeyboardId)
? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
: device->id;
// 移除設備的事件
event->type = DEVICE_REMOVED;
event += 1;
delete device;
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
......
while (mOpeningDevices != nullptr) {
Device* device = mOpeningDevices;
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
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;
// mPendingEventIndex和mPendingEventCount分別代表待處理事件的索引和待處理事件的個數
// 當通過epoll讀取到epoll_event事件之后就會回圈處理所有的mPendingEventItems
while (mPendingEventIndex < mPendingEventCount) {
// 根據索引取出一個epoll_event事件
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
......
// 根據epoll_data.fd獲取對應的設備
Device* device = getDeviceByFdLocked(eventItem.data.fd);
......
// This must be an input event
if (eventItem.events & EPOLLIN) {
// 從輸入設備中讀取輸入事件,放入到readBuffer
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) {
......
} else if ((readSize % sizeof(struct input_event)) != 0) {
......
} else {
int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
size_t count = size_t(readSize) / sizeof(struct input_event);
// 將讀取到的所有input_event轉換成RawEvent
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
event->when = processEventTimestamp(iev);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
// 傳入的buffer已經填滿,將mPendingEventIndex索引減一后退出while回圈
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;
}
}
}
}
......
// Poll for events.
// When a device driver has pending (unread) events, it acquires
// a kernel wake lock. Once the last pending event has been read, the device
// driver will release the kernel wake lock, but the epoll will hold the wakelock,
// since we are using EPOLLWAKEUP. The wakelock is released by the epoll when epoll_wait
// is called again for the same fd that produced the event.
// 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.
// 重置輸入事件的索引為0
mPendingEventIndex = 0;
mLock.unlock(); // release lock before poll
// 等待input事件的到來,并將獲取到的epoll_event事件填充到mPendingEventItems
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
mLock.lock(); // reacquire lock after poll
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);
// 系統出現錯誤則休眠1s
usleep(100000);
}
} else {
// Some events occurred.
// epoll_wait的回傳值為input事件的個數
mPendingEventCount = size_t(pollResult);
}
}
// All done, return the number of events we read.
return event - buffer;
}
EventHub采用iNotify + epoll機制實作監聽目錄/dev/input下的設備節點,在getEvents方法中將input_event結構體 + deviceId 轉換成RawEvent結構體;
1.7 InputReader.processEventsLocked
[-> InputReader.cpp]
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
// 回圈處理每一個RawEvent
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;
}
// 真正處理RawEvent的邏輯[見1.8小節]
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;
}
}
這里會根據RawEvent的type來分別處理:如果是真正的input輸入事件則單獨處理,否則再繼續細分處理方案(包括輸入設備的添加,洗掉和掃描不是本篇的重點,這里不作討論);
1.8 InputReader.processEventsForDeviceLocked
[-> InputReader.cpp]
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
size_t count) {
auto deviceIt = mDevices.find(eventHubId);
// 沒找到輸入設備
if (deviceIt == mDevices.end()) {
ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
return;
}
std::shared_ptr<InputDevice>& device = deviceIt->second;
if (device->isIgnored()) {
// ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
// 直接呼叫輸入設備的proesss方法[見1.9小節]
device->process(rawEvents, count);
}
1.9 InputDevice.process
[-> InputDevice.cpp]
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.
for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
mDropUntilNextSync = false;
}
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
// 根據RawEvent的deviceId查找對應的InputMapper,并繼續執行其process方法[1.10方法]
for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
mapper.process(rawEvent);
});
}
--count;
}
}
// run a function against every mapper on a specific subdevice
inline void for_each_mapper_in_subdevice(int32_t eventHubDevice,
std::function<void(InputMapper&)> f) {
// mDevices是一個map:key為deviceId,value為DevicePair
auto deviceIt = mDevices.find(eventHubDevice);
if (deviceIt != mDevices.end()) {
// mDevices的second是一個DevicePair
auto& devicePair = deviceIt->second;
// DevicePair的second是一個InputMapper
auto& mappers = devicePair.second;
for (auto& mapperPtr : mappers) {
f(*mapperPtr);
}
}
}
在添加輸入設備的程序中,InputReader會根據輸入設備的class型別添加不同的InputMapper,一種或者多種class可能對應一個InputMapper,比如代表按鍵事件的KeyboardInputMapper,代表單點觸摸的SingleTouchInputMapper和代表多點觸摸的MultiTouchInputMapper,它們都是InputMapper的子類:
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
// 已經添加過的就不再重復添加
if (mDevices.find(eventHubId) != mDevices.end()) {
return;
}
// 初始化InputDeviceContext,this代表InputDevice
std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
uint32_t classes = contextPtr->getDeviceClasses();
std::vector<std::unique_ptr<InputMapper>> mappers;
......
// Keyboard-like devices.
uint32_t keyboardSource = 0;
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
keyboardSource |= AINPUT_SOURCE_KEYBOARD;
}
if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
}
if (classes & INPUT_DEVICE_CLASS_DPAD) {
keyboardSource |= AINPUT_SOURCE_DPAD;
}
if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
keyboardSource |= AINPUT_SOURCE_GAMEPAD;
}
// 根據class獲取不同的keyboardSource
if (keyboardSource != 0) {
mappers.push_back(
std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
}
// Touchscreens and touchpad devices.
if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
// 多點觸摸則添加MultiTouchInputMapper
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
} else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
// 單點觸摸則添加SingleTouchInputMapper
mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
}
......
// insert the context into the devices set
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
}
接下來我們將以KeyboardInputMapper為例來展開說明;
1.10 KeyboardInputMapper.process
[-> KeyboardInputMapper.cpp]
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)) {
// procesKey[見1.11小節]
processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
}
break;
}
case EV_MSC: {
......
}
case EV_SYN: {
......
}
}
}
1.11 KeyboardInputMapper.processKey
[-> KeyboardInputMapper.cpp]
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
int32_t keyCode;
int32_t keyMetaState;
uint32_t policyFlags;
// 根據scanCode找到對應的keyCode
if (getDeviceContext().mapKey(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) {
keyCode = rotateKeyCode(keyCode, getOrientation());
}
// 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
// mKeyDowns記錄著所有按下的鍵
keyCode = mKeyDowns[keyDownIndex].keyCode;
} else {
// key down
if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
return;
}
if (policyFlags & POLICY_FLAG_GESTURE) {
getDeviceContext().cancelTouch(when);
}
KeyDown keyDown;
keyDown.keyCode = keyCode;
keyDown.scanCode = scanCode;
// 將此次down事件壓入堆疊頂
mKeyDowns.push_back(keyDown);
}
// 同時記錄down事件時間
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[keyDownIndex].keyCode;
// 按鍵抬起,則移除down事件
mKeyDowns.erase(mKeyDowns.begin() + (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().c_str(), keyCode, scanCode);
return;
}
}
nsecs_t downTime = mDownTime;
// 創建NotifyKeyArgs物件, when記錄eventTime, downTime記錄按下時間;
NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, getDisplayId(),
policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
// 通過getListener->notifyKey將事件通知出去,這里的getListener指誰呢?[見1.12小節]
getListener()->notifyKey(&args);
}
[-> InputMapper.h]
// KeyboardInputMapper呼叫父類InputMapper.getListener
inline InputListenerInterface* getListener() { return getContext()->getListener(); }
// InputMapper.getContext又呼叫了mDeviceContext.getContext()
inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }
// mDeviceContext是在InputMapper建構式中通過傳入的InputDeviceContext初始化的,在1.9節中的addEventHubDevice中可以看
// 到這里的deviceContext是指InputDevice,繼續呼叫InputDevice.getContext()
InputMapper::InputMapper(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
// InputDevice的mContext也是在建構式中傳入的
inline InputReaderContext* getContext() { return mContext; }
[-> InputDevice.cpp]
InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
const InputDeviceIdentifier& identifier)
: mContext(context),
mId(id),
mGeneration(generation),
mControllerNumber(0),
mIdentifier(identifier),
mClasses(0),
mSources(0),
mIsExternal(false),
mHasMic(false),
mDropUntilNextSync(false) {}
[-> InputReader.cpp]
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
int32_t eventHubId, const InputDeviceIdentifier& identifier) {
auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&
devicePair.second->getDescriptor() == identifier.descriptor;
});
std::shared_ptr<InputDevice> device;
if (deviceIt != mDevices.end()) {
device = deviceIt->second;
} else {
int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
// InputDevice在createDeviceLocked中創建,其mContext也是在InputReader的建構式中賦值的即InputReader
device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
identifier);
}
device->addEventHubDevice(eventHubId);
return device;
}
// 最終getListener()指向的還是QueuedListener
InputListenerInterface* InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener.get();
}
通過一級級的往上回溯,最終我們找到了getListener()回傳值即在InputReader建構式中創建的QueuedListener;
1.12 QueuedListener.notifyKey
[-> InputListener.cpp]
std::vector<NotifyArgs*> mArgsQueue;
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyKeyArgs(*args));
}
void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyMotionArgs(*args));
}
不管是NotifyKeyArgs(按鍵事件)還是NotifyMotionArgs(觸摸事件),它們都繼承于NotifyArgs,這里都會把它們壓堆疊到mArgsQueue中,等待下一步的處理;
1.13 QueuedListener.flush()
[-> InputListener.cpp]
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
// 依次從mArgsQueue中取出每一個NotifyArgs,并執行其notify方法[見1.14小節]
args->notify(mInnerListener);
delete args;
}
mArgsQueue.clear();
}
// notify方法又呼叫了mInnerListener.notifyKey[見1.14小節]
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyKey(this);
}
根據1.1和1.2小節的分析,mInnerListener就是傳入InputReader的InputClassifier;
1.14 InputClassifier.notifyKey
[-> InputClassifier.cpp]
void InputClassifier::notifyKey(const NotifyKeyArgs* args) {
// pass through
// 直接呼叫mListener->notifyKey[見1.15小節]
mListener->notifyKey(args);
}
同樣根據前幾篇文章的分析,這里的mListener就是傳入InputClassfier建構式中的InputDispatcher;
1.15 InputDispatcher.notifyKey
[-> InputDispatcher.cpp]
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
// 按鍵事件只支持KEY_DOWN和KEY_UP
if (!validateKeyEvent(args->action)) {
return;
}
......
KeyEvent event;
// 將NotifyKeyArgs轉換為KeyEvent
event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
args->downTime, args->eventTime);
android::base::Timer t;
// 由NativeInputManager經IMS->WMS->InputManagerCallback將按鍵訊息交由PhoneWindowManager確認是否提前處理
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
// 處理時間是否超過50ms
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
std::to_string(t.duration().count()).c_str());
}
bool needWake;
{ // acquire lock
mLock.lock();
// 是否需要攔截輸入事件
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
// 輸入事件被InputFilter消費就不再往下傳遞
return; // event was consumed by the filter
}
mLock.lock();
}
// 構造KeyEntry
KeyEntry* newEntry =
new KeyEntry(args->id, args->eventTime, args->deviceId, args->source,
args->displayId, policyFlags, args->action, flags, keyCode,
args->scanCode, metaState, repeatCount, args->downTime);
// 將KeyEntry添加到mInboundQueue佇列
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {
// 喚醒InputDispatcher的執行緒
mLooper->wake();
}
}
首先將NotifyKeyArgs轉換成KeyEvent,然后交由mPolicy(在第一篇文章中我們分析過這里的mPolicy是經由JNI層的NativeManager指向Java層的IMS)分別經過interceptKeyBeforeQueueing和filterInputEvent的處理;如果事件不被攔截的話最侄訓入隊到mInboundQueue中,這里的mInboundQueue正是我們在第三篇中分析的InputDispatcher處理輸入事件的來源:有了它InputDispatcher就可以不斷的從中取出事件并通過InputChannel的socket發送給應用端去處理了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/287177.html
標籤:其他
