程序员Android开发Android 技术开发

Android触摸事件的传递(五)--输入系统-InputCha

2018-07-22  本文已影响334人  凯玲之恋

了解更多,移步Android触摸事件传递机制系列详解

1 InputChannel的创建

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    ....
  if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
       //首先是创建了一个InputChannel
       mInputChannel = new InputChannel();
   }
  ....
  //将InputChannel添加到WindowManagerService中创建socketpair(一对socket)用来发送和接受事件
  res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
  ....

//开启了对于InputChannel中输入事件的监听
if (mInputChannel != null) {
   if (mInputQueueCallback != null) {
       mInputQueue = new InputQueue();
       mInputQueueCallback.onInputQueueCreated(mInputQueue);
  }
   mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
}


  ...
}

2 将InputChannel添加到WindowManagerService中创建socketpair(一对socket)用来发送和接受事件

 public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
      ....

      final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
      if  (openInputChannels) {
          win.openInputChannel(outInputChannel);
      }
      ....
}
void openInputChannel(InputChannel outInputChannel) {
    if (mInputChannel != null) {
        throw new IllegalStateException("Window already has an input channel.");
     }
     String name = makeInputChannelName();
     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);
      }
       //`InputChannel`设置到`InputDispatcher`
       mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
status_t InputChannel::openInputChannelPair(const String8& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
        status_t result = -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));

    String8 serverChannelName = name;
    serverChannelName.append(" (server)");
    outServerChannel = new InputChannel(serverChannelName, sockets[0]);

    String8 clientChannelName = name;
    clientChannelName.append(" (client)");
    outClientChannel = new InputChannel(clientChannelName, sockets[1]);
    return OK;
}
status_t InputChannel::sendMessage(const InputMessage* msg) {
    size_t msgLength = msg->size();
    ssize_t nWrite;
    do {
        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);
     .....
    return OK;
}
status_t InputChannel::receiveMessage(InputMessage* msg) {
    ssize_t nRead;
    do {
        nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
    } while (nRead == -1 && errno == EINTR);
    ......
    return OK;
}

3 开启输入事件的监听接受事件

if (mInputChannel != null) {
   if (mInputQueueCallback != null) {
       mInputQueue = new InputQueue();
       mInputQueueCallback.onInputQueueCreated(mInputQueue);
  }
   mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
}

WindowInputEventReceiver的构造函数如下,其继承自InputEventReceiver

final class WindowInputEventReceiver extends InputEventReceiver {
     public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
         super(inputChannel, looper);
     }
      ....
}
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
     ....
     mInputChannel = inputChannel;
     mMessageQueue = looper.getQueue();
     mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);
  }

这里调用了native方法来做初始化,相关的native方法的实现在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);
  sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, 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;
}

initialize()方法中,只调用了一个函数setFdEvents

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);
        }
    }
}
int ALooper_addFd(ALooper* looper, int fd, int ident, int events,
        ALooper_callbackFunc callback, void* data) {
    return ALooper_to_Looper(looper)->addFd(fd, ident, events, callback, data);
}

Looper的addFd的实现如下

int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
    Request request;
    request.fd = fd;
    request.ident = ident;
    request.events = events;
    request.seq = mNextRequestSeq++;
    request.callback = callback;
     request.data = data;
     if (mNextRequestSeq == -1) mNextRequestSeq = 0;
     struct epoll_event eventItem;
     request.initEventItem(&eventItem);
     ssize_t requestIndex = mRequests.indexOfKey(fd);
      if (requestIndex < 0) {
          int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
          if (epollResult < 0) {
                return -1;
            }
         mRequests.add(fd, request);
       } 
}

···

