http://my.eoe.cn/10407/archive/1176.html
作者:powq更新于 02月27日访问(578)评论(2)
Android在分发Input event(Key, Motion, Pointer, TrackBall)的流程牵扯到的WindowMangerService, ViewRootImpl和InputDispatcher Thread三位角色. 这三位角色的工作关系会依以下三个阶段来分析.
1. 起源.
2. 指定接受者.
3. 处理输入事件流程.
起源
在之前的输入法研究分析可以知道, 在android一开机的时候会去启动Input Manager service, 此service会再去启动InputReaderThread和InputDispatcherThread, 前者是从driver哪边获取input event放入Queue中在通知InputDispatcherThread去Queue中捞出来放进linux中的共享内存, 之后在通知 ViewRootImpl去作分发的处理. 这一篇着重在于分发的过程. 至于input event在android中的流程机制之前就有作过分析了. 这里就不再重复描述. 就从InputDispatcherThread被启动的流程开始分析.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
threadLoop @InputDispatcher.cpp
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
threadLoop @InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
// do something
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime,
nextWakeupTime);
mLooper->pollOnce(timeoutMillis); 1
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
pollOnce @Looper.cpp
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
for (;;) {
// do something
result = pollInner(timeoutMillis);
}
}
pollInner@ Looper.cpp
int Looper::pollInner(int timeoutMillis) {
//do something
int result = ALOOPER_POLL_WAKE;
mResponses.clear();
mResponseIndex = 0;
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd, eventItems,
EPOLL_MAX_EVENTS, timeoutMillis); 1
//处理所监听到的相关事件
//do something
sp<MessageHandler> handler = messageEnvelope.handler;
Message message = messageEnvelope.message;
mMessageEnvelopes.removeAt(0);
mSendingMessage = true;
mLock.unlock();
handler->handleMessage(message); 2
//do something
if (response.request.ident == ALOOPER_POLL_CALLBACK) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
int callbackResult = response.request.callback->handleEvent(fd,
events, data); 3
if (callbackResult == 0) {
removeFd(fd);
}
response.request.callback.clear();
result = ALOOPER_POLL_CALLBACK;
}
|
利用epoll_wait函数来监听目前looper上的event, 一有event其eventCount就会回传event的数目. 假若在最后一个参数指定的timeoutMillis内都没有事件发生, 其eventCount就会回传0, 若有发生错误回传-1. 由 EPOLL_MAX_EVENTS 的定义值可以知道, 所监听到的event数最多为16个event.
呼叫执行所有在looper中的闲置中的Message所带的CallBack function handleMessage
呼叫执行所有在looper中的reponse event CallBack function handleEvent
由上面的程序代码分析可以知道在一开始InputDispatcherThread就会一直开始监听目前looper上是否有message或是event需要处理.
指定接受者.
当Android app一开始要去绘制整个layout时, WindowsManager会先作 addView 的处理还将自己的View先设定到目前的Window上. 就从WindowManager的addView function开始分析.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
addView@ WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
//do something
root.setView(view, wparams, panelParentView);
//do something
}
setView@ ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
//do something
mInputEventReceiver = new
WindowInputEventReceiver(mInputChannel,
Looper.myLooper()); 1
//do something
}
WindowInputEventReceiver@ ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper
looper) {
super(inputChannel, looper); 2
}
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
@Override
public void onBatchedInputEventPending() {
scheduleConsumeBatchedInput();
}
@Override
public void dispose() {
unscheduleConsumeBatchedInput();
super.dispose();
}
}
|
产生一个带有两个CallBack function实作的WindowInputEventReceiver物件 . 这两个CallBack function onInputEvent 和 onBatchedInputEventPending 会跟在native layer的 InputDispatcherThread 监听事件处理有相关.
跟目前所在的Looper注册request CallBack object NativeInputEventReceiver
处理输入事件流程.
由前面起源的分析可以知道, InputDispatcherThread 一直处在监听looper上的事件阶段, 一旦监听到looper上有event就会接者呼叫执行event所带的CallBack function handleEvent . 至于是呼叫哪一个event所带的handleEvent 函数. 这就要由程序代码 response.request.callback->handleEvent 开始分析. 就由前面指定接受者的第二个步骤开始分析.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
WindowInputEventReceiver@ ViewRootImpl.java
public WindowInputEventReceiver(InputChannel inputChannel, Looper
looper) {
super(inputChannel, looper);
}
InputEventReceiver@ InputEventReceiver.java
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
//do something
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(this, inputChannel, mMessageQueue);
//do somthing
}
nativeInit@ android_view_InputEventReceiver.cpp
static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
jobject inputChannelObj, jobject messageQueueObj) {
//do something
status_t status = receiver->initialize();
//do something
}
NativeInputEventReceiver::initialize@ android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::initialize() {
int receiveFd = mInputConsumer.getChannel()->getFd();
mMessageQueue->getLooper()->addFd(receiveFd, 0,
ALOOPER_EVENT_INPUT, this, NULL);
return OK;
}
Looper::addFd@Looper.cpp
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>&
callback, void* data) {
//do something
Request request;
request.fd = fd;
request.ident = ident;
request.callback = callback;
request.data = data;
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event));
eventItem.events = epollEvents;
eventItem.data.fd = fd;
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex < 0) {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &
eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d, errno=%d", fd,
errno);
return -1;
}
mRequests.add(fd, request);
} else {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, &
eventItem);
if (epollResult < 0) {
ALOGE("Error modifying epoll events for fd %d, errno=%d",
fd, errno);
return -1;
}
mRequests.replaceValueAt(requestIndex, request);
}
//do something
}
|
由上面的程序代码流程可以知道, 在一开始初始化WindowInputEventReceiver对象时, 又去呼叫父类别InputEventReceiver建构子. 这时就又去呼叫JNI函数nativeInit去做初始化流程, 此初始化的流程就正式注册Looper上的CallBack event 所带的信息. 也就是说先把request的information记录下来, 等到要回reponse的时候就知道要回给哪一个request. 由此可知, 此程序代码 response.request.callback->handleEvent 等同于
(NativeInputEventReceiver *)receiver-> handleEvent.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
NativeInputEventReceiver::handleEvent@ android_view_InputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
//do something
status_t status = consumeEvents(env, false /*consumeBatches*/, -1);
//do something
return status == OK || status == NO_MEMORY ? 1 : 0;
}
NativeInputEventReceiver::consumeEvents@ android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime) {
//do something
for (;;) {
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
//do something
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY:
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast<KeyEvent*>(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION:
inputEventObj =
android_view_MotionEvent_obtainAsCopy(env,
static_cast<MotionEvent*>(inputEvent));
break;
default:
assert(false);
inputEventObj = NULL;
}
env->CallVoidMethod(mReceiverObjGlobal,
gInputEventReceiverClassInfo.dispatchInputEvent,
seq, inputEventObj);
//do something
}
}
dispatchInputEvent@ InputEventReceiver.java
// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
|
这一路下来, 由native layer的 handleEvent function 藉由InputConsumer 对象将新的input event取出来, 然后就传给java layer的 dispatchInputEvent 函数继续作分发的处理. 这里值得一提的是我们发现dispatchInputEvent函数会继续将event传给onInputEvent函数, 然而此函数所属的InputEventReceiver是一个抽像类别, 抽象类是无法实体化的, 所以此函数最有可能实作在抽像类别所衍生的类别里. InputEventReceiver类别衍生的类别是 WindowInputEventReceiver类别, 所以就继续从WindowInputEventReceiver的onInputEvent函数分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
onInputEvent@ ViewRootImpl.java
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
enqueueInputEvent @ ViewRootImpl.java
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
//do something
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
doProcessInputEvents@ ViewRootImpl.java
void doProcessInputEvents() {
while (mCurrentInputEvent == null && mFirstPendingInputEvent != null)
{
QueuedInputEvent q = mFirstPendingInputEvent;
mFirstPendingInputEvent = q.mNext;
q.mNext = null;
mCurrentInputEvent = q;
deliverInputEvent(q);
}
// We are done processing all input events that we can process right now
// so we can clear the pending flag immediately.
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}
deliverInputEvent @ ViewRootImpl.java
private void deliverInputEvent(QueuedInputEvent q) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
try {
if (q.mEvent instanceof KeyEvent) {
deliverKeyEvent(q);
} else {
final int source = q.mEvent.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0)
{
deliverPointerEvent(q);
} else if ((source &
InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
deliverTrackballEvent(q);
} else {
deliverGenericMotionEvent(q);
}
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
deliverKeyEvent @ ViewRootImpl.java
private void deliverKeyEvent(QueuedInputEvent q) {
//do something
deliverKeyEventPostIme(q);
}
deliverKeyEventPostIme @ ViewRootImpl.java
private void deliverKeyEventPostIme(QueuedInputEvent q) {
//do something
mView.dispatchKeyEvent(event)
//do something
}
dispatchKeyEvent @View.java
public boolean dispatchKeyEvent(KeyEvent event) {
//do something
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnKeyListener != null && (mViewFlags &
ENABLED_MASK) == ENABLED
&& li.mOnKeyListener.onKey(this,
event.getKeyCode(), event)) { 1
return true;
}
if (event.dispatch(this, mAttachInfo != null
? mAttachInfo.mKeyDispatchState : null, this)) { 2
return true;
}
//do something
}
|
自定义的view若有注册Key Listener, 就会由此接收到
Key event.
一般的Key event是由此函数 dispatch来作分发.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
dispatch @ KeyEvent.java
public final boolean dispatch(Callback receiver, DispatcherState state,
Object target) {
//do something
switch (mAction) {
case ACTION_DOWN:
//do something
receiver.onKeyDown(mKeyCode, this);
case ACTION_UP:
//do something
receiver.onKeyUp(mKeyCode, this);
case ACTION_MULTIPLE:
//do something
receiver.onKeyMultiple(code, count, this)
}
}
|