IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android R input (四) 之 InputChannel之发送事件处理反馈 -> 正文阅读

[移动开发]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);
    }
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-25 12:38:54  更:2021-10-25 12:39:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:02:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码