天天看点

【Touch事件传递-- 粗略索引记录笔记- 从Native到Java IMS到View Looper 监听UnixDomainSocket】目的

目的

  • 粗略的索引,便于我的记忆
  • 可能不适合你观看

线程、进程

IMS,WMS都是在SystemService进程内的不同线程

结构

  • IMS两个Thread
    • InputReaderThread 轮训设备 dev/input
    • InputDispatcherThread 分发
      • 通过 InputMoniter和WMS连接
      • 通过InputChannel 和APP连接
        • 通过UnixDomainSocket 连接APP
        • Looper的epoll监听了这个fd的变化
  • App的Looper传递给ViewRootImpl
    • Looper回调 InputEventReceiver
    • InputEventReceiver 传递给ViewRootImpl
  • ViewRootImpl 传递给 Activity
  • Activity传递给PhoneWindow
  • PhoneWIndow传递给DecorView
  • DecorView作为ViewGroup
  • ViewGroup传递给View

IPC

InputChannel通过UnixDomainSocket 连接APP

  • InputChannel 为ViewRootImpl的字段
  • setView时IPC给WMS
  • WMS将InputChannel 传递给 IMS的dispatcher

InputChannel将fd绑定到Looper的代码

// ViewRootImpl
                    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());

//WindowInputEventReceiver                    
final class WindowInputEventReceiver extends InputEventReceiver 

//InputEventReceiver 
    private InputChannel mInputChannel;
    private MessageQueue mMessageQueue;
    public InputEventReceiver(InputChannel inputChannel, Looper looper) {
//***
        mInputChannel = inputChannel;
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);

//android_view_InputEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject inputChannelObj, jobject messageQueueObj) {
    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
    if (inputChannel == nullptr) {
        jniThrowRuntimeException(env, "InputChannel is not initialized.");
        return 0;
    }
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
            receiverWeak, inputChannel, messageQueue);
// NativeInputEventReceiver
class NativeInputEventReceiver : public LooperCallback {

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

mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);

Looper epoll 监听的fd

  • 额外监听的IMS用的InputChannle(IPC用的unix domain socket)
  • MessageQueue enqueue导致pipe的fd变化
  • 屏幕刷新的那个