日期:
来源:郭霖收集编辑:小余的自习室
https://juejin.cn/post/7169835311868936222
开机后SystemServer启动过程中创建了InputManagerService,InputManagerService构造方法中在native层创建了NativeInputManager对象。 NativeInputManager构造方法中又创建了一个InputManager对象,InputManager构造方法中又创建了InputDispatcher和InputReader对象以及他们两个工作对应的线程 InputDispatcherThread和InputReaderThread。 InputManagerService在实例化完成后,SystemServer启动过程会继续调用其start方法启动IMS,实际是启动InputDispatcherThread和InputReaderThread线程。 在InputReaderThread线程中使用EventHub的getEvents方法去设备节点/dev/input下面获取节点数据。并在事件加工完成后并唤醒InputDispatcherThread线程去处理。
问题1:窗口什么时候传入IMS输入系统的?IMS是如何找到对应的Window窗口的? 问题2:IMS和WMS是通过什么方式通讯将事件分发出去的?
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
...
KeyEntry* newEntry = new KeyEntry(args->eventTime,args->deviceId, ...);//1
needWake = enqueueInboundEventLocked(newEntry); //2
if (needWake) {
mLooper->wake();//3
}
}
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
...
mInboundQueue.enqueueAtTail(entry);
}
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();//mDispatcher 是InputDispatcher类型对象
return true;
}
void InputDispatcher::dispatchOnce() {
...
if (!haveCommandsLocked()) {//1
dispatchOnceInnerLocked(&nextWakeupTime);
}
...
if (runCommandsLockedInterruptible()) {//2
nextWakeupTime = LONG_LONG_MIN;
}
mLooper->pollOnce(timeoutMillis);
}
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
switch (mPendingEvent->type) {
...
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
...
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
...
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}
if (done) {
...
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
...
Vector<InputTarget> inputTargets;
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime); //1
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
...
addMonitoringTargetsLocked(inputTargets);//2
// Dispatch the key.
dispatchEventLocked(currentTime, entry, inputTargets); //3
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
mInputChannel = new InputChannel();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
if (mInputChannel != null) {
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,Looper.myLooper());
}
}
frameworks\base\services\core\java\com\android\server\wm\Session.java
public int addToDisplay(IWindow window,...InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
WMS:
public int addWindow(Session session, IWindow client...InputChannel outInputChannel) {
...
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
...
win.openInputChannel(outInputChannel); //1
if (focusChanged) {
mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);//2
}
}
void openInputChannel(InputChannel outInputChannel) {
...
String name = getName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);//1
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
mClientChannel = null;
}
...
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);//2
}
InputChannel.java:
public static InputChannel[] openInputChannelPair(String name) {
...
return nativeOpenInputChannelPair(name);
}
android_view_InputChannel.cpp:
static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env...) {
...
sp<InputChannel> serverChannel;
sp<InputChannel> clientChannel;
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
std::make_unique<NativeInputChannel>(serverChannel));
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
std::make_unique<NativeInputChannel>(clientChannel));
...
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
return channelPair;
}
status_t InputChannel::openInputChannelPair(const String8& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
...
return result;
}
...
outServerChannel = new InputChannel(serverChannelName, sockets[0]);
outClientChannel = new InputChannel(clientChannelName, sockets[1]);
return OK;
}
void openInputChannel(InputChannel outInputChannel) {
...
String name = getName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);//1
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
mClientChannel = null;
}
...
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);//2
}
mInputChannel:服务端的InputChannel mClientChannel:客户端的InputChannel outInputChannel:app层传递进来的InputChannel
frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
...
status_t status = im->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);//1
}
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
return mInputManager->getDispatcher()->registerInputChannel(
inputChannel, inputWindowHandle, monitor);
}
frameworks/native/services/inputflinger/InputDispatcher.cpp
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
...
sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);
...
// registerInputChannel里面传入的monitor是false --> nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
// 所以这个流程不会将窗口的channel放到mMonitoringChannels里面
if (monitor) {
mMonitoringChannels.push(inputChannel);
}
...
}
inputChannel:WMS在服务端InputChannel inputWindowHandle:WMS内的一个包含Window所有信息的实例。 monitor:值为false,表示不加入监控
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
..
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime); //1
dispatchEventLocked(currentTime, entry, inputTargets); //2
}
int32_t InputDispatcher::findFocusedWindowTargetsLocked(...inputTargets){
...
addWindowTargetLocked(mFocusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
inputTargets);
...
}
void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
inputTargets.push();
const InputWindowInfo* windowInfo = windowHandle->getInfo();
InputTarget& target = inputTargets.editTop();
target.inputChannel = windowInfo->inputChannel;
target.flags = targetFlags;
target.xOffset = - windowInfo->frameLeft;
target.yOffset = - windowInfo->frameTop;
target.scaleFactor = windowInfo->scaleFactor;
target.pointerIds = pointerIds;
}
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
@Override
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
...
if (focusChanged) {
mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
}
mInputMonitor.updateInputWindowsLw(false /*force*/);
...
}
// frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
...
mWindowHandles = inputWindowHandles;
sp<InputWindowHandle> newFocusedWindowHandle;
...
for (size_t i = 0; i < mWindowHandles.size(); i++) {
const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
...
if (windowHandle->getInfo()->hasFocus) {
newFocusedWindowHandle = windowHandle;
}
...
mFocusedWindowHandle = newFocusedWindowHandle;
}
...
}
mWindowHandles:代表所有Window的Handler对象 mFocusedWindowHandle:表示焦点Window的Handler对象 通过这些代码就让我们IMS中获取到了需要处理的焦点Window。
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);
}
...
}
}
ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
if (connection->inputChannel.get() == inputChannel.get()) {
return connectionIndex;
}
}
return -1;
}
void InputDispatcher::enqueueDispatchEntriesLocked(connection,..){
// Enqueue dispatch entries for the requested modes.
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,...);//1
...
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.isEmpty()) {//2
startDispatchCycleLocked(currentTime, connection);//3
}
}
void InputDispatcher::enqueueDispatchEntryLocked(
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
int32_t dispatchMode) {
...
DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry,
inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
inputTarget->scaleFactor);
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
dispatchEntry->resolvedAction = keyEntry->action;
dispatchEntry->resolvedFlags = keyEntry->flags;
...
break;
}
...
}
...
connection->outboundQueue.enqueueAtTail(dispatchEntry);
...
}
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
while (connection->status == Connection::STATUS_NORMAL
&& !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
...
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
// Publish the key event.
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);
break;
}
...
connection->outboundQueue.dequeue(dispatchEntry);
connection->waitQueue.enqueueAtTail(dispatchEntry)
}
...
}
status_t InputDispatcher::registerInputChannel(...) {
...
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
...
}
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
InputDispatcher* d = static_cast<InputDispatcher*>(data);
...
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
...
d->runCommandsLockedInterruptible();
...
}
void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
CommandEntry* commandEntry) {
sp<Connection> connection = commandEntry->connection;
...
DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
...
if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
connection->waitQueue.dequeue(dispatchEntry);
...
}
}