前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android中窗口Input事件接收

Android中窗口Input事件接收

作者头像
None_Ling
发布2020-09-28 11:22:32
3.6K0
发布2020-09-28 11:22:32
举报
文章被收录于专栏:Android相关Android相关

简述

窗口接收事件主要分为三步骤 :

  1. 窗口与InputManagerService建立连接
    • InputManagerService初始化的时候会创建InputReaderInputDispatcher两个线程监听/dev/input的事件 , 并且进行分发
    • ActivityThread.performResumeActivity中开始创建客户端的InputChannel
    • 通过Seesion.addToDisplay通过out的方式让InputManagerService填充客户端InputChannel
    • InputManagerService中会通过socketpair创建基于fd的socket,然后通过epoll监听该文件事件
  2. InputManagerService选择窗口
    • InputDispatcher监听到InputReader中的事件后 , 会根据当前x、y来找到已经注册的WindowHandle
    • 接着根据WindowHandle找到对应的InputChannel以及Connection
    • 接着将MotionEvent对应的二进制数据通过SocketFD发送给客户端窗口
  3. 窗口响应事件
    • Activity.attach的时候 , 会创建PhoneWindow,并且设置Callback
    • ViewRootImpl.setView中 , 创建WindowInputEventReceiver用于接收InputChannel的事件
    • WindowInputEventReceiver中会将客户端SocketClientFD通过Looper.addFd()添加到Looper监听中
    • 当接收到SocketServer发送的二进制数据后 , InputConsumer会将二进制数据解析成MotionEventInputEvent
    • 最后会通过PhoneWindow注册的Callback,也就是Ativity进行dispatchTouchEvent
    • Activity.dispatchTouchEvent中 , 会优先进行DecorView中Touch事件的分发 , 如果都没有处理的话 , 则调用Activity.onTouch

Activity与ViewGroup分发事件的流程

窗口与InputManagerService建立连接

  1. ViewRootImpl.setView()
代码语言:javascript
复制
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());
                }
                ...
            }
        }
    }
  1. 在创建IWindowSession.aidl中 , 通过在AIDL上添加out关键字 , 允许服务端向客户端填充相关内容.
代码语言:javascript
复制
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);
    ...
}
  1. 在SystemServer的Session.addToDisplay最终会调用到WMS.addWindow
代码语言:javascript
复制
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;
    }
  1. WindowState.openInputChannel
  • 通过InputChannel.openInputChannelPair在Native层创建基于文件的两个Socket
  • 将SocketClient、SocketServer赋值给outInputChannel
代码语言:javascript
复制
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);
    }
  1. 通过NaticeOpenInputChannelPair方法创建对应的InputChannel
代码语言:javascript
复制
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<InputChannel> serverChannel;
    sp<InputChannel> 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<NativeInputChannel>(serverChannel));
    if (env->ExceptionCheck()) {
        return NULL;
    }
    // 创建clientChanneld对象
    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
            std::make_unique<NativeInputChannel>(clientChannel));
    if (env->ExceptionCheck()) {
        return NULL;
    }
    // 为数组赋值
    env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
    env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
    // 返回数组
    return channelPair;
}
  1. openInputChannelPair中创建client/server的Socket
代码语言:javascript
复制
tatus_t InputChannel::openInputChannelPair(const String8& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& 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);
}
  1. 在创建完SocketPair后 , 会将InputChannel注册到InputManager中registerInputChannel , 最后会在Native层的nativeRegisterInputChannel完成注册
代码语言:javascript
复制
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>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
      // 调用Dispatcher.regisgerInputChannel
    return mInputManager->getDispatcher()->registerInputChannel(
            inputChannel, inputWindowHandle, monitor);
}
  1. registerInputChannelInputDispatcher中注册InputChannel
代码语言:javascript
复制
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& 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> 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选择窗口分发事件

  1. 之前说到 , 在InputDispathcer.dispatchMotionLocked中会找到应用的窗口
代码语言:javascript
复制
bool InputDispatcher::dispatchMotionLocked(
        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ...
    // 判断是否为触碰消息
    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
    // 找到接收事件的窗口
    Vector<InputTarget> 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;
  1. findTouchedWindowTargetsLocked , 根据x,y以及窗口坐标找到匹配的WindowHandle
代码语言:javascript
复制
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
        const MotionEntry* entry, Vector<InputTarget>& 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<InputWindowHandle> newTouchedWindowHandle;
        bool isTouchModal = false;
        // 遍历所有的WindowHandle
        size_t numWindows = mWindowHandles.size();
        for (size_t i = 0; i < numWindows; i++) {
            sp<InputWindowHandle> 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<InputWindowHandle> oldTouchedWindowHandle =
                    mTempTouchState.getFirstForegroundWindowHandle();
            // 根据x、y、display ID获取TouchWindow
            sp<InputWindowHandle> newTouchedWindowHandle =
                    findTouchedWindowAtLocked(displayId, x, y);
            if (oldTouchedWindowHandle != newTouchedWindowHandle
                    && newTouchedWindowHandle != NULL) {
                //  如果本次与上次接收TouchEvent的窗口不一样的话 , 就更新mTempTouchState
                mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
                        InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
              ....
            }
        }
        ...
    }
  1. dispatchEventLocked开始分发Touch事件
