Touch事件的获取与分发

Android输入系统整体结构

Android系统支持触摸屏与键盘等很多输入设备。当输入设备可用时,Android系统会在Linux内核/dev/input下创建event0~n或其他名称的的设备节点;当输入设备不可用时会删除相应的节点。在用户空间可以通过ioctl的方式从这些设备节点中获取信息。
Android 输入系统简单说就是监控/dev/input下的所有节点,然后将获取的原始信息进行加工,然后分发到对应的窗口中,再分发到对应的View上。
对于Android的touch事件,我们常常关心的只是从Activity到View的一个分发过程,实际上,在Touch事件到达Activity之前,还需要做很多数据的加工,传输等操作。上图是Touch事件从驱动获取数据到最终加工成MotionEvent,分发到各个View的一个整体过程。
在这里插入图片描述

  • 输入设备节点:输入设备节点是Android系统下所有输入设备挂载的目录。不管是触摸屏还是键盘,都会在/dev/input/目录下形成一个输入源
  • InputManagerService:InputManagerService是整个输入事件的核心。InputManagerService可以看做是一个容器,管理EventHub、InputReader和InputDispatcher
  • WindowManagerService:Android系统中窗口管理的服务。InputManagerService从WindowManagerService获取窗口信息,然后决定将事件分发到哪些窗口。
  • ViewRootImpl:这个类负责App端事件的接收,在App进程中,这个类最先得到输入事件。得到输入事件后将事件分发到Activity,然后再分发到各个ViewGroup和View。

IMS的启动和初始化

同其他服务一样,InputManagerService启动是在SystemService启动时启动的。

frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
     new SystemServer().run();
}
private void run() {
...
        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();//启动服务
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        ...
}
private void startOtherServices() {
    ...
    traceBeginAndSlog("StartInputManagerService");
    //InputManagerService 创建
    inputManager = new InputManagerService(context);
    traceEnd();
    traceBeginAndSlog("StartWindowManagerService");
    // WMS needs sensor service ready
    ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
    mSensorServiceStart = null;
    wm = WindowManagerService.main(context, inputManager,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
            !mFirstBoot, mOnlyCore, new PhoneWindowManager());
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
    traceEnd();
    ...
    traceBeginAndSlog("StartInputManager");
    inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
    inputManager.start();//InputManagerService 启动
    traceEnd();
    ...
 }

java层的服务启动同时也会调用Native层的启动。

InputManagerService初始化

InputManagerService初始化的同时会初始化native层的InputManagerService

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public InputManagerService(Context context) {
this.mContext = context;
        ...
 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
       ...
}

 frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

在InputMangerService中mPtr实际是NativeInputManager对象的地址。NativeInputManager是native层和java层(IMS)进行通信的桥梁。

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {

    ...
//创建EventHub
    sp<EventHub> eventHub = new EventHub();
//创建native InputManager
    mInputManager = new InputManager(eventHub, this, this);
}

在NativeInputManager 创建时很重要的是操作是创建EventHub和InputManager对象,EventHub是从驱动读取输入事件的关键类,InputManager则是负责事件加工,分发的关键类

frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    //创建InputDispatcher
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    //创建InputReader
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}
//创建线程
void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

InputManager初始化主要创建InputDispatcher(事件分发器)、InputReader(事件读取器);创建InputReaderThread、InputDispatcherThread线程,为事件读取和分发提供“动力”。
IMS整体结构图如下:
在这里插入图片描述

InputManagerService启动

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);
        ...
    }

InputManagerService的start方法会在SystemServer中启动,在java层的InputManagerService会启动native层的InputManager

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

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.");
    }
}

从这函数可以看出,会调用native层InputManager
frameworks/native/services/inputflinger/InputManager.cpp

status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);

        mDispatcherThread->requestExit();
        return result;
    }

    return OK;
}

InputManager的start函数做的工作就是启动ReaderThread和DispatcherThread。这样输入系统就可以读取事件了。
在这里插入图片描述

   IMS成员关系图

在这里插入图片描述

基础知识

文件描述符(File Descriptor)

概念:
Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行I/O操作的系统调用都会通过文件描述符。

详细介绍可以参考:
文件描述符(File Descriptor)简介
文件描述符 维基百科
理解inode

INotify

用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能够更好地管理设备,给用户提供更好的服务。 hotplug、udev 和 inotify 就是这种需求催生的。
INotify是Linux内核提供的一种文件系统变化通知机制。他可以为应用程序监控文件系统的变化,如新建、删除读写等。

INotify机制有两个基本对象,分别为INotify对象和watch对象,都用fd表示。
inotyfy对象对应一个队列,应用程序可以向inotify对象添加多个监听对象。被监听的事件发生时可以通过read()函数读取。
文件系统的变化事件被称做 watches 的一个对象管理,每一个 watch 是一个二元组(目标,事件掩码),目标可以是文件或目录,事件掩码表示应用希望关注的 inotify 事件,每一个位对应一个 inotify 事件。Watch 对象通过 watch描述符引用,watches 通过文件或目录的路径名来添加。目录 watches 将返回在该目录下的所有文件上面发生的事件。

Inotify 可以监视的文件系统事件包括:

  • IN_ACCESS,即文件被访问
  • IN_MODIFY,文件被 write
  • IN_ATTRIB,文件属性被修改,如 chmod、chown、touch 等
  • IN_CLOSE_WRITE,可写文件被 close
  • IN_CLOSE_NOWRITE,不可写文件被 close
  • IN_OPEN,文件被 open
  • IN_MOVED_FROM,文件被移走,如 mv
  • IN_MOVED_TO,文件被移来,如 mv、cp
  • IN_CREATE,创建新文件
  • IN_DELETE,文件被删除,如 rm
  • IN_DELETE_SELF,自删除,即一个可执行文件在执行时删除自己
  • IN_MOVE_SELF,自移动,即一个可执行文件在执行时移动自己
  • IN_UNMOUNT,宿主文件系统被 umount
  • IN_CLOSE,文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
  • IN_MOVE,文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO)

使用方法:
1、初始化创建INotify对象

int mINotifyFd = inotify_init();

2、添加监听到INotify对象中

 int result = inotify_add_watch(mINotifyFd, "/dev/input", IN_DELETE | IN_CREATE);

3、通过read函数从INotify对象中读取监听事件,当没有事件发生时INotify对象中没有任何可读数据

  res = read(mINotifyFd, event_buf, sizeof(event_buf));

读取出来的事件结构体:

/* Structure describing an inotify event.  */
struct inotify_event
{
  int wd;   /* Watch descriptor.  */
  uint32_t mask;  /* Watch mask.  */
  uint32_t cookie;  /* Cookie to synchronize two events.  */
  uint32_t len;   /* Length (including NULs) of name.  */
  char name __flexarr;  /* Name.  */
};

通过mask和wd就可以知道发生了什么事件

参考资料:
inotify – Linux 2.6 内核中的文件系统变化通知机制

Epoll

Epoll能够在内核发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。

Epoll的使用
1、创建Epoll对象

