InputChannel发送Input给App-Android12

Posted xhBruce

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了InputChannel发送Input给App-Android12相关的知识,希望对你有一定的参考价值。

InputChannel发送Input给App-android12

android12-release


1. App的ViewRootImpl建立InputChannel

查看 InputChannel通道建立-Android12 1. APP界面建立InputChannel,下面看图:

  • InputChannel / WindowInputEventReceiver建立联系,并建立服务端Connection
  • InputStage责任链:SyntheticInputStage - ViewPostImeInputStage - NativePostImeInputStage - EarlyPostImeInputStage - ImeInputStage - ViewPreImeInputStage - NativePreImeInputStage

2. InputChannel通过socket发送Input给App

2.1 InputChannel通过socket发送

查看 InputDispatcher线程分发事件-Android12InputPublisher::publishKeyEvent通过mChannel->sendMessage(&msg)发送

  • nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL)目标Fd写入

frameworks/native/libs/input/InputTransport.cpp

status_t InputChannel::sendMessage(const InputMessage* msg) 
    const size_t msgLength = msg->size();
    InputMessage cleanMsg;
    msg->getSanitizedCopy(&cleanMsg);
    ssize_t nWrite;
    do 
        nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
     while (nWrite == -1 && errno == EINTR);

    if (nWrite < 0) 
        int error = errno;
#if DEBUG_CHANNEL_MESSAGES
        ALOGD("channel '%s' ~ error sending message of type %d, %s", mName.c_str(),
              msg->header.type, strerror(error));
#endif
        if (error == EAGAIN || error == EWOULDBLOCK) 
            return WOULD_BLOCK;
        
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) 
            return DEAD_OBJECT;
        
        return -error;
    

    if (size_t(nWrite) != msgLength) 
#if DEBUG_CHANNEL_MESSAGES
        ALOGD("channel '%s' ~ error sending message type %d, send was incomplete",
                mName.c_str(), msg->header.type);
#endif
        return DEAD_OBJECT;
    

#if DEBUG_CHANNEL_MESSAGES
    ALOGD("channel '%s' ~ sent message of type %d", mName.c_str(), msg->header.type);
#endif
    return OK;

2.2 WindowInputEventReceiver接收input消息

  • WindowInputEventReceiver中LooperCallback回调handleEvent()在android_view_InputEventReceiver.cpp中,最终调用到WindowInputEventReceiver.onInputEventNativeInputEventReceiver::handleEvent -- consumeEvents -- gInputEventReceiverClassInfo.dispatchInputEvent -> InputEventReceiver.onInputEvent(event) -> WindowInputEventReceiver.onInputEvent

frameworks/base/core/java/android/view/InputEventReceiver.java
frameworks/base/core/jni/android_view_InputEventReceiver.cpp

2.3 ViewRootImpl中执行InputStage 责任链

  1. 通过enqueueInputEvent -> doProcessInputEvents -> deliverInputEvent -> stage.deliver(q)调用执行InputStage 责任链
  2. InputStage的各子类Input事件result = onProcess(q)处理,再判断是forward()向下传递,还是finish()结束
abstract class InputStage 
    // ... ...
    public final void deliver(QueuedInputEvent q) 
        if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) 
            forward(q);
         else if (shouldDropInputEvent(q)) 
            finish(q, false);
         else 
            traceEvent(q, Trace.TRACE_TAG_VIEW);
            final int result;
            try 
                result = onProcess(q);
             finally 
                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            
            apply(q, result);
        
    

    /**
     * Marks the the input event as finished then forwards it to the next stage.
     */
    protected void finish(QueuedInputEvent q, boolean handled) 
        q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
        if (handled) 
            q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
        
        forward(q);
    

    /**
     * Forwards the event to the next stage.
     */
    protected void forward(QueuedInputEvent q) 
        onDeliverToNext(q);
    

    /**
     * Applies a result code from @link #onProcess to the specified event.
     */
    protected void apply(QueuedInputEvent q, int result) 
        if (result == FORWARD) 
            forward(q);
         else if (result == FINISH_HANDLED) 
            finish(q, true);
         else if (result == FINISH_NOT_HANDLED) 
            finish(q, false);
         else 
            throw new IllegalArgumentException("Invalid result: " + result);
        
    

    /**
     * Called when an event is ready to be processed.
     * @return A result code indicating how the event was handled.
     */
    protected int onProcess(QueuedInputEvent q) 
        return FORWARD;
    

    /**
     * Called when an event is being delivered to the next stage.
     */
    protected void onDeliverToNext(QueuedInputEvent q) 
        if (DEBUG_INPUT_STAGES) 
            Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
        
        if (mNext != null) 
            mNext.deliver(q);
         else 
            finishInputEvent(q);
        
    
    // ... ...

3. 例如ViewPostImeInputStage中processKeyEvent

关注KeyEvent事件分发给APP界面窗口。mView就是App的RootViewImpl.setView设置,涉及PhoneWindow.java、DecorView.java,查看DecorView.dispatchKeyEvent 最终会分发到真正需要处理该时间的窗口。这里handled可以判断应用是否拦截KeyEvent事件,但是需要明白的是不管应用拦不拦截,Input事件都已经发送给应用了。

3.1 Activity设置的回调Window.Callback

cb.dispatchKeyEvent(event) 调用到Activity中,这里app可以重载拦截事件。win.superDispatchKeyEvent(event)通过此方法进入view层级中。其具体实现是在PhoneWindow中。

3.2 finishInputEvent(q)

最终socket通信发送给服务端执行InputDispatcher::handleReceiveCallback,进行 gotOne 下一个事件发送【IMS:InputDispatcher 接收反馈进行下一次发送

以上是关于InputChannel发送Input给App-Android12的主要内容,如果未能解决你的问题,请参考以下文章

Android R input 之 InputChannel之发送事件处理反馈

Android R input 之 InputChannel之发送事件处理反馈

Android R input 之 InputChannel之发送事件处理反馈

由浅入深学习android input系统 - InputChannel解析

InputManagerService实体按键及组合按键-Android12

InputManagerService实体按键及组合按键-Android12