代码语言:javascript
复制
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, const Vector<InputTarget>& 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> 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

代码语言:javascript
复制
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    ...
    
    // 如果Entry需要分割一下的话 , 则分割后再分发
    if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(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);
}
  1. enqueueDispatchEntriesLocked
代码语言:javascript
复制
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
        const sp<Connection>& 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);
    }
}
  1. enqueueDispatchEntryLocked
代码语言:javascript
复制
void InputDispatcher::enqueueDispatchEntryLocked(
        const sp<Connection>& 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<KeyEntry*>(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<MotionEntry*>(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);
}
  1. startDispatchCycleLocked
代码语言:javascript
复制
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& 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<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;
        }

        case EventEntry::TYPE_MOTION: {
            // 如果是MotionEvent
            MotionEntry* motionEntry = static_cast<MotionEntry*>(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);
    }
}
  1. InputPublisher::publishMotionEvent
代码语言:javascript
复制
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);
}
  1. sendMessage通过send函数 , 通过Socket的FD将二进制数据给到客户端窗口
代码语言:javascript
复制
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发送给对应的窗口

窗口响应事件

  1. session.addToDispaly函数调用后 , InputManagerService将InputChannel信息填充给对应的Window
代码语言:javascript
复制
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());
                }
                ...
            }
        }
    }
  1. WindowInputEventReceiver继承自InputEventReceiver
代码语言:javascript
复制
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<InputEventReceiver>(this),
                inputChannel, mMessageQueue);

        mCloseGuard.open("dispose");
    }
  1. nativeInit
代码语言:javascript
复制
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject inputChannelObj, jobject messageQueueObj) {
    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
      ...
    //   获取Native对应的MessageQueue对象
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    ...
    // 创建NativeInputEventReceiver对象
    sp<NativeInputEventReceiver> 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<jlong>(receiver.get());
}
  1. NativeInputEventReceiver中会通过setFdEvents来监听socket文件的事件
代码语言:javascript
复制
NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
        jobject receiverWeak, const sp<InputChannel>& inputChannel,
        const sp<MessageQueue>& 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;
}
  1. setFdEvents中 , 将socket文件的监听放到主线程Looper中
代码语言:javascript
复制
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);
        }
    }
}
  1. 当Looper监听到相应FD的事件时 , 就会回调handleEvent
代码语言:javascript
复制
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;
}
  1. 当接收到socket事件后 , 开始消费事件 , 即开始分发给对应的View
代码语言:javascript
复制
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    ...
    ScopedLocalRef<jobject> 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<KeyEvent*>(inputEvent));
                break;

            case AINPUT_EVENT_TYPE_MOTION: {
                // 将MotionEvent赋值给inputEventObj
                MotionEvent* motionEvent = static_cast<MotionEvent*>(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

代码语言:javascript
复制
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;
}
  1. InputEventReceiver.dispatchInputEvent中 , 开始分发应用层的事件 , 而在ViewRootImpl中 , 使用的是子类WindowInputEventReceiver
代码语言:javascript
复制
    // 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();
        }
    }
  1. enqueueInputEvent判断是否是立即分发 , 还是插入队列等待执行. 上一个函数为true代表立即执行
代码语言:javascript
复制
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();
        }
    }
  1. doProcessInputEvents
代码语言:javascript
复制
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);
        }
        ...
    }
  1. 开始向Stage进行分发 , 在ViewRootImpl中有很多个Stage , 用来给各个子系统分发事件
代码语言:javascript
复制
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);
        }
    }
  1. setView的函数中 , 会生成InputStage pipeline , 也就是会将该事件一层层往下传递
代码语言:javascript
复制
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;
}
  1. ViewPostImeInputStage中 , 开始向DecorView分发事件
代码语言:javascript
复制
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中注册的

代码语言:javascript
复制
/**
* 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);
        }
        ...
}
  1. Activity.dispatchTouchEvent
代码语言:javascript
复制
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事件分发机制

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简述
  • Activity与ViewGroup分发事件的流程
  • 窗口与InputManagerService建立连接
  • InputManagerSercice选择窗口分发事件
  • 窗口响应事件
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档