一文搞明白 Android R Input按键事件 前世今生

原文链接:https://blog.csdn.net/qq_34211365/article/details/108843167

 

一、Linux下的INotifyEpoll机制 


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;
}


InputReaderstart函数就和InputDispatcher有异曲同工之妙了,只不过线程的名字和两个Lambda表达式不一样,所以我们知道最终这个线程启动之后会调用InputReaderloopOnce()函数。

InputManager的start函数中分别调用了InputDispatcher和InputReader的start函数,即分别启动了其内部线程InputThreadImpl,InputDispatcher内部线程(名字:“InputDispatcher”)启动调用了自己的dispatchOnce()函数,InputReader内部线程(名字:“InputReader”)启动调用了自己的loopOnce()函数。
 

三、InputReader线程读取输入事件

InputReaderloopOnce()

//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,并调用QueuedInputListenernotifyKeyNotifyKeyArgs发送出去,

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,这里继续调用InputListenerInterfacenotifyKey函数,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(对于按键事件来说),接着会调用InputDispatchernotifyKey函数将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封装的事件信息解析出来,构造两个结构体KeyEventKeyEntry,为什么是两个?因为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.javadispatchInputEvent方法将事件发送到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;
  	......
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值