开局叠甲,可能理解有误,请大佬们斧正。
- Android Framework-Input-1 基础梳理
- Android Framework-Input-2 构建和启动
- Android Framework-Input-3 数据处理
- Android Framework-Input-4 IQ到OQ
- Android Framework-Input-5 分发事件
- Android Framework-Input-6 事件分发到View
- Android Framework-Input-7 事件的移除
- Android Framework-Input-8 ANR相关
//省略
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.empty()) { //开始派发数据
startDispatchCycleLocked(currentTime, connection); }
开始真正的分析一下startDispatchCycleLocked的内容
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
//这里会不断循环 直到队列里有了消息 DispatchEntry 里面有参数seq 在移除消息的时候会用到
while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
const std::chrono::nanoseconds timeout =
getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
dispatchEntry->timeoutTime = currentTime + timeout.count();
// Publish the event.
status_t status;
//转换为 EventEntry
const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
switch (eventEntry.type) {
//省略
case EventEntry::Type::MOTION: {
//又转换为 MotionEntry
const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
PointerCoords scaledCoords[MAX_POINTERS];
const PointerCoords* usingCoords = motionEntry.pointerCoords;
if ((motionEntry.source & AINPUT_SOURCE_CLASS_POINTER) &&
!(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
float globalScaleFactor = dispatchEntry->globalScaleFactor;
if (globalScaleFactor != 1.0f) {
for (uint32_t i = 0; i < motionEntry.pointerCount; i++) {
scaledCoords[i] = motionEntry.pointerCoords[i];
scaledCoords[i].scale(globalScaleFactor, 1 /* windowXScale */,
1 /* windowYScale */);
}
usingCoords = scaledCoords;
}
} else {
if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
for (uint32_t i = 0; i < motionEntry.pointerCount; i++) {
scaledCoords[i].clear();
}
usingCoords = scaledCoords;
}
}
std::array<uint8_t, 32> hmac = getSignature(motionEntry, *dispatchEntry);
// 发布
status = connection->inputPublisher
.publishMotionEvent(dispatchEntry->seq,
dispatchEntry->resolvedEventId,
motionEntry.deviceId, motionEntry.source,
motionEntry.displayId, std::move(hmac),
dispatchEntry->resolvedAction,
motionEntry.actionButton,
dispatchEntry->resolvedFlags,
motionEntry.edgeFlags, motionEntry.metaState,
motionEntry.buttonState,
motionEntry.classification,
dispatchEntry->transform,
motionEntry.xPrecision, motionEntry.yPrecision,
motionEntry.xCursorPosition,
motionEntry.yCursorPosition,
dispatchEntry->displaySize.x,
dispatchEntry->displaySize.y,
motionEntry.downTime, motionEntry.eventTime,
motionEntry.pointerCount,
motionEntry.pointerProperties, usingCoords);
break;
}
//省略
}
//省略
//传输完毕后
//oq 队列删除该消息
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
traceOutboundQueueLength(*connection);
//加入到wq 我们此刻还不知道应用端处理没处理 需要等他处理完告知后我们才能删除该消息
connection->waitQueue.push_back(dispatchEntry);
//如果如果成功就添加到ANR 监听里面后面判断ANR 会用到
if (connection->responsive) {
mAnrTracker.insert(dispatchEntry->timeoutTime,
connection->inputChannel->getConnectionToken());
}
traceWaitQueueLength(*connection);
}
}
publishMotionEvent
status_t InputPublisher::publishMotionEvent(
uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
int32_t edgeFlags, int32_t metaState, int32_t buttonState,
MotionClassification classification, const ui::Transform& transform, float xPrecision,
float yPrecision, float xCursorPosition, float yCursorPosition, int32_t displayWidth,
int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
//省略
InputMessage msg;
msg.header.type = InputMessage::Type::MOTION;
msg.header.seq = seq;
msg.body.motion.eventId = eventId;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.displayId = displayId;
msg.body.motion.hmac = std::move(hmac);
msg.body.motion.action = action;
msg.body.motion.actionButton = actionButton;
msg.body.motion.flags = flags;
msg.body.motion.edgeFlags = edgeFlags;
msg.body.motion.metaState = metaState;
msg.body.motion.buttonState = buttonState;
msg.body.motion.classification = classification;
msg.body.motion.dsdx = transform.dsdx();
msg.body.motion.dtdx = transform.dtdx();
msg.body.motion.dtdy = transform.dtdy();
msg.body.motion.dsdy = transform.dsdy();
msg.body.motion.tx = transform.tx();
msg.body.motion.ty = transform.ty();
msg.body.motion.xPrecision = xPrecision;
msg.body.motion.yPrecision = yPrecision;
msg.body.motion.xCursorPosition = xCursorPosition;
msg.body.motion.yCursorPosition = yCursorPosition;
msg.body.motion.displayWidth = displayWidth;
msg.body.motion.displayHeight = displayHeight;
msg.body.motion.downTime = downTime;
msg.body.motion.eventTime = eventTime;
msg.body.motion.pointerCount = pointerCount;
for (uint32_t i = 0; i < pointerCount; i++) {
//循环复制 将消息 拷贝到 body.motion.pointers里
msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
}
return mChannel->sendMessage(&msg);
}
sendMessage
//native/libs/gui/DisplayEventDispatcher.cpp
int DisplayEventDispatcher::getFd() const {
return mReceiver.getFd();
}
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
//socket pair 你这边发 那边就收到了
nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
//省略
return OK;
}
//native/libs/input/InputTransport.cpp
//socketpair的相关 socket 适合数据量大的情况 触摸的数据是很大的 一秒可能几十上百个触点
/** getFd()的由来
应用端是怎么接收到消息的?这里涉及到ViewRootImp里面的 InputEventReceiver,
在调用 setView 的时候
if (inputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
}
WindowInputEventReceiver 继承InputEventReceiver
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
在调用 nativeInit(),调用JNI方法 进入了 android_view_InputEventReceiver,然后调用
NativeInputEventReceiver::initialize(),构建了FD,当有消息回调的时候,就会调用到 consumeEvents。
//base/core/jni/android_view_InputEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
//省略
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);
status_t status = receiver->initialize();
//省略
receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
//base/core/jni/android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
if (consumeBatches) {
mBatchedInputEventPending = false;
}
if (outConsumedBatch) {
*outConsumedBatch = false;
}
ScopedLocalRef<jobject> receiverObj(env, nullptr);
bool skipCallbacks = false;
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
//从 mChannel->receiveMessage 然后构建 MotionEvent 并填充 这里就相当于把那边write的信息拿到了
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
if (status != OK && status != WOULD_BLOCK) {
return status;
}
if (status == WOULD_BLOCK) {
if (!skipCallbacks && !mBatchedInputEventPending && mInputConsumer.hasPendingBatch()) {
// There is a pending batch. Come back later.
if (!receiverObj.get()) {
receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
if (!receiverObj.get()) {
return DEAD_OBJECT;
}
}
mBatchedInputEventPending = true;
//回调 InputEventReceiver. onBatchedInputEventPending 回调来源 sorce
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.onBatchedInputEventPending,
mInputConsumer.getPendingBatchSource());
if (env->ExceptionCheck()) {
mBatchedInputEventPending = false; // try again later
}
}
return OK;
}
assert(inputEvent);
if (!skipCallbacks) {
if (!receiverObj.get()) {
receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
if (!receiverObj.get()) {
return DEAD_OBJECT;
}
}
jobject inputEventObj;
switch (inputEvent->getType()) {
//省略
case AINPUT_EVENT_TYPE_MOTION: {
//走这里
MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
*outConsumedBatch = true;
}
//copy消息 赋值过去 android_view_MotionEvent. obtainAsCopy 构建 MotionEvent
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
break;
}
//省略
if (inputEventObj) {
//回调java层 回调 WindowInputEventReceiver. dispatchInputEvent ,经过几道手以后会加入队列 然后调用 doProcessInputEvents , 然后调用 deliverInputEvent 这里会调用消息的清除
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
if (env->ExceptionCheck()) {
skipCallbacks = true;
}
env->DeleteLocalRef(inputEventObj);
} else {
skipCallbacks = true;
}
}
if (skipCallbacks) {
mInputConsumer.sendFinishedSignal(seq, false);
}
}
}
//JNI注册的方法
int register_android_view_InputEventReceiver(JNIEnv* env) {
int res = RegisterMethodsOrDie(env, "android/view/InputEventReceiver",
gMethods, NELEM(gMethods));
jclass clazz = FindClassOrDie(env, "android/view/InputEventReceiver");
gInputEventReceiverClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
gInputEventReceiverClassInfo.dispatchInputEvent = GetMethodIDOrDie(env,
gInputEventReceiverClassInfo.clazz,
"dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
gInputEventReceiverClassInfo.onFocusEvent =
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onFocusEvent", "(ZZ)V");
gInputEventReceiverClassInfo.onPointerCaptureEvent =
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onPointerCaptureEvent",
"(Z)V");
gInputEventReceiverClassInfo.onDragEvent =
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onDragEvent", "(ZFF)V");
gInputEventReceiverClassInfo.onBatchedInputEventPending =
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onBatchedInputEventPending",
"(I)V");
return res;
}
然后JNI调用,回到Java层的
为什么会回调到这里 WindowInputEventReceiver的dispatchInputEvent(),到此,就回到了java层,
接下来就是Java层的事件分发和消费。
这里我们总结下:
将我们要分发的事件,开始分发,完毕后会从OQ删除,进入WQ,因为我们在ViewRootImp构建的时候,构建了对应的监听,将通过JNI方式回调回来,开始了Java层的分发。这里其实不要背方法名字,记不住的。
下面是我之前串流程的笔记。
WindowInputEventReceiver 在ViewRootImp里构建 基类 InputEventReceiver 会调用
nativeInit()
然后调用 android_view_InputEventReceiver 的 nativeInit
构建 InputChanel 和 NativeInputEventReceiver 然后调用 initialize
调用setFdEvents 就注册进去了监听
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
NativeInputEventReceiver 实现了 LooperCallback
LooperCallback 是在Looper.h 里面 那么就当被触发的时候会 调用 handleEvent 然后该方法里 调用了 consumeEvents 回调回了 java层
怎么串联的 connection 里面的channel 通过fd 收发消息 receiveMessage 互相对应 sendMessage
就是event 触发以后 才去通过fd 拿数据也就是将发过来的msg 取出来封装
为什么sendMsg 会触发 Looper的 handleEvent 就是因为 addfd
就是监听 你这个fd 发消息就会触发
mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
**/
//native/libs/gui/DisplayEventDispatcher.cpp
status_t DisplayEventDispatcher::initialize() {
status_t result = mReceiver.initCheck();
if (mLooper != nullptr) {
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
}
return OK;
}
class LooperCallback : public virtual RefBase {
protected:
virtual ~LooperCallback();
public:
virtual int handleEvent(int fd, int events, void* data) = 0;
};