mEpollFd = epoll_create(EPOLL_SIZE_HINT);

2、填充epoll_event结构体
为每一个需要监听的描述符填充epoll_event结构体,以描述需要监听的事件,通过epoll_ctl()函数将此描述符与epoll_event结构体注册进epoll对象。

struct epoll_event
{
  uint32_t events;  /* Epoll events */
  epoll_data_t data;    /* User data variable */
};

typedef union epoll_data
{
  void *ptr;
  int fd;
  uint32_t u32;
  uint64_t u64;
} epoll_data_t;

epoll_event中的events字段,代表的是事件掩码,常见的事件有EPOLLIN(可读)EPOLLOUT(可写)EPOLLRR(出错)EPOLLHUP(挂起)
在epoll_data中实际使用的经常为epoll_event.data.fd设置需要监听的文件描述符

struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
eventItem.data.u32 = EPOLL_ID_INOTIFY;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);

3、使用epoll_wait()函数等待事件
当注册的事件发生一件就会立即返回,并携带刚才发生的事件的详细信息

/* Wait for events on an epoll instance "epfd". Returns the number of
   triggered events returned in "events" buffer. Or -1 in case of
   error with the "errno" variable set to the specific error code. The
   "events" parameter is a buffer that will contain triggered
   events. The "maxevents" is the maximum number of events to be
   returned ( usually size of "events" ). The "timeout" parameter
   specifies the maximum wait time in milliseconds (-1 == infinite).

   This function is a cancellation point and therefore not marked with
   __THROW.  */
int epoll_wait (int __epfd, struct epoll_event *__events,
               int __maxevents, int __timeout);

参考资料:
聊聊IO多路复用之select、poll、epoll详解
聊聊Linux 五种IO模型

Native层的Looper和MessageQueue

Native层的Looper和MessageQueue

原始事件数据读取与加工

事件读取整体结构

InputReader的运行实际依托的是InputReaderThread类的运行。

frameworks/native/services/inputflinger/InputReader.cpp

bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    Vector<InputDeviceInfo> inputDevices;
    { 
        ...
    //从eventHub中读取事件
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

   
...
//加工事件
            processEventsLocked(mEventBuffer, count);
        }

        ...
//将事件推给dispatcher处理
    mQueuedListener->flush();
}

很明显,InputReader的一次线程读取分成了三个部分
1、事件读取,事件读取是从EventHub中抽取未处理的事件列表。这些事件分为两类,一类是从设备节点读取的原始的输入事件,另一类是输入设备可用性变化事件,简称设备事件
2、通过processEvenitsLocked处理事件。此函数根据设备的可用性加载或移除设备的对应信息。对于原始的输入事件,则进行转译,加工,封装;然后将结果暂存到mQueuedListener中。
3、所有事件加工完成后,调用mQueuedListener->flush(),将所有暂存的事件一次性交付给InputDispatcher

EventHub事件读取

EventHub初始化

EventHub初始化主要通过INotify和Epoll机制,实现对输入设备节点的增删事件的监听。
frameworks/native/services/inputflinger/EventHub.cpp

EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    //构建Epoll对象
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
    //构建INotify
    mINotifyFd = inotify_init();
    int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",
            DEVICE_PATH, errno);
    //INotify和Epoll绑定,作为Epoll的一个监听对象,当INotify事件发生时,epoll_wait()立即返回
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    eventItem.data.u32 = EPOLL_ID_INOTIFY;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    ...
}

getEvent整体结构

EventHub的getEvent方法能够读取内核驱动事件,是整个EventHub最核心的函数。

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) 

可以看出从getEvent读取出来的事件,数据结构是RawEvent。

/*
 * A raw event as retrieved from the EventHub.
 */
struct RawEvent {
    nsecs_t when;// 事件发生的时间
    int32_t deviceId;//产生事件的设备ID
    int32_t type;//事件类型
    int32_t code;//事件代码
    int32_t value;//事件值
};

EventHub专门为输入设备的增删事件定义了3种类型:DEVICE_ADD、DEVICE_REMOVE、FINISHED_DEVICE_SCAN

输入设备的管理

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ALOG_ASSERT(bufferSize >= 1);

    AutoMutex _l(mLock);

    struct input_event readBuffer[bufferSize];

    RawEvent* event = buffer;
    size_t capacity = bufferSize;
    bool awoken = false;
    for (;;) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        //reopen是先close然后再open
        // Reopen input devices if needed.
        if (mNeedToReopenDevices) {
            mNeedToReopenDevices = false;

            ALOGI("Reopening all input devices due to a configuration change.");

            closeAllDevicesLocked();//关闭device
            mNeedToScanDevices = true;
            break; // return to the caller before we actually rescan
        }

        // Report any devices that had last been added/removed.
        //生成device remove事件
        while (mClosingDevices) {
            Device* device = mClosingDevices;
            ALOGV("Reporting device closed: id=%d, name=%s\n",
                 device->id, device->path.string());
            mClosingDevices = device->next;
            event->when = now;
            event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
            event->type = DEVICE_REMOVED;
            event += 1;
            delete device;
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) {
                break;
            }
        }

        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked();//opendevice
            mNeedToSendFinishedDeviceScan = true;
        }
        //生成deviceAdd事件
        while (mOpeningDevices != NULL) {
            Device* device = mOpeningDevices;
            ALOGV("Reporting device opened: id=%d, name=%s\n",
                 device->id, device->path.string());
            mOpeningDevices = device->next;
            event->when = now;
            event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
            event->type = DEVICE_ADDED;
            event += 1;
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) {
                break;
            }
        }
        //生成device scan结束事件
        if (mNeedToSendFinishedDeviceScan) {
            mNeedToSendFinishedDeviceScan = false;
            event->when = now;
            event->type = FINISHED_DEVICE_SCAN;
            event += 1;
            if (--capacity == 0) {
                break;
            }
        }
 // Grab the next input event.
        bool deviceChanged = false;
        while (mPendingEventIndex < mPendingEventCount) {
            //读取设备的增删事件
            const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
            if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
                if (eventItem.events & EPOLLIN) {
                    mPendingINotify = true;
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
                }
                continue;
            }
.....
}
// readNotify() will modify the list of devices so this must be done after
        // processing all other events to ensure that we read all remaining events
        // before closing the devices.
        if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
            mPendingINotify = false;
            readNotifyLocked();//处理设备变化事件
            deviceChanged = true;
        }

        // Report added or removed devices immediately.
        //上报设备变化事件
        if (deviceChanged) {
            continue;
        }
//等待读取事件
        int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
......
}

先看一下device的close(remove)

void EventHub::closeAllDevicesLocked() {
    while (mDevices.size() > 0) {
        closeDeviceLocked(mDevices.valueAt(mDevices.size() - 1));
    }
}

