Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android按鍵事件發布流程

Android按鍵事件發布流程

編輯:關於Android編程

總結一下,Android按鍵事件發布流程

//InputReader.cpp
void InputReader::loopOnce() {
     ...
     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

     if (count) {
        processEventsLocked(mEventBuffer, count);
     }
     ...
 }
InputReader線程啟動後,循環調用loopOnce,loopOnce調用mEventHub的getEvents函數,有事件返回底層事件數count,沒有則休眠。

//InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
     ...
     processEventsForDeviceLocked(deviceId, rawEvent, batchSize);

     ...
}
隨後調動上述方法,把事件發送給指定設備。

//InputReader.cpp
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
      ...
      device->process(rawEvents, count);
      ...
} 
設備處理該事件

//InputReader.cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    ...
    mapper->process(rawEvent);
    ...
}

每個設備可能有多種mapper,比如既有按鍵又有觸摸板,把事件發給相應的mapper

//InputReader.cpp
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    ...
    processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
    ...

}

鍵盤mapper處理事件

//InputReader.cpp
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
        int32_t scanCode, uint32_t policyFlags) {
    ...
    getListener()->notifyKey(&args);
    ...

}
調用InputDispatcher的notifyKey函數。

//InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    ....
    needWake = enqueueInboundEventLocked(newEntry);
    if(needWake){
     mLooper->wake();
    }
 }
notify函數,將事件加入inputDispatcher的 inbound隊列,此時應需要選擇是否喚醒inputDispatcher線程

//InputDispatcher.cpp
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    mInboundQueue.enqueueAtTail(entry);
    ....
    return needWake;
}


//InputDispatcher.cpp
void InputDispatcher::dispatchOnce(){
  ...
   dispatchOnceInnerLocked(&nextWakeupTime);
  ...
   mLooper->pollOnce(timeoutMillis);
}
喚醒後,inputdispatcher線程,繼續執行dispatchOnce函數,如果沒有事件,則休眠在looper的pollOnce函數。

//InputDispatcher.cpp
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
     ...
     dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
     ...
 }

如果有事件發生,則發布。

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

首先尋找獲得焦點的窗口,並將事件發送給它

//InputDispatcher.cpp
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, const Vector& inputTargets) {
      ...
    for (size_t i = 0; i < inputTargets.size(); i++) {
        const InputTarget& inputTarget = inputTargets.itemAt(i);
        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if (connectionIndex >= 0) {
            sp connection = mConnectionsByFd.valueAt(connectionIndex);
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
        } 
       ...
    }
}

//InputDispatcher.cpp
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget){
   ...
   enqueueDispatchEntriesLocked(currentTime, connection,
                    splitMotionEntry, inputTarget);
   ...
 }



//InputDispathcer.cpp
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
        const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    ...
    startDispatchCycleLocked(currentTime, connection);
    ...

}
將事件加入到outbound隊列,准備發送到app
//InputDispatcher.cpp
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        const sp& 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);

      ...

}


//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) {

    ...
    return mChannel->sendMessage(&msg);
} 
通過通道,發送事件消息
//InputTransport.cpp
status_t InputChannel::sendMessage(const InputMessage* msg) {
    size_t msgLength = msg->size();
    ssize_t nWrite;
    do {
        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
     ...
}


//Looper.cpp
int Looper::pollInner(int timeoutMillis) {
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    //等待消息
    int eventCount = 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) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
            // callback--------NativeInputEventRecieverd
            int callbackResult = response.request.callback->handleEvent(fd, events, data);
            if (callbackResult == 0) {
                removeFd(fd);
            }
            response.request.callback.clear();
            result = ALOOPER_POLL_CALLBACK;
        }
    }
    return result;
}
app looper會監測channel下socket fd,當fd發生變化,回調當時注冊的函數NativeInputEventReciever
//android_view_InputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
   ...
    status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
   ...

}

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

}


通過jni調用java函數,dispatchInputevent
//InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
        ...
            status_t result = mChannel->receiveMessage(&mMsg);
        ...
}
//通過通道收取消息,初始化按鍵事件

 //InputEventReceiver.java
// Called from native code.
    @SuppressWarnings("unused")
    private void dispatchInputEvent(int seq, InputEvent event) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event);
    }
此處onInputEent調用重寫的子類方法。即WindowInputEventReceiver的方法

//ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }

        @Override
        public void onInputEvent(InputEvent event) {
            enqueueInputEvent(event, this, 0, true);
        }


//ViewRootImpl.java 
void enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately) {
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);

        ...
        if (processImmediately) {
            doProcessInputEvents();
        } else {
            scheduleProcessInputEvents();
        }
    }




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved