这个进程涉及到soketchpair和epoll机制(比方InputEventReceiver接纳Event被唤醒),这里不过多赘述,有爱好能够独自查找下这些底层原理
# Android 从问题动身探究KeyEvent分发流程(1) PhoneWindowManager是怎么收到事情的
现在回到这篇记载的Step 4开端往下走,探究下事情是怎样跑到Activity里边的
所与标出的类途径的根目录都是frameworks目录
Step 1 InputDispatcher调用 enqueueInboundEventLocked将封装的KeyEntry参加行列,一起唤醒Looper
/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
std::unique_ptr<KeyEntry> newEntry =
std::make_unique<KeyEntry>(args->id, args->eventTime, args->deviceId, args->source,
args->displayId, policyFlags, args->action, flags,
keyCode, args->scanCode, metaState, repeatCount,
args->downTime);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // release lock
if (needWake) {
mLooper->wake();
}
}
bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry) {
bool needWake = mInboundQueue.empty();
mInboundQueue.push_back(std::move(newEntry));
EventEntry& entry = *(mInboundQueue.back());
traceInboundQueueLengthLocked();
}
Step 2 唤醒后回调dispatchOnce, 这个使命在Dispatcher的start()函数有定义, 调用途径dispatchOnce -> dispatchOnceInnerLocked 后续根据事情类型调用不同的dispatch函数,这里使用dispatchKeyLocked途径持续分析
/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}
/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
switch (mPendingEvent->type) {
case EventEntry::Type::KEY: {
done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::Type::MOTION: {
done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::Type::SENSOR: {
dispatchSensorLocked(currentTime, sensorEntry, &dropReason, nextWakeupTime);
done = true;
break;
}
}
}
Step 3 判断KeyEvent是否是可重复按键(也便是长按重复上报),然后调用dispatchEventLocked进行真正的转发
/native/services/inputflinger/dispatcher/InputDispatcher.cpp
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
if (!entry->dispatchInProgress) {
if (entry->repeatCount == 0 && entry->action == AKEY_EVENT_ACTION_DOWN &&
(entry->policyFlags & POLICY_FLAG_TRUSTED) &&
(!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
if (mKeyRepeatState.lastKeyEntry &&
mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode &&
mKeyRepeatState.lastKeyEntry->deviceId == entry->deviceId) {
entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
} else {
// Not a repeat. Save key down state in case we do see a repeat later.
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
}
mKeyRepeatState.lastKeyEntry = entry;
} else if (entry->action == AKEY_EVENT_ACTION_UP && mKeyRepeatState.lastKeyEntry &&
mKeyRepeatState.lastKeyEntry->deviceId != entry->deviceId) {
// The key on device 'deviceId' is still down, do not stop key repeat
if (DEBUG_INBOUND_EVENT_DETAILS) {
ALOGD("deviceId=%d got KEY_UP as stale", entry->deviceId);
}
} else if (!entry->syntheticRepeat) {
resetKeyRepeatLocked();
}
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
Step 4 dispatchEventLocked -> prepareDispatchCycleLocked -> enqueueDispatchEntriesLocked 事情经过这个流程后被参加到待分发行列outboundQueue,调用startDispatchCycleLocked开端转发
/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
std::shared_ptr<EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
for (const InputTarget& inputTarget : inputTargets) {
sp<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
}
}
}
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
enqueueDispatchEntriesLocked(currentTime, connection, std::move(splitMotionEntry),
inputTarget);
return;
}
}
// Not splitting. Enqueue dispatch entries for the event as is.
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
bool wasEmpty = connection->outboundQueue.empty();
// Enqueue dispatch entries for the requested modes.
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.empty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
待转发行列之前为空,新事情参加后不为空就开端调用startDispatchCycleLocked
Step 5 调用connection->inputPublisher.publishKeyEvent分发事情
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
const std::chrono::nanoseconds timeout = getDispatchingTimeoutLocked(connection);
dispatchEntry->timeoutTime = currentTime + timeout.count();
// Publish the event.
status_t status;
const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
switch (eventEntry.type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
std::array<uint8_t, 32> hmac = getSignature(keyEntry, *dispatchEntry);
// Publish the key event.
status = connection->inputPublisher
.publishKeyEvent(dispatchEntry->seq,
dispatchEntry->resolvedEventId, keyEntry.deviceId,
keyEntry.source, keyEntry.displayId,
std::move(hmac), dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags, keyEntry.keyCode,
keyEntry.scanCode, keyEntry.metaState,
keyEntry.repeatCount, keyEntry.downTime,
keyEntry.eventTime);
break;
}
}
}
}
从Connection的构造函数能够看到inputPublisher实际赋值传入的是InputChannel,inputChannel是一个android封装的socketpair,咱们只需要暂时记住这是一个进程间通信的方法,有点相似java中socket使用,分为客户端和服务端,InputDispatcher这一边的逻辑就相当于服务端。
可是咱们找遍Connection也没找到InputChannel在哪里,直接查找也没找到InputChannel.cpp方位,这时分咱们猜测下这个类可能定义在别的类中,Connection是从引入的类拜访他,所以能够看下Connection引入的类,Connection引入的类很少,很简单找到一个InputTransport,后续函数都在这个类中
Step 6 InputChannel调用sendMessage发送事情
/native/libs/input/InputTransport.cpp
status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action,
int32_t flags, int32_t keyCode, int32_t scanCode,
int32_t metaState, int32_t repeatCount, nsecs_t downTime,
nsecs_t eventTime) {
InputMessage msg;
msg.header.type = InputMessage::Type::KEY;
msg.header.seq = seq;
msg.body.key.eventId = eventId;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.displayId = displayId;
msg.body.key.hmac = std::move(hmac);
msg.body.key.action = action;
msg.body.key.flags = flags;
msg.body.key.keyCode = keyCode;
msg.body.key.scanCode = scanCode;
msg.body.key.metaState = metaState;
msg.body.key.repeatCount = repeatCount;
msg.body.key.downTime = downTime;
msg.body.key.eventTime = eventTime;
return mChannel->sendMessage(&msg);
}
/native/libs/input/InputTransport.cpp
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
return OK;
}
通过文件描述符向该文件写入数据
Step 7 反向寻找事情监听者
现在事情发送出去了,问题就在于在哪里里接纳的,咱们就要回头找是谁,先确认这个Fd(文件描述符是多少),回头找到InputDispatcher.cpp
/native/services/inputflinger/dispatcher/InputDispatcher.cpp
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
{ // acquire lock
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
return clientChannel;
}
这里显现在创立InputChannel时分,他在关心ALOOPER_EVENT_INPUT这个描述符,也便是输入事情,虽然InputDispatcher有LooperEventCallback可是内部并没有转发逻辑,咱们通过命令行查找 grep -rwn ‘ALOOPER_EVENT_INPUT’ framework目录,发现有不少类使用过,找到一个/base/core/jni/android_view_InputEventReceiver.cpp,这个实际是咱们要找到接纳者, 他对应的java类是InputEventReceiver.java
/base/core/jni/android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
/base/core/java/android/view/InputEventReceiver.java
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("InputEventReceiver.dispose");
}
他的jni类在初始化对象时分实际做的便是在looper中设置ALOOPER_EVENT_INPUT事情监听,这样InputTransport中写入事情,这边就收到事情到来被唤醒去处理,
他的完成类很多,其间的WindowInputEventReceiver是咱们要找的,他是ViewRootImpl的内部类
Step 8 WindowInputEventReceiver接纳并持续处理事情
/base/core/java/android/view/ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
@Override
public void onInputEvent(InputEvent event) {
if (processedEvents != null) {
if (processedEvents.isEmpty()) {
// InputEvent consumed by mInputCompatProcessor
finishInputEvent(event, true);
} else {
for (int i = 0; i < processedEvents.size(); i++) {
enqueueInputEvent(
processedEvents.get(i), this,
QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY, true);
}
}
} else {
enqueueInputEvent(event, this, 0, true);
}
}
}
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
void doProcessInputEvents() {
// Deliver all pending input events in the queue.
while (mPendingInputEventHead != null) {
deliverInputEvent(q);
}
}
上面一套线性调用,获取事情->参加行列->取出事情处理,一直到deliverInputEvent进行分发调用
Step 9 找到方针InputStage,持续传递事情
/base/core/java/android/view/ViewRootImpl.java
private void deliverInputEvent(QueuedInputEvent q) {
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
handleWindowFocusChanged();
stage.deliver(q);
} else {
finishInputEvent(q);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
这里KeyEvent最终是被ViewPostImeInputStage处理,能够在setView函数看到InputStage的创立进程和多个不同InputStage的包含联系
Step 10 ViewPostImeInputStage调用processKeyEvent将事情传递给DecorView
/base/core/java/android/view/ViewRootImpl.java
private int processKeyEvent(QueuedInputEvent q) {
final KeyEvent event = (KeyEvent)q.mEvent;
if (mUnhandledKeyManager.preViewDispatch(event)) {
if (ViewDebugManager.DEBUG_ENG) {
Log.v(mTag, "App handle dispatchUnique event = " + event + ", mView = " + mView
+ ", this = " + this);
}
return FINISH_HANDLED;
}
// Deliver the key to the view hierarchy.
if (mView.dispatchKeyEvent(event)) {
if (ViewDebugManager.DEBUG_ENG) {
Log.v(mTag, "App handle key event: event = " + event + ", mView = " + mView
+ ", this = " + this);
}
return FINISH_HANDLED;
}
}
mView是在setView赋值,Activity通过WindowManager的addView直接调用这个函数,传入的便是View便是DecorView
Step 11 DecorView回调Window.Callback将事情传递到Activity
/base/core/java/com/android/internal/policy/DecorView.java
public boolean dispatchKeyEvent(KeyEvent event) {
if (!mWindow.isDestroyed()) {
final Window.Callback cb = mWindow.getCallback();
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
if (handled) {
return true;
}
}
return isDown ? mWindow.onKeyDown(mFeatureId, event.getKeyCode(), event)
: mWindow.onKeyUp(mFeatureId, event.getKeyCode(), event);
}
mWindow便是PhoneWindow,callback,Activity完成了这个接口,这个calback便是Activity在attch函数中创立PhoneWindow时分设置的
/base/core/java/android/app/Activity.java
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
IBinder shareableActivityToken) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
}
至此,Activty怎么收到KeyEvent的进程就结束了