void EventHub::closeDeviceLocked(Device* device) {
    ....
//从epoll监听中去除
        if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
            ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
        }

    releaseControllerNumberLocked(device);
    //从mDevices中移除
    mDevices.removeItem(device->id);
    device->close();

    // Unlink for opening devices list if it is present.
    //从opening devices 链中去除
    Device* pred = NULL;
    bool found = false;
    for (Device* entry = mOpeningDevices; entry != NULL; ) {
        if (entry == device) {
            found = true;
            break;
        }
        pred = entry;
        entry = entry->next;
    }
    if (found) {
        if (pred) {
            pred->next = device->next;
        } else {
            mOpeningDevices = device->next;
        }
        delete device;
    } else {
        device->next = mClosingDevices;
        mClosingDevices = device;//加入closing的device
    }
}

输入设备的打开

void EventHub::scanDevicesLocked() {
       //打开"/dev/input"这个目录下的所有设备
    status_t res = scanDirLocked(DEVICE_PATH);
    ...
}

status_t EventHub::scanDirLocked(const char *dirname)
{
    char devname[PATH_MAX];
    char *filename;
    DIR *dir;
    struct dirent *de;
    dir = opendir(dirname);
    if(dir == NULL)
        return -1;
    strcpy(devname, dirname);
    filename = devname + strlen(devname);
    *filename++ = '/';
    while((de = readdir(dir))) {
        if(de->d_name[0] == '.' &&
           (de->d_name[1] == '\0' ||
            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
            continue;
        strcpy(filename, de->d_name);
        openDeviceLocked(devname);//打开一个具体的设备
    }
    closedir(dir);
    return 0;
}

status_t EventHub::openDeviceLocked(const char *devicePath) {
    char buffer[80];
    // 打开设备文件,获取fd,用于获取输入事件
    int fd = open(devicePath, O_RDWR | O_CLOEXEC);
    if(fd < 0) {
        ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
        return -1;
    }
    //读取厂商信息
    InputDeviceIdentifier identifier;

   ...

    // Allocate device.  (The device object takes ownership of the fd at this point.)
    //分配device id
    int32_t deviceId = mNextDeviceId++;
    //构建device对象
    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
    // Load the configuration file for the device.
    loadConfigurationLocked(device);
    //通过ioctl获取事件位掩码,事件位掩码指定了输入设备可以产生何种类型的输入事件,在后面事件处理中很关键
    // Figure out the kinds of events the device reports.
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
    ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
    ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
    ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
    ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);

//通过事件位掩码等一些信息决定是属于那种类型的输入设备,设置device的class字段
    bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
                    sizeof_bit_array(KEY_MAX + 1));
    bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
                    sizeof_bit_array(BTN_MOUSE))
            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
                    sizeof_bit_array(BTN_DIGI));
    if (haveKeyboardKeys || haveGamepadButtons) {
        device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
    }

    // See if this is a cursor device such as a trackball or mouse.
    if (test_bit(BTN_MOUSE, device->keyBitmask)
            && test_bit(REL_X, device->relBitmask)
            && test_bit(REL_Y, device->relBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_CURSOR;
    }

    // See if this is a rotary encoder type device.
    String8 deviceType = String8();
    if (device->configuration &&
        device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
            if (!deviceType.compare(String8("rotaryEncoder"))) {
                device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
            }
    }

    ...

    // Register with epoll.
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    if (mUsingEpollWakeup) {
        eventItem.events |= EPOLLWAKEUP;
    }
    eventItem.data.u32 = deviceId;
//注册到epoll中,监听输入事件
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
        delete device;
        return -1;
    }

  ...
//添加到mDevice中
    addDeviceLocked(device);
    return 0;
}

void EventHub::addDeviceLocked(Device* device) {
    mDevices.add(device->id, device);
    device->next = mOpeningDevices;
    mOpeningDevices = device;
}

最终会形成下图这种事件序列
在这里插入图片描述

R 表示DEVICE_REMOVE事件,A表示DEVICE_ADD事件,F表示FINISHED_DEVICE_SCAN事件

输入事件的读取

在监听到输入设备的加入事件之后,会把这个输入设备加入Epoll监听,当有输入事件发生时,能够及时收到输入事件。

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {

        ...

        while (mPendingEventIndex < mPendingEventCount) {
            const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
            ...

            ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
            if (deviceIndex < 0) {
                ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
                        eventItem.events, eventItem.data.u32);
                continue;
            }
           //输入事件读取
            Device* device = mDevices.valueAt(deviceIndex);
            if (eventItem.events & EPOLLIN) {
                int32_t readSize = read(device->fd, readBuffer,
                        sizeof(struct input_event) * capacity);
                //错误处理
                ...
                    //事件构建
                    int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;

                    size_t count = size_t(readSize) / sizeof(struct input_event);
                    for (size_t i = 0; i < count; i++) {
                        struct input_event& iev = readBuffer[i];
                        ...//错误处理
                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;
                        capacity -= 1;
                    }
                    if (capacity == 0) {
                        mPendingEventIndex -= 1;
                        break;
                    }
                }
            } else if (eventItem.events & EPOLLHUP) {
                ALOGI("Removing device %s due to epoll hang-up event.",
                        device->identifier.name.string());
                deviceChanged = true;
                closeDeviceLocked(device);
            } else {
                ALOGW("Received unexpected epoll event 0x%08x for device %s.",
                        eventItem.events, device->identifier.name.string());
            }
        }

getEvent剩下的就是等待事件获取

// Return now if we have collected any events or if we were explicitly awoken.
//读到了事件就立即返回
        if (event != buffer || awoken) {
            break;
        }

        ....
        //阻塞获取事件
        int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

        ....
//错误处理

EventHub读取输入事件结构图
在这里插入图片描述

InputReader事件加工

InputReader对原始输入事件的处理,主要分为2个部分:输入设备增加删除事件处理;原始输入事件处理。
frameworks/native/services/inputflinger/InputReader.cpp

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            //同一个设备的事件放到一起处理
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
#if DEBUG_RAW_EVENTS
            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endif
            //处理输入事件
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::DEVICE_REMOVED:
                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::FINISHED_DEVICE_SCAN:
                handleConfigurationChangedLocked(rawEvent->when);
                break;
            default:
                ALOG_ASSERT(false); // can't happen
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

输入设备增加删除事件处理

增加输入设备的事件主要是创建一个对应的InputDevice对象,用于后续这个Device产生的输入事件的加工。InputDevice和EventHub中的Device对象,一个重要区别是,不仅仅存储了设备信息,还加入了处理输入事件的InputMapper,而这些InputMapper就是真正的加工输入事件的对象。
frameworks/native/services/inputflinger/InputReader.cpp

void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex >= 0) {
        return;
    }
    //从EventHub读取InputDeviceIdentifier,构建InputDevice
    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
    int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
    //创建InputDevice
    InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
    device->configure(when, &mConfig, 0);
    device->reset(when);

    if (device->isIgnored()) {
        ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
                identifier.name.string());
    } else {
        ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
                identifier.name.string(), device->getSources());
    }

    mDevices.add(deviceId, device);
    bumpGenerationLocked();

    if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
        notifyExternalStylusPresenceChanged();
    }
}
//从EventHub读取InputDeviceIdentifier,实际读取的是EventHub中的Device信息。
virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const {
        Device* device = getDevice(deviceId);
        return device ? device->identifier : InputDeviceIdentifier();
    }