4 处理事件 handleEvent--事件读出来

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
        return 0;  //移除窗口或者IME对话框, 则移除该事件
    }

    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        //【见小节3.3】
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY ? 1 : 0;
    }

    if (events & ALOOPER_EVENT_OUTPUT) {
        for (size_t i = 0; i < mFinishQueue.size(); i++) {
            const Finish& finish = mFinishQueue.itemAt(i);
            //【见小节3.4】
            status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
            if (status) {
                mFinishQueue.removeItemsAt(0, i);

                if (status == WOULD_BLOCK) {
                    return 1; //保留callback,稍后重试
                }

                if (status != DEAD_OBJECT) {
                    JNIEnv* env = AndroidRuntime::getJNIEnv();
                    String8 message;
                    message.appendFormat("Failed to finish input event. status=%d", status);
                    jniThrowRuntimeException(env, message.string());
                    mMessageQueue->raiseAndClearException(env, "finishInputEvent");
                }
                return 0; //移除callback
            }
        }
        mFinishQueue.clear();
        setFdEvents(ALOOPER_EVENT_INPUT);
        return 1;
    }
    return 1;
}
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    ...

    ScopedLocalRef<jobject> receiverObj(env, NULL);
    bool skipCallbacks = false;
    for (;;) {
        uint32_t seq;
        InputEvent* inputEvent;
        //consume 处理(接收事件)
        status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent);
        if (status) {
            if (status == WOULD_BLOCK) {
                ...
                return OK; //消费完成
            }
            return status; //消失失败
        }

        if (!skipCallbacks) {
            if (!receiverObj.get()) {
                receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
                if (!receiverObj.get()) {
                    return DEAD_OBJECT;
                }
            }

            jobject inputEventObj;
            switch (inputEvent->getType()) {
                case AINPUT_EVENT_TYPE_KEY:
                    //由Native的inputEvent来生成Java层的事件
                    inputEventObj = android_view_KeyEvent_fromNative(env,
                            static_cast<KeyEvent*>(inputEvent));
                    break;
                ...
            }

            if (inputEventObj) {
                //执行Java层的InputEventReceiver.dispachInputEvent
                env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
                if (env->ExceptionCheck()) {
                    skipCallbacks = true; //分发过程发生异常
                }
                env->DeleteLocalRef(inputEventObj);
            } else {
                skipCallbacks = true;
            }
        }

        if (skipCallbacks) {
            //发生异常,则直接向InputDispatcher线程发送完成信号。
            mInputConsumer.sendFinishedSignal(seq, false);
        }
    }
}
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {

    *outSeq = 0;
    *outEvent = NULL;

    //循环遍历所有的Event
    while (!*outEvent) {
        if (mMsgDeferred) {
            mMsgDeferred = false; //上一次没有处理的消息
        } else {
            //收到新消息【见小节3.3.2】
            status_t result = mChannel->receiveMessage(&mMsg);
            if (result) {
                if (consumeBatches || result != WOULD_BLOCK) {
                    result = consumeBatch(factory, frameTime, outSeq, outEvent);
                    if (*outEvent) {
                        break;
                    }
                }
                return result;
            }
        }

        switch (mMsg.header.type) {
          case InputMessage::TYPE_KEY: {
              //从mKeyEventPool池中取出KeyEvent
              KeyEvent* keyEvent = factory->createKeyEvent();
              if (!keyEvent) return NO_MEMORY;

              //将msg封装成KeyEvent
              initializeKeyEvent(keyEvent, &mMsg);
              *outSeq = mMsg.body.key.seq;
              *outEvent = keyEvent;
              break;
          }
          ...
        }
    }
    return OK;
}
status_t InputChannel::receiveMessage(InputMessage* msg) {
    ssize_t nRead;
    do {
        //读取InputDispatcher发送过来的消息
        nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
    } while (nRead == -1 && errno == EINTR);

    if (nRead < 0) {
        int error = errno;
        if (error == EAGAIN || error == EWOULDBLOCK) {
            return WOULD_BLOCK;
        }
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
            return DEAD_OBJECT;
        }
        return -error;
    }

    if (nRead == 0) {
        return DEAD_OBJECT;
    }

    if (!msg->isValid(nRead)) {
        return BAD_VALUE;
    }

    return OK;
}

5 传递给ViewRootImpl

