Android InputChannel连接

InputChannel是InputDispatcher 和应用程序 (InputTarget) 的通讯桥梁,InputDispatcher 通知应用程序有输入事件,通过InputChannel中的socket进行通信。

连接InputDispatcher和窗口

WinodwManagerService:addwindow: WMS 添加窗口时,会创建一对 InputChannel,其中一个保存在 WindowState 中,并注册给 IMS,它是服务端,另一个则通过传出参数 outInputChannel 交给调用者,是客户端

1.服务端连接的建立

addwindow 函数中,有以下三项工作:

通过 WindowState.setInputChannel 函数保存服务端的 InputChannel

通过 IMS.registerInputChannel 将 InputChannel 注册到 IMS

通过 InputMonitor.updateInputWindowsLw 将所有窗口的信息更新到 IMS

2.窗口端连接的建立

当窗口端通过 addwindow 函数获取 InputChannel,便会使用它创建一个 InputEventReceiver 对象,可以接收来自InputChannel 的输入事件,触发 onInputEvent 回调

InputEventRecevier 如何工作?将 InputChannel 的可读事件注册到 Looper,然后在事件到来时从 InputChannel 中读取 InputMessage,并翻译成 InputEvent,然后回调 InputEventReceiver 的 onInputEvent

详细调用栈如下: 

@frameworks/base/core/java/android/view/ViewRootImpl.java
setView
    inputChannel = new InputChannel();
@frameworks/base/services/core/java/com/android/server/wm/Session.java
    mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes, mDisplay.getDisplayId(), userId, inputChannel
@frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java    
        Service.addWindow(this, window, attrs, viewVisibility, displayId, userId, requestedVisibilities, outInputChannel,    //WinodwManagerService:addwindow
@frameworks/base/services/core/java/com/android/server/wm/WindowState.java
            win.openInputChannel(outInputChannel);
@frameworks/base/services/core/java/com/android/server/input/InputManagerService.java            
                mInputChannel = mWmService.mInputManager.createInputChannel(name);
@frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp                
                    nativeCreateInputChannel(mPtr, name);
                        NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
                        base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(env, name);
@frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp                        
                            mInputManager->getDispatcher()->createInputChannel(name);
@frameworks/native/libs/input/InputTransport.cpp
                                status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
                                    socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)
                                    std::string serverChannelName = name + " (server)";
                                    outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
                                    std::string clientChannelName = name + " (client)";
                                    outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
@frameworks/native/services/inputflinger/dispatcher/Connection.cpp
                                sp<Connection> connection = new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);
                                    inputChannel(inputChannel),
                                    inputPublisher(inputChannel),
                                std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token);
                                mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
                mInputChannel.copyTo(outInputChannel);  //复制给outInputChannel
            if (focusChanged) { displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus, false /*updateInputWindows*/);
@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
            displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
                scheduleUpdateInputWindows();
                    mHandler.post(mUpdateInputWindows);
                        run()
                            mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
                                updateInputFocusRequest(mRecentsAnimationInputConsumer);
                                    requestFocus(recentsAnimationInputConsumer.mWindowHandle.token, recentsAnimationInputConsumer.mName);
@frameworks/base/core/java/android/view/SurfaceControl.java
                                        mInputTransaction.setFocusedWindow(mInputFocus, windowName, mDisplayId);     
                                            nativeSetFocusedWindow(mNativeObject, token,  windowName, null /* focusedToken */, null /* focusedWindowName */, displayId);
@frameworks/native/libs/gui/SurfaceComposerClient.cpp                                            
                                                transaction->setFocusedWindow(request);
                                                    mInputWindowCommands.focusRequests.push_back(request);
@frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
                                                        SurfaceFlinger::handleMessageTransaction
                                                            if (getTransactionFlags(eTransactionFlushNeeded)) { flushTransactionQueues();}
                                                                applyTransactionState(transaction.states,  transaction.displays, transaction.inputWindowCommands,
                                                                    transactionFlags |= addInputWindowCommands(inputWindowCommands);
@frameworks/native/libs/gui/LayerState.cpp                                                                    
                                                                        bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);
                                                                            focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()),
                                                                                SurfaceFlinger::onMessageInvalidate
                                                                                    updateInputFlinger();
@frameworks/native/services/inputflinger/InputManager.cpp                                                                                    
                                                                                        for (const auto& focusRequest : mInputWindowCommands.focusRequests) { mInputFlinger->setFocusedWindow(focusRequest);}
                                                                                            mDispatcher->setFocusedWindow(request);
@frameworks/base/core/jni/android_view_SurfaceControl.cpp                            
    mInputEventReceiver = new WindowInputEventReceiver(inputChannel, Looper.myLooper());
@frameworks/base/core/java/android/view/InputEventReceiver.java
        super(inputChannel, looper);
@frameworks/base/core/jni/android_view_InputEventReceiver.cpp
            mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this), inputChannel, mMessageQueue);
                sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env, receiverWeak, inputChannel, messageQueue);
                status_t status = receiver->initialize();
                    setFdEvents(ALOOPER_EVENT_INPUT);
                        mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
    // Set up the input pipeline.
    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;


//InputDispatcher向InputChannel使用socket写入输入事件,触发InputEventReceiver调用来接收输入事件
@frameworks/base/core/jni/android_view_InputEventReceiver.cpp
NativeInputEventReceiver::handleEvent
    NativeInputEventReceiver::consumeEvents(env, false /*consumeBatches*/, -1, nullptr)
@frameworks/native/libs/input/InputTransport.cpp
        mInputConsumer.consume(&mInputEventFactory, consumeBatches, frameTime, &seq, &inputEvent);
            status_t result = mChannel->receiveMessage(&mMsg);
                nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);   //从socket中读输入事件
            case InputMessage::Type::FOCUS: {
                initializeFocusEvent(focusEvent, &mMsg);
            case InputMessage::Type::MOTION: {
                initializeMotionEvent(motionEvent, &mMsg);
                //构造java的event事件
        case AINPUT_EVENT_TYPE_FOCUS: { 
            env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onFocusEvent, jboolean(focusEvent->getHasFocus()), jboolean(focusEvent->getInTouchMode()));
@frameworks/base/core/java/android/view/ViewRootImpl.java
                onFocusEvent
                    windowFocusChanged(hasFocus, inTouchMode);
                        msg.what = MSG_WINDOW_FOCUS_CHANGED;
                        mHandler.sendMessage(msg);
                            case MSG_WINDOW_FOCUS_CHANGED: { handleWindowFocusChanged(); }                                
        case AINPUT_EVENT_TYPE_MOTION: {
            inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
        if (inputEventObj) {  env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
@frameworks/base/core/java/android/view/InputEventReceiver.java    
            dispatchInputEvent
@frameworks/base/core/java/android/view/ViewRootImpl.java
                onInputEvent(event);
                    enqueueInputEvent(event, this, 0, true);
                        if (processImmediately) { doProcessInputEvents(); }
                            deliverInputEvent(q);  //在deliverInputEvent函数中做输入事件的实际分发
                                stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;  //这里开始选择 责任链的入口,具体请看InputStage的处理流程
                                stage.deliver(q);  //这里主要调用InputStage的deliver方法进行分发,InputStage代表了输入事件的处理阶段,使用责任链模式设计模式。
                                    result = onProcess(q);
                                        NativePreImeInputStage::onProcess

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛文旺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值