在EventHub中创建Device的时候,会根据设备产生的事件类型,匹配相应的设备类型,在InputReader创建InputDevice时,根据设备类型,生成相应的InputMapper。
在这里插入图片描述

InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
        const InputDeviceIdentifier& identifier, uint32_t classes) {
    InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
            controllerNumber, identifier, classes);
    ...
    // Touchscreens and touchpad devices.对于触摸屏设备,添加MultiTouchInputMapper或者SingleTouchInputMapper
    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
        device->addMapper(new MultiTouchInputMapper(device));
    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
        device->addMapper(new SingleTouchInputMapper(device));
    }
    ...

    return device;
}

输入事件的加工

对于输入事件processEventsLocked主要工作是将一个设备的事件规整,一次交出去给processEventsForDeviceLocked处理
frameworks/native/services/inputflinger/InputReader.cpp

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
    //把同一个设备产生的事件放一起
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
#if DEBUG_RAW_EVENTS
            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endif
//加工事件
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } 
    ....
}

processEventsForDeviceLocked最终会通过deviceId找到对应的Device,然后调用Device的process方法,device的方法最终,调用对应的InputMapper。
frameworks/native/services/inputflinger/InputReader.cpp

void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    ...
    device->process(rawEvents, count);
}
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    
    size_t numMappers = mMappers.size();
    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
        ...
            for (size_t i = 0; i < numMappers; i++) {
                InputMapper* mapper = mMappers[i];
                mapper->process(rawEvent);
            }
        --count;
    }
}

以触摸事件为例看一下InputMapper对原始事件的加工。

可以使用adb命令读取原始输入事件

  1. 输入adb shell
  2. 输入 getevent就可以读取原始输入事件
    一次滑动读取处理的原始输入数据
输入设备事件类型事件code事件value
/dev/input/event20003003900004693
/dev/input/event20001014a00000001
/dev/input/event20001014500000001
/dev/input/event20003003500000150
/dev/input/event20003003600000666
/dev/input/event20003003000000005
/dev/input/event20003003100000003
/dev/input/event20000000000000000
/dev/input/event20003003500000162
/dev/input/event20003003600000665
/dev/input/event20003003100000004
/dev/input/event20000000000000000
/dev/input/event200030035000001d6
/dev/input/event2000300360000065e
/dev/input/event20003003000000004
/dev/input/event20003003100000003
/dev/input/event20000000000000000
/dev/input/event200030039ffffffff
/dev/input/event20001014a00000000
/dev/input/event20001014500000000
/dev/input/event20000000000000000

可以发现,每隔一段就会出现一个全零的事件,这个其实是一个输入事件结束的标记。
对应的是rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT
MultiTouchInputMapper结构是对于普通事件通过基类TouchInputMapper和MultiTouchMotionAccumulato存储事件信息,当全零事件出现时,对信息进行整合
frameworks/native/services/inputflinger/InputReader.cpp

void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
//调用基类的process方法,
    TouchInputMapper::process(rawEvent);
//收集多点触摸的信息
    mMultiTouchMotionAccumulator.process(rawEvent);
}

void TouchInputMapper::process(const RawEvent* rawEvent) {
    mCursorButtonAccumulator.process(rawEvent);
    mCursorScrollAccumulator.process(rawEvent);
    mTouchButtonAccumulator.process(rawEvent);

    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
        //开始合并信息
        sync(rawEvent->when);
    }
}

对于各种事件和MotionEvent的映射,可以查看参考资料的。

  • BTN_LEFT:映射到 MotionEvent.BUTTON_PRIMARY。
  • BTN_RIGHT:映射到 MotionEvent.BUTTON_SECONDARY。
  • BTN_MIDDLE:映射到 MotionEvent.BUTTON_MIDDLE。
  • BTN_BACK 和 BTN_SIDE:映射到 MotionEvent.BUTTON_BACK。按此按钮还可以合成按键(使用按键代码 KeyEvent.KEYCODE_BACK)。
  • BTN_FORWARD 和 BTN_EXTRA:映射到 MotionEvent.BUTTON_FORWARD。按此按钮还可以合成按键(使用按键代码 KeyEvent.KEYCODE_FORWARD)。
  • BTN_STYLUS:映射到 MotionEvent.BUTTON_SECONDARY。
  • BTN_STYLUS2:映射到 MotionEvent.BUTTON_TERTIARY。
    frameworks/native/services/inputflinger/InputReader.cpp
void TouchInputMapper::sync(nsecs_t when) {
    const RawState* last = mRawStatesPending.isEmpty() ?
            &mCurrentRawState : &mRawStatesPending.top();

    // Push a new state.
    mRawStatesPending.push();
    RawState* next = &mRawStatesPending.editTop();
    next->clear();
    next->when = when;
    ...

    // Sync touch 这一步主要目的是将之前保存的信息,整合到RawState中
    syncTouch(when, next);
    ...
    //加工RawState数据对象
    processRawTouches(false /*timeout*/);
}
//MultiTouchInputMapper重写了
void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
    ...

    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
        ...
        RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
        outPointer.x = inSlot->getX();
        outPointer.y = inSlot->getY();
        outPointer.pressure = inSlot->getPressure();
        outPointer.touchMajor = inSlot->getTouchMajor();
        outPointer.touchMinor = inSlot->getTouchMinor();
        ...
}
void TouchInputMapper::processRawTouches(bool timeout) {
    ...
        //真正加工RawState
        cookAndDispatch(mCurrentRawState.when);
    ...
}

cookAndDispatch分为两部分,cookPointerData和dispatchPointerUsage,cookPointerData将原来RawState加工成CookedState数据,主要是实现从设备坐标向屏幕坐标的转换。dispatchPointerUsage先将CookedState加工成PointerGesture,最后加工成NotifyMotionArgs;通过notifyMotion存入

void TouchInputMapper::cookAndDispatch(nsecs_t when) {
    ...
    cookPointerData();

    ...
        //进一步将CookedState加工成PointerGesture,存储在mPointerGesture最终调用dispatchMotion分发
        dispatchPointerUsage(when, policyFlags, pointerUsage);
   ....
}

void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
        int32_t action, int32_t actionButton, int32_t flags,
        int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
        const PointerProperties* properties, const PointerCoords* coords,
        const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
        float xPrecision, float yPrecision, nsecs_t downTime) {
   ...
    //最终形成NotifyMotionArgs对象
    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
            action, actionButton, flags, metaState, buttonState, edgeFlags,
            mViewport.displayId, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
            xPrecision, yPrecision, downTime);
// 将事件NotifyMotionArgs存入QueuedInputListener的mArgsQueue队列中
    getListener()->notifyMotion(&args);
}

frameworks/native/services/inputflinger/InputListener.cpp

void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
    mArgsQueue.push(new NotifyMotionArgs(*args));
}

参考资料:
https://source.android.com/devices/input/touch-devices

