Android Framework-Input-7 事件的移除

339 阅读5分钟

开局叠甲,可能理解有误,请大佬们斧正。

我们在上篇讲到 再 调用 processPointerEvent()后,事件最终分发到了ViewRootImp里的mView。 最后返回了 FINISH_HANDLED

//android/view/ViewRootImpl.java
 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 {
                //我们已经知道这里的返回值是 FINISH_HANDLED
                    result = onProcess(q);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                }
                apply(q, result);
            }
        }
        
           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);
            }
        }
//-->      //这里handled是true
 protected void finish(QueuedInputEvent q, boolean handled) {
                
            q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
            if (handled) {
            //注意flag
                q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
            }
            forward(q);
        }
        
        protected void forward(QueuedInputEvent q) {  
        onDeliverToNext(q);  
            }
            
           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);
            }
        }  
           
           
       private void finishInputEvent(QueuedInputEvent q) {
        Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
                q.mEvent.getId());

        if (q.mReceiver != null) {
            boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
            boolean modified = (q.mFlags & QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY) != 0;
            if (modified) {
                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "processInputEventBeforeFinish");
                InputEvent processedEvent;
                try {
                    processedEvent =
                            mInputCompatProcessor.processInputEventBeforeFinish(q.mEvent);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                }
                if (processedEvent != null) {
                    q.mReceiver.finishInputEvent(processedEvent, handled);
                }
            } else {
                q.mReceiver.finishInputEvent(q.mEvent, handled);
            }
        } else {
            q.mEvent.recycleIfNeededAfterDispatch();
        }

        recycleQueuedInputEvent(q);
    }    

//这里的基本调用逻辑就是  finish(q, true);-->

这里代码比较多,我们简单梳理一下。 apply(QueuedInputEvent q, int result) 该方法,因为返回值的原因,走了 finish(q, true); 所以 q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;。然后调用了 finishInputEvent(QueuedInputEvent q);方法。因为flag的原因 调用到了 q.mReceiver.finishInputEvent(q.mEvent, handled);。还是不要看细节,记住最后调用回到了finishInputEvent()就好。

image.png

finishInputEvent()会调用到 nativeFinishInputEvent(mReceiverPtr, seq, handled); 这里看出传参里面包含一个参数seq,之前说过seq 是很关键的一个参数,主要用来查询消息。

public final void finishInputEvent(InputEvent event, boolean handled) {
        if (event == null) {
           //省略
        }
        if (mReceiverPtr == 0) {
            //省略
        } else {
            int index = mSeqMap.indexOfKey(event.getSequenceNumber());
            if (index < 0) {
                //省略
            } else {
                int seq = mSeqMap.valueAt(index);
                mSeqMap.removeAt(index);
                nativeFinishInputEvent(mReceiverPtr, seq, handled);
            }
        }
        event.recycleIfNeededAfterDispatch();
    }

再次进入 android_view_InputEventReceiver.cpp

static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
        jint seq, jboolean handled) {
    sp<NativeInputEventReceiver> receiver =
            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
    status_t status = receiver->finishInputEvent(seq, handled);
    if (status == OK || status == WOULD_BLOCK) {
        return; // normal operation
    }
    if (status != DEAD_OBJECT) {
        std::string message =
                android::base::StringPrintf("Failed to finish input event.  status=%s(%d)",
                                            statusToString(status).c_str(), status);
        jniThrowRuntimeException(env, message.c_str());
    }
}

调用到 NativeInputEventReceiver的finishInputEvent(seq);

status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
   
//省略
    Finish finish{
            .seq = seq,
            .handled = handled,
    };
    //加入mOutboundQueue
    mOutboundQueue.push_back(finish);
    return processOutboundEvents();
}

看到这里是不是好奇,咋消息又进了 mOutboundQueue 也就是我们说的OQ;按照道理来说这玩意还有啥用? 秘密在 processOutboundEvents()里。

