Android IMS原理解析之processEvent

       接着上篇文章Android IMS原理解析之InputChannel,上篇文章讲到,当有事件到来时,触发NativeInputEventReceiver的回调接下来会调用到Java层InputEventReceiver的方法,看一下Java层的事件处理:

Input事件处理

       前面分析到事件已经发送到对应的窗口了,接下来就是事件的处理流程,从onInputEvent()来开始分析:

final class WindowInputEventReceiver extends InputEventReceiver {
    @Override
    public void onInputEvent(InputEvent event, int displayId) {
        enqueueInputEvent(event, this, 0, true);
    }
}

       在onInputEvent()内部会执行enqueueInputEvent(),传入了this及InputEvent等参数,接下来看一下enqueueInputEvent():

void enqueueInputEvent(InputEvent event,InputEventReceiver receiver, int flags, boolean processImmediately) {
        adjustInputEventForCompatibility(event);
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
        QueuedInputEvent last = mPendingInputEventTail;
        if (last == null) {
            mPendingInputEventHead = q;
            mPendingInputEventTail = q;
        } else {
            last.mNext = q;
            mPendingInputEventTail = q;
        }
        mPendingInputEventCount += 1;
        if (processImmediately) {
            doProcessInputEvents();
        } else {
            scheduleProcessInputEvents();
        }
}

       该方法内部执行执行三项工作:
       1.通过obtainQueuedInputEvent()来获取QueuedInputEvent实例,对InputEvent进行封装,类似Message处理;
       2.对mPendingInputEventTail及mPendingInputEventTail进相关的处理,接下来事件处理会用到;
       3.由于processImmediately为true,因此执行doProcessInputEvents()进行逻辑处理;
       接下来对以上三项工作进行一一分析:

private QueuedInputEvent obtainQueuedInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags) {
        QueuedInputEvent q = mQueuedInputEventPool;
        if (q != null) {
            mQueuedInputEventPoolSize -= 1;
            mQueuedInputEventPool = q.mNext;
            q.mNext = null;
        } else {
            q = new QueuedInputEvent();
        }

        q.mEvent = event;
        q.mReceiver = receiver;
        q.mFlags = flags;
        return q;
}

       从obtainQueuedInputEvent()可以看到,执行逻辑跟obtainMessage逻辑是一致的,先从pool里面取,如果没有的话就重新创建,然后进行赋值,对比messgae的处理逻辑,也有对应的recycle方法:

private void recycleQueuedInputEvent(QueuedInputEvent q) {
        q.mEvent = null;
        q.mReceiver = null;

        if (mQueuedInputEventPoolSize < MAX_QUEUED_INPUT_EVENT_POOL_SIZE) {
            mQueuedInputEventPoolSize += 1;
            q.mNext = mQueuedInputEventPool;
            mQueuedInputEventPool = q;
        }
    }

       mQueuedInputEventPool赋值是在recycleQueuedInputEvent()内部,pool Size最大为10,超过后就不处理了。
       第二项工作是赋值操作,是为第三项工作做准备的,直接看第三项工作doProcessInputEvents():

void doProcessInputEvents() {
        // Deliver all pending input events in the queue.
        while (mPendingInputEventHead != null) {
            QueuedInputEvent q = mPendingInputEventHead;
            mPendingInputEventHead = q.mNext;
            if (mPendingInputEventHead == null) {
                mPendingInputEventTail = null;
            }
            q.mNext = null;

            mPendingInputEventCount -= 1;
            ......
            deliverInputEvent(q);
        }

        .....
    }

       在doProcessInputEvents()内部最终执行了deliverInputEvent(q):

private void deliverInputEvent(QueuedInputEvent q) {
       .....
        InputStage stage;
        if (q.shouldSendToSynthesizer()) {
            stage = mSyntheticInputStage;
        } else {
            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
        }

        if (stage != null) {
            stage.deliver(q);
        } else {
            finishInputEvent(q);
        }
    }

       在deliverInputEvent()内部会执行InputStage的deliver()方法,stage是在setView()中进行赋值的,此处对应的是ViewPostImeInputStage,一起看一下:

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 {
            apply(q, onProcess(q));
        }
    }

    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);
            }
        }
    .....
}