InputReader与InputDispatcher事件传递

frameworks/native/services/inputflinger/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();
}

frameworks/native/services/inputflinger/InputListener.cpp

void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyMotion(this);
}

遍历mArgsQueue,通过notifyMotion将事件存入InputDispatcher的mInboundQueue队列中
frameworks/native/services/inputflinger/InputDispatcher.cpp

void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
    ...

        // Just enqueue a new motion event.
        MotionEntry* newEntry = new MotionEntry(args->eventTime,
                args->deviceId, args->source, policyFlags,
                args->action, args->actionButton, args->flags,
                args->metaState, args->buttonState,
                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                args->displayId,
                args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);

        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    if (needWake) {
        mLooper->wake();
    }
}

小结
输入事件读取结构图
在这里插入图片描述

事件分发

在InputReade将事件塞入InputDispatcher事件分发mInboundQueue的同时会唤醒Dispatcher线程进行事件分发。

Motion事件派发

事件的派发始于dispatchOnce
dispatchOnce主要工作

  • 进行一次事件派发
  • 一次事件派发完成后下次唤醒的时间

frameworks/native/services/inputflinger/InputDispatcher.cpp

void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { 
        if (!haveCommandsLocked()) {
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

 
        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;
        }
    } // release lock
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    mLooper->pollOnce(timeoutMillis);
}

真正进行事件派发的函数dispatchOnceInnerLocked,事件的派发是一个串行的过程,排在队首的事件被派发完成或者丢弃前,不会对后续事件进行派发
dispatchOnceInnerLocked函数主要完成的工作:

  • 如果派发队列为空,陷入无限等待状态
  • 取出一个派发的事件放入mPendingEvent中
  • 处理事件各种被丢弃的case
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
   ...
    //从派发队列中取出一个派发事件出来存入mPendingEvent中
    if (! mPendingEvent) {
           ...
            // Inbound queue has at least one entry.
            mPendingEvent = mInboundQueue.dequeueAtHead();
        ...
    }

    //检查事件是否需要被丢弃
    ALOG_ASSERT(mPendingEvent != NULL);
    bool done = false;
    DropReason dropReason = DROP_REASON_NOT_DROPPED;
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
        dropReason = DROP_REASON_POLICY;
    } else if (!mDispatchEnabled) {
        dropReason = DROP_REASON_DISABLED;
    }

    if (mNextUnblockedEvent == mPendingEvent) {
        mNextUnblockedEvent = NULL;
    }
    //按事件的类型开始分发事件
    switch (mPendingEvent->type) {
    ....

    case EventEntry::TYPE_MOTION: {
        //Motion事件被丢弃原因
        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
            dropReason = DROP_REASON_APP_SWITCH;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED
                && isStaleEventLocked(currentTime, typedEntry)) {
            dropReason = DROP_REASON_STALE;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
            dropReason = DROP_REASON_BLOCKED;
        }
//分发Motion事件
        done = dispatchMotionLocked(currentTime, typedEntry,
                &dropReason, nextWakeupTime);
        break;
    }
    ...
}

dispatchMotionLocked 函数做的核心工作:

  • 找到合适目标窗口
  • 调用dispatchEventLocked将事件派发到相应的窗口
bool InputDispatcher::dispatchMotionLocked(
        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ...
    //找到目标窗口
    // Identify targets.
    Vector<InputTarget> inputTargets;

    bool conflictingPointerActions = false;
    int32_t injectionResult;
    if (isPointerEvent) {
        // Pointer event.  (eg. touchscreen)
        injectionResult = findTouchedWindowTargetsLocked(currentTime,
                entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
    } else {
        // Non touch event.  (eg. trackball)
        injectionResult = findFocusedWindowTargetsLocked(currentTime,
                entry, inputTargets, nextWakeupTime);
    }
   ...
//如果成功找到,将事件派发到相应的窗口
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

findTouchedWindowTargetsLocked找到的窗口信息存在InputTarget结构中,InputTarget存储的信息中,最重要的是InputChannel对象。Dispatcher通过它将事件传递给目标窗口,目标窗口将相应传给Dispatcher。后面详细介绍InputChannel结构

dispatchEventLocked主要工作:

  • 找到对应的窗口Connection,然后向相应的窗口分发事件
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
    ...
    //遍历选中的窗口
    for (size_t i = 0; i < inputTargets.size(); i++) {
        const InputTarget& inputTarget = inputTargets.itemAt(i);

        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if (connectionIndex >= 0) {
//找到相应的Connection,
            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
//向相应的窗口发送事件
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
        } else {
#if DEBUG_FOCUS
            ALOGD("Dropping event delivery to target with channel '%s' because it "
                    "is no longer registered with the input dispatcher.",
                    inputTarget.inputChannel->getName().c_str());
#endif
        }
    }
}

prepareDispatchCycleLocked主要工作:

  • 判断Connection的状态
  • 将EventEntry加入Connection派发队列,具体实现是将传入的EventEntry转化成DispatchEntry,然后加入Connection的outboundQueue队列。
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    //判断Connection是不是正常
    if (connection->status != Connection::STATUS_NORMAL) {
#if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
                connection->getInputChannelName().c_str(), connection->getStatusLabel());
#endif
        return;
    }

    ...
//将需要派发的事件加入Connection的派发队列
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}

在这里插入图片描述

目标窗口的查找
window的添加
PhoneWindow 的创建
在Activity attach方法中会创建PhoneWindow
frameworks/base/core/java/android/app/Activity.java

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window, ActivityConfigCallback activityConfigCallback) {
    attachBaseContext(context);

    mFragments.attachHost(null /*parent*/);
    // 创建PhoneWindow
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowControllerCallback(this);
    //Activity 实现了Window.Callback
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    。。。
    //
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
        mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();
    。。。
}

WindowManager实现,新创建一个WindowManagerImpl
ActivityThread#handleResumeActivity方法,我们看看这个方法的源码:
frameworks/base/core/java/android/app/ActivityThread.java

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) { 
    //...
    ActivityClientRecord r = performResumeActivity(token, clearHide); // 这里会调用到onResume()方法

    if (r != null) {
        final Activity a = r.activity;

        //...
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow(); // 获得window对象
            View decor = r.window.getDecorView(); // 获得DecorView对象
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager(); // 获得windowManager对象
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (a.mVisibleFromClient) {
                a.mWindowAdded = true;
                wm.addView(decor, l); // 调用addView方法
            }
            //...
        }
    }
}

在该方法内部,获取该activity所关联的window对象,DecorView对象,以及windowManager对象,而WindowManager是抽象类,它的实现类是WindowManagerImpl,所以后面调用的是WindowManagerImpl#addView方法
frameworks/base/core/java/android/view/Window.java

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
        boolean hardwareAccelerated) {
    mAppToken = appToken;
    mAppName = appName;
    mHardwareAccelerated = hardwareAccelerated
            || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
    if (wm == null) {
        wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
    }
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}