status_t NativeInputEventReceiver::processOutboundEvents() {
    while (!mOutboundQueue.empty()) {
        OutboundEvent& outbound = *mOutboundQueue.begin();
        status_t status;

        if (std::holds_alternative<Finish>(outbound)) {
            const Finish& finish = std::get<Finish>(outbound);
             //发送给消费者
            status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
        } else if (std::holds_alternative<Timeline>(outbound)) {
            const Timeline& timeline = std::get<Timeline>(outbound);
            status = mInputConsumer.sendTimeline(timeline.inputEventId, timeline.timeline);
        } else {
         
            status = BAD_VALUE;
        }
        if (status == OK) {
            //成功就移除
            mOutboundQueue.erase(mOutboundQueue.begin());
            continue;
        }

        // Publisher is busy, try again later. Keep this entry (do not erase)
        if (status == WOULD_BLOCK) {
            if (kDebugDispatchCycle) {
                ALOGD("channel '%s' ~ Remaining outbound events: %zu.",
                      getInputChannelName().c_str(), mOutboundQueue.size());
            }
            setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
            return WOULD_BLOCK; // try again later
        }


      
        return status;
    }

  
    setFdEvents(ALOOPER_EVENT_INPUT);
    return OK;
}

这里我们看了下核心代码就得看的mInputConsumer.sendFinishedSignal(),如果拷贝消息发送成功了就移除,否则就循环等待。我们看下代码的调用逻辑。其实可以理解为事件的删除之旅。

status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
    InputMessage msg;
    msg.header.type = InputMessage::Type::FINISHED;
    msg.header.seq = seq;//序列号很关键 靠他找消息
    msg.body.finished.handled = handled;
    msg.body.finished.consumeTime = getConsumeTime(seq);
    //核心代码
    status_t result = mChannel->sendMessage(&msg);
    if (result == OK) {
​
        popConsumeTime(seq);
    }
    return result;
}

进行了一次转化 ,将seqhandled 转了一次,调用sendMessage(const InputMessage* msg) 注意这里的  msg.header.type = InputMessage::Type::FINISHED;下面会用到。

status_t InputChannel::sendMessage(const InputMessage* msg) {
    const size_t msgLength = msg->size();
    InputMessage cleanMsg;
  // 数据的拷贝转移
    msg->getSanitizedCopy(&cleanMsg);
    ssize_t nWrite;
    do {
      //socketpair 发送 进入inputDisPatcher
        nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);
​
  //省略
​
    return OK;
}

涉及FD再次到达InputDispatcher.cpp,这里为什么回掉handleReceiveCallback是因为 在构造里有注册。

//native/services/inputflinger/dispatcher/InputDispatcher.cpp
 std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token);
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);

这段代码涉及消息的收取转换receiveConsumerResponse()和处理 finishDispatchCycleLocked()

//native/services/inputflinger/dispatcher/InputDispatcher.cpp
int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
    std::scoped_lock _l(mLock);
  
  //找 connection 
    sp<Connection> connection = getConnectionLocked(connectionToken);
    if (connection == nullptr) {
       //找不到 g
        return 0; // remove the callback
    }
​
    bool notify;
    if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
        if (!(events & ALOOPER_EVENT_INPUT)) {
          
            return 1;
        }
​
        nsecs_t currentTime = now();
        bool gotOne = false;
        status_t status = OK;
        for (;;) {
          //先收取消息
            Result<InputPublisher::ConsumerResponse> result =
                    connection->inputPublisher.receiveConsumerResponse();
            if (!result.ok()) {
                status = result.error().code();
                break;
            }
​
            if (std::holds_alternative<InputPublisher::Finished>(*result)) {
                const InputPublisher::Finished& finish =
                        std::get<InputPublisher::Finished>(*result);
               //转化成功 调用这里finishDispatchCycleLocked
                finishDispatchCycleLocked(currentTime, connection, finish.seq, finish.handled,
                                          finish.consumeTime);
            } else if (std::holds_alternative<InputPublisher::Timeline>(*result)) {
                if (shouldReportMetricsForConnection(*connection)) {
                    const InputPublisher::Timeline& timeline =
                            std::get<InputPublisher::Timeline>(*result);
                    mLatencyTracker
                            .trackGraphicsLatency(timeline.inputEventId,
                                                  connection->inputChannel->getConnectionToken(),
                                                  std::move(timeline.graphicsTimeline));
                }
            }
            gotOne = true;
        }
        if (gotOne) {
            runCommandsLockedInterruptible();
            if (status == WOULD_BLOCK) {
                return 1;
            }
        }
​
        notify = status != DEAD_OBJECT || !connection->monitor;
       
    } else {
    
        const bool stillHaveWindowHandle =
                getWindowHandleLocked(connection->inputChannel->getConnectionToken()) != nullptr;
        notify = !connection->monitor && stillHaveWindowHandle;
    
    // Remove the channel.
    removeInputChannelLocked(connection->inputChannel->getConnectionToken(), notify);
    return 0; // remove the callback
}

