Android按键事件发布流程
来源:互联网 发布:黑猫警长知乎 编辑:程序博客网 时间:2024/06/05 03:34
总结一下,Android按键事件发布流程
InputReader线程启动后,循环调用loopOnce,loopOnce调用mEventHub的getEvents函数,有事件返回底层事件数count,没有则休眠。12345678910//InputReader.cpp
void
InputReader::loopOnce() {
...
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
if
(count) {
processEventsLocked(mEventBuffer, count);
}
...
}
随后调动上述方法,把事件发送给指定设备。1234567//InputReader.cpp
void
InputReader::processEventsLocked(
const
RawEvent* rawEvents, size_t count) {
...
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
...
}
设备处理该事件1234567//InputReader.cpp
void
InputReader::processEventsForDeviceLocked(int32_t deviceId,
const
RawEvent* rawEvents, size_t count) {
...
device->process(rawEvents, count);
...
}
123456//InputReader.cpp
void
InputDevice::process(
const
RawEvent* rawEvents, size_t count) {
...
mapper->process(rawEvent);
...
}
每个设备可能有多种mapper,比如既有按键又有触摸板,把事件发给相应的mapper
1234567//InputReader.cpp
void
KeyboardInputMapper::process(
const
RawEvent* rawEvent) {
...
processKey(rawEvent->when, rawEvent->value !=
0
, keyCode, scanCode, flags);
...
}
键盘mapper处理事件
调用InputDispatcher的notifyKey函数。12345678//InputReader.cpp
void
KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
int32_t scanCode, uint32_t policyFlags) {
...
getListener()->notifyKey(&args);
...
}
notify函数,将事件加入inputDispatcher的 inbound队列,此时应需要选择是否唤醒inputDispatcher线程12345678//InputDispatcher.cpp
void
InputDispatcher::notifyKey(
const
NotifyKeyArgs* args) {
....
needWake = enqueueInboundEventLocked(newEntry);
if
(needWake){
mLooper->wake();
}
}
1234567//InputDispatcher.cpp
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
bool needWake = mInboundQueue.isEmpty();
mInboundQueue.enqueueAtTail(entry);
....
return
needWake;
}
唤醒后,inputdispatcher线程,继续执行dispatchOnce函数,如果没有事件,则休眠在looper的pollOnce函数。1234567//InputDispatcher.cpp
void
InputDispatcher::dispatchOnce(){
...
dispatchOnceInnerLocked(&nextWakeupTime);
...
mLooper->pollOnce(timeoutMillis);
}
123456//InputDispatcher.cpp
void
InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
...
dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
...
}
如果有事件发生,则发布。
123456789101112//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);
...
}
首先寻找获得焦点的窗口,并将事件发送给它
123456789101112131415//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>
12345678//InputDispatcher.cpp
void
InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const
sp<connection>& connection, EventEntry* eventEntry,
const
InputTarget* inputTarget){
...
enqueueDispatchEntriesLocked(currentTime, connection,
splitMotionEntry, inputTarget);
...
}</connection>
将事件加入到outbound队列,准备发送到app123456789//InputDispathcer.cpp
void
InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const
sp<connection>& connection, EventEntry* eventEntry,
const
InputTarget* inputTarget) {
...
startDispatchCycleLocked(currentTime, connection);
...
}
</connection>
1234567891011121314//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>
通过通道,发送事件消息1234567891011121314151617//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);
}
12345678//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);
...
}
app looper会监测channel下socket fd,当fd发生变化,回调当时注册的函数NativeInputEventReciever12345678910111213141516171819202122232425//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;
}
1234567//android_view_InputEventReceiver.cpp
int
NativeInputEventReceiver::handleEvent(
int
receiveFd,
int
events,
void
* data) {
...
status_t status = consumeEvents(env,
false
/*consumeBatches*/
, -
1
, NULL);
...
}
123456789101112//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函数,dispatchInputevent1//通过通道收取消息,初始化按键事件1234567//InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
...
status_t result = mChannel->receiveMessage(&mMsg);
...
}
此处onInputEent调用重写的子类方法。即WindowInputEventReceiver的方法1234567//InputEventReceiver.java
// Called from native code.
@SuppressWarnings
(
"unused"
)
private
void
dispatchInputEvent(
int
seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
12345678910//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
);
}
123456789101112//ViewRootImpl.java
void
enqueueInputEvent(InputEvent event,
InputEventReceiver receiver,
int
flags,
boolean
processImmediately) {
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
...
if
(processImmediately) {
doProcessInputEvents();
}
else
{
scheduleProcessInputEvents();
}
}
0 0
- Android按键事件发布流程
- Android按键事件发布流程
- Android按键事件发布流程
- Android 按键事件流程概要
- Android按键事件处理流程
- Android按键事件传递流程
- Android按键事件处理流程 KeyEvent
- Android按键事件处理流程 -- KeyEvent
- Android按键事件处理流程 -- KeyEvent
- Android按键事件处理流程 -- KeyEvent
- Android按键事件传递流程(二)
- Android按键事件传递流程(一)
- Android Activity的按键事件处理流程
- Android按键事件处理流程 -- KeyEvent
- Android 上从外部应用注入按键事件流程分析
- Android 4.0按键事件以及电源管理流程分析
- Android 4.0按键事件以及系统流程分析
- Android 4.0按键事件以及电源管理流程分析
- Java 过滤掉所有的HTML标签
- sonar下载地址&使用
- 如何选择机器学习算法
- nrf51822 GPIOTE
- 用一个低仿界面来说说自定义viewgroup和事件分发的一些知识
- Android按键事件发布流程
- ThumbnailUtils.extractThumbnail Android图片缩略图显示总结及比较
- C++11中auto、decltype等关键字不能在codeblacks的GNU编译器识别通过的问题的解决
- 初学unity,关于解决有向匀速运动的问题
- 单例模式
- ios8.0下CLLocationManager定位服务需要授权了
- TextLable,TextView首行缩进问题
- Queue接口的实现与使用
- sql cookbook笔录(二)