WindowManagerImpl添加View
在Activity的sentContent方法中会创建DecorView;当Activity的onCreate方法结束时,会把创建添加到WindowManagerservice中,

frameworks/base/core/java/android/view/WindowManagerImpl.java

@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
WindowManagerGlobal 添加addView
frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
   ...

        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(wparams);

        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);

        // do this last because it fires off messages to start doing things
        try {
            //通过ViewRootImpl添加Window到WindowManagerService
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            if (index >= 0) {
                removeViewLocked(index, true);
            }
            throw e;
        }
    }
}

ViewRootImpl 的setView除了添加window,还在ViewRootImpl的setView方法中还做了一个重要的操作

从代码可以看到这里的mInputChannel对象已经传到WindowManagerService中,这样就可以接受输入事件。
frameworks/base/core/java/android/view/ViewRootImpl.java

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
//如果能接收输入事件,会创建一个InputChannel对象
  if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
//创建Java层的InputChannel
                    mInputChannel = new InputChannel();
                }
    ...
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);

    ...
//创建事件接收对象
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
//创建各种InputStage
mSyntheticInputStage = new SyntheticInputStage();
                InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
                InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
                        "aq:native-post-ime:" + counterSuffix);
                InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
                InputStage imeStage = new ImeInputStage(earlyPostImeStage,
                        "aq:ime:" + counterSuffix);
                InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
                InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
                        "aq:native-pre-ime:" + counterSuffix);

                mFirstInputStage = nativePreImeStage;
                mFirstPostImeInputStage = earlyPostImeStage;
}

mWindowSession在ViewRootImpl创建时初始化
mWindowSession = WindowManagerGlobal.getWindowSession();
我们再看WindowManagerGlobal
frameworks/base/core/java/android/view/WindowManagerGlobal.java
public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
            try {
                InputMethodManager imm = InputMethodManager.getInstance();
                IWindowManager windowManager = getWindowManagerService();
                sWindowSession = windowManager.openSession(
                        new IWindowSessionCallback.Stub() {
                            @Override
                            public void onAnimatorScaleChanged(float scale) {
                                ValueAnimator.setDurationScale(scale);
                            }
                        },
                        imm.getClient(), imm.getInputContext());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowSession;
    }
}
public static IWindowManager getWindowManagerService() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowManagerService == null) {
            sWindowManagerService = IWindowManager.Stub.asInterface(
                    ServiceManager.getService("window"));
            try {
                if (sWindowManagerService != null) {
                    ValueAnimator.setDurationScale(
                            sWindowManagerService.getCurrentAnimatorScale());
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowManagerService;
    }
}

从这段代码可以看出,实际上是通过Binder,拿到IWindowManager,然后拿到IWindowSession;
我们再看看WindowManagerService的openSession方法
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
        IInputContext inputContext) {
    if (client == null) throw new IllegalArgumentException("null client");
    if (inputContext == null) throw new IllegalArgumentException("null inputContext");
    Session session = new Session(this, callback, client, inputContext);
    return session;
}

这里实质是创建了一个Session对象
frameworks/base/services/core/java/com/android/server/wm/Session.java

@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
        Rect outStableInsets, Rect outOutsets,
        DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
            outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}

从这可以看到,最后会调用到addWindow,应该注意一点就是我们平时说的PhoneWindow并不是添加到WindowManagerService中的window,而是IWindow

窗口信息更新到Dispatcher中

先看WindowManagerService的addWindow
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
...
//创建windowState,保存窗口信息
final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], seq, attrs, viewVisibility, session.mUid,
                    session.mCanAddInternalSystemWindow);
        ...
            final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
        //注册InputChannel
                win.openInputChannel(outInputChannel);
            }

      ....
//将所有cache的信息提供给Input Dispatcher
mInputMonitor.updateInputWindowsLw(false /*force*/);
    }

addwindow跟输入事件直接相关的是两个点:

  • 创建InputChannel,注册到Dispatcher
  • 将窗口信息更新到Dispatcher

注册InputChannel
注册InputChannel是在WindowState对象中完成
frameworks/base/services/core/java/com/android/server/wm/WindowState.java

void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
        String name = getName();
        InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
        mInputChannel = inputChannels[0];
        mClientChannel = inputChannels[1];
        mInputWindowHandle.inputChannel = inputChannels[0];
        if (outInputChannel != null) {
            mClientChannel.transferTo(outInputChannel);
            mClientChannel.dispose();
            mClientChannel = null;
        } else {
            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
        }
        mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
    }

openInputChannel函数主要工作:

  • 创建InputChannel对,然后transferTo outInputChannel,outInputChannel也就是我们调用session.addToDisplay传入的对象;这样应用进程与系统进程就建立了联系。
  • 把InputChannel注册到Dispatcher中
    frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void registerInputChannel(InputChannel inputChannel,
            InputWindowHandle inputWindowHandle) {
        if (inputChannel == null) {
            throw new IllegalArgumentException("inputChannel must not be null.");
        }

        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
    }
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
tatic void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
    ...

    status_t status = im->registerInputChannel(
            env, inputChannel, inputWindowHandle, monitor);
    ...
}
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
        const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
    ATRACE_CALL();
//注册到Dispatcher中
    return mInputManager->getDispatcher()->registerInputChannel(
            inputChannel, inputWindowHandle, monitor);
}

frameworks/native/services/inputflinger/InputDispatcher.cpp

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
...
//构建一个Connection,将InputChannel和inputWindowHandle保存
        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);

        int fd = inputChannel->getFd();
        //将Connection添加到mConnection的map中
        mConnectionsByFd.add(fd, connection);

        if (monitor) {
            mMonitoringChannels.push(inputChannel);
        }
        //添加对InputChannel的事件监听,当InputChannel有输入事件,会回调handleReceiveCallback
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock

    // Wake the looper because some connections have changed.
    mLooper->wake();
    return OK;
}

窗口信息更新到Dispatcher
当窗口有更新,都是通过InputMonitor的updateInputWindowsLw函数将信息更新到Dispatcher里。
frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java

/* Updates the cached window information provided to the input dispatcher. */
    void updateInputWindowsLw(boolean force) {
       ...

        // Add all windows on the default display.
        //将窗口信息更新到Dispatcher,窗口信息存在InputWindowHandle这个对象中。
        mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
    }
private void updateInputWindows(boolean inDrag) {

            ...

            // Send windows to native code.
            mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);

            clearInputWindowHandlesLw();

            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public void setInputWindows(InputWindowHandle[] windowHandles,
            InputWindowHandle focusedWindowHandle) {
        nativeSetInputWindows(mPtr, windowHandles);
    }

最终会调用InputDispatcher的setInputWindows方法。这个方法更新window的方法很暴力直接替换原来的
frameworks/native/services/inputflinger/InputDispatcher.cpp

void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
#if DEBUG_FOCUS
    ALOGD("setInputWindows");
#endif
    { // acquire lock
        AutoMutex _l(mLock);
        //直接替换老的WindowHandle
        Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
        mWindowHandles = inputWindowHandles;
        //查找新的焦点窗口
        //更新焦点窗口

        ...
    // Wake up poll loop since it may need to make new input dispatching choices.
    mLooper->wake();
}

