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线程分发事件-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_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.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的主要内容,如果未能解决你的问题,请参考以下文章
Android R input 之 InputChannel之发送事件处理反馈
Android R input 之 InputChannel之发送事件处理反馈
Android R input 之 InputChannel之发送事件处理反馈
由浅入深学习android input系统 - InputChannel解析