简述
窗口接收事件主要分为三步骤 :
- 窗口与InputManagerService建立连接
- 在
InputManagerService
初始化的时候会创建InputReader
、InputDispatcher
两个线程监听/dev/input
的事件 , 并且进行分发 - 在
ActivityThread.performResumeActivity
中开始创建客户端的InputChannel
- 通过
Seesion.addToDisplay
通过out
的方式让InputManagerService
填充客户端InputChannel
- 在
InputManagerService
中会通过socketpair
创建基于fd
的socket,然后通过epoll
监听该文件事件
- 在
- InputManagerService选择窗口
- 在
InputDispatcher
监听到InputReader
中的事件后 , 会根据当前x、y
来找到已经注册的WindowHandle
- 接着根据
WindowHandle
找到对应的InputChannel
以及Connection
- 接着将MotionEvent对应的二进制数据通过
Socket
的FD
发送给客户端窗口
- 在
- 窗口响应事件
- 在
Activity.attach
的时候 , 会创建PhoneWindow
,并且设置Callback
- 在
ViewRootImpl.setView
中 , 创建WindowInputEventReceiver
用于接收InputChannel
的事件 - 在
WindowInputEventReceiver
中会将客户端SocketClient
的FD
通过Looper.addFd()
添加到Looper监听中 - 当接收到
SocketServer
发送的二进制数据后 ,InputConsumer
会将二进制数据解析成MotionEvent
、InputEvent
- 最后会通过
PhoneWindow
注册的Callback,也就是Ativity进行dispatchTouchEvent - 在
Activity.dispatchTouchEvent
中 , 会优先进行DecorView
中Touch事件的分发 , 如果都没有处理的话 , 则调用Activity.onTouch
- 在
Activity与ViewGroup分发事件的流程
窗口与InputManagerService建立连接
- 在
ViewRootImpl.setView()
中
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
...
requestLayout();
// 如果没有特别设置INPUT_FEATURE_NO_INPUT_CHANNEL的时候 , 就会创建一个InputChannel
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
// 创建InputChannel , 和Surface一样 , 都由System_Server填充内容
mInputChannel = new InputChannel();
}
mForceDecorViewVisibility = (mWindowAttributes.privateFlags
& PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
try {
...
// 调用Session.addToDisplay
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
} catch (RemoteException e) {
} finally {
if (restore) {
attrs.restore();
}
}
...
// 初始化InputQueue
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
...
}
}
}
- 在创建
IWindowSession.aidl
中 , 通过在AIDL上添加out关键字 , 允许服务端向客户端填充相关内容.
interface IWindowSession {
...
// 通过在AIDL上添加out关键字 , 允许服务端向客户端填充相关内容
int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outContentInsets,
out Rect outStableInsets, out Rect outOutsets, out InputChannel outInputChannel);
...
}
- 在SystemServer的
Session.addToDisplay
最终会调用到WMS.addWindow
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
// 省去一大堆WindowToken、Type校验
...
// 创建WindowState对象
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
...
// 再次判断窗口的INPUT_FEATURE_NO_INPUT_CHANNEL属性
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
// 如果需要打开的话 ,则调用openInputChannel打开窗口
win.openInputChannel(outInputChannel);
}
...
boolean focusChanged = false;
if (win.canReceiveKeys()) {
// 更新FocusWindow
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,false);
}
...
if (focusChanged) {
// 设置FocusWindow
mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
}
// 更新Window
mInputMonitor.updateInputWindowsLw(false /*force*/);
...
return res;
}
WindowState.openInputChannel
- 通过
InputChannel.openInputChannelPair
在Native层创建基于文件的两个Socket - 将SocketClient、SocketServer赋值给outInputChannel
void openInputChannel(InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
String name = getName();
// 通过`InputChannel.openInputChannelPair`在Native层创建基于文件的两个Socket
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
// 保存客户端Socket fd
mInputChannel = inputChannels[0];
// 保存服务端Socket fd
mClientChannel = inputChannels[1];
// 在构造函数中初始化
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
// 将ClientChannel发送给客户端保存
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
mClientChannel = null;
} else {
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
// 将InputChannel与InputWindowHandle注册到InputManager中
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
- 通过
NaticeOpenInputChannelPair
方法创建对应的InputChannel
static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
jclass clazz, jstring nameObj) {
const char* nameChars = env->GetStringUTFChars(nameObj, NULL);
String8 name(nameChars);
env->ReleaseStringUTFChars(nameObj, nameChars);
sp serverChannel;
sp clientChannel;
// 调用openInputChannelPair方法 , 将serverChannel、clientChannel赋值
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
// 创建返回值
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
if (env->ExceptionCheck()) {
return NULL;
}
// 得到serverChannel对象
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
std::make_unique(serverChannel));
if (env->ExceptionCheck()) {
return NULL;
}
// 创建clientChanneld对象
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
std::make_unique(clientChannel));
if (env->ExceptionCheck()) {
return NULL;
}
// 为数组赋值
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
// 返回数组
return channelPair;
}
-
openInputChannelPair
中创建client/server
的Socket
tatus_t InputChannel::openInputChannelPair(const String8& name,
sp& outServerChannel, sp& outClientChannel) {
int sockets[2];
// 通过socketpair生成fd , 创建两个socket
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
status_t result = -errno;
ALOGE("channel '%s' ~ Could not create socket pair. errno=%d",
name.string(), errno);
outServerChannel.clear();
outClientChannel.clear();
return result;
}
int bufferSize = SOCKET_BUFFER_SIZE;
// 设置socket的buffer
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
// 设置socket的buffer
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
// 设置InputChannel名字
String8 serverChannelName = name;
serverChannelName.append(" (server)");
outServerChannel = new InputChannel(serverChannelName, sockets[0]);
String8 clientChannelName = name;
clientChannelName.append(" (client)");
outClientChannel = new InputChannel(clientChannelName, sockets[1]);
return OK;
}
InputChannel::InputChannel(const String8& name, int fd) :
mName(name), mFd(fd) {
// 设置fd为no block
int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
}
- 在创建完SocketPair后 , 会将InputChannel注册到InputManager中
registerInputChannel
, 最后会在Native层的nativeRegisterInputChannel
完成注册
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
...
//
status_t status = im->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);
if (status) {
String8 message;
message.appendFormat("Failed to register input channel. status=%d", status);
jniThrowRuntimeException(env, message.string());
return;
}
// 传入的monitor为false
if (! monitor) {
// 设置dispose callback
android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
handleInputChannelDisposed, im);
}
}
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
const sp& inputChannel,
const sp& inputWindowHandle, bool monitor) {
// 调用Dispatcher.regisgerInputChannel
return mInputManager->getDispatcher()->registerInputChannel(
inputChannel, inputWindowHandle, monitor);
}
-
registerInputChannel
在InputDispatcher
中注册InputChannel
status_t InputDispatcher::registerInputChannel(const sp& inputChannel,
const sp& inputWindowHandle, bool monitor) {
{ // acquire lock
AutoMutex _l(mLock);
// 获取inputChannel的FD , 如果已经注册过了 , 则报错
if (getConnectionIndexLocked(inputChannel) >= 0) {
ALOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().string());
return BAD_VALUE;
}
// 创建一个Connection
sp connection = new Connection(inputChannel, inputWindowHandle, monitor);
// 获取fd
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);
// 将fd添加到Looper中 , 如果有事件来了 , 就会回调handleReceiveCallback
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
} // release lock
// 唤醒Looper
mLooper->wake();
return OK;
}
至此 , 在InputMangerService与应用窗口间就建立了Socket
连接.
InputManagerSercice选择窗口分发事件
- 之前说到 , 在
InputDispathcer.dispatchMotionLocked
中会找到应用的窗口
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
...
// 判断是否为触碰消息
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
// 找到接收事件的窗口
Vector inputTargets;
...
int32_t injectionResult;
if (isPointerEvent) {
// Touch事件
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
// Key、轨迹球事件
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
}
...
// 分发事件
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
-
findTouchedWindowTargetsLocked
, 根据x
,y
以及窗口坐标找到匹配的WindowHandle
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const MotionEntry* entry, Vector& inputTargets, nsecs_t* nextWakeupTime,
bool* outConflictingPointerActions) {
// 找到displayID
int32_t displayId = entry->displayId;
int32_t action = entry->action;
...
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
// 如果是TouchDown
int32_t pointerIndex = getMotionEventActionPointerIndex(action);
// 找到屏幕对应的x
int32_t x = int32_t(entry->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_X));
// 找到屏幕对应的Y
int32_t y = int32_t(entry->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_Y));
sp newTouchedWindowHandle;
bool isTouchModal = false;
// 遍历所有的WindowHandle
size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
sp windowHandle = mWindowHandles.itemAt(i);
// 从WindowHandle中找到windowInfo , 其中存储了窗口信息
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId != displayId) {
// 判断display是否为同一个 , 因为Android除了主屏幕外, 还有副屏幕与虚拟屏幕
continue;
}
int32_t flags = windowInfo->layoutParamsFlags;
if (windowInfo->visible) {
// 如果窗口可见
if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
| InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
// 判断当前窗口是否可以触摸、是否拥有焦点
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
// 如果可以触摸、允许拥有焦点 , 则判断当前x、y是否在窗口内
// 如果在的话 , 就确定是该window Handle
newTouchedWindowHandle = windowHandle;
break; // found touched window, exit window loop
}
}
}
}
// 如果没有找到可以接收touch事件的window的话
if (newTouchedWindowHandle == NULL) {
// 尝试将touch window给到上一个可见的窗口
newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
if (newTouchedWindowHandle == NULL) {
ALOGI("Dropping event because there is no touchable window at (%d, %d).", x, y);
// 如果这都没有能接收 , 则丢弃
injectionResult = INPUT_EVENT_INJECTION_FAILED;
goto Failed;
}
}
...
// 最后更新最近可用窗口信息
mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
} else {
// 处理MOVE事件
// 检查action以及pointercount是否只有1个
if (maskedAction == AMOTION_EVENT_ACTION_MOVE
&& entry->pointerCount == 1
&& mTempTouchState.isSlippery()) {
// 获取x、y
int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
// 获取上一个WindowHandle
sp oldTouchedWindowHandle =
mTempTouchState.getFirstForegroundWindowHandle();
// 根据x、y、display ID获取TouchWindow
sp newTouchedWindowHandle =
findTouchedWindowAtLocked(displayId, x, y);
if (oldTouchedWindowHandle != newTouchedWindowHandle
&& newTouchedWindowHandle != NULL) {
// 如果本次与上次接收TouchEvent的窗口不一样的话 , 就更新mTempTouchState
mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
....
}
}
...
}
-
dispatchEventLocked
开始分发Touch
事件
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector& inputTargets) {
...
// 开始遍历找到的`inputTargets`
for (size_t i = 0; i < inputTargets.size(); i++) {
const InputTarget& inputTarget = inputTargets.itemAt(i);
// 根据inputChannel找到对应的Connection
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
sp connection = mConnectionsByFd.valueAt(connectionIndex);
// 开始分发
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
} else {
#if DEBUG_FOCUS
ALOGD("Dropping event delivery to target with channel '%s' because it "
"is no longer registered with the input dispatcher.",
inputTarget.inputChannel->getName().string());
#endif
}
}
}
4.prepareDispatchCycleLocked
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
...
// 如果Entry需要分割一下的话 , 则分割后再分发
if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
MotionEntry* originalMotionEntry = static_cast(eventEntry);
if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
MotionEntry* splitMotionEntry = splitMotionEvent(
originalMotionEntry, inputTarget->pointerIds);
if (!splitMotionEntry) {
return; // split event was dropped
}
// 也是调用enqueueDispatchEntriesLocked分发
enqueueDispatchEntriesLocked(currentTime, connection,
splitMotionEntry, inputTarget);
splitMotionEntry->release();
return;
}
}
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
enqueueDispatchEntriesLocked
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
bool wasEmpty = connection->outboundQueue.isEmpty();
// 根据Flag开始分发 相应的Entry
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);
// 通过`enqueueDispatchEntryLocked`会将Entry添加到outboundQueue中
// 如果原来的outboundQueue为空 , 并且现在不为空 , 则开始分发这些事件
// 因为如果不为空 , 则认为publisher正在分发 , 所以只要加入队列即可
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
enqueueDispatchEntryLocked
void InputDispatcher::enqueueDispatchEntryLocked(
const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
int32_t dispatchMode) {
int32_t inputTargetFlags = inputTarget->flags;
if (!(inputTargetFlags & dispatchMode)) {
return;
}
inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
// 创建DispatchEntry
DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
inputTarget->scaleFactor);
// 根据entry type来生成对应的Entry
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast(eventEntry);
dispatchEntry->resolvedAction = keyEntry->action;
dispatchEntry->resolvedFlags = keyEntry->flags;
if (!connection->inputState.trackKey(keyEntry,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
connection->getInputChannelName());
#endif
delete dispatchEntry;
return; // skip the inconsistent event
}
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast(eventEntry);
if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
} else {
dispatchEntry->resolvedAction = motionEntry->action;
}
if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
&& !connection->inputState.isHovering(
motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
connection->getInputChannelName());
#endif
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
}
dispatchEntry->resolvedFlags = motionEntry->flags;
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
}
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
}
...
}
if (dispatchEntry->hasForegroundTarget()) {
// 等待dispatch结束 , 增加索引
incrementPendingForegroundDispatchesLocked(eventEntry);
}
// 加入connection队列
connection->outboundQueue.enqueueAtTail(dispatchEntry);
}
startDispatchCycleLocked
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp& connection) {
// 如果connection状态正常 , 并且queue不为空
while (connection->status == Connection::STATUS_NORMAL
&& !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
// 获取分发时间
dispatchEntry->deliveryTime = currentTime;
// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
// 根据entry type进行publish
switch (eventEntry->type) {
// 如果是key Event
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast(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;
}
case EventEntry::TYPE_MOTION: {
// 如果是MotionEvent
MotionEntry* motionEntry = static_cast(eventEntry);
...
// Publish the motion event.
status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
motionEntry->deviceId, motionEntry->source,
dispatchEntry->resolvedAction, motionEntry->actionButton,
dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
motionEntry->metaState, motionEntry->buttonState,
xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, motionEntry->eventTime,
motionEntry->pointerCount, motionEntry->pointerProperties,
usingCoords);
break;
}
default:
ALOG_ASSERT(false);
return;
}
...
// 从outboundQueue中出队列
connection->outboundQueue.dequeue(dispatchEntry);
// 在waitQueue中加入队列
connection->waitQueue.enqueueAtTail(dispatchEntry);
}
}
InputPublisher::publishMotionEvent
status_t InputPublisher::publishMotionEvent(
uint32_t seq,
int32_t deviceId,
int32_t source,
int32_t action,
int32_t actionButton,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
int32_t buttonState,
float xOffset,
float yOffset,
float xPrecision,
float yPrecision,
nsecs_t downTime,
nsecs_t eventTime,
uint32_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
...
// 构建InputMessage
InputMessage msg;
msg.header.type = InputMessage::TYPE_MOTION;
msg.body.motion.seq = seq;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.action = action;
msg.body.motion.actionButton = actionButton;
msg.body.motion.flags = flags;
msg.body.motion.edgeFlags = edgeFlags;
msg.body.motion.metaState = metaState;
msg.body.motion.buttonState = buttonState;
msg.body.motion.xOffset = xOffset;
msg.body.motion.yOffset = yOffset;
msg.body.motion.xPrecision = xPrecision;
msg.body.motion.yPrecision = yPrecision;
msg.body.motion.downTime = downTime;
msg.body.motion.eventTime = eventTime;
msg.body.motion.pointerCount = pointerCount;
for (uint32_t i = 0; i < pointerCount; i++) {
msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
}
// 通过InputChannel发送消息
return mChannel->sendMessage(&msg);
}
-
sendMessage
通过send
函数 , 通过Socket
的FD将二进制数据给到客户端窗口
status_t InputChannel::sendMessage(const InputMessage* msg) {
size_t msgLength = msg->size();
ssize_t nWrite;
do {
// 通过send函数 , 发送给客户端窗口
// mFD为最开始通过sockerpair打开的socket fd
nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) {
int error = errno;
if (error == EAGAIN || error == EWOULDBLOCK) {
return WOULD_BLOCK;
}
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
return DEAD_OBJECT;
}
return -error;
}
if (size_t(nWrite) != msgLength) {
return DEAD_OBJECT;
}
return OK;
}
至此 , InputManagerService中接收到的Input消息通过Socket发送给对应的窗口
窗口响应事件
- 在
session.addToDispaly
函数调用后 , InputManagerService将InputChannel
信息填充给对应的Window
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
...
requestLayout();
// 如果没有特别设置INPUT_FEATURE_NO_INPUT_CHANNEL的时候 , 就会创建一个InputChannel
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
// 创建InputChannel , 和Surface一样 , 都由System_Server填充内容
mInputChannel = new InputChannel();
}
mForceDecorViewVisibility = (mWindowAttributes.privateFlags
& PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
try {
...
// 调用Session.addToDisplay
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
} catch (RemoteException e) {
} finally {
if (restore) {
attrs.restore();
}
}
...
// 初始化InputQueue
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
// 创建WindouInpuTEventReceiver对象 , 使用主线程Looper
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
...
}
}
}
-
WindowInputEventReceiver
继承自InputEventReceiver
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);
}
}
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
mInputChannel = inputChannel;
// 获取祝线程队列
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
nativeInit
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
sp inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
...
// 获取Native对应的MessageQueue对象
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
// 创建NativeInputEventReceiver对象
sp receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);
// 初始化
status_t status = receiver->initialize();
if (status) {
String8 message;
message.appendFormat("Failed to initialize input event receiver. status=%d", status);
jniThrowRuntimeException(env, message.string());
return 0;
}
receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast(receiver.get());
}
-
NativeInputEventReceiver
中会通过setFdEvents
来监听socket
文件的事件
NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
jobject receiverWeak, const sp& inputChannel,
const sp& messageQueue) :
mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mInputConsumer(inputChannel), mMessageQueue(messageQueue),
mBatchedInputEventPending(false), mFdEvents(0) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
}
}
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
-
setFdEvents
中 , 将socket
文件的监听放到主线程Looper中
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
// 获取client端Socket文件的fd
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
// 将fd添加到Looper中监听, 并且将callback设置为this
mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
- 当Looper监听到相应FD的事件时 , 就会回调
handleEvent
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
// epoll返回错误
return 0; // remove the callback
}
if (events & ALOOPER_EVENT_INPUT) {
// 如果是输入的事件
JNIEnv* env = AndroidRuntime::getJNIEnv();
// 调用consumeEents来处理事件
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
// FD输出事件 , 暂时没想到会有那种情况会通过socket向InputManagerService发送事件
if (events & ALOOPER_EVENT_OUTPUT) {
for (size_t i = 0; i < mFinishQueue.size(); i++) {
const Finish& finish = mFinishQueue.itemAt(i);
status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
if (status) {
mFinishQueue.removeItemsAt(0, i);
if (status == WOULD_BLOCK) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Sent %zu queued finish events; %zu left.",
getInputChannelName(), i, mFinishQueue.size());
}
return 1; // keep the callback, try again later
}
if (status != DEAD_OBJECT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
String8 message;
message.appendFormat("Failed to finish input event. status=%d", status);
jniThrowRuntimeException(env, message.string());
mMessageQueue->raiseAndClearException(env, "finishInputEvent");
}
return 0; // remove the callback
}
}
mFinishQueue.clear();
setFdEvents(ALOOPER_EVENT_INPUT);
return 1;
}
return 1;
}
- 当接收到
socket
事件后 , 开始消费事件 , 即开始分发给对应的View
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
...
ScopedLocalRef receiverObj(env, NULL);
bool skipCallbacks = false;
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
// 通过InputConsumer.consume来组装对应的InputEvent , 并且赋值给inputEvent
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
...
jobject inputEventObj;
// 根据inputevent的type进行处理
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY:
// 将keyevent赋值给inputEventObj
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION: {
// 将MotionEvent赋值给inputEventObj
MotionEvent* motionEvent = static_cast(inputEvent);
if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
*outConsumedBatch = true;
}
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
break;
}
default:
assert(false); // InputConsumer should prevent this from ever happening
inputEventObj = NULL;
}
if (inputEventObj) {
// 将inputEventObj回调给Java层的InputEventReceiver.dispatchInputEvent
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
// 检查是否出现异常
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching input event.");
skipCallbacks = true;
}
// 删除本地引用
env->DeleteLocalRef(inputEventObj);
} else {
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
skipCallbacks = true;
}
}
if (skipCallbacks) {
mInputConsumer.sendFinishedSignal(seq, false);
}
}
}
// JNI注册函数
int register_android_view_InputEventReceiver(JNIEnv* env) {
// 注册InputEventReceiver函数
int res = RegisterMethodsOrDie(env, "android/view/InputEventReceiver",
gMethods, NELEM(gMethods));
jclass clazz = FindClassOrDie(env, "android/view/InputEventReceiver");
gInputEventReceiverClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
// 得到InputEventRecever.dispatchInputEvent的函数地址
gInputEventReceiverClassInfo.dispatchInputEvent = GetMethodIDOrDie(env,
gInputEventReceiverClassInfo.clazz,
"dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
// 得到InputEventReceiver.dispatchBatchedInputEventPending函数地址
gInputEventReceiverClassInfo.dispatchBatchedInputEventPending = GetMethodIDOrDie(env,
gInputEventReceiverClassInfo.clazz, "dispatchBatchedInputEventPending", "()V");
return res;
}
8.consume
函数从InputChannel的socket中读取二进制的Message来填充outEvent
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
*outSeq = 0;
*outEvent = NULL;
while (!*outEvent) {
if (mMsgDeferred) {
// mMsg contains a valid input message from the previous call to consume
// that has not yet been processed.
mMsgDeferred = false;
} else {
// 从mChannel中读取消息. 即从socket中读取二进制消息
status_t result = mChannel->receiveMessage(&mMsg);
if (result) {
// Consume the next batched event unless batches are being held for later.
if (consumeBatches || result != WOULD_BLOCK) {
result = consumeBatch(factory, frameTime, outSeq, outEvent);
if (*outEvent) {
break;
}
}
return result;
}
}
// 根据msg的header.type构建对应的事件
switch (mMsg.header.type) {
case InputMessage::TYPE_KEY: {
// 构建KeyEvent
KeyEvent* keyEvent = factory->createKeyEvent();
if (!keyEvent) return NO_MEMORY;
// 从msg中读取事件 , 初始化keyEvent
initializeKeyEvent(keyEvent, &mMsg);
*outSeq = mMsg.body.key.seq;
*outEvent = keyEvent;
break;
}
case AINPUT_EVENT_TYPE_MOTION: {
ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
if (batchIndex >= 0) {
Batch& batch = mBatches.editItemAt(batchIndex);
if (canAddSample(batch, &mMsg)) {
batch.samples.push(mMsg);
break;
} else {
mMsgDeferred = true;
status_t result = consumeSamples(factory,
batch, batch.samples.size(), outSeq, outEvent);
mBatches.removeAt(batchIndex);
if (result) {
return result;
}
break;
}
}
// Start a new batch if needed.
if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE
|| mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
mBatches.push();
Batch& batch = mBatches.editTop();
batch.samples.push(mMsg);
break;
}
// 构建MotionEvent
MotionEvent* motionEvent = factory->createMotionEvent();
if (! motionEvent) return NO_MEMORY;
updateTouchState(&mMsg);
initializeMotionEvent(motionEvent, &mMsg);
*outSeq = mMsg.body.motion.seq;
*outEvent = motionEvent;
break;
}
default:
ALOGE("channel '%s' consumer ~ Received unexpected message of type %d",
mChannel->getName().string(), mMsg.header.type);
return UNKNOWN_ERROR;
}
}
return OK;
}
-
InputEventReceiver.dispatchInputEvent
中 , 开始分发应用层的事件 , 而在ViewRootImpl
中 , 使用的是子类WindowInputEventReceiver
// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@Override
public void onInputEvent(InputEvent event) {
// 将InputEvent加入队列
enqueueInputEvent(event, this, 0, true);
}
@Override
public void onBatchedInputEventPending() {
if (mUnbufferedInputDispatch) {
super.onBatchedInputEventPending();
} else {
scheduleConsumeBatchedInput();
}
}
@Override
public void dispose() {
unscheduleConsumeBatchedInput();
super.dispose();
}
}
-
enqueueInputEvent
判断是否是立即分发 , 还是插入队列等待执行. 上一个函数为true
代表立即执行
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
// 传入的参数enqueueInputEvent(event, this, 0, true);
adjustInputEventForCompatibility(event);
// 从Queue中获取InputEvent
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
// 获取队列的tail
QueuedInputEvent last = mPendingInputEventTail;
// 将事件插入到队列尾部
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
mPendingInputEventCount += 1;
// 是否立即处理
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
doProcessInputEvents
void doProcessInputEvents() {
while (mPendingInputEventHead != null) {
// 从Header开始遍历
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;
mPendingInputEventCount -= 1;
// 更新InputEvent接收的事件戳
mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
// 开始分发
deliverInputEvent(q);
}
...
}
- 开始向
Stage
进行分发 , 在ViewRootImpl
中有很多个Stage
, 用来给各个子系统分发事件
private void deliverInputEvent(QueuedInputEvent q) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
}
InputStage stage;
// 判断该Event是否要发给mSyntheticInputStage
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
// 判断该Event是否不是发给输入法
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
// 通过stage进行继续分发
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
- 在
setView
的函数中 , 会生成InputStage pipeline
, 也就是会将该事件一层层往下传递
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
// Set up the input pipeline.
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
}
- 在
ViewPostImeInputStage
中 , 开始向DecorView分发事件
final class ViewPostImeInputStage extends InputStage {
public ViewPostImeInputStage(InputStage next) {
super(next);
}
@Override
protected int onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) {
return processKeyEvent(q);
} else {
final int source = q.mEvent.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
// 开始处理MotionEvent
return processPointerEvent(q);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
return processTrackballEvent(q);
} else {
return processGenericMotionEvent(q);
}
}
}
...
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
mAttachInfo.mUnbufferedDispatchRequested = false;
mAttachInfo.mHandlingPointerEvent = true;
// DecorView.dispatchPointerEvent 分发MotionEvent
boolean handled = mView.dispatchPointerEvent(event);
maybeUpdatePointerIcon(event);
maybeUpdateTooltip(event);
mAttachInfo.mHandlingPointerEvent = false;
if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
mUnbufferedInputDispatch = true;
if (mConsumeBatchedInputScheduled) {
scheduleConsumeBatchedInputImmediately();
}
}
return handled ? FINISH_HANDLED : FORWARD;
}
...
}
15.在DecorView.dispatchTouchEvent
中 , 会通过Window Callback
来处理事件 , 而Window Callback则是在Activity.attach
中注册的
/**
* DecorView.java
**/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
/**
* 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) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
// 创建PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
// 设置Callback为Activity
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
...
}
- 在
Activity.dispatchTouchEvent
中
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
// 给到DecorView的rootView开始分发 , 也就是走View的
// dispatchTouchEvent、onInterceptTouchEvent、Listener.onTouchEvent、onTouchEvent
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
// 回调Activity的onTouchEvent
return onTouchEvent(ev);
}
参考资料
Android事件分发机制