窗口查找
dispatchMotionLocked会调用findTouchedWindowTargetsLocked函数查找窗口
frameworks/native/services/inputflinger/InputDispatcher.cpp

int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
        const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
        bool* outConflictingPointerActions) {
...
     // 遍历Dispacher中的mWindowHandles,得到InputWindowerHandler,这个类保存了窗口的布局信息,尺寸,InputChannel等
        size_t numWindows = mWindowHandles.size();
        for (size_t i = 0; i < numWindows; i++) {
            sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
            const InputWindowInfo* windowInfo = windowHandle->getInfo();
            if (windowInfo->displayId != displayId) {
                continue; // wrong display
            }

            int32_t flags = windowInfo->layoutParamsFlags;
            if (windowInfo->visible) {
                if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
                    isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
                            | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
                    if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
                        newTouchedWindowHandle = windowHandle;
                        break; // found touched window, exit window loop
                    }
                }

                if (maskedAction == AMOTION_EVENT_ACTION_DOWN
                        && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
                    mTempTouchState.addOrUpdateWindow(
                            windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE, BitSet32(0));
                }
            }
        }
    ...
        mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);

// 确保窗口能够接受事件
    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
        const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
            // Check whether the window is ready for more input.
            std::string reason = checkWindowReadyForMoreInputLocked(currentTime,
                    touchedWindow.windowHandle, entry, "touched");
            if (!reason.empty()) {
                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
                        NULL, touchedWindow.windowHandle, nextWakeupTime, reason.c_str());
                goto Unresponsive;
            }
        }
    }

    ....
    //将mTempTouchState转换成InputTarget
    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
        const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                touchedWindow.pointerIds, inputTargets);
    }

}

这个函数主要做的工作:

  • 遍历mWindowHandle,根据坐标等信息选取合适的窗口
  • 检测窗口能否接收事件
  • 将InputWindowHandle转换成InputTarget传出来
    在这里插入图片描述

理解InputChannel

InputChannel对本质上是SocketPair对,进程间通过SocketPair进行事件传递。一对SocketPair通过socketpair()函数创建,其使用者可以因此得到两个相互连接的文件描述符。这两个描述符可以通过套接字接口send()和recv()进行写入和读取。
InputChannel就是对SocketPair描述符及其操作进行封装,而且是成对使用,配对的两个InputChannel分别保有一个SocketPair的描述符,并分配给InputDispatcher与窗口

InputChannel有两个实现,Java层的和Native层
Java层的实现,实际就是对native层InputChannel的一个封装。里面的成员变量只有一个native对象的地址,所有的方法通过jni代理到了native
frameworks/base/core/java/android/view/InputChannel.java

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

frameworks/native/libs/input/InputTransport.cpp

status_t InputChannel::openInputChannelPair(const std::string& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    int sockets[2];
    // 创建socketPair
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
        status_t result = -errno;
        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d",
                name.c_str(), errno);
        outServerChannel.clear();
        outClientChannel.clear();
        return result;
    }

    int bufferSize = SOCKET_BUFFER_SIZE;
    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));

    std::string serverChannelName = name;
    serverChannelName += " (server)";
    //创建InputChannel
    outServerChannel = new InputChannel(serverChannelName, sockets[0]);

    std::string clientChannelName = name;
    clientChannelName += " (client)";
    //创建InputChannel
    outClientChannel = new InputChannel(clientChannelName, sockets[1]);
    return OK;
}

InputChannel对socketpair进一步封装了sendMessage和receiveMessage

Connection进行事件分发

先看一下事件派发,InputDispatcher的prepareDispatchCycleLocked最后会将事件放入Connection的派发队列
frameworks/native/services/inputflinger/InputDispatcher.cpp

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    //判断Connection是不是正常
    if (connection->status != Connection::STATUS_NORMAL) {
#if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
                connection->getInputChannelName().c_str(), connection->getStatusLabel());
#endif
        return;
    }

    ...
//将需要派发的事件加入Connection的派发队列
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    bool wasEmpty = connection->outboundQueue.isEmpty();

    // 更加不同的模式,将eventEntry转换成dispatchEntry,加入队列
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
            InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
    ...
    // If the outbound queue was previously empty, start the dispatch cycle going.
    if (wasEmpty && !connection->outboundQueue.isEmpty()) {
        //开始事件发送
        startDispatchCycleLocked(currentTime, connection);
    }
}
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::enqueueDispatchEntryLocked(
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
        int32_t dispatchMode) {
    ...
switch (eventEntry->type) {
    case EventEntry::TYPE_KEY: {
    case EventEntry::TYPE_MOTION: {
        ...
        break;
    }
    }

    ...
    // 将构建出来的dispatchEntry,加入outboundQueue
    connection->outboundQueue.enqueueAtTail(dispatchEntry);
    traceOutboundQueueLengthLocked(connection);
}

frameworks/native/services/inputflinger/InputDispatcher.cpp

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection) {
#if DEBUG_DISPATCH_CYCLE
    ALOGD("channel '%s' ~ startDispatchCycle",
            connection->getInputChannelName().c_str());
#endif

    while (connection->status == Connection::STATUS_NORMAL
            && !connection->outboundQueue.isEmpty()) {
        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
        dispatchEntry->deliveryTime = currentTime;

        // Publish the event.
        status_t status;
        EventEntry* eventEntry = dispatchEntry->eventEntry;
        switch (eventEntry->type) {
        case EventEntry::TYPE_KEY: 
        ...

        case EventEntry::TYPE_MOTION: {
            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);

            PointerCoords scaledCoords[MAX_POINTERS];
            const PointerCoords* usingCoords = motionEntry->pointerCoords;

            // Set the X and Y offset depending on the input source.
            float xOffset, yOffset;
            if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                    && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
                float scaleFactor = dispatchEntry->scaleFactor;
                xOffset = dispatchEntry->xOffset * scaleFactor;
                yOffset = dispatchEntry->yOffset * scaleFactor;
                if (scaleFactor != 1.0f) {
                    for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                        scaledCoords[i] = motionEntry->pointerCoords[i];
                        scaledCoords[i].scale(scaleFactor);
                    }
                    usingCoords = scaledCoords;
                }
            } else {
                xOffset = 0.0f;
                yOffset = 0.0f;

                // We don't want the dispatch target to know.
                if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
                    for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                        scaledCoords[i].clear();
                    }
                    usingCoords = scaledCoords;
                }
            }

            // Publish the motion event.构建InputMessage,给InputChannel发送
            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
                    motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
                    dispatchEntry->resolvedAction, motionEntry->actionButton,
                    dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
                    motionEntry->metaState, motionEntry->buttonState,
                    xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
                    motionEntry->downTime, motionEntry->eventTime,
                    motionEntry->pointerCount, motionEntry->pointerProperties,
                    usingCoords);
            break;
        }

        default:
            ALOG_ASSERT(false);
            return;
        }

        ...
        // 将事件从派发队列outboundQueue中移除
        connection->outboundQueue.dequeue(dispatchEntry);
        traceOutboundQueueLengthLocked(connection);
        // 将事件加入派发队列waitQueue中,等待事件应用处理完成后,收到响应,再从waitQueue中移除
        connection->waitQueue.enqueueAtTail(dispatchEntry);
        traceWaitQueueLengthLocked(connection);
    }
}

