原文链接:https://blog.csdn.net/qq_34211365/article/details/108843167
一、Linux下的INotify
与Epoll
机制
INotify是Linux提供给用户态监听内核文件系统变化的机制,可以监听文件/目录的增删等。INotify的用法很简单,首先需要调用如下代码创建一个文件描述符:
int inotifyfd = inotify_init();
接着需要通过inotify_add_watch将我们关注的事件添加到监听:
int wd = inotify_add_watch(inotifyfd, path, event_mask)
inotify_add_watch的第一个参数是inotify_init创建的文件描述符,第二个参数是要监听的路径,第三个参数是事件的类型,如文件创建IN_CREATE,文件删除IN_DELETE等。
上面两步完成之后当指定路径发生了我们想要监听的事件就会写到inotifyfd中,此时就可以通过read函数对inotifyfd进行读取:
char event_buf[512];
int ret;
struct inotify_event *event;
ret = read(inotifyfd, event_buf, sizeof(event_buf));
读取到的信息封装为inotify_event结构体,使用while循环就可以将所有事件读取出来:
while(ret > (int)sizeof(struct inotify_event)) {
event = (struct inotify_event*)(event_buf + event_pos);
......
}
其实INotify的用法就三步:
使用inotify_init创建一个inotify对象
使用inotify_add_watch对文件路径进行监听
使用read对读取监听到的事件
其实Android SDK就提供了一个监听文件的类FileObserver,它的底层原理就是使用的INotify机制,有兴趣可以去看看它内部的几个native函数。
接下来进入实践环节,写一个简单的INotify测试类,如下目录创建两个类
//demo 代码
#include <sys/inotify.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <log/log.h>
int read_events(int fd) {
char event_buf[512];
int ret;
int event_pos = 0;
int event_size = 0;
struct inotify_event *event;
ALOGD("dongjiao...block read........");
//通过read函数读取目标文件路径发生的事件,没有事件则阻塞
ret = read(fd, event_buf, sizeof(event_buf));
//read的返回值表示实际读取的事件大小,如果小于一个事件大小则说明读取事件失败
if(ret < (int)sizeof(struct inotify_event)) {
ALOGD("dongjiao...read error,could get event");
return -1;
}
//将所有事件循环取出来
while(ret > (int)sizeof(struct inotify_event)) {
event = (struct inotify_event*)(event_buf + event_pos);
ALOGD("dongjiao...event->len = :%d",event->len);
if(event->len) {
if(event->mask & IN_CREATE) {
//文件创建
ALOGD("dongjiao...create file:%s successfully \n", event->name);
} else {
//文件删除
ALOGD("dongjiao...delete file:%s successfully \n", event->name);
}
}
event_size = sizeof(struct inotify_event) + event->len;
ret -= event_size;
event_pos += event_size;
}
return 0;
}
int main(int argc, char** argv) {
//inotify读取到一次事件就会结束,这里使用死循环读取
while(true){
int inotifyFd;
int ret;
const char* path = argv[1];
ALOGD("dongjiao...argc = :%d",argc);
//初始化inotify
inotifyFd = inotify_init();
if(inotifyFd == -1) {
ALOGD("dongjiao...inotify_init error!\n");
return -1;
}
ALOGD("dongjiao...listen target patch:%s \n", path);
//对目标文件路径进行监听,监听的事件是文件创建IN_CREATE,和文件删除IN_DELETE
ret = inotify_add_watch(inotifyFd, path, IN_CREATE | IN_DELETE) ;
//等待目标文件路径的事件发生
read_events(inotifyFd);
//删除inotifyFd
if(inotify_rm_watch(inotifyFd, ret) == -1) {
ALOGD("dongjiao...notify_rm_watch error!\n");
return -1;
}
//关闭inotifyFd
close(inotifyFd);
}
return 0;
}
Epoll 机制
INotify有个问题就是需要主动调用read函数去读取事件,这并不是Input系统想要的,Input系统需要的是INotify监听的目标路径发生变化之后来能通知自己而不是自己主动去读,这就需要结合另一个机制Epoll来实现,Epoll是一种I/O多路复用技术,主要作用就是去监听Linux下的fd,当这些fd发生事件之后会通过回调来通Epoll,
Epoll提供三个操作函数epoll_create,epoll_ctl,epoll_wait。
Epoll
事件类型通常有如下:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说
的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,
需要再次把这个socket加入到EPOLL队列里
EPOLLWAKEUP:系统会在事件排队时就保持唤醒,从epoll_wait调用开始,持续要下一次epoll_wait调用
Epoll的使用步骤:
1. 通过epoll_create创建epoll对象。
2. 为需要监听的fd构建一个epoll_event结构体,并注册到epoll_ctl进行监听。
3. 调用epoll_wait进入监听状态,传入一个epoll_event结构体数组,用于收集监听到的事件。
4. 遍历第三步的epoll_event结构体数组,依次取出事件处理。
INotify和Epoll 实战:
//demo 代码
#include <sys/inotify.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <log/log.h>
int read_events(int fd) {
char event_buf[512];
int ret;
int event_pos = 0;
int event_size = 0;
struct inotify_event *event;
ALOGD("dongjiao...block read........");
//通过read函数读取目标文件路径发生的事件,没有事件则阻塞
ret = read(fd, event_buf, sizeof(event_buf));
//read的返回值表示实际读取的事件大小,如果小于一个事件大小则说明读取事件失败
if(ret < (int)sizeof(struct inotify_event)) {
ALOGD("dongjiao...read error,could get event");
return -1;
}
//将所有事件循环取出来
while(ret > (int)sizeof(struct inotify_event)) {
event = (struct inotify_event*)(event_buf + event_pos);
ALOGD("dongjiao...event->len = :%d",event->len);
if(event->len) {
if(event->mask & IN_CREATE) {
//文件创建
ALOGD("dongjiao...create file:%s successfully \n", event->name);
} else {
//文件删除
ALOGD("dongjiao...delete file:%s successfully \n", event->name);
}
}
event_size = sizeof(struct inotify_event) + event->len;
ret -= event_size;
event_pos += event_size;
}
return 0;
}
int main(int argc, char** argv) {
//inotify读取到一次事件就会结束,这里使用死循环读取
while(true){
int inotifyFd;
int ret;
int mEpollFd;
int result;
int EPOLL_MAX_EVENTS = 16;
struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];
const char* path = argv[1];
ALOGD("dongjiao...argc = :%d",argc);
//初始化inotify
inotifyFd = inotify_init();
//初始化epoll
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
//创建封装inotifyFd的结构体epoll_event
struct epoll_event eventItem = {};
eventItem.events = EPOLLIN | EPOLLWAKEUP;
eventItem.data.fd = inotifyFd;
//将inotifyFd添加到epoll进行监听
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, inotifyFd, &eventItem);
if(inotifyFd == -1) {
ALOGD("dongjiao...inotify_init error!\n");
return -1;
}
ALOGD("dongjiao...listen target patch:%s \n",path);
//对目标文件路径进行监听,监听的事件是文件创建IN_CREATE,和文件删除IN_DELETE
ret = inotify_add_watch(inotifyFd, path, IN_CREATE | IN_DELETE) ;
ALOGD("dongjiao...epoll_wait.....");
//等待事件的发生,会阻塞
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, -1);
ALOGD("dongjiao...epoll event happened pollResult = :%d",pollResult);
for(auto &event:mPendingEventItems){
if(event.data.fd == inotifyFd){
//当inotifyFd上有事件发生,则读取事件
read_events(inotifyFd);
}
}
//删除inotifyFd
if(inotify_rm_watch(inotifyFd, ret) == -1) {
ALOGD("dongjiao...notify_rm_watch error!\n");
return -1;
}
//关闭inotifyFd
close(inotifyFd);
}
return 0;
}
二、Input子系统的启动
InputManagerService
InputManagerService
是java层的一个系统服务,继承IInputManager.Stub
,作为binder服务端,在SystemServer
中启动:InputManagerService
构造函数中创建了一个InputManagerHandler
,使用的是"android.display"线程的looper对象,运行在"android.display"线程。
public InputManagerService(Context context) {
this.mContext = context;
//创建handler,运行在"android.display"线程
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
......
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}
nativeInit
nativeInit实际上就做了一件事,拿到java层InputManagerService传递下来的"android.display"线程的Looper对应的MessageQueue获取native层MessageQueue,之后通过此native层MessageQueue的Looper创建NativeInputManager。
// com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
//java层MessageQueue的mPtr指向native层MessageQueue,这里
//就是将mPtr强转为native层MessageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == nullptr) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
//创建NativeInputManager
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
NativeInputManager
NativeInputManager构造函数也很简单,就是创建了InputManager,并添加到ServiceManager,InputManager是binder服务端,它的构造函数中接收两个对象:InputReaderPolicyInterface和InputDispatcherPolicyInterface。
而NativeInputManager
是这两个对象的子类,所以传递的是this。
// com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
//java层的InputManagerService对象
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;
mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
}
mInteractive = true;
//创建InputManager
mInputManager = new InputManager(this, this);
//将mInputManager添加到ServiceManager,可以通过getService获取
defaultServiceManager()->addService(String16("inputflinger"),
mInputManager, false);
}
InputManager
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
//(1)
mDispatcher = createInputDispatcher(dispatcherPolicy);
//(2)
mClassifier = new InputClassifier(mDispatcher);
//(3)
mReader = createInputReader(readerPolicy, mClassifier);
}
InputManager构造函数中创建了这三个对象:
private:
sp<InputDispatcherInterface> mDispatcher;
sp<InputClassifierInterface> mClassifier;
sp<InputReaderInterface> mReader;
};
InputDispatcher
mDispatcher = createInputDispatcher(dispatcherPolicy)
//InputDispatcherFactory.cpp
sp<InputDispatcherInterface> createInputDispatcher(
const sp<InputDispatcherPolicyInterface>& policy) {
return new android::inputdispatcher::InputDispatcher(policy);
}
InputDispatcher是一个非常重要的对象,它是Input事件发送到对应窗口的分发者
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mAppSwitchSawKeyDown(false),
mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(nullptr),
mDispatchEnabled(false),
mDispatchFrozen(false),
mInputFilterEnabled(false),
// mInTouchMode will be initialized by the WindowManager to the default device config.
// To avoid leaking stack in case that call never comes, and for tests,
// initialize it here anyways.
mInTouchMode(true),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
//创建自己的Looper
mLooper = new Looper(false);
mReporter = createInputReporter();
mKeyRepeatState.lastKeyEntry = nullptr;
//获取java层的一些配置参数,写到mConfig中,主要就是如下两个值:
//public static final int DEFAULT_LONG_PRESS_TIMEOUT = 400;
//private static final int KEY_REPEAT_DELAY = 50;
policy->getDispatcherConfiguration(&mConfig);
}
mClassifier
= new InputClassifier(mDispatcher);
// --- InputClassifier ---
InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
: mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this))
{
}
它的构造函数非常简单,将前面创建的InputDispatcher保存在了mListener中,并创建了一个监听HAL的死亡回调对象,InputClassifierM是一个空壳子,它提供的如下函数内部实现都是调用到了InputDispatcher中去:
class InputClassifier : public InputClassifierInterface {
public:
explicit InputClassifier(const sp<InputListenerInterface>& listener);
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
virtual void notifyKey(const NotifyKeyArgs* args) override;
virtual void notifyMotion(const NotifyMotionArgs* args) override;
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
mReader
= createInputReader(readerPolicy, mClassifier);
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener) {
return new InputReader(std::make_unique<EventHub>(), policy, listener);
}
同样是直接new的一个InputReader,它接收了一个EventHub对象,这个对象非常重要,它是读取驱动原始Input事件的主要类,InputReader构造函数比较简单,代码不多,所以我们先来分析EventHub的初始化。
// --- InputReader ---
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mGlobalMetaState(0),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener);
{ // acquire lock
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
EventHub
EventHub
继承EventHubInterface
,这是它的构造函数:
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,对EPOLL_CLOEXEC个fd进行监听
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
//创建inotify
mINotifyFd = inotify_init();
//对"/dev/input"目录下的文件进行监听,监听事件是文件的创建与删除
mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
if (isV4lScanningEnabled()) {
//对"/dev"目录进行监听
mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
} else {
mVideoWd = -1;
}
//创建epoll事件结构体
struct epoll_event eventItem = {};
//监听事件:
//EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
//EPOLLWAKEUP:系统会在事件排队时就保持唤醒,从epoll_wait调用开始,持续要下一次epoll_wait调用
eventItem.events = EPOLLIN | EPOLLWAKEUP;
//epoll监听的fd为mINotifyFd
eventItem.data.fd = mINotifyFd;
//将mINotifyFd添加到epoll
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
int wakeFds[2];
//创建管道
result = pipe(wakeFds);
//读管道
mWakeReadPipeFd = wakeFds[0];
//写管道
mWakeWritePipeFd = wakeFds[1];
//将读写管道都设置为非阻塞
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
eventItem.data.fd = mWakeReadPipeFd;
//将读管道添加到epoll
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}
EventHub构造函数中结合INotify与Epoll对"/dev/input"目录进行监听,以及创建了一对管道,将读端mWakeReadPipeFd添加到Epoll进行监听,之后只需要调用epoll_wait等待事件发生就行了,至于在哪里调的epoll_wait,我们后面再看。
InputManagerService
构造方法中调用的nativeInit
函数就结束了,接着再回到SystemService
中,InputManagerService
创建完成之后,会调用它的start
方法:
InputManagerService.start
//InputManagerService.java
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// 添加Watchdog的监听
Watchdog.getInstance().addMonitor(this);
//注册一系列Settings数据库值的监听
.....
}
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
nativeStart
这个方法,mPtr指向nativeInit
中创建的NativeInputManager
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
status_t InputManager::start() {
//(1)
status_t result = mDispatcher->start();
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
//(2)
result = mReader->start();
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;
}
InputDispatcher::start
//InputDispatcher.cpp
status_t InputDispatcher::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
mThread如果已经存在则返回,否则创建,mThread类型为InputThread,InputThread内部有一个Thread,InputThread的构造函数中接受三个参数:
class InputThread {
public:
explicit InputThread(std::string name, std::function<void()> loop,
std::function<void()> wake = nullptr);
一个string,代表此线程名称,还有两个std::function,传递的则是两个Lambda表达式,这两个Lambda表达式中分别调用dispatchOnce()和mLooper->wake()这两个函数,接着再看InputThread构造函数的具体实现:
//InputThread.cpp
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
: mName(name), mThreadWake(wake) {
mThread = new InputThreadImpl(loop);
mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}
InputThread构造函数中将接收的两个Lambda表达式一个传递给了InputThreadImpl,另一个保存在了自己mThreadWake中,
InputThreadImpl继承Thread,是一个线程,
接着调用run函数启动线程,线程启动之后就会调用自己的threadLoop函数:
class InputThreadImpl : public Thread {
public:
explicit InputThreadImpl(std::function<void()> loop)
: Thread(/* canCallJava */ true), mThreadLoop(loop) {}
~InputThreadImpl() {}
private:
std::function<void()> mThreadLoop;
bool threadLoop() override {
mThreadLoop();
return true;
}
};
InputThreadImpl的threadLoop函数很简单,调用了自己的mThreadLoop函数,mThreadLoop接收了一个Lambda表达式:([this]() { dispatchOnce(); }),即
InputThreadImpl线程启动时就会调用InputDispatcher的dispatchOnce函数,至于dispatchOnce的细节我们在后面再分析。
InputReader.
start
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
InputReader
的start
函数就和InputDispatcher
有异曲同工之妙了,只不过线程的名字和两个Lambda
表达式不一样,所以我们知道最终这个线程启动之后会调用InputReader
的loopOnce()
函数。
InputManager的start函数中分别调用了InputDispatcher和InputReader的start函数,即分别启动了其内部线程InputThreadImpl,InputDispatcher内部线程(名字:“InputDispatcher”)启动调用了自己的dispatchOnce()函数,InputReader内部线程(名字:“InputReader”)启动调用了自己的loopOnce()函数。
三、InputReader线程读取输入事件
InputReader
的loopOnce()
//InputReader.cpp
void InputReader::loopOnce() {
//(1)
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> 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
//(2)
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
//(3)
processEventsLocked(mEventBuffer, count);
}
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now >= mNextTimeout) {
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
}
//(4)
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();
}
1. requestRefreshConfiguration
每一个设备节点都对应了一张kl(key layout)表,如果外接一个键盘或游戏手柄就可能会增加设备节点,这时inputDevicesChanged就会发生变化,变量inputDevices代表一个InputDeviceInfo的集合,InputDeviceInfo描述了dev/input目录这些输入设备节点的特性和功能(例如设备ID,kl表名称),变量mGeneration会在dev/input设备节点增加或删除时发生变化,变量mConfigurationChangesToRefresh描述了一些input配置信息的变化,由函数requestRefreshConfiguration进行修改,
void InputReader::requestRefreshConfiguration(uint32_t changes) {
AutoMutex _l(mLock);
if (changes) {
bool needWake = !mConfigurationChangesToRefresh;
mConfigurationChangesToRefresh |= changes;
if (needWake) {
mEventHub->wake();
}
}
}
参数changes可以是以下枚举值
struct InputReaderConfiguration {
// Describes changes that have occurred.
enum {
// The pointer speed changed.
CHANGE_POINTER_SPEED = 1 << 0,
// The pointer gesture control changed.
CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1,
// The display size or orientation changed.
CHANGE_DISPLAY_INFO = 1 << 2,
// The visible touches option changed.
CHANGE_SHOW_TOUCHES = 1 << 3,
// The keyboard layouts must be reloaded.
CHANGE_KEYBOARD_LAYOUTS = 1 << 4,
// The device name alias supplied by the may have changed for some devices.
CHANGE_DEVICE_ALIAS = 1 << 5,
// The location calibration matrix changed.
CHANGE_TOUCH_AFFINE_TRANSFORMATION = 1 << 6,
// The presence of an external stylus has changed.
CHANGE_EXTERNAL_STYLUS_PRESENCE = 1 << 7,
// The pointer capture mode has changed.
CHANGE_POINTER_CAPTURE = 1 << 8,
// The set of disabled input devices (disabledDevices) has changed.
CHANGE_ENABLED_STATE = 1 << 9,
// All devices must be reopened.
CHANGE_MUST_REOPEN = 1 << 31,
};
2. mEventHub->getEvents
2.1 首次进入此函数时mNeedToScanDevices为true,会调用scanDevicesLocked扫描并打开设备
2.2 通过epoll_wait等待mEpollFd上的事件发生,mEpollFd添加了mINotifyFd和mWakeReadPipeFd监听,epoll_wait实际上就是等待mINotifyFd和mWakeReadPipeFd上发生事件,事件发生之后放入mPendingEventItems数组,然后由一个while循环来处理这些事件,对于mINotifyFd发生的事件(设备节点的增删)则调用readNotifyLocked函数更新设备,对于input事件,则将事件封装为RawEvent。
参数mEventBuffer
是一个存储RawEvent
的数组,大小为EVENT_BUFFER_SIZE
(256):
//InputReader.h
// The event queue.
static const int EVENT_BUFFER_SIZE = 256;
RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
/*
* A raw event as retrieved from the EventHub.
*/
//EventHub.h
struct RawEvent {
nsecs_t when; //事件发生的事件
int32_t deviceId; //事件发生的设备节点ID
int32_t type; //事件的类型
int32_t code; //扫描码scancode
int32_t value;
};
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
....
struct input_event readBuffer[bufferSize];
//原始事件
RawEvent* event = buffer;
size_t capacity = bufferSize;
bool awoken = false;
//死循环获取事件
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// 是否需要重新打开设备
if (mNeedToReopenDevices) {
mNeedToReopenDevices = false;
//关闭所有设备
closeAllDevicesLocked();
mNeedToScanDevices = true;
break; // return to the caller before we actually rescan
}
// 是否删除所有设备
while (mClosingDevices) {
Device* device = mClosingDevices;
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;
//设备数量达到256则break
if (--capacity == 0) {
break;
}
}
//是否需要扫描并打开设备,初始化为true
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
//扫描并打开设备
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
//是否正在打开的设备不为空
while (mOpeningDevices != nullptr) {
Device* device = mOpeningDevices;
//指向下一个打开的设备
mOpeningDevices = device->next;
//当前时间
event->when = now;
//设备节点ID
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;
//mPendingEventCount描述了从dev/input目录下各个设备节点发生的事件个数,
//初始化为0,
//mPendingEventIndex 描述了正在处理的事件下标,初始化为0
//这个while循环作用就是依次处理dev/input目录下各个设备节点
//发生的所有事件,首次到这里时因为没有任何事件,则为fasle
while (mPendingEventIndex < mPendingEventCount) {
//mPendingEventItems是一个epoll_event类型数组,size为16,
//epoll_event是用来描述通过epoll_wait监听到的内核事件,
//这里的事件也就是监听mINotifyFd和mWakeReadPipeFd获取到的
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
//是否是监听mINotifyFd获取到的事件
if (eventItem.data.fd == mINotifyFd) {
//是否可以读取事件
if (eventItem.events & EPOLLIN) {
//设置mPendingINotify为true,后面处理
mPendingINotify = true;
} else {
...
}
continue;
}
//是否是监听mWakeReadPipeFd获取到的事件
if (eventItem.data.fd == mWakeReadPipeFd) {
//从mWakeReadPipeFd读取到的事件不是我们分析重点,省略
.......
}
//根据fd类型获取对应设备,可以是输入设备或者视频设备(不太清楚视频设备相关)
//Device是用来描述dev/input目录下设备节点信息的结构体
Device* device = getDeviceByFdLocked(eventItem.data.fd);
if (!device) {
...
continue;
}
//是否是视频设备
if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
//不是重点,省略
....
continue;
}
//可读取的input事件
if (eventItem.events & EPOLLIN) {
//通过read函数读取dev/input目录下各个设备节点发生的事件,device->fd
//的值是在打开设备时赋值的,其实就是dev/input目录下的各个设备节点
//将事件放入readBuffer数组
//readSize / sizeof(struct input_event) = 事件个数,必须为整数倍,否则
//读取异常。
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.
...
deviceChanged = true;
closeDeviceLocked(device);
//异常情况
} else if (readSize < 0) {
if (errno != EAGAIN && errno != EINTR) {
}
//异常情况
} else if ((readSize % sizeof(struct input_event)) != 0) {
...
} else {//处理事件
//mBuiltInKeyboardId是一个枚举值NO_BUILT_IN_KEYBOARD,具体含义不是
//太清楚,但从dump的input信息看,一般device->id不会等于mBuiltInKeyboardId
int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
//读取到的事件个数
size_t count = size_t(readSize) / sizeof(struct input_event);
//for循环分别处理每一个事件,将input_event转换为RawEvent
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
//将每一个事件都封装为原始事件RawEvent
event->when = processEventTimestamp(iev);
//事件的设备节点ID
event->deviceId = deviceId;
//事件类型
event->type = iev.type;
//事件code
event->code = iev.code;
//事件value
event->value = iev.value;
//指向下一个事件
event += 1;
//容量-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) {
deviceChanged = true;
//关闭设备
closeDeviceLocked(device);
} else {
//异常情况,发生不合法事件
device->identifier.name.c_str());
}
}
// 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.
//mPendingINotify 为true代表在mINotifyFd上读取到了dev/input目录下设备节点的
//删除或者创建,mPendingEventIndex >= mPendingEventCount代表当前这一轮input
//事件已经处理完成
if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
mPendingINotify = false;
//通知更新dev/input目录下设备节点
readNotifyLocked();
deviceChanged = true;
}
// 报告dev/input目录下设备节点发生了增加或者删除
if (deviceChanged) {
continue;
}
// 读取到事件,结束最开始的for(;;)
if (event != buffer || awoken) {
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.
mPendingEventIndex = 0;
mLock.unlock(); // release lock before poll
//通过epoll_wait等待mEpollFd上事件发生,没有则阻塞,mEpollFd添加了mINotifyFd和
//mWakeReadPipeFd监听,实际上就是监听mINotifyFd和mWakeReadPipeFd上发生的事件,
//事件发生之后放入mPendingEventItems数组,返回值pollResult为事件的数量
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
mLock.lock(); // reacquire lock after poll
//如果pollResult 为0,说明超时了,因为不超时会一直阻塞在epoll_wait
if (pollResult == 0) {
// Timed out.
mPendingEventCount = 0;
break;
}
//pollResult < 0,发生异常
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) {
usleep(100000);
}
} else {
//发生事件的数量
mPendingEventCount = size_t(pollResult);
}
}
//返回获取到的事件数量
return event - buffer;
}
3. processEventsLocked
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;
//小于FIRST_SYNTHETIC_EVENT代表除DEVICE_ADDED,DEVICE_REMOVED,
//FINISHED_DEVICE_SCAN的其他事件
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) {
//如果事件类型是DEVICE_ADDED,DEVICE_REMOVED,FINISHED_DEVICE_SCAN,
//或者不是发生在同一设备节点的事件则break
break;
}
//同一设备节点的事件数量
batchSize += 1;
}
//处理事件
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
//如果事件类型为DEVICE_ADDED
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
//如果事件类型为DEVICE_REMOVED
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
//如果事件类型为FINISHED_DEVICE_SCAN
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
enum {
// 设备添加
DEVICE_ADDED = 0x10000000,
// 设备移除
DEVICE_REMOVED = 0x20000000,
// 设备扫描
FINISHED_DEVICE_SCAN = 0x30000000,
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
};
processEventsLocked
函数比较简单,就是根据事件的类型调不同的函数,我们先来看
3.1 processEventsForDeviceLocked
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;
}
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.
//遍历原始事件
for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
mDropUntilNextSync = false;
} else {
...
}
} 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 {
for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
mapper.process(rawEvent);
});
}
--count;
}
}
KeyboardInputMapper::process
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);
}
break;
}
//其他事件
case EV_MSC: {
if (rawEvent->code == MSC_SCAN) {
mCurrentHidUsage = rawEvent->value;
}
break;
}
//同步事件
case EV_SYN: {
if (rawEvent->code == SYN_REPORT) {
mCurrentHidUsage = 0;
}
}
}
}
KeyboardInputMapper::processKey
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
int32_t keyCode;
int32_t keyMetaState;
uint32_t policyFlags;
if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
&policyFlags)) {
keyCode = AKEYCODE_UNKNOWN;
keyMetaState = mMetaState;
policyFlags = 0;
}
//按下事件
if (down) {
...
// Add key down.
ssize_t keyDownIndex = findKeyDown(scanCode);
if (keyDownIndex >= 0) {
//重复事件
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;
keyDown.keyCode = keyCode;
keyDown.scanCode = scanCode;
//放入mKeyDowns
mKeyDowns.push_back(keyDown);
}
mDownTime = when;
} else {//抬起事件
// Remove key down.
ssize_t keyDownIndex = findKeyDown(scanCode);
if (keyDownIndex >= 0) {
// 一个按键事件抬起之后将该事件以及之前的所以事件从mKeyDowns移除
keyCode = mKeyDowns[keyDownIndex].keyCode;
mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
} else {
//该事件只有抬起没有按下,异常情况
return;
}
}
......
nsecs_t downTime = mDownTime;
...
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(&args);
}
函数最后根据RawEvent
解析出的按键信息构造了一个NotifyKeyArgs
,并调用QueuedInputListener
的notifyKey
将NotifyKeyArgs
发送出去,
getDeviceContext().mapKey
有个非常重要的操作就是getDeviceContext().mapKey
,它会将按键扫描码scanCode转换为keyCode,scanCode是驱动提供的,上层java使用的就是转换之后的keyCode,扫描码定义在kl(key layout)文件中,
QueuedInputListener::notifyKey 仅仅就是将NotifyKeyArgs
放入mArgsQueue
集合
//InputListener.cpp
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyKeyArgs(*args));
}
仅仅就是将NotifyKeyArgs放入mArgsQueue集合
3.2 addDeviceLocked
函数:
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
if (mDevices.find(eventHubId) != mDevices.end()) {
//如果要添加的设备已经存在则return
ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
return;
}
//InputDeviceIdentifier用来标识设备
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
//通过设备ID和InputDeviceIdentifier创建InputDevice
std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
device->configure(when, &mConfig, 0);
device->reset(when);
....
//将InputDevice和设备ID一一对应到mDevices这个map中
mDevices.emplace(eventHubId, device);
...
}
创建InputDevice InputReader::createDeviceLocked
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
int32_t eventHubId, const InputDeviceIdentifier& identifier) {
//通过find_if判断要创建的InputDevice是否已经存在
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传入了4个参数,mContext指向InputReader
device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
identifier);
}
//将设备ID添加到InputDevice
device->addEventHubDevice(eventHubId);
return device;
}
InputDevice::addEventHubDevice
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
if (mDevices.find(eventHubId) != mDevices.end()) {
//如果已经添加过了直接return
return;
}
//创建InputDeviceContext,这个类主要提供一些访问EventHub的函数
std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
uint32_t classes = contextPtr->getDeviceClasses();
//mappers是一个InputMapper类型的集合,
//InputMapper是原始事件加工的类,不同类型事件对应不同InputMapper,
//这里的类型有键盘,鼠标,触摸屏等,都是InputMapper子类
std::vector<std::unique_ptr<InputMapper>> mappers;
//populateMappers默认值为true
if (!populateMappers) {
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
return;
}
// 开关类型InputMapper
if (classes & INPUT_DEVICE_CLASS_SWITCH) {
mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
}
// 滑动类型InputMapper
if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
}
//震动类型InputMapper
if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
}
// 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;
}
//键盘类型InputMapper
if (keyboardSource != 0) {
mappers.push_back(
std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
}
//鼠标类型InputMapper
if (classes & INPUT_DEVICE_CLASS_CURSOR) {
mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
}
//触摸屏类型InputMapper
if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
} else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
}
// 操纵杆类型InputMapper
if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
}
// 外部触控笔类型InputMapper
if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
}
// mDevices是一个map,提供了eventHubId,contextPtr,InputMapper集合的一一映射,
//即一个eventHubId对应一个InputDeviceContext对应一个InputMapper集合
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
}
createDeviceLocked和addEventHubDevice函数主要功能就是创建了InputDevice,每一个eventHubId对应一个InputDevice,并将InputReader的mContext传给了InputDevice,然后创建InputDeviceContext,此类提供一系列访问EventHub的函数,接着根据eventHubId,获取设备类型,根据设备类型创建不同的InputMapper,用于处理该设备的原始事件,每个InputMapper构造函数中都接收一个contextPtr用于访问EventHub,最后再InputDevice的mDevices成员变量中提供eventHubId,contextPtr,mappers的一一映射。
4.QueuedListener::flush
//InputListener.cpp
void 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();
}
这里会遍历mArgsQueue,并调用NotifyArgs的notify函数,NotifyArgs是一个父类,不同事件类型对应不同的子类,有如下几种类型:
NotifyConfigurationChangedArgs
NotifyKeyArgs
NotifyMotionArgs
NotifySwitchArgs
NotifyDeviceResetArgs
因为我们分析的是按键事件,对应的是NotifyKeyArgs,即NotifyKeyArgs::notify,这里继续调用InputListenerInterface
的notifyKey
函数,InputListenerInterface
是一个父类,我们需要找其子类的具体实现,子类其实就是InputDispatcher
,输入事件就顺理成章的从InputReader
发送到了InputDispatcher,
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyKey(this);//this代表NotifyKeyArgs
}
class InputDispatcher : public android::InputDispatcherInterface{
...
}
InputReader对input事件处理过程大致可以分为三大步:
1. EventHub通过INotify与Epoll监听/dev/input下的事件,在读取到事件之后放入mEventBuffer,此步骤将input_event转换为了RawEvent。
2.拿到原始事件RawEvent之后调用processEventsLocked对事件进行加工,不同事件类型有不同的加工厂(InputMapper),此步骤将RawEvent转换为了NotifyKeyArgs。
3. 通过QueuedListener的flush函数将事件发送到InputDispatcher线程。
四、InputDispatcher线程分发输入事件
EventHub
读取了输入系统的原始事件之后会将其转换为NotifyKeyArgs
(对于按键事件来说),接着会调用InputDispatcher
的notifyKey
函数将NotifyKeyArgs
发送到InputDispatcher
线程做进一步处理。
NotifyKeyArgs结构体
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
......
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(&args);
......
}
构造函数
// --- NotifyKeyArgs ---
NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime)
: NotifyArgs(id, eventTime), //eventTime:事件发生的时间
deviceId(deviceId), //事件发生的设备ID
source(source), //事件的来源,可以是物理键盘,游戏手柄等
displayId(displayId), //事件发生的显示器ID
policyFlags(policyFlags), //事件的flag,指示该事件是否有特殊含义,如唤醒设备等
action(action), //事件是按下还是抬起
flags(flags), //此参数为AKEY_EVENT_FLAG_FROM_SYSTEM,用来确认事件来自真实用户的点击
keyCode(keyCode), //Android键盘码
scanCode(scanCode), //系统扫描码
metaState(metaState),
downTime(downTime) //记录时间按下的时间,对于down事件其实就等于eventTime
{
}
InputDispatcher::notifyKey
函数会将NotifyKeyArgs
封装的事件信息解析出来,构造两个结构体KeyEvent
和KeyEntry
,为什么是两个?因为KeyEvent
是会首先传递到java层的PhoneWindowManager
中去判断是否将此事件加入分发队列
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
//对事件有效性进行简单判断
if (!validateKeyEvent(args->action)) {
return;
}
//将NotifyKeyArgs中的事件信息解析出来
uint32_t policyFlags = args->policyFlags;
int32_t flags = args->flags;
int32_t metaState = args->metaState;
constexpr int32_t repeatCount = 0;
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;
}
//表示当前事件可信任,添加特定flag
policyFlags |= POLICY_FLAG_TRUSTED;
int32_t keyCode = args->keyCode;
//构造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);
android::base::Timer t;
//mPolicy指向NativeInputManager,这个函数最终会通过JNI调到java层
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
std::to_string(t.duration().count()).c_str());
}
//是否需要唤醒InputDispatcher线程
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();
}
//构造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);
//将事件加入队列
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake();
}
}
NativeInputManager::interceptKeyBeforeQueueing
1.通过函数android_view_KeyEvent_fromNative将native层keyEvent转换为java层的keyEvent,
2.通过InputManagerService的interceptKeyBeforeQueueing的方法将keyEvent传递到java层。
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
uint32_t& policyFlags) {
ATRACE_CALL();
//mInteractive初始默认值为true,这个值用来表示当前是否处于用户交互状态
//可通过函数setInteractive修改
bool interactive = mInteractive.load();
if (interactive) {
policyFlags |= POLICY_FLAG_INTERACTIVE;
}
//InputDispatcher的notifyKey函数中已经将policyFlags添加了POLICY_FLAG_TRUSTED
//所以这里为true
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
nsecs_t when = keyEvent->getEventTime();
JNIEnv* env = jniEnv();
//将native层keyEvent转换为java层keyEvent
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
jint wmActions;
if (keyEventObj) {
//mServiceObj指向java层InputManagerService,这里调用其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;
}
}
}
keyEvent
的转换
jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
ScopedLocalRef<jbyteArray> hmac = toJbyteArray(env, event->getHmac());
jobject eventObj =
env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, gKeyEventClassInfo.obtain,
event->getId(),
nanoseconds_to_milliseconds(event->getDownTime()),
nanoseconds_to_milliseconds(event->getEventTime()),
event->getAction(), event->getKeyCode(),
event->getRepeatCount(), event->getMetaState(),
event->getDeviceId(), event->getScanCode(),
event->getFlags(), event->getSource(),
event->getDisplayId(), hmac.get(), nullptr);
if (env->ExceptionCheck()) {
ALOGE("An exception occurred while obtaining a key event.");
LOGE_EX(env);
env->ExceptionClear();
return NULL;
}
return eventObj;
}
直接解析native层KeyEvent,构造java层的KeyEvent,gKeyEventClassInfo.clazz指向android.view.KeyEvent.java这个类,gKeyEventClassInfo.obtain指向这个类的构造方法。
接着java层KeyEvent构造好了之后会调用InputManagerService的interceptKeyBeforeQueueing方法:
InputManagerService.interceptKeyBeforeQueueing
// Native callback.
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}
InputDispatcher::enqueueInboundEventLocked
mInboundQueue是一个存储EventEntry的队列,EventEntry是各种类型事件的顶级父类,除了Key类型事件KeyEntry,还有如下这些子类:
MotionEntry,DeviceResetEntry,ConfigurationChangedEntry。
上面这个函数将KeyEntry保存到了mInboundQueue
尾部,并对几个特殊按键HOME,ENDCALL,APP_SWITCH增加了0.5s超时时间,超时之后会丢弃其他按键事件。
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
//如果mInboundQueue队列为空则一定会唤醒InputDispatcher线程
bool needWake = mInboundQueue.empty();
//事件放入队列尾部
mInboundQueue.push_back(entry);
traceInboundQueueLengthLocked();
//事件类型
switch (entry->type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*entry);
//这里主要是对APP切换事件的判断,包含HOME,ENDCALL,APP_SWITCH三种事件
if (isAppSwitchKeyEvent(keyEntry)) {
if (keyEntry.action == AKEY_EVENT_ACTION_DOWN) {
mAppSwitchSawKeyDown = true;
} else if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
if (mAppSwitchSawKeyDown) {
//当满足条件时,增加按键0.5s的超时时间,超时之后其他按键事件会丢弃
mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
mAppSwitchSawKeyDown = false;
needWake = true;
}
}
}
break;
}
.......
}
return needWake;
}
mLooper->wake()
if (needWake) {
//唤醒InputDispatcher线程
mLooper->wake();
}
InputDispatcher::dispatchOnce
对于InputDispatcher线程来说,主要监听了两个fd,一个是Looper创建时就会默认添加到监听的mWakeEventFd
,另一个是后面要分析的InputChannel
机制的fd。epoll
机制的都应该知道epoll
主要作用是对目标fd进行监听,当fd上没有事件发生时则会陷入等待状态,mWakeEventFd
的作用就是唤醒epoll
,具体如何唤醒的呢?就是调用Looper的wake
函数:Looper的wake函数实现很简单,就是向mWakeEventFd中写入了一个int 1,此时Looper就被唤醒了,即InputDispatcher线程被唤醒了,唤醒之后首先判断haveCommandsLocked函数返回false即mCommandQueue为空才会执行dispatchOnceInnerLocked。
void Looper::wake() {
uint64_t inc = 1;
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
LOG_ALWAYS_FATAL("Could not write wake signal to fd %d (returned %zd): %s",
mWakeEventFd.get(), nWrite, strerror(errno));
}
}
}
bool InputDispatcher::haveCommandsLocked() const {
return !mCommandQueue.empty();
}
typedef std::function<void(InputDispatcher&, CommandEntry*)> Command;
struct CommandEntry {
explicit CommandEntry(Command command);
......
}
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{
if (!haveCommandsLocked()) {
//事件分发核心函数
dispatchOnceInnerLocked(&nextWakeupTime);
}
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
// If we are still waiting for ack on some events,
// we might have to wake up earlier to check if an app is anr'ing.
const nsecs_t nextAnrCheck = processAnrsLocked();
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
// We are about to enter an infinitely long sleep, because we have no commands or
// pending or queued events
if (nextWakeupTime == LONG_LONG_MAX) {
mDispatcherEnteredIdle.notify_all();
}
} // release lock
//进入等待
mLooper->pollOnce(timeoutMillis);
}
如果mCommandQueue
不为空会是什么情况?不为空就会调用runCommandsLockedInterruptible
函数执行mCommandQueue
中的指令:
bool InputDispatcher::runCommandsLockedInterruptible() {
if (mCommandQueue.empty()) {
return false;
}
do {
std::unique_ptr<CommandEntry> commandEntry = std::move(mCommandQueue.front());
mCommandQueue.pop_front();
Command command = commandEntry->command;
command(*this, commandEntry.get()); // commands are implicitly 'LockedInterruptible'
commandEntry->connection.clear();
} while (!mCommandQueue.empty());
return true;
}
接着mCommandQueue
队列为空就会调用dispatchOnceInnerLocked
函数:
InputDispatcher::dispatchOnceInnerLocked
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
//当前时间
nsecs_t currentTime = now();
//mDispatchEnabled默认为false
if (!mDispatchEnabled) {
//重置上一个事件
resetKeyRepeatLocked();
}
// 分发被冻结,WMS冻屏时会设置这个值,例如转屏
if (mDispatchFrozen) {
if (DEBUG_FOCUS) {
ALOGD("Dispatch frozen. Waiting some more.");
}
return;
}
//对于特殊按键HOME,END_CALL,APP_SWITCH增加了0.5s超时时间,
//超时之后会丢弃其他即将处理的按键事件。即isAppSwitchDue为true的情况
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
...
//如果待处理的事件mPendingEvent为空
if (!mPendingEvent) {
//mInboundQueue队列为空,表明没有任何事件
if (mInboundQueue.empty()) {
....
} else {
//否则取出mInboundQueue队头事件
mPendingEvent = mInboundQueue.front();
//并从队列移除
mInboundQueue.pop_front();
traceInboundQueueLengthLocked();
}
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
//这里将会调到java层PowerManagerService中去
pokeUserActivityLocked(*mPendingEvent);
}
}
bool done = false;
//初始化事件丢弃原因
DropReason dropReason = DropReason::NOT_DROPPED;
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
//当前事件不包含POLICY_FLAG_PASS_TO_USER的标志,则不合法,需要丢弃
dropReason = DropReason::POLICY;
} else if (!mDispatchEnabled) {
//当前事件被禁止分发,需要丢弃
dropReason = DropReason::DISABLED;
}
...
switch (mPendingEvent->type) {
......
//对于按键类型事件的处理分支
case EventEntry::Type::KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEvent(*typedEntry)) {
//重置mAppSwitchDueTime
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DropReason::NOT_DROPPED) {
//由于APP切换需要丢弃非HOME,ENDCALL,APP_SWITCH之外的事件
dropReason = DropReason::APP_SWITCH;
}
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry)) {
//当前处理事件的时间减去事件产生的时间大于10s也需要丢弃
dropReason = DropReason::STALE;
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
//对按键类型事件来说不会走到这,mNextUnblockedEvent默认值为null
dropReason = DropReason::BLOCKED;
}
//进一步分发按键事件
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
......
}
//事件处理完成
if (done) {
if (dropReason != DropReason::NOT_DROPPED) {
//最后事件还是被丢弃
dropInboundEventLocked(*mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
//将事件release掉
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
InputDispatcher::dispatchKeyLocked
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
//对按键重复性的一些细节处理,不关注,省略
......
// interceptKeyResult用来描述当前按键的执行结果,
//初始化默认值为INTERCEPT_KEY_RESULT_UNKNOWN
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
//延迟处理当前按键,interceptKeyWakeupTime延迟处理的时间
if (currentTime < entry->interceptKeyWakeupTime) {
if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
*nextWakeupTime = entry->interceptKeyWakeupTime;
}
//因为当前按键会被延迟处理,这里直接返回了
return false; // wait until next wakeup
}
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
entry->interceptKeyWakeupTime = 0;
}
// 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,command函数为doInterceptKeyBeforeDispatchingLockedInterruptible
std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
&InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
//focusedWindowHandle 用来描述当前获得焦点的窗口信息
sp<InputWindowHandle> focusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(*entry));
if (focusedWindowHandle != nullptr) {
//这里将当前焦点窗口的inputChannel保存到commandEntry中,
//inputChannel是一个很重要的东西,它是用来唤醒目标窗口处理事件的
commandEntry->inputChannel = getInputChannelLocked(focusedWindowHandle->getToken());
}
//将当前按键KeyEntry保存到CommandEntry
commandEntry->keyEntry = entry;
//将CommandEntry加入Command队列,待执行
postCommandLocked(std::move(commandEntry));
entry->refCount += 1;
//直接返回,等待Command队列执行
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) {
//interceptKeyResult 为INTERCEPT_KEY_RESULT_SKIP,会丢弃该事件
if (*dropReason == DropReason::NOT_DROPPED) {
*dropReason = DropReason::POLICY;
}
}
if (*dropReason != DropReason::NOT_DROPPED) {
//该按键被丢弃
setInjectionResult(entry,
*dropReason == DropReason::POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
: INPUT_EVENT_INJECTION_FAILED);
//丢弃之后的回调
mReporter->reportDroppedKey(entry->id);
return true;
}
std::vector<InputTarget> inputTargets;
//寻找合法焦点窗口
int32_t injectionResult =
findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResult(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
return true;
}
// Add monitor channels from event's or focused display.
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
//分发按键
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
dispatchKeyLocked函数中对于输入事件,并不是直接拿到就处理,而是首先为其构造CommandEntry,并添加到mCommandQueue队列,然后此函数就返回了,返回的false表明此事件并未处理完成。
而我们前面有说过mCommandQueue这个队列,它会在runCommandsLockedInterruptible函数中被遍历出来执行其内部Command函数,构造CommandEntry时传入的函数指针为doInterceptKeyBeforeDispatchingLockedInterruptible,接下来会先调用这个函数判断按键事件是否提前拦截:
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
CommandEntry* commandEntry) {
//将KeyEntry转换为KeyEvent
KeyEntry* entry = commandEntry->keyEntry;
KeyEvent event = createKeyEvent(*entry);
mLock.unlock();
android::base::Timer t;
sp<IBinder> token = commandEntry->inputChannel != nullptr
? commandEntry->inputChannel->getConnectionToken()
: nullptr;
//这里会通过JNI调到java层PhoneWindowManager中去提前处理按键
nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token, &event, entry->policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
std::to_string(t.duration().count()).c_str());
}
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();
}
按键在发给应用窗口之前先将按键发给java层PhoneWindowManager的interceptKeyBeforeDispatching方法,这就给了我们提前拦截按键的机会,像如果有需求禁用HOME,RECENT,BACK就可以到interceptKeyBeforeDispatching方法中对应case中返回-1就行了。
最后此函数有三个结果,1. 完全拦截按键,2. 按键立即执行,3. 按键延时执行。
接着按键的提前拦截执行完之后,再次执行到dispatchKeyLocked函数之时就可以根据PhoneWindowManager提前拦截的结果进行下一步处理了,如果entry->interceptKeyResult不等于INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER和INTERCEPT_KEY_RESULT_SKIP就会接着调用findFocusedWindowTargetsLocked函数寻找按键分发的焦点窗口:
InputDispatcher::findFocusedWindowTargetsLocked
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry& entry,
std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime) {
std::string reason;
int32_t displayId = getTargetDisplayId(entry);
//首先找到焦点窗口,关于焦点窗口如何得来的,以后有时间单独分析
sp<InputWindowHandle> focusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
//找到焦点应用程序,由java层InputMonitor传下来
sp<InputApplicationHandle> focusedApplicationHandle =
getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
//没有焦点窗口,没有焦点应用
//按键事件分发状态为失败
return INPUT_EVENT_INJECTION_FAILED;
}
if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
//没有焦点窗口,有焦点应用
//这种情况可能导致ANR,mNoFocusedWindowTimeoutTime用来对ANR timeout进行计时
if (!mNoFocusedWindowTimeoutTime.has_value()) {
//获取ANR计时timeout,默认值为5s
const nsecs_t timeout = focusedApplicationHandle->getDispatchingTimeout(
DEFAULT_INPUT_DISPATCHING_TIMEOUT.count());
//ANR的timeout时间为:按键在InputDispatch线程开始分发的时间 + 默认值(5s)
mNoFocusedWindowTimeoutTime = currentTime + timeout;
//可能发生ANR的应用
mAwaitedFocusedApplication = focusedApplicationHandle;
ALOGW("Waiting because no window has focus but %s may eventually add a "
"window when it finishes starting up. Will wait for %" PRId64 "ms",
mAwaitedFocusedApplication->getName().c_str(), ns2ms(timeout));
//记录ANR的时间
*nextWakeupTime = *mNoFocusedWindowTimeoutTime;
//按键事件分发状态为等待
return INPUT_EVENT_INJECTION_PENDING;
} else if (currentTime > *mNoFocusedWindowTimeoutTime) {
//当前时间大于ANR的timeout,则说明已经发生ANR了
ALOGE("Dropping %s event because there is no focused window",
EventEntry::typeToString(entry.type));
//按键事件状态为失败
return INPUT_EVENT_INJECTION_FAILED;
} else {
//按键事件分发状态为等待
return INPUT_EVENT_INJECTION_PENDING;
}
}
//走到这里说明当前按键事件可以有效分发个窗口了,
//此函数会将ANR timeout和可能发生ANR的应用程序清空
resetNoFocusedWindowTimeoutLocked();
// 权限检查
......
if (focusedWindowHandle->getInfo()->paused) {
ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
return INPUT_EVENT_INJECTION_PENDING;
}
//对于按键类型事件,需要等之前的输入事件全部处理完成之后再进行,因为之前的事件可能
//导致焦点窗口的变化。
if (entry.type == EventEntry::Type::KEY) {
if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) {
*nextWakeupTime = *mKeyIsWaitingForEventsTimeout;
return INPUT_EVENT_INJECTION_PENDING;
}
}
// 按键事件到这里就能成功发给目标窗口了
addWindowTargetLocked(focusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
BitSet32(0), inputTargets);
//按键事件分发状态为成功
return INPUT_EVENT_INJECTION_SUCCEEDED;
}
InputDispatcher::addWindowTargetLocked
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds,
std::vector<InputTarget>& inputTargets) {
//查找inputTargets集合中是否已经包含了目标焦点窗口的InputTarget
std::vector<InputTarget>::iterator it =
std::find_if(inputTargets.begin(), inputTargets.end(),
[&windowHandle](const InputTarget& inputTarget) {
return inputTarget.inputChannel->getConnectionToken() ==
windowHandle->getToken();
});
const InputWindowInfo* windowInfo = windowHandle->getInfo();
//没有包含
if (it == inputTargets.end()) {
InputTarget inputTarget;
//获取目标窗口的inputChannel
sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
if (inputChannel == nullptr) {
ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
return;
}
//构造inputTarget
inputTarget.inputChannel = inputChannel;
inputTarget.flags = targetFlags;
inputTarget.globalScaleFactor = windowInfo->globalScaleFactor;
//放入inputTargets
inputTargets.push_back(inputTarget);
it = inputTargets.end() - 1;
}
it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop,
windowInfo->windowXScale, windowInfo->windowYScale);
}
InputDispatcher::dispatchEventLocked
这里会遍历inputTargets,并调用prepareDispatchCycleLocked函数,这里有个很重要的参数connection,它是用来描述窗口的连接,每一个窗口在创建时都会创建一个连接,这个连接就是用来将输入事件传递到目标窗口,后面我会单独写一篇分析窗口的connection。
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
const std::vector<InputTarget>& inputTargets) {
ATRACE_CALL();
//调到java层PowerManagerService
pokeUserActivityLocked(*eventEntry);
//遍历inputTargets
for (const InputTarget& inputTarget : inputTargets) {
//获取目标窗口的连接
sp<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
//执行prepareDispatchCycleLocked
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
} else {
//异常情况
.....
}
}
}
InputDispatcher::prepareDispatchCycleLocked
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget) {
...
// Skip this event if the connection status is not normal.
// We don't want to enqueue additional outbound events if the connection is broken.
if (connection->status != Connection::STATUS_NORMAL) {
//connection状态不正常,return
...
return;
}
//目标焦点窗口处于分屏模式
if (inputTarget.flags & InputTarget::FLAG_SPLIT) {
//跳过
......
}
// 非分屏情况
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
InputDispatcher::enqueueDispatchEntriesLocked
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget) {
.....
//目标窗口的connection的outboundQueue是否为空
bool wasEmpty = connection->outboundQueue.empty();
// 调用了六次enqueueDispatchEntryLocked函数,仅仅最后一个参数不同
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);
//如果目标窗口的connection的outboundQueue在执行enqueueDispatchEntryLocked之前为空
//并且在执行完enqueueDispatchEntryLocked之后不为空
if (wasEmpty && !connection->outboundQueue.empty()) {
//这种情况才继续往下执行
startDispatchCycleLocked(currentTime, connection);
}
}
InputDispatcher::enqueueDispatchEntryLocked
void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
EventEntry* eventEntry,
const InputTarget& inputTarget,
int32_t dispatchMode) {
int32_t inputTargetFlags = inputTarget.flags;
if (!(inputTargetFlags & dispatchMode)) {
//异常
return;
}
//这个规则目前不清楚
inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
//将EventEntry转换为DispatchEntry
std::unique_ptr<DispatchEntry> dispatchEntry =
createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
// 再重新从DispatchEntry中获取EventEntry
EventEntry* newEntry = dispatchEntry->eventEntry;
//输入事件类型
switch (newEntry->type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*newEntry);
//简单将KeyEntry的一些信息解析出来存入dispatchEntry
dispatchEntry->resolvedEventId = keyEntry.id;
dispatchEntry->resolvedAction = keyEntry.action;
dispatchEntry->resolvedFlags = keyEntry.flags;
if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags)) {
return; // skip the inconsistent event
}
break;
}
//其他类型,暂不关注
......
}
...
// 最后将dispatchEntry加入connection的outboundQueue队列
connection->outboundQueue.push_back(dispatchEntry.release());
}
对于按键类型的输入事件,此函数并不复杂,就是将KeyEntry转换为了DispatchEntry,最后加入目标窗口的connection的outboundQueue队列。
至于enqueueDispatchEntryLocked函数多此调用,传入不同的InputTargetflag只是标识当前输入事件的一些特性,在分析整体输入事件传递的流程上不必过多在意。
InputDispatcher::startDispatchCycleLocked
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
//目标窗口连接状态正常,并且连接的outboundQueue队列不为空
while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {
//取出队列头部DispatchEntry
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
const nsecs_t timeout =
getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
dispatchEntry->timeoutTime = currentTime + timeout;
// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
//输入事件类型
switch (eventEntry->type) {
case EventEntry::Type::KEY: {
const KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
std::array<uint8_t, 32> hmac = getSignature(*keyEntry, *dispatchEntry);
// 调用publishKeyEvent函数分发按键
status =
connection->inputPublisher
.publishKeyEvent(dispatchEntry->seq, dispatchEntry->resolvedEventId,
keyEntry->deviceId, keyEntry->source,
keyEntry->displayId, std::move(hmac),
dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags, keyEntry->keyCode,
keyEntry->scanCode, keyEntry->metaState,
keyEntry->repeatCount, keyEntry->downTime,
keyEntry->eventTime);
break;
}
//其他类型事件,暂不关注
......
}
// 分发结果
if (status) {
//分发失败
...
return;
}
//将处理完成的dispatchEntry从connection的outboundQueue移除
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
//将outboundQueue队列的dispatchEntry放入connection的waitQueue队列
connection->waitQueue.push_back(dispatchEntry);
...
}
}
startDispatchCycleLocked会将目标窗口connection的outboundQueue队列中的dispatchEntry依次取出来,对于按键类型的输入事件会调用connection->inputPublisher的publishKeyEvent进行分发,分发成功之后会将outboundQueue队列中的dispatchEntry移除,并转移到waitQueue中,分发失败的情况我们就不去讨论了。
InputPublisher::publishKeyEvent
status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action,
int32_t flags, int32_t keyCode, int32_t scanCode,
int32_t metaState, int32_t repeatCount, nsecs_t downTime,
nsecs_t eventTime) {
......
if (!seq) {
//异常情况
return BAD_VALUE;
}
//拿到输入事件的各种信息之后构造一个InputMessage
InputMessage msg;
msg.header.type = InputMessage::Type::KEY;
msg.body.key.seq = seq;
msg.body.key.eventId = eventId;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.displayId = displayId;
msg.body.key.hmac = std::move(hmac);
msg.body.key.action = action;
msg.body.key.flags = flags;
msg.body.key.keyCode = keyCode;
msg.body.key.scanCode = scanCode;
msg.body.key.metaState = metaState;
msg.body.key.repeatCount = repeatCount;
msg.body.key.downTime = downTime;
msg.body.key.eventTime = eventTime;
//通过InputChannel将InputMessage分发给目标窗口
return mChannel->sendMessage(&msg);
}
InputChannel::sendMessage
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) {
//异常情况,发送失败
return -error;
}
if (size_t(nWrite) != msgLength) {
return DEAD_OBJECT;
}
return OK;
}
mFd其实就是一对socket的其中一个,InputChannel在构造的时候是一对,对应了一对socket,一个代表"client"端,一个代表"server"端,"server"端被注册到了InputDispatcher,"client"端返回给了APP进程,InputDispatcher和APP进程都会对自己的socket一端进行监听,所以APP进程和InputDispatcher就这样完成了通信。
这个过程做一个总结:
1. InputReader线程将驱动获取的原始输入事件封装为NotifyKeyArgs传递给了InputDispatcher线程,在放入InputDispatcher线程mInboundQueue队列之前会先将事件传递到java层
PhoneWindowManager,没有被拦截的情况下才会将NotifyKeyArgs转换为KeyEntry并放入mInboundQueue队列,接着会唤醒InputDispatcher线程。
2. InputDispatcher线程启动后就陷入了Looper死循环,等待输入事件的发生,被唤醒之后调用函数dispatchOnceInnerLocked处理事件,此函数在一些列判断之后没有丢弃事件则会进一步调用dispatchKeyLocked函数。
3. dispatchKeyLocked函数在分发之前又会首先将按键事件传到java层PhoneWindowManager的interceptKeyBeforeDispatching中给个提前拦截的机会,如果没有被拦截则会通过findFocusedWindowTargetsLocked找到目标焦点窗口。
4. findFocusedWindowTargetsLocked函数会从两个容器mFocusedWindowHandlesByDisplay和mFocusedApplicationHandlesByDisplay获得当前的焦点窗口和焦点应用,并且会对可能出现ANR的情况进行ANR timeout即ANR发生窗口的标记。
5. 如果findFocusedWindowTargetsLocked函数返回结果为成功分发,则调用dispatchEventLocked函数继续分发输入事件,接着会将KeyEntry再转换为DispatchEntry,并存入目标窗口连接connection的outboundQueue队列,然后调用publishKeyEvent继续分发。
6. publishKeyEvent函数中构造描述输入事件信息的InputMessage并通过InputChannel向"server"端socket写入数据以唤醒APP进程的socket"client"端,自此输入事件成功从InputDispatcher发送到了APP。
7. 最后将DispatchEntry从目标窗口连接connection的outboundQueue队列中移除,并转移到目标窗口连接connection的waitQueue队列中。
整个过程中有三个重要队列,mInboundQueue,outboundQueue,waitQueue。
mInboundQueue位于InputDispatcher线程,代表即将分发的输入事件,outboundQueue位于目标窗口的connection,代表即将要分发给目标窗口的输入事件,waitQueue位于目标窗口的connection,代表等待目标窗口处理的输入事件。
五、InputChannel注册,建立APP和InputDispatcher的连接
WindowManagerGlobal.addView
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
...
root = new ViewRootImpl(view.getContext(), display);
......
root.setView(view, wparams, panelParentView);
......
...
}
ViewRootImpl.setView
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
......
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
inputChannel = new InputChannel();
}
try {
...
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
...
} catch (RemoteException e) {
inputChannel = null;
}
......
}
WindowManagerService.addWindow
public int addWindow(Session session, IWindow client, int seq,
LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
int requestUserId) {
......
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
......
}
}
WindowState.openInputChannel
void openInputChannel(InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
//窗口名称
String name = getName();
//创建InputChannelPair
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
//服务端InputChannel
mInputChannel = inputChannels[0];
//客户端InputChannel
mClientChannel = inputChannels[1];
//将服务端InputChannel注册到InputDispatcher
mWmService.mInputManager.registerInputChannel(mInputChannel);
//token唯一标识了接收input事件的窗口
mInputWindowHandle.token = mInputChannel.getToken();
if (outInputChannel != null) {
/将客户端InputChannel设置到ViewRootImpl的outInputChannel中
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
mClientChannel = null;
} else {
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
mWmService.mInputToWindowMap.put(mInputWindowHandle.token, this);
}
InputChannel.openInputChannelPair
public static InputChannel[] openInputChannelPair(String name) {
if (name == null) {
throw new IllegalArgumentException("name must not be null");
}
if (DEBUG) {
Slog.d(TAG, "Opening input channel pair '" + name + "'");
}
return nativeOpenInputChannelPair(name);
}
static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
jclass clazz, jstring nameObj) {
ScopedUtfChars nameChars(env, nameObj);
std::string name = nameChars.c_str();
sp<InputChannel> serverChannel;
sp<InputChannel> clientChannel;
//构造一对native层InputChannel
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
if (result) {
std::string message = android::base::StringPrintf(
"Could not open input channel pair : %s", strerror(-result));
jniThrowRuntimeException(env, message.c_str());
return nullptr;
}
//构造一个java层InputChannel类型数组
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, nullptr);
if (env->ExceptionCheck()) {
return nullptr;
}
//将native层InputChannel转换为java层InputChannel
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env, serverChannel);
if (env->ExceptionCheck()) {
return nullptr;
}
//将native层InputChannel转换为java层InputChannel
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env, clientChannel);
if (env->ExceptionCheck()) {
return nullptr;
}
//将转换的java层InputChannel存到前面构造的数组
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
//返回给java层
return channelPair;
}
status_t InputChannel::openInputChannelPair(const std::string& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
...
//异常
return result;
}
//32KB
int bufferSize = SOCKET_BUFFER_SIZE;
//设置socket发送和接收缓冲区大小为bufferSize
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
//创建BBinder,用于标识APP进程的窗口
sp<IBinder> token = new BBinder();
std::string serverChannelName = name + " (server)";
android::base::unique_fd serverFd(sockets[0]);
//server端InputChannel保存了server端socket的fd
outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
std::string clientChannelName = name + " (client)";
android::base::unique_fd clientFd(sockets[1]);
//client端InputChannel保存了client端socket的fd
outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
return OK;
}
InputChannel::create
sp<InputChannel> InputChannel::create(const std::string& name, android::base::unique_fd fd,
sp<IBinder> token) {
const int result = fcntl(fd, F_SETFL, O_NONBLOCK);
if (result != 0) {
LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(),
strerror(errno));
return nullptr;
}
return new InputChannel(name, std::move(fd), token);
}
//InputChannel构造函数
InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token)
: mName(name), mFd(std::move(fd)), mToken(token) {
if (DEBUG_CHANNEL_LIFECYCLE) {
ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), mFd.get());
}
}
InputManagerService.registerInputChannel
public void registerInputChannel(InputChannel inputChannel) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
nativeRegisterInputChannel(mPtr, inputChannel);
}
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputChannelObj) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
//获取native层InputChannel
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
...
status_t status = im->registerInputChannel(env, inputChannel);
if (status) {
//异常情况
return;
}
//给mDisposeCallback赋值为handleInputChannelDisposed
android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
handleInputChannelDisposed, im);
}
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
const sp<InputChannel>& inputChannel) {
ATRACE_CALL();
return mInputManager->getDispatcher()->registerInputChannel(inputChannel);
}
InputDispatcher::registerInputChannel
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
#if DEBUG_REGISTRATION
ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str());
#endif
{ // acquire lock
std::scoped_lock _l(mLock);
//如果已经存在Connection,则不必重复注册
sp<Connection> existingConnection = getConnectionLocked(inputChannel->getConnectionToken());
if (existingConnection != nullptr) {
ALOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().c_str());
return BAD_VALUE;
}
//创建Connection,将“server”端inputChannel传进去
sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator);
//server端inputChannel的"socket" fd
int fd = inputChannel->getFd();
//以"socket"的fd为key,connection为value,保存到map中
mConnectionsByFd[fd] = connection;
//创建inputChannel时,接收了一个BBinder的参数,就是其Token,用于标识APP进程的窗口
//的唯一标识
mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel;
//重点:将”server端“socket的fd添加到looper监听
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
}
//唤醒InputDispatcher
mLooper->wake();
return OK;
}
上面函数做的事情如下:
如果是首次注册InputChannel,则会创建一个Connection连接,并以InputChannel的"socket"的fd为key,此连接为value,存储到InputDispatcher的mConnectionsByFd中,InputChannel的token对象则保证了注册InputChannel的窗口的唯一性,token为key,InputChannel为value保存在了InputDispatcher的mInputChannelsByToken中。
将”server端“socket的fd添加到InputDispatcher内部的looper进行监听,待事件发生之后回调其handleReceiveCallback函数,这里的事件发生即”client端“socket写入了数据。
WindowInputEventReceiver
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
}
java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
......
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
inputChannel = new InputChannel();
}
try {
...
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
...
} catch (RemoteException e) {
inputChannel = null;
}
......
if (inputChannel != null) {
....
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
}
......
}
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
}
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
//UI线程的MessageQueue
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
//java层InputChannel转换得到native层InputChannel,client端
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
if (inputChannel == nullptr) {
jniThrowRuntimeException(env, "InputChannel is not initialized.");
return 0;
}
//APP UI线程对应native层的MessageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == nullptr) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
//创建NativeInputEventReceiver,将inputChannel,messageQueue保存到其内部成员变量
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);
status_t status = receiver->initialize();
if (status) {
String8 message;
message.appendFormat("Failed to initialize input event receiver. status=%d", status);
jniThrowRuntimeException(env, message.string());
return 0;
}
receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
NativeInputEventReceiver::initialize
此函数取出client端InputChannel的"socket"的fd添加到APP进程的UI线程的Looper进行监听事件类型为ALOOPER_EVENT_INPUT,并在接收到事件之后("server端"socket写入数据)回调NativeInputEventReceiver的handleEvent函数。到此“server端”和“client”端InputChannel
的“socket”注册已经分析完成,“server端”被注册到InputDispatcher
的Looper线程,“client”端被注册到了APP的UI线程,这样他们就可以完成通信了。
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
//mInputConsumer就是保存到其内部的client端InputChannel,
//fd指向client端InputChannel内部的client端"socket"的fd
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
//将client端"socket"的fd添加到Looper进行监听
mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
} else {
//异常情况
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
过程进行一个总结:
首先当一个APP启动时,会将自己的Window添加到WMS,并传递一个空InputChannel过去。
WMS端,通过openInputChannel方法会创建一对InputChannel,是在native层完成的,这对InputChannel被分为“client”端和“server”端,其内部又会创建一对socket,和这对InputChannel一一对应。
“server”端InputChannel会被注册到InputDispatcher中去,注册的原理就是将InputChannel内部的socket添加到其Looper进行监听,注册过程中还会创建一个Connection对象,Connection用来描述InputDispatcher与此次注册InputChannel的窗口的连接。
"client"端InputChannel会被设置到APP进程中,接着通过InputEventReceiver注册到APP UI线程,同样是将InputChannel内部的socket添加到UI线程的Looper进行监听。
对于InputDispatcher线程,在接收到"client"端socket的消息时会回调其handleReceiveCallback函数,对于APP UI线程,在接收到"server"端socket的消息时会回调InputEventReceiver对应的native层对象NativeInputEventReceiver的handleEvent函数。
六、UI线程对Input事件的分发
NativeInputEventReceiver::handleEvent
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
//异常情况
return 0; // remove the callback
}
if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
if (events & ALOOPER_EVENT_OUTPUT) {
.....
.....
return 1;
}
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
"events=0x%x", getInputChannelName().c_str(), events);
return 1;
}
NativeInputEventReceiver::consumeEvents
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
//status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
...
ScopedLocalRef<jobject> receiverObj(env, nullptr);
bool skipCallbacks = false;
//死循环
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
//获取输入事件
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
if (status != OK && status != WOULD_BLOCK) {
ALOGE("channel '%s' ~ Failed to consume input event. status=%d",
getInputChannelName().c_str(), status);
return status;
}
if (status == WOULD_BLOCK) {
if (!skipCallbacks && !mBatchedInputEventPending && mInputConsumer.hasPendingBatch()) {
// There is a pending batch. Come back later.
if (!receiverObj.get()) {
//异常情况
return DEAD_OBJECT;
}
}
mBatchedInputEventPending = true;
//回调java层InputEventReceiver.java的onBatchedInputEventPending方法
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.onBatchedInputEventPending,
mInputConsumer.getPendingBatchSource());
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching batched input events.");
mBatchedInputEventPending = false; // try again later
}
}
return OK;
}
assert(inputEvent);
if (!skipCallbacks) {
if (!receiverObj.get()) {
//异常
return DEAD_OBJECT;
}
}
jobject inputEventObj;
switch (inputEvent->getType()) {
//按键事件
case AINPUT_EVENT_TYPE_KEY:
//将native层KeyEvent转换为java层KeyEvent
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast<KeyEvent*>(inputEvent));
break;
//触摸事件....
...
default:
assert(false); // InputConsumer should prevent this from ever happening
inputEventObj = nullptr;
}
//输入事件不为空
if (inputEventObj) {
//调到java层InputEventReceiver.java的dispatchInputEvent方法
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
...
env->DeleteLocalRef(inputEventObj);
} else {
ALOGW("channel '%s' ~ Failed to obtain event object.",
getInputChannelName().c_str());
skipCallbacks = true;
}
}
if (skipCallbacks) {
//异常情况,发送完成信号
mInputConsumer.sendFinishedSignal(seq, false);
}
}
}
此函数首先调用InputConsumer的consume函数来获得InputEvent,对于按键类型事件的处理就非常简单了,然后将native层KeyEvent转换为java层KeyEvent,并调用java层InputEventReceiver.java的dispatchInputEvent方法将Input事件分发到java层。
InputConsumer::consume
status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
*outSeq = 0;
*outEvent = nullptr;
//如果outEvent为空
while (!*outEvent) {
//mMsgDeferred默认值为false
if (mMsgDeferred) {
// mMsg contains a valid input message from the previous call to consume
// that has not yet been processed.
mMsgDeferred = false;
} else {
//获取InputDispatcher发送过来的InputMessage,InputMessage封装了Input事件
//的各种信息,通过sendMessage发送
status_t result = mChannel->receiveMessage(&mMsg);
//如果result不为OK
if (result) {
...
}
return result;
}
}
//Input事件类型
switch (mMsg.header.type) {
case InputMessage::Type::KEY: {
//创建一个KeyEvent空对象
KeyEvent* keyEvent = factory->createKeyEvent();
if (!keyEvent) return NO_MEMORY;
//用InputMessage中的信息填充此空KeyEvent
initializeKeyEvent(keyEvent, &mMsg);
*outSeq = mMsg.body.key.seq;
*outEvent = keyEvent;
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
mChannel->getName().c_str(), *outSeq);
}
break;
}
.....
.....
//触摸事件及其他事件,省略
}
}
return OK;
}
InputEventReceiver.java
的dispatchInputEvent
方法将事件发送到java层:
InputEventReceiver.dispatchInputEvent
// Called from native code.
@SuppressWarnings("unused")
@UnsupportedAppUsage
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
WindowInputEventReceiver.onInputEvent
@Override
public void onInputEvent(InputEvent event) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "processInputEventForCompatibility");
List<InputEvent> processedEvents;
try {
//做一些兼容性处理,在大于M的版本直接返回null
processedEvents =
mInputCompatProcessor.processInputEventForCompatibility(event);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
if (processedEvents != null) {
....
} else {
enqueueInputEvent(event, this, 0, true);
}
}
ViewRootImpl.enqueueInputEvent
@UnsupportedAppUsage
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
//构造一个QueuedInputEvent对象,使用obtainQueuedInputEvent构造对象,类似
//Message.obtain,通过池的形式保存回收对象,内部使用链表
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
//mPendingInputEventTail代表QueuedInputEvent链表尾节点
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
//如果是首次进入,头尾节点都指向第一个构造的QueuedInputEvent
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
//否则,将QueuedInputEvent添加到链表尾部
last.mNext = q;
//尾节点重新指向新添加的QueuedInputEvent
mPendingInputEventTail = q;
}
//QueuedInputEvent数量加1
mPendingInputEventCount += 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
ViewRootImpl.doProcessInputEvents
void doProcessInputEvents() {
//头节点不为空,代表链表中有事件处理
while (mPendingInputEventHead != null) {
//按顺序取出
QueuedInputEvent q = mPendingInputEventHead;
//头节点后移
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
//将取出来的QueuedInputEvent的mNext置空
q.mNext = null;
//QueuedInputEvent链表数量减一
mPendingInputEventCount -= 1;
//此事件发生的时间
long eventTime = q.mEvent.getEventTimeNano();
long oldestEventTime = eventTime;
//如果是触摸事件
if (q.mEvent instanceof MotionEvent) {
....
}
mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
//分发事件
deliverInputEvent(q);
}
// We are done processing all input events that we can process right now
// so we can clear the pending flag immediately.
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}
ViewRootImpl.deliverInputEvent
private void deliverInputEvent(QueuedInputEvent q) {
try {
if (mInputEventConsistencyVerifier != null) {
try {
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
} finally {
}
}
InputStage stage;
if (q.shouldSendToSynthesizer()) {
//如果事件中带有FLAG_UNHANDLED的flag
stage = mSyntheticInputStage;
} else {
//shouldSkipIme代表事件是否传递给输入法,对于按键事件,
//仅仅在主动设置了FLAG_DELIVER_POST_IME时返回true,
//触摸事件则是判断其事件来源,一般情况的触摸事件都是返回true
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
//如果是按键事件
if (q.mEvent instanceof KeyEvent) {
try {
mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
if (stage != null) {
handleWindowFocusChanged();
//分发事件
stage.deliver(q);
} else {
finishInputEvent(q);
}
} finally {
}
}
InputEventReceiver.finishInputEvent
public final void finishInputEvent(InputEvent event, boolean handled) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to finish an input event but the input event "
+ "receiver has already been disposed.");
} else {
int index = mSeqMap.indexOfKey(event.getSequenceNumber());
if (index < 0) {
Log.w(TAG, "Attempted to finish an input event that is not in progress.");
} else {
int seq = mSeqMap.valueAt(index);
mSeqMap.removeAt(index);
nativeFinishInputEvent(mReceiverPtr, seq, handled);
}
}
event.recycleIfNeededAfterDispatch();
}
static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
jint seq, jboolean handled) {
sp<NativeInputEventReceiver> receiver =
reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
status_t status = receiver->finishInputEvent(seq, handled);
......
}
status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
if (status) {
if (status == WOULD_BLOCK) {
...
Finish finish;
finish.seq = seq;
finish.handled = handled;
mFinishQueue.add(finish);
if (mFinishQueue.size() == 1) {
setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
}
return OK;
}
}
return status;
}
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
......
//处理ALOOPER_EVENT_INPUT类型事件
if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
//处理ALOOPER_EVENT_OUTPUT类型事件
if (events & ALOOPER_EVENT_OUTPUT) {
for (size_t i = 0; i < mFinishQueue.size(); i++) {
const Finish& finish = mFinishQueue.itemAt(i);
status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
if (status) {//如果status大于0,说明此次
//sendFinishedSignal依然失败了
mFinishQueue.removeItemsAt(0, i);
if (status == WOULD_BLOCK) {
...
//返回1,此次Looper回调会再次被执行
return 1; later
}
...
...
//返回0,Looper会移除此次回调
return 0;
}
}
//正常情况,成功通知到InputDispatcher,清空mFinishQueue
mFinishQueue.clear();
//移除ALOOPER_EVENT_OUTPUT类型事件监听
setFdEvents(ALOOPER_EVENT_INPUT);
return 1;
}
return 1;
}
七、View的事件分发机制
DecorView.dispatchTouchEvent
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
Activity.dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
PhoneWindow.superDispatchTouchEvent
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
ViewGroup.dispatchTouchEvent
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
......
boolean handled = false;
//判断此次触摸事件是否被过滤掉,条件由两个flag决定,FILTER_TOUCHES_WHEN_OBSCURED
//和MotionEvent.FLAG_WINDOW_IS_OBSCURED,这两个flag用来表示
//当前接收触摸事件的View是否被遮挡或者隐藏,只有未被遮挡或隐藏才能
//进一步处理事件。
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;
if (actionMasked == MotionEvent.ACTION_DOWN) {
//当ACTION_DOWN事件到来时,会清除并重置之前设置的各种状态,
//这是因为Android的事件分发是以一个事件序列为单位进行分发
//和拦截,当一个此次事件为ACTION_DOWN则表明这是一个新的
//事件序列,所以需要清空和重置上一个事件序列的状态
cancelAndClearTouchTargets(ev);
resetTouchState();
}
//代表此次事件是否被拦截
final boolean intercepted;
//两种情况下会走进事件拦截的流程,1.此次事件为ACTION_DOWN,
//2.mFirstTouchTarget != null,mFirstTouchTarget描述的是
//接收此次事件的目标
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
//子View是否有请求过父View不要拦截事件,通过调用父View的
//requestDisallowInterceptTouchEvent方法来请求
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
//如果子View没有请求View不要拦截事件,则走正常
//父View事件拦截流程
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
//对于非ACTION_DOWN事件并且mFirstTouchTarget为空则直接拦截
//此次事件序列的后续事件
intercepted = true;
}
...
//检查是否需要取消事件,由resetCancelNextUpFlag或者事件本身
//决定,resetCancelNextUpFlag的实现很简单,对于添加了
//PFLAG_CANCEL_NEXT_UP_EVENT的View清空此状态并返回true,
//这个PFLAG_CANCEL_NEXT_UP_EVENT的含义从注释字面意思看
//是View和ViewGroup处于分离状态
final boolean canceled = resetCancelNextUpFlag(this)
|| actionMasked == MotionEvent.ACTION_CANCEL;
......
//记录接收事件的目标
TouchTarget newTouchTarget = null;
//记录是否成功分发事件的状态值
boolean alreadyDispatchedToNewTouchTarget = false;
//如果事件没有被取消并且没有被拦截
if (!canceled && !intercepted) {
...
//ACTION_POINTER_DOWN和ACTION_HOVER_MOVE是多点触控与
//鼠标相关的事件本篇不讨论,这里只看ACTION_DOWN会走进如下分支
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
//多点触控相关的逻辑,省略...
final int childrenCount = mChildrenCount;
if (newTouchTarget == null && childrenCount != 0) {
final float x =
isMouseEvent ? ev.getXCursorPosition() : ev.getX(actionIndex);
final float y =
isMouseEvent ? ev.getYCursorPosition() : ev.getY(actionIndex);
//这里会将ViewGroup所有的子View重新以Z-order的顺序
//从小到大排列,返回一个list
final ArrayList<View> preorderedList = buildTouchDispatchChildList();
//子View是否自定义绘制顺序,一般情况都为false
final boolean customOrder = preorderedList == null
&& isChildrenDrawingOrderEnabled();
final View[] children = mChildren;
//对所有子View进行遍历
for (int i = childrenCount - 1; i >= 0; i--) {
//对于没有自定义子View绘制顺序的情况,
//childIndex就等于i
final int childIndex = getAndVerifyPreorderedIndex(
childrenCount, i, customOrder);
//这里会从前面得到的根据Z-order排好序的preorderedList
//中获取View,并且是从Z-order最大的View开始遍历
final View child = getAndVerifyPreorderedView(
preorderedList, children, childIndex);
if (!child.canReceivePointerEvents()
|| !isTransformedTouchPointInView(x, y, child, null)) {
//如果此View无法接收事件或者当前事件的
//落点不在这个View区域内则返回进行下一轮循环
continue;
}
//走到这里说明当前View既能接收事件,并且
//事件也落在View内,接着就需要进一步处理事件了
//对于单点触控事件,newTouchTarget此时为空
newTouchTarget = getTouchTarget(child);
if (newTouchTarget != null) {
// Child is already receiving touch within its bounds.
// Give it the new pointer in addition to the ones it is handling.
newTouchTarget.pointerIdBits |= idBitsToAssign;
break;
}
//如果有设置PFLAG_CANCEL_NEXT_UP_EVENT,在此清除
resetCancelNextUpFlag(child);
//这里就会执行子View事件分发处理逻辑了,待后面详细分析
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
//走进来说明子View成功消费事件
....
//为消费此次事件的子View构建TouchTarget,
//并且会将构建的TouchTarget赋值给mFirstTouchTarget
//和newTouchTarget,对于单点触控来说
//TouchTarget链表只有mFirstTouchTarget一个元素
newTouchTarget = addTouchTarget(child, idBitsToAssign);
//alreadyDispatchedToNewTouchTarget赋值为true
alreadyDispatchedToNewTouchTarget = true;
break;
}
...
}
//清空preorderedList
if (preorderedList != null) preorderedList.clear();
}
...
}
}
if (mFirstTouchTarget == null) {
//mFirstTouchTarget为空说明没有子View接收此次事件
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
//遍历TouchTarget链表,因为mFirstTouchTarget不为空,所以已经找到目标,只需要进行事件分发即可
while (target != null) {
final TouchTarget next = target.next;
if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
handled = true;
} else {
final boolean cancelChild = resetCancelNextUpFlag(target.child)
|| intercepted;
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
if (cancelChild) {
if (predecessor == null) {
mFirstTouchTarget = next;
} else {
predecessor.next = next;
}
target.recycle();
target = next;
continue;
}
}
predecessor = target;
target = next;
}
}
if (canceled
|| actionMasked == MotionEvent.ACTION_UP
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
//如果事件被取消或者一个事件序列结束就需要重置事件的各种状态,
//最重要的状态就是将mFirstTouchTarget置空
resetTouchState();
} else if (split && actionMasked == MotionEvent.ACTION_POINTER_UP) {
//多点触控相关的收尾
...
}
}
if (!handled && mInputEventConsistencyVerifier != null) {
//事件未被处理,回调通知
mInputEventConsistencyVerifier.onUnhandledEvent(ev, 1);
}
return handled;
......
}