Android按键事件发布流程

来源:互联网 发布:黑猫警长知乎 编辑:程序博客网 时间:2024/06/05 03:34

总结一下,Android按键事件发布流程

?
1
2
3
4
5
6
7
8
9
10
//InputReader.cpp
voidInputReader::loopOnce() {
     ...
     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
 
     if(count) {
        processEventsLocked(mEventBuffer, count);
     }
     ...
 }
InputReader线程启动后,循环调用loopOnce,loopOnce调用mEventHub的getEvents函数,有事件返回底层事件数count,没有则休眠。

?
1
2
3
4
5
6
7
//InputReader.cpp
voidInputReader::processEventsLocked(constRawEvent* rawEvents, size_t count) {
     ...
     processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
 
     ...
}
随后调动上述方法,把事件发送给指定设备。

?
1
2
3
4
5
6
7
//InputReader.cpp
voidInputReader::processEventsForDeviceLocked(int32_t deviceId,
        constRawEvent* rawEvents, size_t count) {
      ...
      device->process(rawEvents, count);
      ...
}
设备处理该事件

?
1
2
3
4
5
6
//InputReader.cpp
voidInputDevice::process(constRawEvent* rawEvents, size_t count) {
    ...
    mapper->process(rawEvent);
    ...
}

每个设备可能有多种mapper,比如既有按键又有触摸板,把事件发给相应的mapper

?
1
2
3
4
5
6
7
//InputReader.cpp
voidKeyboardInputMapper::process(constRawEvent* rawEvent) {
    ...
    processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
    ...
 
}

键盘mapper处理事件

?
1
2
3
4
5
6
7
8
//InputReader.cpp
voidKeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
        int32_t scanCode, uint32_t policyFlags) {
    ...
    getListener()->notifyKey(&args);
    ...
 
}
调用InputDispatcher的notifyKey函数。

?
1
2
3
4
5
6
7
8
//InputDispatcher.cpp
voidInputDispatcher::notifyKey(constNotifyKeyArgs* args) {
    ....
    needWake = enqueueInboundEventLocked(newEntry);
    if(needWake){
     mLooper->wake();
    }
 }
notify函数,将事件加入inputDispatcher的 inbound队列,此时应需要选择是否唤醒inputDispatcher线程

?
1
2
3
4
5
6
7
//InputDispatcher.cpp
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    mInboundQueue.enqueueAtTail(entry);
    ....
    returnneedWake;
}


?
1
2
3
4
5
6
7
//InputDispatcher.cpp
voidInputDispatcher::dispatchOnce(){
  ...
   dispatchOnceInnerLocked(&nextWakeupTime);
  ...
   mLooper->pollOnce(timeoutMillis);
}
唤醒后,inputdispatcher线程,继续执行dispatchOnce函数,如果没有事件,则休眠在looper的pollOnce函数。

?
1
2
3
4
5
6
//InputDispatcher.cpp
voidInputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
     ...
     dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
     ...
 }

如果有事件发生,则发布。

?
1
2
3
4
5
6
7
8
9
10
11
12
//InputDispatcher.cpp
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        DropReason* dropReason, nsecs_t* nextWakeupTime) {
 
     ...
     int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
            entry, inputTargets, nextWakeupTime);
 
 
     dispatchEventLocked(currentTime, entry, inputTargets);
     ...
}

首先寻找获得焦点的窗口,并将事件发送给它

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//InputDispatcher.cpp
voidInputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, constVector<inputtarget>& inputTargets) {
      ...
    for(size_t i = 0; i < inputTargets.size(); i++) {
        constInputTarget& inputTarget = inputTargets.itemAt(i);
        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if(connectionIndex >= 0) {
            sp<connection> connection = mConnectionsByFd.valueAt(connectionIndex);
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
        }
       ...
    }
}
</connection></inputtarget>

