本文主要是介绍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线程分发事件-Android12 ,
InputPublisher::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_MESSAGESALOGD("channel '%s' ~ error sending message of type %d, %s", mName.c_str(),msg->header.type, strerror(error));
#endifif (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_MESSAGESALOGD("channel '%s' ~ error sending message type %d, send was incomplete",mName.c_str(), msg->header.type);
#endifreturn DEAD_OBJECT;}#if DEBUG_CHANNEL_MESSAGESALOGD("channel '%s' ~ sent message of type %d", mName.c_str(), msg->header.type);
#endifreturn OK;
}
2.2 WindowInputEventReceiver接收input消息
- WindowInputEventReceiver中LooperCallback回调
handleEvent()
在android_view_InputEventReceiver.cpp中,最终调用到WindowInputEventReceiver.onInputEvent
:NativeInputEventReceiver::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 责任链
- 通过
enqueueInputEvent -> doProcessInputEvents -> deliverInputEvent -> stage.deliver(q)
调用执行InputStage 责任链
- 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!