本文基于Android 12。
一、InputManagerService启动
SystemServer初始化InputManagerService(),然后调用其start()方法。
InputManagerService()构造方法中和start()分别调用了两个native方法:
1.1NativeImpl() 初始化
InputManagerService(Injector injector) {
mNative = injector.getNativeService(this);
}
NativeInputManagerService getNativeService(InputManagerService service) {
return new NativeInputManagerService.NativeImpl(service, mContext, mLooper.getQueue());
}
1.2 start() 启动
public void start() {
mNative.start();
}
其中mLooper是DisplayThread.get().getLooper(),DisplayThread是systemserver进程中的单例模式,只能被WindowManager,DisplayManager, InputManager使用。
二、NativeInputManager, InputManager
2.1 NativeInputManager
NativeInputManagerService.NativeImpl()方法初始化NativeInputManager对象,参数中还把InputManagerService和mLooper也一起传递过去了,NativeInputManager定义在jni代码中。
// com_android_server_input_InputManagerService.cpp
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface {}
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
mLocked.systemUiLightsOut = false;
mLocked.pointerSpeed = 0;
mLocked.pointerAcceleration = android::os::IInputConstants::DEFAULT_POINTER_ACCELERATION;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
}
mInteractive = true;
InputManager* im = new InputManager(this, this);
mInputManager = im;
defaultServiceManager()->addService(String16("inputflinger"), im);
}
static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
- NativeInputManager实现了InputReaderPolicyInterface,InputDispatcherPolicyInterface,PointerControllerPolicyInterface接口,
- serviceObj和looper分别赋值给mServiceObj和mLooper变量,后续可以通过mServiceObj调用Java层InputManagerService对象的方法了。
- 把自己作为参数实例化InputManager。
- 添加“inputflinger”到ServiceManager。
2.2 InputManager
InputManager初始化:
// InputManager.cpp
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = createInputDispatcher(dispatcherPolicy);
mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
mReader = createInputReader(readerPolicy, *mBlocker);
}
InputManager定义了四个重要的变量,也是一个InputEvent的传递流程:
InputReader -> UnwantedInteractionBlocker -> InputClassifier -> InputDispatcher
- mReader:通过EventHub监听"/dev/input"事件。
- mBlocker:拦截不需要的事件。
- mClassifier:对事件分类。
- mDispatcher:分发事件。
其中mReader和mDispatcher还传递了NativeInputManager对象参数,赋值到各自的mPolicy变量,后续可直接通过mPolicy调用Java层InputMangerService对象方法。
初始化流程大概就是这样,接着1.2 start()开始启动InputManger。
// InputManager.cpp
status_t InputManager::start() {
status_t result = mDispatcher->start();
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReader->start();
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;
}
调用mDispatcher和mReader各自start()方法。
2.2.1 事件传递
事件的传递流程是:InputReader -> UnwantedInteractionBlocker -> InputClassifier -> InputDispatcher
但是查看各个类结构,并没有看到其中相互关联了,原因是使用了代理设计模式:
QueuedListener,UnwantedInteractionBlocker,InputClassifier,InputDispatcher都实现了InputListenerInterface接口,他们都是输入事件的监听者,输入事件的链式传递就是通过QueuedListener实现的,这里使用了代理设计模式,代理对象是InputListenerInterface。
InputListenerInterface定义了事件监听接口:
// InputListener.h
class InputListenerInterface {
public:
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
virtual void notifyKey(const NotifyKeyArgs* args) = 0;
virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
virtual void notifySensor(const NotifySensorArgs* args) = 0;
virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) = 0;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0;
};
为了实现优雅的链式调用,QueuedListener内部持有一个InputListenerInterface实例化对象mInnerListener,和一个vector mArgsQueue管理所有输入事件,flush()方法遍历mArgsQueue所有输入事件,将其传递给mInnerListener,也就是下一个环节:
// InputListener.h
class QueuedInputListener : public InputListenerInterface {
public:
void flush();
private:
InputListenerInterface& mInnerListener;
std::vector<std::unique_ptr<NotifyArgs>> mArgsQueue;
};
// InputListner.cpp
QueuedInputListener::QueuedInputListener(InputListenerInterface& innerListener)
: mInnerListener(innerListener) {}
void QueuedInputListener::flush() {
for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {
args->notify(mInnerListener);
}
mArgsQueue.clear();
}
而InputReader,UnwantedInteractionBlocker,InputClassifier都只需要持有QueuedInputListener引用就好了,类设计者不必关心下个环节具体是谁,只需要在处理事件后调用QueuedInputListener.flush()就可以把任务传递下去。
class InputReader : public InputReaderInterface {
private:
QueuedInputListener mQueuedListener;
}
class UnwantedInteractionBlocker : public UnwantedInteractionBlockerInterface {
private:
QueuedInputListener mQueuedListener;
}
class InputClassifier : public InputClassifierInterface {
private:
QueuedInputListener mQueuedListener;
}
InputManager初始化时实例化了以上对象,构造方法中传递mQueuedListener参数,在实例化的过程中确定了调用链环节。
三、InputReader
mReader = createInputReader(readerPolicy, *mBlocker);初始化InputReader。
// InputReaderFactory.cpp
std::unique_ptr<InputReaderInterface> createInputReader(
const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {
return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);
}
InputReaderFactory实例化了一个EventHub对象传递给InputReader构造方法。
3.1 EventHub
// EventHub.cpp
EventHub::EventHub(void)
: mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
mNextDeviceId(1),
mControllerNumbers(),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false),
mNeedToScanDevices(true),
mPendingEventCount(0),
mPendingEventIndex(0),
mPendingINotify(false) {
ensureProcessCanBlockSuspend();
// 1.创建一个新的epoll实例
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
// 2.创建一个新的inotify实例,Inotify API用于检测文件系统变化的机制。Inotify可用于检测单个文件,也可以检测整个目录。
// 当目录下的设备节点发生增删事件时,可已通过 read(fd) 获取事件的详细信息
mINotifyFd = inotify_init1(IN_CLOEXEC);
std::error_code errorCode;
bool isDeviceInotifyAdded = false;
// 3.添加 /dev/input 或者 /dev 目录的Inotify
if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
addDeviceInputInotify();
} else {
addDeviceInotify();
isDeviceInotifyAdded = true;
}
struct epoll_event eventItem = {};
eventItem.events = EPOLLIN | EPOLLWAKEUP;
eventItem.data.fd = mINotifyFd;
// 4. 把 inotify 添加到 epoll 监听队列中,当 inotify 事件到来时,epoll_wait() 会
// 立即返回,EventHub 可以从 fd 中读取设备节点的增删信息并进行处理
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
// 5. 创建管道,fds[0] 表示管道的读端,fds[1] 表示管道的写端
int wakeFds[2];
result = pipe2(wakeFds, O_CLOEXEC);
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
// 设置唤醒读端为非阻塞式
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
// 设置唤醒写端为非阻塞式
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
//6. 把唤醒读端的 fd 添加到 epoll 监听队列中,目的是在必要时唤醒 reader 线程
eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}
EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点,后续inputReader的loopOnce循环调用EventHub::getEvents()方法,解析数据封装为RawEvent对象。
3.2 InputReader::start
// InputReader.cpp
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
status_t InputReader::stop() {
if (mThread && mThread->isCallingThread()) {
ALOGE("InputReader cannot be stopped from its own thread!");
return INVALID_OPERATION;
}
mThread.reset();
return OK;
}
1.1NativeImpl完成初始化后,1.2 mNative.start()调用InputManager::start()启动InputDispatcher和InputReader。
Start()启动"InputReader"线程,threadLoop()中循环调用loopOnce(),stop()方法调用mThread.reset(),执行mEventHub->wake()。
3.3 InputReader::loopOnce
// InputReader.cpp
void InputReader::loopOnce() {
// 1. 通过EventHub读取输入事件
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
// 2. 处理输入事件
if (count) {
processEventsLocked(mEventBuffer, count);
}
}
// 3. 清空mQueuedListener,将事件传递给 mBlocker(UnwantedInteractionBlocker)处理
mQueuedListener.flush();
}
loopOnce()方法包含了inputReader最主要的运行逻辑,先通过EventHub::getEvents()读取解析/dev/input节点下的事件,processEventsLocked()根据类型处理事件,最后通过QueuedListener传递给下一环,也就是mBlocker(UnwantedInteractionBlocker对象)。
3.3.1 EventHub::getEvents
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
RawEvent* event = buffer;
for (;;) {
// 1. 输入设备移除事件
for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
event->type = DEVICE_REMOVED;
}
// 2. 输入设备添加事件
while (!mOpeningDevices.empty()) {
event->type = DEVICE_ADDED;
}
// 3. 输入设备扫描完成事件
if (mNeedToSendFinishedDeviceScan) {
event->type = FINISHED_DEVICE_SCAN;
}
// 4. 输入事件
while (mPendingEventIndex < mPendingEventCount) {
if (eventItem.events & EPOLLIN) {
event->when = processEventTimestamp(iev);
event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
}
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
mPendingEventCount = size_t(pollResult);
}
}
EventHub通过epoll读取输入事件,封装成RawEvent对象,event->type区分事件类型。
3.3.2 InputReader::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;
// 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;
}
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
// 2.输入设备添加事件,InputDevice
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
// 3.输入设备移除事件
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
// 4.输入设备扫描完成事件
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
从EventHub获取到封装好的RawEvent后,RawEvent保存了事件的原始数据,并没有对事件进行细致的解析,设备添加事件也是一个RawEvent,还有比如用户输入事件,键盘、鼠标、传感器等事件在这里都没有被区分开,processEventsLocked()对原始事件进行处理。
3.3.2.1设备添加事件
先看下设备添加事件DEVICE_ADDED的处理流程:
inputflinger定义了InputDevice类描述输入设备对象,InputMapper把原始事件RawEvent解析成具体对应事件的参数,InputMapper的具体实现类有:
- CursorInputMapper
- KeyboardInputMapper
- TouchInputMapper
- SensorInputMapper
等等。
addDeviceLocked()调用createDeviceLocked()创建一个InputDevice对象,device->addEventHubDevice(eventHubId)将InputDevice和InputMapper实现类关联起来,添加到mDevices变量管理。
// InputDevice.h
private:
std::unordered_map<int32_t, DevicePair> mDevices;
// InputDevice.cpp
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
// mappers
std::vector<std::unique_ptr<InputMapper>> mappers;
if (classes.test(InputDeviceClass::KEYBOARD)) {
keyboardSource |= AINPUT_SOURCE_KEYBOARD;
}
if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
} else if (classes.test(InputDeviceClass::TOUCH)) {
mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
}
// 添加到 mDevices
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
}
3.3.2.2 输入事件
对于输入事件,inputReader调用processEventsForDeviceLocked()方法处理:
// InputReader.cpp
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
size_t count) {
auto deviceIt = mDevices.find(eventHubId);
device->process(rawEvents, count);
}
mDevices管理着所有输入设备,找到对应的输入设备调用process()方法。
// InputDevice.cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
mapper.process(rawEvent);
});
}
}
InputDevice也是从mDevices变量找到对应的InputMapper对象,交给mapper.process(rawEvent);处理。接下来就是InputMapper的各种实现类解析RawEvent数据了,这里我们关注键盘输入KeyboardInputMapper实现类。
KeyboardInputMapper剔除多余不感兴趣的数据,KeyboardInputMapper::processKey()将数据解析封装成一个NotifyKeyArgs对象,交给下一个环节:
// KeyboardInputMapper.cpp
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
if (isKeyboardOrGamepadKey(scanCode)) {
processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, scanCode,
usageCode);
}
break;
}
}
}
void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,
int32_t usageCode) {
NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
getDisplayId(), policyFlags,
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
getListener().notifyKey(&args);
}
getListener()返回的是InputReader的mQueuedListener对象。
// InputListener.cpp
void QueuedInputListener::notifyConfigurationChanged(
const NotifyConfigurationChangedArgs* args) {
traceEvent(__func__, args->id);
mArgsQueue.emplace_back(std::make_unique<NotifyConfigurationChangedArgs>(*args));
}
2.2.1小节中提到过,InputListener.mArgsQueue是一个vector数组,保存管理着loopOnce()执行一次读取的所有输入事件,刚解析的键盘输入事件被添加到mArgsQueue变量。
3.3.3 mQueuedListener.flush()
事件的读取解析都完成了,接下来InputReader将处理流程交给下一个环节UnwantedInteractionBlocker了。
// InputListener.cpp
void QueuedInputListener::flush() {
for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {
args->notify(mInnerListener);
}
mArgsQueue.clear();
}
void NotifyKeyArgs::notify(InputListenerInterface& listener) const {
listener.notifyKey(this);
}
这里的mInnerListener就是mBlocker,交给mBlocker的notifyKey()方法处理后,清空数组mArgsQueue。
mBlocker将事件传递给mClassifier,mClassifier将事件传递给mDispatcher。
四、InputDispatcher
4.1 InputDispatcher::notifyKey
键盘输入事件传递到InputDispatcher::notifyKey()。
// InputDispatcher.h
std::deque<std::shared_ptr<EventEntry>> mInboundQueue GUARDED_BY(mLock);
// InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
// 1.封装成 KeyEvent
KeyEvent event;
event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
args->downTime, args->eventTime);
// 2.在event事件入队前处理
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
{
mLock.lock();
std::unique_ptr<KeyEntry> newEntry =
std::make_unique<KeyEntry>(args->id, args->eventTime, args->deviceId, args->source,
args->displayId, policyFlags, args->action, flags,
keyCode, args->scanCode, metaState, repeatCount,
args->downTime);
// 3.event入队
needWake = enqueueInboundEventLocked(std::move(newEntry));
mLock.unlock();
}
// 4.唤醒 mLooper
if (needWake) {
mLooper->wake();
}
}
notifyKey主要做了四件事:
- EventHub将事件读取解析为RawEvent,KeyboardInputMapper将RawEvent封装成NotifyKeyArgs,事件传递到InputDispatcher,终于被封装成了KeyEvent对象。
- InputDispatcher持有mInboundQueue变量,管理所有到达需要处理的事件,使用EventEntry对象描述,所有需要分发的事件都被封装成EventEntry入队到mInboundQueue。这里在入队之前调用了interceptKeyBeforeQueueing()方法,在事件被设备读取之前先进行一些处理,比如power按键需要对应用程序的生命周期处理,2.2小节提到过,InputDispatcher和InputReader都各自持有mPolicy对象,实际实现是NativeInputManger对象,这样就可以调用Java层的InputMangerService方法了,最终调用到熟悉的PhoneWindowManger.interceptKeyBeforeQueueing()。
// InputManagerCallback.java /** * Provides an opportunity for the window manager policy to intercept early key * processing as soon as the key has been read from the device. */ @Override public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags); }
- 封装成EventEntry入队。
- 唤醒mLooper开始处理事件分发。
4.2 InputDispatcher::start
2.2小节中,InputManager::start()分别调用了InputDispatcher和InputReader的start()方法,之前已经分析了InputReader.start(),现在看下InputDispatcher.start()的启动过程。
// InputDispathcer.h
using Command = std::function<void()>;
std::deque<Command> mCommandQueue GUARDED_BY(mLock);
// InputDispatcher.cpp
status_t InputDispatcher::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
启动"InputDispatcher"线程,循环调用dispatchOnce()方法。
4.3 InputDispatcher::dispatchOnce
// InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all();
// 1. 如果mCommandQueue没有待处理的Command,则执行dispatchOnceInnerLocked去产生Command
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
//2. 如果mCommandQueue队列消息不为空,则循环从中取出Command进行处理
if (runCommandsLockedInterruptable()) {
nextWakeupTime = LONG_LONG_MIN;
}
// 3.判断是否要触发ANR
const nsecs_t nextAnrCheck = processAnrsLocked();
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
if (nextWakeupTime == LONG_LONG_MAX) {
mDispatcherEnteredIdle.notify_all();
}
}
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
// 4. mLooper睡眠等待时间timeoutMillis
mLooper->pollOnce(timeoutMillis);
}
mCommandQueue队列变量管理Command对象,Command实际指向一个函数std::function<void()>,执行一些必要特殊的操作,通知Java层的InputMangerService,比如焦点改变:sendFocusChangedCommandLocked(),ANR发生:onAnrLocked()等等。
4.3.1 dispatchOnceInnerLocked
事件的分发逻辑在dispatchOnceInnerLocked()实现:
// InputDispatcher.cpp
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
// 1.当前没有在等待的事件,从mInboundQueue获取。
if (!mPendingEvent) {
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
}
// 2.根据type分别处理
switch (mPendingEvent->type) {
case EventEntry::Type::MOTION: {
std::shared_ptr<MotionEntry> motionEntry =
std::static_pointer_cast<MotionEntry>(mPendingEvent);
if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
dropReason = DropReason::APP_SWITCH;
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
dropReason = DropReason::STALE;
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DropReason::BLOCKED;
}
done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
break;
}
}
}
mPendingEvent保存当前处理的事件,没有的话从mInboundQueue队列中取出,4.1小节enqueueInboundEventLocked()方法,键盘输入事件就被封装成EventEntry入队到mInboundQueue队列中,后续将在这里被处理。
这里我们关心MOTION触屏输入事件,继续交给dispatchMotionLocked()处理。
4.3.2 dispatchMotionLocked
// InputDispatcher.cpp
bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
const bool isPointerEvent = isFromSource(entry->source, AINPUT_SOURCE_CLASS_POINTER);
// Identify targets.
std::vector<InputTarget> inputTargets;
if (isPointerEvent) {
// Pointer event. (eg. touchscreen)
injectionResult =
findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
&conflictingPointerActions);
} else {
// Non touch event. (eg. trackball)
injectionResult =
findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
}
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
isPointerEvent区分是触摸屏幕还是轨迹球,InputTarget具体说明了输入事件如何分发到具体的window上,其中保存了数据传输路径InputChannel等。
为了找到正确的焦点窗口,mFocusedApplicationHandlesByDisplay变量保存了当前持有焦点的App,每启动一个新的App,焦点App都会通过InputMonitor更新,InputMonitor在View的显示过程中被初始化:https://blog.csdn.net/qq_36063677/article/details/129908973:
// InputMonitor.java
void setFocusedAppLw(ActivityRecord newApp) {
// Focused app has changed.
mService.mInputManager.setFocusedApplication(mDisplayId,
newApp != null ? newApp.getInputApplicationHandle(true /* update */) : null);
}
// InputDispatcher.cpp
// Focused applications.
std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>>
mFocusedApplicationHandlesByDisplay GUARDED_BY(mLock);
mFocusedWindowTokenByDisplay变量保存了各个Display设备(考虑到多个显示设备的情况)当前的焦点Window,由surfaceflinger进程负责更新:
// SurfaceFlinger.cpp
void SurfaceFlinger::updateInputFlinger() {
for (const auto& focusRequest : inputWindowCommands.focusRequests) {
inputFlinger->setFocusedWindow(focusRequest);
}
}
// FocusResolver.h
std::unordered_map<int32_t /* displayId */, NamedToken> mFocusedWindowTokenByDisplay;
对于触摸屏幕,findTouchedWindowTargetsLocked()对分屏的使用情景进行了适配,isSplit变量标识当前是否处于分屏状态。
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const MotionEntry& entry,
std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime,
bool* outConflictingPointerActions) {
// 1.添加包含点击坐标的窗口到inputTargets
sp<InputWindowHandle> newTouchedWindowHandle =
findTouchedWindowAtLocked(displayId, x, y, &tempTouchState,
isDown /*addOutsideTargets*/, true /*addPortalWindows*/);
tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
// 2.添加设置了FLAG_DISPATCH_AS_OUTSIDE(FLAG_WATCH_OUTSIDE_TOUCH)的窗口到inputTargets
if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
sp<InputWindowHandle> foregroundWindowHandle =
tempTouchState.getFirstForegroundWindowHandle();
if (foregroundWindowHandle) {
const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
tempTouchState.addOrUpdateWindow(inputWindowHandle,
InputTarget::FLAG_ZERO_COORDS,
BitSet32(0));
}
}
}
}
}
}
findTouchedWindowTargetsLocked在MotionEvent的各种case中找到恰当的InputWindowHandle,并添加到vector中。
- 添加包含点击坐标的窗口到inputTargets,这是最常见的情况,也就是按下事件AMOTION_EVENT_ACTION_DOWN。
sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
int32_t y, TouchState* touchState,
bool addOutsideTargets,
bool addPortalWindows) {
const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId == displayId) {
int32_t flags = windowInfo->layoutParamsFlags;
if (windowInfo->visible) {
if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
bool isTouchModal = (flags &
(InputWindowInfo::FLAG_NOT_FOCUSABLE |
InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
return windowHandle;
}
}
}
}
}
}
std::vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(
int32_t displayId) const {
return getValueByKey(mWindowHandlesByDisplay, displayId);
}
getWindowHandlesLocked(displayId);在一个map中拿到对应displayId的mWindowHandlesByDisplay,mWindowHandlesByDisplay由surfaceflinger负责更新,继而判断window状态:
- windowInfo->visible:窗口可见。
- !(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE):没有设置FLAG_NOT_TOUCHABLE。
- flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE | InputWindowInfo::FLA G_NOT_TOUCH_MODAL):没有设置FLAG_NOT_FOCUSABLE或FLAG_NOT_TOUCH_MODAL其中任何一个flag。
- windowInfo->touchableRegionContainsPoint(x, y):窗口范围包含触控坐标(x,y)。
可见要将触摸事件传递给对应的窗口需要满足条件:( 1 && 2 && ( 3 || 4 ) )。
2.添加设置了FLAG_DISPATCH_AS_OUTSIDE(FLAG_WATCH_OUTSIDE_TOUCH)的窗口到inputTargets。
同样是AMOTION_EVENT_ACTION_DOWN触控事件按下时,获取前台窗口,收集与前台窗口uid不一致,且设置了FLAG_DISPATCH_AS_OUTSIDE(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)的窗口到inputTargets。
将触控事件发送给所有的inputTargets。
找到了正确的inputTargets后,dispatchEventLocked(currentTime, entry, inputTargets);继续分发过程。
4.3.3 dispatchEventLocked
// InputDispatcher.cpp
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
std::shared_ptr<EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
for (const InputTarget& inputTarget : inputTargets) {
sp<Connection> =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
}
}
}
getConnectionLocked()方法通过InputChannel的token获取链接Connection对象,mConnectionsByToken是一个map变量,InputDispatcher维护mConnectionsByToken变量,保存所有当前连接的Connection,key值是token,Binder类型。关于InputChanel的建立,参考下一章节。
接下来prepareDispatchCycleLocked()调用enqueueDispatchEntriesLocked()方法:
4.3.4 enqueueDispatchEntriesLocked
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
// 1. 添加分发条目到队列连接对象 connection
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// 2. 开始分发
if (wasEmpty && !connection->outboundQueue.empty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
enqueueDispatchEntryLocked()添加分发条目到队列连接对象Connection,然后开始分发工作,查看enqueueDispatchEntryLocked()具体实现:
4.3.4.1 enqueueDispatchEntryLocked
void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget,
int32_t dispatchMode) {
// 1. 封装 DispatchEntry对象
std::unique_ptr<DispatchEntry> dispatchEntry =
createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
// 2. 添加到 connection->outboundQueue队列
connection->outboundQueue.push_back(dispatchEntry.release());
}
在这里EventEntry又被解析封装成DispatchEntry对象,专门用于分发工作。
回到分发流程startDispatchCycleLocked()。
4.3.4.2 startDispatchCycleLocked
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
switch (eventEntry.type) {
case EventEntry::Type::MOTION: {
// Publish the motion event.
status = connection->inputPublisher
.publishMotionEvent(dispatchEntry->seq,
dispatchEntry->resolvedEventId,
motionEntry.deviceId, motionEntry.source,
motionEntry.displayId, std::move(hmac),
dispatchEntry->resolvedAction,
motionEntry.actionButton,
dispatchEntry->resolvedFlags,
motionEntry.edgeFlags, motionEntry.metaState,
motionEntry.buttonState,
motionEntry.classification,
dispatchEntry->transform,
motionEntry.xPrecision, motionEntry.yPrecision,
motionEntry.xCursorPosition,
motionEntry.yCursorPosition,
dispatchEntry->rawTransform,
motionEntry.downTime, motionEntry.eventTime,
motionEntry.pointerCount,
motionEntry.pointerProperties, usingCoords);
break;
}
}
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
}
}
从connection->outboundQueue不断取出DispatchEntry,调用connection->inputPublisher.publishMotionEvent()发送输入事件,分发完成后在outboundQueue中擦除对象。connection从InputChannel对象获取,InputChannel描述了inputflinger和事件接受对象的连接,那么InputChannel是怎么建立的呢,在(InputChannel文章)继续分析。