frameworks/native/libs/input/InputTransport.cpp

status_t InputPublisher::publishMotionEvent(
        uint32_t seq,
        int32_t deviceId,
        int32_t source,
        int32_t displayId,
        int32_t action,
        int32_t actionButton,
        int32_t flags,
        int32_t edgeFlags,
        int32_t metaState,
        int32_t buttonState,
        float xOffset,
        float yOffset,
        float xPrecision,
        float yPrecision,
        nsecs_t downTime,
        nsecs_t eventTime,
        uint32_t pointerCount,
        const PointerProperties* pointerProperties,
        const PointerCoords* pointerCoords) {
    ...
    InputMessage msg;
    msg.header.type = InputMessage::TYPE_MOTION;
    msg.body.motion.seq = seq;
    msg.body.motion.deviceId = deviceId;
    msg.body.motion.source = source;
   ...
    return mChannel->sendMessage(&msg);
}

小结

在这里插入图片描述

应用层事件分发

在ViewRootImpl的setView方法中,会创建一个WindowInputEventReceiver接收输入事件.WindowInputEventReceiver继承自InputEventReceiver,InputEventReceiver在初始化时,会通过InputChannel,注册监听InputChannel

//创建事件接收对象
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());

frameworks/base/core/java/android/view/ViewRootImpl.java

final class WindowInputEventReceiver extends InputEventReceiver {
}
frameworks/base/core/java/android/view/InputEventReceiver.java
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;
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);

        mCloseGuard.open("dispose");
    }

frameworks/base/core/jni/android_view_InputEventReceiver.cpp

static jlong nati veInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject inputChannelObj, jobject messageQueueObj) {
    ...

    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
            receiverWeak, inputChannel, messageQueue);
    status_t status = receiver->initialize();
    ...
}

status_t NativeInputEventReceiver::initialize() {
    setFdEvents(ALOOPER_EVENT_INPUT);
    return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
    if (mFdEvents != events) {
        mFdEvents = events;
        int fd = mInputConsumer.getChannel()->getFd();
        if (events) {
            mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
        } else {
            mMessageQueue->getLooper()->removeFd(fd);
        }
    }
}

当收到输入事件,会调用handleEvent,然后通过JNI调用Java层的函数。
frameworks/base/core/jni/android_view_InputEventReceiver.cpp

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    ...

    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        //处理事件
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY ? 1 : 0;
    }
    ...
}
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    ...
    for (;;) {
        uint32_t seq;
        InputEvent* inputEvent;
        int32_t displayId;
//从mInputConsumer读取事件
        status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent, &displayId);
        ...
            //构建InputEvent对象
            jobject inputEventObj;
            switch (inputEvent->getType()) {
            case AINPUT_EVENT_TYPE_KEY:
                if (kDebugDispatchCycle) {
                    ALOGD("channel '%s' ~ Received key event.", getInputChannelName().c_str());
                }
                inputEventObj = android_view_KeyEvent_fromNative(env,
                        static_cast<KeyEvent*>(inputEvent));
                break;

            case AINPUT_EVENT_TYPE_MOTION: {
                if (kDebugDispatchCycle) {
                    ALOGD("channel '%s' ~ Received motion event.", getInputChannelName().c_str());
                }
                MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
                if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
                    *outConsumedBatch = true;
                }
                inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
                break;
            }

            default:
                assert(false); // InputConsumer should prevent this from ever happening
                inputEventObj = NULL;
            }

            if (inputEventObj) {
                if (kDebugDispatchCycle) {
                    ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName().c_str());
                }
//通过JNI 回调Java层的dispatchInputEvent方法
                env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj,
                        displayId);
                ...
}

frameworks/base/core/java/android/view/InputEventReceiver.java

// Called from native code.
    @SuppressWarnings("unused")
    @UnsupportedAppUsage
    private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event, displayId);
    }

因为WindowInputEventReceiver重写了onInputEvent方法
frameworks/base/core/java/android/view/ViewRootImpl.java

@Override
        public void onInputEvent(InputEvent event, int displayId) {
            //注意这个flag = 0
            enqueueInputEvent(event, this, 0, true);
        }
 @UnsupportedAppUsage
    void enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately) {
        adjustInputEventForCompatibility(event);
        //把InputEvent简单封装成QueuedInputEvent
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);

      
            doProcessInputEvents();
        ...
    }
void doProcessInputEvents() {
        ...
           deliverInputEvent(q);
        ...
    }


private void deliverInputEvent(QueuedInputEvent q) {
       //根据q的标识位,得到stage,这些stage其实是在ViewRootImpl的setView方法中创建的。这里各种stage,太绕了,知道最后结果就行。在stage饶一大圈,之后会在ViewPostImeInputStage的onProcess出来。开始分发事件
        ...
            stage.deliver(q);
        ...
    }

ViewPostImeInputStage的onProcess方法,对于Motion事件,会走processPointerEvent
frameworks/base/core/java/android/view/ViewRootImpl.java

 @Override
        protected int onProcess(QueuedInputEvent q) {
            if (q.mEvent instanceof KeyEvent) {
                return processKeyEvent(q);
            } else {
                final int source = q.mEvent.getSource();
                if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                    return processPointerEvent(q);
                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                    return processTrackballEvent(q);
                } else {
                    return processGenericMotionEvent(q);
                }
            }
        }

private int processPointerEvent(QueuedInputEvent q) {
            final MotionEvent event = (MotionEvent)q.mEvent;

            ...
            //调用mView的dispatchPointerEvent,mView实际就是DecorView
            boolean handled = mView.dispatchPointerEvent(event);
            ..
        }

frameworks/base/core/java/android/view/View.java
这个View是DecorView

@UnsupportedAppUsage
    public final boolean dispatchPointerEvent(MotionEvent event) {
        if (event.isTouchEvent()) {
            return dispatchTouchEvent(event);
        } else {
            return dispatchGenericMotionEvent(event);
        }
    }

frameworks/base/core/java/com/android/internal/policy/DecorView.java

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        final Window.Callback cb = mWindow.getCallback();
        // 这个Callback实际是Activity对象,这样就实现了事件分发到Activity
        return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
                ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
    }

frameworks/base/core/java/android/app/Activity.java

public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        //调用PhoneWindow的superDispatchTouchEvent
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java

@Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }

frameworks/base/core/java/com/android/internal/policy/DecorView.java

public boolean superDispatchTouchEvent(MotionEvent event) {
        //到这一步,实际走的就是ViewGroup事件发分发逻辑了
        return super.dispatchTouchEvent(event);
    }

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值