Android按键事件发布流程


2014-09-13      我来说两句    来源:Ron的专栏  
收藏     我要投稿

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

?
1
2
3
4
5
6
7
8
9
10
//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,没有则休眠。

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

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

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

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

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

键盘mapper处理事件

?
1
2
3
4
5
6
7
8
//InputReader.cpp
void KeyboardInputMapper::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
void InputDispatcher::notifyKey( const NotifyKeyArgs* 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);
     ....
     return needWake;
}


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

?
1
2
3
4
5
6
//InputDispatcher.cpp
void InputDispatcher::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
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
         EventEntry* eventEntry, const Vector<inputtarget>& 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> connection = mConnectionsByFd.valueAt(connectionIndex);
             prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
         }
        ...
     }
}
</connection></inputtarget>

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



?
1
2
3
4
5
6
7
8
9
//InputDispathcer.cpp
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
         const sp<connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
     ...
     startDispatchCycleLocked(currentTime, connection);
     ...
 
}
</connection>
将事件加入到outbound队列,准备发送到app
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//InputDispatcher.cpp
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
         const sp<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) {
 
     ...
     return mChannel->sendMessage(&msg);
}
通过通道,发送事件消息
?
1
2
3
4
5
6
7
8
//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);
      ...
}


?
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
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
?
1
2
3
4
5
6
7
//android_view_InputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent( int receiveFd, int events, 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" )
     private void dispatchInputEvent( int seq, InputEvent event) {
         mSeqMap.put(event.getSequenceNumber(), seq);
         onInputEvent(event);
     }
此处onInputEent调用重写的子类方法。即WindowInputEventReceiver的方法

?
1
2
3
4
5
6
7
8
9
10
//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 );
         }


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



U    kernel/include/linux/input.h
U    frameworks/native/include/android/keycodes.h
U    frameworks/base/core/jni/android_os_SystemProperties.cpp
U    frameworks/base/core/java/android/os/Build.java
U    frameworks/base/core/java/android/view/KeyEvent.java
U    frameworks/base/core/res/res/values/attrs.xml
U    frameworks/base/include/androidfw/KeycodeLabels.h
U    frameworks/base/libs/androidfw/Input.cpp
U    frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
U    mediatek/platform/mt6589/kernel/drivers/keypad/kpd.c
U    mediatek/config/smarttimes89_wet_jb2/mtk-kpd.kl
A    mediatek/config/mt6589/navi.xml
U    mediatek/config/mt6589/AndroidBoard.mk
A    mediatek/config/mt6589/baidu.sh
U    mediatek/config/mt6589/init.rc
U    mediatek/custom/st8988/kernel/dct/dct/codegen.dws

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值