Android R input 之 InputChannel之发送事件处理反馈
Posted pecuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android R input 之 InputChannel之发送事件处理反馈相关的知识,希望对你有一定的参考价值。
文章托管在gitee上 Android Notes , 同步csdn
Client处理完input事件后, 会向ims发送finish反馈信号,即向对端的server InputChannel发送反馈, server 端InputChannel被InputDispatcher所管理 .这个操作通常在InputEventReceiver的finishInputEvent方法.
InputEventReceiver#finishInputEvent
/// @frameworks/base/core/java/android/view/InputEventReceiver.java
/**
* Finishes an input event and indicates whether it was handled.
* Must be called on the same Looper thread to which the receiver is attached.
*
* @param event The input event that was finished.
* @param handled True if the event was handled.
*/
public final void finishInputEvent(InputEvent event, boolean handled)
if (event == null)
throw new IllegalArgumentException("event must not be null");
// mReceiverPtr是native的NativeInputEventReceiver地址
if (mReceiverPtr == 0)
Log.w(TAG, "Attempted to finish an input event but the input event "
+ "receiver has already been disposed.");
else
int index = mSeqMap.indexOfKey(event.getSequenceNumber());
if (index < 0)
Log.w(TAG, "Attempted to finish an input event that is not in progress.");
else
int seq = mSeqMap.valueAt(index);
mSeqMap.removeAt(index);
// 调用 native 方法
nativeFinishInputEvent(mReceiverPtr, seq, handled);
event.recycleIfNeededAfterDispatch();
InputEventReceiver JNI函数注册表
/// @frameworks/base/core/jni/android_view_InputEventReceiver.cpp
static const JNINativeMethod gMethods[] =
/* name, signature, funcPtr */
"nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
(void*)nativeInit ,
"nativeDispose", "(J)V",
(void*)nativeDispose ,
"nativeFinishInputEvent", "(JIZ)V",
(void*)nativeFinishInputEvent ,
"nativeConsumeBatchedInputEvents", "(JJ)Z",
(void*)nativeConsumeBatchedInputEvents ,
;
从上可知 nativeFinishInputEvent方法对应的jni函数是android_view_InputEventReceiver.cpp中的nativeFinishInputEvent函数
static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
jint seq, jboolean handled)
sp<NativeInputEventReceiver> receiver =
reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
// 调用NativeInputEventReceiver的finishInputEvent
status_t status = receiver->finishInputEvent(seq, handled);
if (status && status != DEAD_OBJECT)
String8 message;
message.appendFormat("Failed to finish input event. status=%d", status);
jniThrowRuntimeException(env, message.string());
NativeInputEventReceiver::finishInputEvent
status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled)
if (kDebugDispatchCycle)
ALOGD("channel '%s' ~ Finished input event.", getInputChannelName().c_str());
// 通过mInputConsumer发送finish信号
status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
if (status)
if (status == WOULD_BLOCK) // 此时处于阻塞状态,添加到mFinishQueue
if (kDebugDispatchCycle)
ALOGD("channel '%s' ~ Could not send finished signal immediately. "
"Enqueued for later.", getInputChannelName().c_str());
Finish finish;
finish.seq = seq;
finish.handled = handled;
mFinishQueue.add(finish);
// 从0 -> 1 时设置ALOOPER_EVENT_OUTPUT=1事件监听, 当fd可写时收到相关事件,回调NativeInputEventReceiver::handleEvent,
// 然后遍历mFinishQueue中的元素,取出继续发送pending的事件反馈, 所有发送完成后清除队列,并移除ALOOPER_EVENT_OUTPUT监听
if (mFinishQueue.size() == 1)
setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
return OK;
ALOGW("Failed to send finished signal on channel '%s'. status=%d",
getInputChannelName().c_str(), status);
return status;
InputConsumer::sendFinishedSignal
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled)
if (DEBUG_TRANSPORT_ACTIONS)
ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",
mChannel->getName().c_str(), seq, toString(handled));
if (!seq) // seq不能是0
ALOGE("Attempted to send a finished signal with sequence number 0.");
return BAD_VALUE;
// 先处理 batch sequence chain
// Send finished signals for the batch sequence chain first.
size_t seqChainCount = mSeqChains.size();
if (seqChainCount)
uint32_t currentSeq = seq;
uint32_t chainSeqs[seqChainCount];
size_t chainIndex = 0;
for (size_t i = seqChainCount; i > 0; )
i--;
const SeqChain& seqChain = mSeqChains.itemAt(i);
if (seqChain.seq == currentSeq)
currentSeq = seqChain.chain;
chainSeqs[chainIndex++] = currentSeq;
mSeqChains.removeAt(i);
status_t status = OK;
while (!status && chainIndex > 0)
chainIndex--;
status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
if (status)
// An error occurred so at least one signal was not sent, reconstruct the chain.
for (;;)
SeqChain seqChain;
seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
seqChain.chain = chainSeqs[chainIndex];
mSeqChains.push(seqChain);
if (!chainIndex) break;
chainIndex--;
return status;
// Send finished signal for the last message in the batch.
// 发送最后一条
return sendUnchainedFinishedSignal(seq, handled);
InputConsumer::sendUnchainedFinishedSignal
status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled)
InputMessage msg;
msg.header.type = InputMessage::Type::FINISHED;
msg.body.finished.seq = seq;
msg.body.finished.handled = handled ? 1 : 0;
return mChannel->sendMessage(&msg);
InputChannel::sendMessage
status_t InputChannel::sendMessage(const InputMessage* msg)
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do
// 调用send 函数, send a message on a socket
// ssize_t send(int sockfd, const void *buf, size_t len, int flags);
nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) // 发送的长度<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;
接下来看Server端的处理.Server端通常是管理在inputDispatcher. 当收到新消息到来,会触发ims的Looper处理相关fd事件, 之后InputDispatcher::handleReceiveCallback会被回调
InputDispatcher::handleReceiveCallback
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data)
InputDispatcher* d = static_cast<InputDispatcher*>(data);
// acquire lock
std::scoped_lock _l(d->mLock);
// 寻找fd对应的Connection
if (d->mConnectionsByFd.find(fd) == d->mConnectionsByFd.end())
ALOGE("Received spurious receive callback for unknown input channel. "
"fd=%d, events=0x%x",
fd, events);
return 0; // remove the callback
bool notify;
sp<Connection> connection = d->mConnectionsByFd[fd];
if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)))
if (!(events & ALOOPER_EVENT_INPUT)) // 非input事件则返回
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
"events=0x%x",
connection->getInputChannelName().c_str(), events);
return 1;
nsecs_t currentTime = now();
bool gotOne = false;
status_t status;
for (;;)
uint32_t seq;
bool handled;
// 接收client的finish消息
status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
if (status)
break;
// 结束派发反馈的cycle, 将要执行的操作封装成一个CommandEntry,添加到mCommandQueue
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
gotOne = true;
// gotOne为true , 则必然成功收到了client的finish消息, 执行mCommandQueue中的commands
if (gotOne)
d->runCommandsLockedInterruptible();
if (status == WOULD_BLOCK)
return 1;
notify = status != DEAD_OBJECT || !connection->monitor;
if (notify)
ALOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
connection->getInputChannelName().c_str(), status);
else
// Monitor channels are never explicitly unregistered.
// We do it automatically when the remote endpoint is closed so don't warn
// about them.
const bool stillHaveWindowHandle =
d->getWindowHandleLocked(connection->inputChannel->getConnectionToken()) !=
nullptr;
notify = !connection->monitor && stillHaveWindowHandle;
if (notify)
ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. "
"events=0x%x",
connection->getInputChannelName().c_str(), events);
// Unregister the channel.
d->unregisterInputChannelLocked(connection->inputChannel, notify);
return 0; // remove the callback
// release lock
InputPublisher::receiveFinishedSignal
接收来自client的finish 信息
status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled)
if (DEBUG_TRANSPORT_ACTIONS)
ALOGD("channel '%s' publisher ~ receiveFinishedSignal", mChannel->getName().c_str());
InputMessage msg;
// 调用InputChannel的receiveMessage读取msg
status_t result = mChannel->receiveMessage(&msg);
if (result)
*outSeq = 0;
*outHandled = false;
return result;
if (msg.header.type != InputMessage::Type::FINISHED)
ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",
mChannel->getName().c_str(), msg.header.type);
return UNKNOWN_ERROR;
*outSeq = msg.body.finished.seq;
*outHandled = msg.body.finished.handled == 1; // 判断是否handled, 为1则handled
return OK;
InputChannel::receiveMessage
status_t InputChannel::receiveMessage(InputMessage* msg)
ssize_t nRead;
do
// 读取到msg
nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT);
while (nRead == -1 && errno == EINTR);
if (nRead < 0)
int error = errno;
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.c_str(), errno);
#endif
if (error == EAGAIN || error == EWOULDBLOCK)
return WOULD_BLOCK;
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED)
return DEAD_OBJECT;
return -error;
if (nRead == 0) // check for EOF
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.c_str());
#endif
return DEAD_OBJECT;
if (!msg->isValid(nRead))
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ received invalid message", mName.c_str());
#endif
return BAD_VALUE;
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ received message of type %d", mName.c_str(), msg->header.type);
#endif
return OK;
InputDispatcher::finishDispatchCycleLocked
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, uint32_t seq,
bool handled)
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
connection->getInputChannelName().c_str(), seq, toString(handled));
#endif
if (connection->status == Connection::STATUS_BROKEN ||
connection->status == Connection::STATUS_ZOMBIE)
return;
// Notify other system components and prepare to start the next dispatch cycle.
// 结束当前事件循环, 准备执行下一个派发循环
onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
InputDispatcher::onDispatchCycleFinishedLocked
void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime,
const sp<Connection>& connection, uint32_t seq,
bool handled)
// 创建 CommandEntry, 它的command是类成员 InputDispatcher::doDispatchCycleFinishedLockedInterruptible
std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
&InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
commandEntry->connection = connection;
commandEntry->eventTime = currentTime; // 事件处理结束时间
commandEntry->seq = seq;
commandEntry->handled = handled;
postCommandLocked(std::move(commandEntry));
// 添加到 mCommandQueue
void InputDispatcher::postCommandLocked(std::unique_ptr<CommandEntry> commandEntry)
mCommandQueue.push_back(std::move(commandEntry));
接下来看看CommandEntry的定义:
/// @frameworks/native/services/inputflinger/dispatcher/Entry.h
class InputDispatcher;
// A command entry captures state and behavior for an action to be performed in the
// dispatch loop after the initial processing has taken place. It is essentially
// a kind of continuation used to postpone sensitive policy interactions to a point
// in the dispatch loop where it is safe to release the lock (generally after finishing
// the critical parts of the dispatch cycle).
//
// The special thing about commands is that they can voluntarily release and reacquire
// the dispatcher lock at will. Initially when the command starts running, the
// dispatcher lock is held. However, if the command needs to call into the policy to
// do some work, it can release the lock, do the work, then reacquire the lock again
// before returning.
//
// This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
// never calls into the policy while holding its lock.
//
// Commands are implicitly 'LockedInterruptible'.
struct CommandEntry;
// Command 的定义, 本质上是函数指针. 对于InputDispatcher类成员函数而言,第一个参数即是InputDispatcher自身
typedef std::function<void(InputDispatcher&, CommandEntry*)> Command;
class Connection;
struct CommandEntry
explicit CommandEntry(Command command);
~CommandEntry();
Command command;
// parameters for the command (usage varies by command)
sp<Connection> connection;
nsecs_t eventTime;
KeyEntry* keyEntry;
sp<InputApplicationHandle> inputApplicationHandle;
std::string reason;
int32_t userActivityEventType;
uint32_t seq;
bool handled;
sp<InputChannel> inputChannel;
sp<IBinder> oldToken;
sp<IBinder> newToken;
;
看看对Command注释的翻译:
初始处理完成后,命令条目将捕获要在调度循环中执行的操作的状态和行为。 从本质上讲,这是一种延续,用于将敏感的策略交互延迟到分发循环中能安全释放锁的某个点(通常在完成分发周期的关键部分之后)。
关于命令的特殊之处在于它们可以随意释放并重新获取调度程序锁。 最初,当命令开始运行时,将保持调度程序锁定。 但是,如果命令需要调用策略以执行某些工作,则可以释放该锁,执行该工作,然后在返回之前再次重新获取该锁。
这种机制有点笨拙,但有助于保留不变性:在分发保持其锁定状态时永远不会调用策略。
再次回到 InputDispatcher::handleReceiveCallback , 当执行InputDispatcher#finishDispatchCycleLocked后,会将要执行的操作封装成CommandEntry并添加到CommandQueue. 接下来执行InputDispatcher#runCommandsLockedInterruptible方法执行command
InputDispatcher#runCommandsLockedInterruptible
bool InputDispatcher::runCommandsLockedInterruptible()
if (mCommandQueue.empty())
return false;
do
// 从mCommandQueu取出CommandEntry, 然后执行其Command
std::unique_ptr<CommandEntry> commandEntry = std::move(mCommandQueue.front());
mCommandQueue.pop_front();
Command command = commandEntry->command;
command(*this, commandEntry.get()); // commands are implicitly 'LockedInterruptible'
commandEntry->connection.clear();
while (!mCommandQueue.empty());
return true;
InputDispatcher::doDispatchCycleFinishedLockedInterruptible
对于onDispatchCycleFinishedLocked方法中添加的CommandEntry而言,执行command则会调用InputDispatcher::doDispatchCycleFinishedLockedInterruptible方法
void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry)
sp<Connection> connection = commandEntry->connection;
const nsecs_t finishTime = commandEntry->eventTime;
uint32_t seq = commandEntry->seq;
const bool handled = commandEntry->handled;
// Handle post-event policy actions.
// 获取WaitQueue中seq对于的条目
std::deque<DispatchEntry*>::iterator dispatchEntryIt = connection->findWaitQueueEntry(seq);
if (dispatchEntryIt == connection->waitQueue.end())
return;
DispatchEntry* dispatchEntry = *dispatchEntryIt;
const nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) // 事件处理超时
ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(),
ns2ms(eventDuration), dispatchEntry->eventEntry->getDescription().c_str());
// TODO Write some statistics about how long we spend waiting.
reportDispatchStatistics(std::chrono::nanoseconds(eventDuration), *connection, handled);
// 判断是否需要重新派发此事件
bool restartEvent;
if (dispatchEntry->eventEntry->type == EventEntry::Type::KEY) // key事件
KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
// 处理key事件未处理的情况, 返回true则此事件会重新派发
restartEvent =
afterKeyEventLockedInterruptible(connection, dispatchEntry, keyEntry, handled);
else if (dispatchEntry->eventEntry->type == EventEntry::Type::MOTION) // 触摸事件
MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
restartEvent = afterMotionEventLockedInterruptible(connection, dispatchEntry, motionEntry,
handled);
else
restartEvent = false;
// Dequeue the event and start the next cycle.
// Because the lock might have been released, it is possible that the
// contents of the wait queue to have been drained, so we need to double-check
// a few things.
dispatchEntryIt = connection->findWaitQueueEntry(seq); // 重新获取一次,防止wait queue变化
if (dispatchEntryIt != connection->waitQueue.end())
dispatchEntry = *dispatchEntryIt;
connection->waitQueue.erase(dispatchEntryIt); // 将此entry从waitQueue移除
mAnrTracker.erase(dispatchEntry->timeoutTime, // 将此token从mAnrTracker移除
connection->inputChannel->getConnectionToken());
if (!connection->responsive) // 更新connection的responsive状态
connection->responsive = isConnectionResponsive(*connection);
traceWaitQueueLength(connection);
// 如果需要重新派发, 则将此entry添加到outboundQueue的队列头,待下一次派发
if (restartEvent && connection->status == Connection::STATUS_NORMAL)
connection->outboundQueue.push_front(dispatchEntry);
traceOutboundQueueLength(connection);
else // 否则释放此entry
releaseDispatchEntry(dispatchEntry);
// 执行下一个派发循环
// Start the next dispatch cycle for this connection.
startDispatchCycleLocked(now(), connection);
InputDispatcher::afterKeyEventLockedInterruptible
处理unhandled key
bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
DispatchEntry* dispatchEntry,
KeyEntry* keyEntry, bool handled)
// 若此keyEntry已经有fallback标志,则返回以防事件持续未处理 , 以防反复调用
if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)
if (!handled)
// Report the key as unhandled, since the fallback was not handled.
mReporter->reportUnhandledKey(keyEntry->id);
return false;
// Get the fallback key state.
// Clear it out after dispatching the UP.
int32_t originalKeyCode = keyEntry->keyCode;
int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
if (keyEntry->action == AKEY_EVENT_ACTION_UP) // 若是up事件,则移除FallbackKey
connection->inputState.removeFallbackKey(originalKeyCode);
if (handled || !dispatchEntry->hasForegroundTarget())
// If the application handles the original key for which we previously
// generated a fallback or if the window is not a foreground window,
// then cancel the associated fallback key, if any.
if (fallbackKeyCode != -1) // 如果应用处理了原始key或者window不是前台的,则取消fallback key
// Dispatch the unhandled key to the policy with the cancel flag.
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Asking policy to cancel fallback action. "
"keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
keyEntry->policyFlags);
#endif
KeyEvent event = createKeyEvent(*keyEntry);
event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
mLock.unlock();
mPolicy->dispatchUnhandledKey(connection->inputChannel->getConnectionToken(), &event,
keyEntry->policyFlags, &event);
mLock.lock();
// Cancel the fallback key.
if (fallbackKeyCode != AKEYCODE_UNKNOWN)
CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
"application handled the original non-fallback key "
"or is no longer a foreground target, "
"canceling previously dispatched fallback key");
options.keyCode = fallbackKeyCode;
synthesizeCancelationEventsForConnectionLocked(connection, options);
connection->inputState.removeFallbackKey(originalKeyCode);
else
// 处理非fallback key 未处理的情况
// If the application did not handle a non-fallback key, first check
// that we are in a good state to perform unhandled key event processing
// Then ask the policy what to do with it.
bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN && keyEntry->repeatCount == 0;
if (fallbackKeyCode == -1 && !initialDown) // 还没设置fallbackKeyCode且不是初始down事件
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Skipping unhandled key event processing "
"since this is not an initial down. "
"keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
originalKeyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags);
#endif
return false;
// 通过策略派发未处理key事件
// Dispatch the unhandled key to the policy.
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Asking policy to perform fallback action. "
"keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags);
#endif
KeyEvent event = createKeyEvent(*keyEntry);
mLock.unlock();
bool fallback =
mPolicy->dispatchUnhandledKey(connection->inputChannel->getConnectionToken(),
&event, keyEntry->policyFlags, &event);
mLock.lock();
if (connection->status != Connection::STATUS_NORMAL)
connection->inputState.removeFallbackKey(originalKeyCode);
return false;
// Latch the fallback keycode for this key on an initial down.
// The fallback keycode cannot change at any other point in the lifecycle.
if (initialDown)
if (fallback)
fallbackKeyCode = event.getKeyCode();
else
fallbackKeyCode = AKEYCODE_UNKNOWN;
connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
ALOG_ASSERT(fallbackKeyCode != -1);
// Cancel the fallback key if the policy decides not to send it anymore.
// We will continue to dispatch the key to the policy but we will no
// longer dispatch a fallback key to the application.
if (fallbackKeyCode != AKEYCODE_UNKNOWN &&
(!fallback || fallbackKeyCode != event.getKeyCode())) // 处理keyCode不一致的情况
#if DEBUG_OUTBOUND_EVENT_DETAILS
if (fallback)
ALOGD("Unhandled key event: Policy requested to send key %d"
"as a fallback for %d, but on the DOWN it had requested "
"to send %d instead. Fallback canceled.",
event.getKeyCode(), originalKeyCode, fallbackKeyCode);
else
ALOGD("Unhandled key event: Policy did not request fallback for %d, "
"but on the DOWN it had requested to send %d. "
"Fallback canceled.",
originalKeyCode, fallbackKeyCode);
#endif
CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
"canceling fallback, policy no longer desires it");
options.keyCode = fallbackKeyCode;
synthesizeCancelationEventsForConnectionLocked(connection, options);
fallback = false;
fallbackKeyCode = AKEYCODE_UNKNOWN;
if (keyEntry->action != AKEY_EVENT_ACTION_UP)
connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
if (fallback) /// 初始化fallback keyEntry
// Restart the dispatch cycle using the fallback key.
keyEntry->eventTime = event.getEventTime();
keyEntry->deviceId = event.getDeviceId();
keyEntry->source = event.getSource();
keyEntry->displayId = event.getDisplayId();
keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
keyEntry->keyCode = fallbackKeyCode;
keyEntry->scanCode = event.getScanCode();
keyEntry->metaState = event.getMetaState();
keyEntry->repeatCount = event.getRepeatCount();
keyEntry->downTime = event.getDownTime();
keyEntry->syntheticRepeat = false;
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: Dispatching fallback key. "
"originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
originalKeyCode, fallbackKeyCode, keyEntry->metaState);
#endif
return true; // restart the event
else
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: No fallback key.");
#endif
// Report the key as unhandled, since there is no fallback key.
mReporter->reportUnhandledKey(keyEntry->id);
return false;
InputDispatcher::startDispatchCycleLocked
执行新一轮的派发
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection)
if (ATRACE_ENABLED())
std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
connection->getInputChannelName().c_str());
ATRACE_NAME(message.c_str());
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
#endif
while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty())
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
const nsecs_t timeout =
getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
dispatchEntry->timeoutTime = currentTime + timeout;
// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type)
case EventEntry::Type::KEY: // 派发key事件
const KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
std::array<uint8_t, 32> hmac = getSignature(*keyEntry, *dispatchEntry);
// Publish the key event.
status =
connection->inputPublisher
.publishKeyEvent(dispatchEntry->seq, dispatchEntry->resolvedEventId,
keyEntry->deviceId, keyEntry->source,
keyEntry->displayId, std::move(hmac),
dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags, keyEntry->keyCode,
keyEntry->scanCode, keyEntry->metaState,
keyEntry->repeatCount, keyEntry->downTime,
keyEntry->eventTime);
break;
case EventEntry::Type::MOTION:
...
// Publish the motion event.
status = connection->inputPublisher.publishMotionEvent(...)
break;
case EventEntry::Type::FOCUS:
FocusEntry* focusEntry = static_cast<FocusEntry*>(eventEntry);
status = connection->inputPublisher.publishFocusEvent(...);
break;
case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events",
EventEntry::typeToString(eventEntry->type));
return;
// Check the result.
if (status)
if (status == WOULD_BLOCK)
if (connection->waitQueue.empty())
ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
"This is unexpected because the wait queue is empty, so the pipe "
"should be empty and we shouldn't have any problems writing an "
"event to it, status=%d",
connection->getInputChannelName().c_str(), status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
else
// Pipe is full and we are waiting for the app to finish process some events
// before sending more events to it.
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
"waiting for the application to catch up",
connection->getInputChannelName().c_str());
#endif
else
ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
"status=%d",
connection->getInputChannelName().c_str(), status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
return;
// 将已派发的dispatchEntry从outboundQueue移除
// Re-enqueue the event on the wait queue.
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
traceOutboundQueueLength(connection);
// 添加dispatchEntry到waitQueue, 等待client的finish反馈
connection->waitQueue.push_back(dispatchEntry);
if (connection->responsive) // 设置anr检测
mAnrTracker.insert(dispatchEntry->timeoutTime,
connection->inputChannel->getConnectionToken());
traceWaitQueueLength(connection);
以上是关于Android R input 之 InputChannel之发送事件处理反馈的主要内容,如果未能解决你的问题,请参考以下文章
Android R input 之 InputChannel之发送事件处理反馈
Android R input 之 InputDispatcher 工作流程
Android R input 之 InputDispatcher 工作流程
Android R input 之 InputManagerService 的建立