?
1
2
3
4
5
6
7
8
//InputDispatcher.cpp
voidInputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        constsp<connection>& connection, EventEntry* eventEntry, constInputTarget* inputTarget){
   ...
   enqueueDispatchEntriesLocked(currentTime, connection,
                    splitMotionEntry, inputTarget);
   ...
 }</connection>



?
1
2
3
4
5
6
7
8
9
//InputDispathcer.cpp
voidInputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
        constsp<connection>& connection, EventEntry* eventEntry, constInputTarget* inputTarget) {
    ...
    startDispatchCycleLocked(currentTime, connection);
    ...
 
}
</connection>
将事件加入到outbound队列,准备发送到app
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//InputDispatcher.cpp
voidInputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        constsp<connection>& connection){
      ...
      status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
                    keyEntry->deviceId, keyEntry->source,
                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
                    keyEntry->keyCode, keyEntry->scanCode,
                    keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
                    keyEntry->eventTime);
 
      ...
 
}</connection>


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//InputTransport.cpp
status_t InputPublisher::publishKeyEvent(
        uint32_t seq,
        int32_t deviceId,
        int32_t source,
        int32_t action,
        int32_t flags,
        int32_t keyCode,
        int32_t scanCode,
        int32_t metaState,
        int32_t repeatCount,
        nsecs_t downTime,
        nsecs_t eventTime) {
 
    ...
    returnmChannel->sendMessage(&msg);
}
通过通道,发送事件消息
?
1
2
3
4
5
6
7
8
//InputTransport.cpp
status_t InputChannel::sendMessage(constInputMessage* msg) {
    size_t msgLength = msg->size();
    ssize_t nWrite;
    do{
        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
     ...
}


?
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
//Looper.cpp
intLooper::pollInner(inttimeoutMillis) {
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    //等待消息
    inteventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    
 
Done:
    for(size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if(response.request.ident == ALOOPER_POLL_CALLBACK) {
            intfd = response.request.fd;
            intevents = response.events;
            void* data = response.request.data;
            // callback--------NativeInputEventRecieverd
            intcallbackResult = response.request.callback->handleEvent(fd, events, data);
            if(callbackResult == 0) {
                removeFd(fd);
            }
            response.request.callback.clear();
            result = ALOOPER_POLL_CALLBACK;
        }
    }
    returnresult;
}
app looper会监测channel下socket fd,当fd发生变化,回调当时注册的函数NativeInputEventReciever
?
1
2
3
4
5
6
7
//android_view_InputEventReceiver.cpp
intNativeInputEventReceiver::handleEvent(intreceiveFd,intevents,void* data) {
   ...
    status_t status = consumeEvents(env, false/*consumeBatches*/, -1, NULL);
   ...
 
}

?
1
2
3
4
5
6
7
8
9
10
11
12
//android_view_InputEventReceiver.cpp
 
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
....
  status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent);
...
env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
...
 
}

?
1
 
通过jni调用java函数,dispatchInputevent
?
1
2
3
4
5
6
7
//InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
        ...
            status_t result = mChannel->receiveMessage(&mMsg);
        ...
}
//通过通道收取消息,初始化按键事件

?
1
2
3
4
5
6
7
//InputEventReceiver.java
// Called from native code.
    @SuppressWarnings("unused")
    privatevoiddispatchInputEvent(intseq, InputEvent event) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event);
    }
此处onInputEent调用重写的子类方法。即WindowInputEventReceiver的方法

?
1
2
3
4
5
6
7
8
9
10
//ViewRootImpl.java
finalclassWindowInputEventReceiver extendsInputEventReceiver {
        publicWindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }
 
        @Override
        publicvoidonInputEvent(InputEvent event) {
            enqueueInputEvent(event,this,0,true);
        }


?
1
2
3
4
5
6
7
8
9
10
11
12
//ViewRootImpl.java
voidenqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, intflags,booleanprocessImmediately) {
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
 
        ...
        if(processImmediately) {
            doProcessInputEvents();
        }else{
            scheduleProcessInputEvents();
        }
    }

0 0
原创粉丝点击