final class ViewPostImeInputStage extends InputStage {
    ......
    @Override
    protected int onProcess(QueuedInputEvent q) {
        if (q.mEvent instanceof KeyEvent) {
            return processKeyEvent(q);
        } else {
            final int source = q.mEvent.getSource();
            if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                return processPointerEvent(q);
            } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                return processTrackballEvent(q);
            } else {
                return processGenericMotionEvent(q);
            }
        }
    }
    ...... 
}

       可以看到,在执行deliver()时会执行apply(),然后执行onProcess(),在onProcess()内部来选择执行processKeyEvent()或processPointerEvent()[在其内部将Event传递到对应的目标控件,后面进行分析]来对事件进行处理,在处理完后针对不同的返回result来调用finish()-->forward()-->onDeliverToNext()[mNext不null,继续deliver;为null]-->finishInputEvent()来发送事件结束信息到InputDispatcher进行接下来的处理工作,看一下finishInputEvent()方法实现:

private void finishInputEvent(QueuedInputEvent q) {

    if (q.mReceiver != null) {
        boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
        q.mReceiver.finishInputEvent(q.mEvent, handled);
    } else {
        q.mEvent.recycleIfNeededAfterDispatch();
    }

    recycleQueuedInputEvent(q);
}

       q.mReceiver是在obtainQueuedInputEvent()时传入的是InputEventReceiver对象,因此调用的是InputEventReceiver的finishInputEvent(),然后执行recycleQueuedInputEvent(q)来回收QueuedInputEvent ,前面已经分析过,逻辑跟Message处理是一致的,此处用的是享元模式;接下来看一下InputEventReceiver的finishInputEvent()方法:

public final void finishInputEvent(InputEvent event, boolean handled) {
    ......
    int index = mSeqMap.indexOfKey(event.getSequenceNumber());
    int seq = mSeqMap.valueAt(index);
    mSeqMap.removeAt(index);
    nativeFinishInputEvent(mReceiverPtr, seq, handled);
}

       从mSeqMap里面取出对应的seq,然后执行nativeFinishInputEvent(),mReceiverPtr是在nativeInit时返回的NativeInputEventReceiver对象引用,一起去native层去看一下nativeFinishInputEvent()的具体实现:

static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
        jint seq, jboolean handled) {
    sp receiver =
            reinterpret_cast(receiverPtr);
    status_t status = receiver->finishInputEvent(seq, handled);
}

       调用的是NativeInputEventReceiver的finishInputEvent():

status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
     ......
    return status;
}

       接着通过InputConsumer的sendFinishedSignal()来进行发送:

status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
   ......
   return sendUnchainedFinishedSignal(seq, handled);
   ......
}            

       最终是通过mChannel来进行发送;

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;
    return mChannel->sendMessage(&msg);
}

       前面讲到在addView()时执行registerInputChannel()时会在InputDispatcher里面通过mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this)注册了对InputChannel fd的监听,当有可读消息时,会回调handleReceiveCallback()方法:

int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
    InputDispatcher* d = static_cast(data);

    { // acquire lock
        AutoMutex _l(d->mLock);
        ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
        bool notify;
        //根据可读的InputChannel的描述符获取对应的Connection对象
        sp connection = d->mConnectionsByFd.valueAt(connectionIndex);

            nsecs_t currentTime = now();
            bool gotOne = false;
            status_t status;
            for (;;) {
                uint32_t seq;
                bool handled;
                //在循环中不断地读取尽可能多的反馈信息
                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
                if (status) {
                    break;
                }
                //调用finishDispatchCycleLocked()函数完成对反馈的处理
                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
                gotOne = true;
            }
            if (gotOne) {
                d->runCommandsLockedInterruptible();
                if (status == WOULD_BLOCK) {
                    return 1;
                }
            }
        }

        // Unregister the channel.
        d->unregisterInputChannelLocked(connection->inputChannel, notify);
        return 0; // remove the callback
    } // release lock
}

       finishDispatchCycleLocked()函数只是将向InputDispatcher发送一个命令。最终处理反馈的函数是doDispatchCycleFinishedLockedInterruptible(),本文就不详细介绍了,到此一个事件就算闭环了。
       用一张图来总结一下处理及反馈过程:

事件处理及反馈.png

       本文只从整体上分析了事件的处理及反馈过程,对processKeyEvent()及processPointerEvent()的详细介绍请参考下一篇文章Android IMS原理解析之dispatchEvent

你可能感兴趣的:(Android IMS原理解析之processEvent)