InputEventReceiver.dispachInputEvent
[-> InputEventReceiver.java]

private void dispatchInputEvent(int seq, InputEvent event) {
    mSeqMap.put(event.getSequenceNumber(), seq);
    onInputEvent(event);
}

onInputEvent
[-> ViewRootImpl.java ::WindowInputEventReceiver]

final class WindowInputEventReceiver extends InputEventReceiver {
    public void onInputEvent(InputEvent event) {
       enqueueInputEvent(event, this, 0, true);
    }
    ...
}

enqueueInputEvent

void enqueueInputEvent(InputEvent event, InputEventReceiver receiver, int flags, boolean processImmediately) {
    adjustInputEventForCompatibility(event);
    QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);

    QueuedInputEvent last = mPendingInputEventTail;
    if (last == null) {
        mPendingInputEventHead = q;
        mPendingInputEventTail = q;
    } else {
        last.mNext = q;
        mPendingInputEventTail = q;
    }
    mPendingInputEventCount += 1;

    if (processImmediately) {
        doProcessInputEvents(); //doProcessInputEvents
    } else {
        scheduleProcessInputEvents();
    }
}

doProcessInputEvents

[-> ViewRootImpl.java]

void doProcessInputEvents() {
    while (mPendingInputEventHead != null) {
        QueuedInputEvent q = mPendingInputEventHead;
        mPendingInputEventHead = q.mNext;
        if (mPendingInputEventHead == null) {
            mPendingInputEventTail = null;
        }
        q.mNext = null;

        mPendingInputEventCount -= 1;

        long eventTime = q.mEvent.getEventTimeNano();
        long oldestEventTime = eventTime;
        ...
        mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
        //[见小节3.3.7]
        deliverInputEvent(q);
    }

    if (mProcessInputEventsScheduled) {
        mProcessInputEventsScheduled = false;
        mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
    }
}

事件分发deliverInputEvent

[-> ViewRootImpl.java]

private void deliverInputEvent(QueuedInputEvent q) {
     if (mInputEventConsistencyVerifier != null) {
         mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
     }

     InputStage stage;
     if (q.shouldSendToSynthesizer()) {
         stage = mSyntheticInputStage;
     } else {
         stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
     }

     if (stage != null) {
         stage.deliver(q);
     } else {
         finishInputEvent(q); //[见小节3.4]
     }
 }

经过一系列的InputStage调用, 最终会分发到真正需要处理该时间的窗口. 当处理完后会调用finishInputEvent(),

总结

至此对于从硬件设备产生数据,到数据被逐层传递到应用程序中的整个流程就梳理完了。事件相关的创建,传递流程如下所示。


4fc1c74f1eadccf675bb560d15223dca.png
input_summary.jpg

6 前传InputChannel又是如何被设置到InputDispatcher

public void registerInputChannel(InputChannel inputChannel,
            InputWindowHandle inputWindowHandle) {
   if (inputChannel == null) {
      throw new IllegalArgumentException("inputChannel must not be null.");
   }
   nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
static 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);
    if (inputChannel == NULL) {
        throwInputChannelNotInitialized(env);
        return;
    }

    sp<InputWindowHandle> inputWindowHandle =
            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);

    status_t status = im->registerInputChannel(
            env, inputChannel, inputWindowHandle, monitor);
    if (status) {
        String8 message;
        message.appendFormat("Failed to register input channel.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return;
    }

    if (! monitor) {
        android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
                handleInputChannelDisposed, im);
    }
}
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
    { // acquire lock
        AutoMutex _l(mLock);

        if (getConnectionIndexLocked(inputChannel) >= 0) {
            return BAD_VALUE;
        }

        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);

        int fd = inputChannel->getFd();
        mConnectionsByFd.add(fd, connection);

        if (monitor) {
            mMonitoringChannels.push(inputChannel);
        }

        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock

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

参考

Android系统源码剖析-事件分发
Input系统—事件处理全过程

上一篇 下一篇

猜你喜欢

热点阅读