先看下 receiveConsumerResponse() 消息的收取。我们上面说到typeFINISHED

android::base::Result<InputPublisher::ConsumerResponse> InputPublisher::receiveConsumerResponse() {
    if (DEBUG_TRANSPORT_ACTIONS) {
        ALOGD("channel '%s' publisher ~ %s", mChannel->getName().c_str(), __func__);
    }
​
    InputMessage msg;
    status_t result = mChannel->receiveMessage(&msg);
    if (result) {
        return android::base::Error(result);
    }
  //当前是FINISHED
    if (msg.header.type == InputMessage::Type::FINISHED) {
        return Finished{
                .seq = msg.header.seq,
                .handled = msg.body.finished.handled,
                .consumeTime = msg.body.finished.consumeTime,
        };
    }
​
    if (msg.header.type == InputMessage::Type::TIMELINE) {
        return Timeline{
                .inputEventId = msg.body.timeline.eventId,
                .graphicsTimeline = msg.body.timeline.graphicsTimeline,
        };
    }
​
   
    return android::base::Error(UNKNOWN_ERROR);
}

看下处理finishDispatchCycleLocked()调用onDispatchCycleFinishedLocked()

void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
                                                const sp<Connection>& connection, uint32_t seq,
                                                bool handled, nsecs_t consumeTime) {
​
     //省略
​
    
    onDispatchCycleFinishedLocked(currentTime, connection, seq, handled, consumeTime);
}

onDispatchCycleFinishedLocked()

void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime,
                                                    const sp<Connection>& connection, uint32_t seq,
                                                    bool handled, nsecs_t consumeTime) {
  
 // doDispatchCycleFinishedLockedInterruptible 相当于一个回调
    std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
            &InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
    commandEntry->connection = connection;
    commandEntry->eventTime = currentTime;
    commandEntry->seq = seq;
    commandEntry->handled = handled;
    commandEntry->consumeTime = consumeTime;
  //这里会涉及dispatchOnce 里面的 haveCommandsLocked
    postCommandLocked(std::move(commandEntry));
}

调用 doDispatchCycleFinishedLockedInterruptible(),postCommandLocked() 会涉及到ANR部分我们后面再说。

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;
​
    
  //查找该connection 的等待队列
    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 (shouldReportFinishedEvent(*dispatchEntry, *connection)) {
        mLatencyTracker.trackFinishedEvent(dispatchEntry->eventEntry->id,
                                           connection->inputChannel->getConnectionToken(),
                                           dispatchEntry->deliveryTime, commandEntry->consumeTime,
                                           finishTime);
    }
​
    bool restartEvent;
    if (dispatchEntry->eventEntry->type == EventEntry::Type::KEY) {
       //省略
    } else if (dispatchEntry->eventEntry->type == EventEntry::Type::MOTION) {
      
       //只管MOTION
        MotionEntry& motionEntry = static_cast<MotionEntry&>(*(dispatchEntry->eventEntry));
        restartEvent = afterMotionEventLockedInterruptible(connection, dispatchEntry, motionEntry,handled);
    } else {
        restartEvent = false;
    }
​
  
   //根据序列码找到该事件
    dispatchEntryIt = connection->findWaitQueueEntry(seq);
    if (dispatchEntryIt != connection->waitQueue.end()) {
        dispatchEntry = *dispatchEntryIt;
      //从wq 删除该消息
        connection->waitQueue.erase(dispatchEntryIt);
        const sp<IBinder>& connectionToken = connection->inputChannel->getConnectionToken();
        mAnrTracker.erase(dispatchEntry->timeoutTime, connectionToken);
        if (!connection->responsive) {
            connection->responsive = isConnectionResponsive(*connection);
            if (connection->responsive) {
                processConnectionResponsiveLocked(*connection);
            }
        }
        traceWaitQueueLength(*connection);
        if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
            connection->outboundQueue.push_front(dispatchEntry);
            traceOutboundQueueLength(*connection);
        } else {
            releaseDispatchEntry(dispatchEntry);
        }
    }
​
  
    startDispatchCycleLocked(now(), connection);
}

其实这段代码核心部分可以理解,就是依托于seq,找到对应的消息,从WQ删除。自此整个消息从产生到发送,到销毁,经历IQ->OQ->WQ->OQ删除->WQ删除的过程。我们讲ANR将在下一篇进行探秘。