返回顶部
首页 > 资讯 > 精选 >Android事件分发中事件是怎么来的
  • 242
分享到

Android事件分发中事件是怎么来的

2023-07-05 12:07:13 242人浏览 独家记忆
摘要

本文小编为大家详细介绍“Android事件分发中事件是怎么来的”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android事件分发中事件是怎么来的”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Andriod事件

本文小编为大家详细介绍“Android事件分发中事件是怎么来的”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android事件分发中事件是怎么来的”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

Andriod事件分发的事件从何而来

注册事件回调是通过mwindowsession.addToDisplayAsUser来实现的,这是一个Binder调用实际调用的是frameworks/base/services/core/java/com/android/server/wm/Session.java这个类。

 //frameworks/base/services/core/java/com/android/server/wm/Session.java   @Override    public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,            int viewVisibility, int displayId, int userId, InsetsVisibilities requestedVisibilities,            InputChannel outInputChannel, InsetsState outInsetsState,            InsetsSourceControl[] outActiveControls, Rect outAttachedFrame,            float[] outSizeCompatScale) {        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,                requestedVisibilities, outInputChannel, outInsetsState, outActiveControls,                outAttachedFrame, outSizeCompatScale);    }

这里的mService就是WMS.调用的就是WMS的addWindow,addWindow方法很长,其中与事件相关的就两行

//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java......             final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);  win.openInputChannel(outInputChannel);
//frameworks/base/services/core/java/com/android/server/wm/WindowState.javavoid openInputChannel(InputChannel outInputChannel) {        if (mInputChannel != null) {            throw new IllegalStateException("Window already has an input channel.");        }        String name = getName();        mInputChannel = mWmService.mInputManager.createInputChannel(name);        mInputChannelToken = mInputChannel.getToken();        mInputWindowHandle.setToken(mInputChannelToken);        mWmService.mInputToWindowMap.put(mInputChannelToken, this);        if (outInputChannel != null) {          //将native创建的InputChannel复制给参数outInputChannel            mInputChannel.copyTo(outInputChannel);        } else {            // If the window died visible, we setup a fake input channel, so that taps            // can still detected by input monitor channel, and we can relaunch the app.            // Create fake event receiver that simply reports all events as handled.            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mInputChannel);        }    }

调用WMS中的成员mInputManager

调用了WMS中的成员mInputManager来注册了InputChannel,mInputManager是一个InputManagerService。

这下就对了,事件从InputManagerService中来很合理。

    public InputChannel createInputChannel(String name) {        return mNative.createInputChannel(name);    }

调用的mNative的方法

这个对象是在InputManagerService创建的时候初始化的

    public InputManagerService(Context context) {        this(new Injector(context, DisplayThread.get().getLooper()));    }    @VisibleForTesting    InputManagerService(Injector injector) {        // The static association map is accessed by both java and native code, so it must be        // initialized before initializing the native service.        mStaticAssociations = loadStaticInputPortAssociations();        mContext = injector.getContext();        mHandler = new InputManagerHandler(injector.getLooper());        mNative = injector.getNativeService(this);      ....    }//frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java       NativeInputManagerService getNativeService(InputManagerService service) {            return new NativeInputManagerService.NativeImpl(service, mContext, mLooper.getQueue());        }

最终返回的是一个NativeImpl实例。字面意思就知道了,这是一个Native方法的实现,createInputChannel来到了native层。

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cppbase::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(        const std::string& name) {    ATRACE_CALL();    return mInputManager->getDispatcher().createInputChannel(name);}

调用了mInputManager的getDispatcher函数看名字就知道应该有个变量mDispatcher,查看mInputManager是怎么创建的可以发现是在NativeInputManager创建的时候初始化的

    InputManager* im = new InputManager(this, this);    mInputManager = im;

看看InputManager怎么初始化

InputManager::InputManager(        const sp<InputReaderPolicyInterface>& readerPolicy,        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {    mDispatcher = createInputDispatcher(dispatcherPolicy);    mClassifier = std::make_unique<InputClassifier>(*mDispatcher);    mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);    mReader = createInputReader(readerPolicy, *mBlocker);}

这里就出现了重要的两个类InputDispatcherInputReader,createInputChanne方法l最终调用到了InputDispatcher中的createInputChannel。

//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cppResult<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {    if (DEBUG_CHANNEL_CREATION) {        ALOGD("channel '%s' ~ createInputChannel", name.c_str());    }    std::unique_ptr<InputChannel> serverChannel;    std::unique_ptr<InputChannel> clientChannel;  //调用创建了一个serverChannel和一个clientChannel    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);    if (result) {        return base::Error(result) << "Failed to open input channel pair with name " << name;    }    { // acquire lock        std::scoped_lock _l(mLock);        const sp<IBinder>& token = serverChannel->getConnectionToken();        int fd = serverChannel->getFd();        sp<Connection> connection =                new Connection(std::move(serverChannel), false , mIdGenerator);        if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {            ALOGE("Created a new connection, but the token %p is already known", token.get());        }        mConnectionsByToken.emplace(token, connection);        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);    } // release lock    // Wake the looper because some connections have changed.    mLooper->wake();    return clientChannel;}

createInputChannel干了3件事

  • 首先使用openInputChannelPair创建了2个InputChannel,一个clientChannel和一个serverChannel

  • 将serverChannel封装成connection,并放入成员变量mConnectionsByToken中管理,这样在事件到来的时候就可以使用connection向客户端发送事件了

  • 利用Looper持续监听serverChannel,事件处理的回调消息会就到InputDispatcher::handleReceiveCallback回调,最后把clientChannel返回给客户端,也就是最初在WMS中得到的InputChannel。

首先看下openInputChannelPair

//frameworks/native/libs/input/InputTransport.cppstatus_t InputChannel::openInputChannelPair(const std::string& name,                                            std::unique_ptr<InputChannel>& outServerChannel,                                            std::unique_ptr<InputChannel>& outClientChannel) {    int Sockets[2];  //真正创建了socket    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {        status_t result = -errno;        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%s(%d)", name.c_str(),              strerror(errno), errno);        outServerChannel.reset();        outClientChannel.reset();        return result;    }//设置了socket传输的大小为32k    int bufferSize = SOCKET_BUFFER_SIZE;    setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));    sp<IBinder> token = new BBinder();    std::string serverChannelName = name + " (server)";    android::base::unique_fd serverFd(sockets[0]);    outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);    std::string clientChannelName = name + " (client)";    android::base::unique_fd clientFd(sockets[1]);    outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);    return OK;}

熟悉linux的话就知道socketpair创建了一对双向的socket,往socket[0]中写能从socket[1]读,反向也是一样,分别创建了outServerChannel和outClientChannel,两个InputChannel有着同一个BBinder作为token。

回到createInputChannel中

 const sp<IBinder>& token = serverChannel->getConnectionToken();        int fd = serverChannel->getFd();//拿到socket fd        sp<Connection> connection =                new Connection(std::move(serverChannel), false , mIdGenerator);        if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {            ALOGE("Created a new connection, but the token %p is already known", token.get());        }        mConnectionsByToken.emplace(token, connection); 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);

这里将创建的serverChannel封装成了connection,同时用token作为key,存到了mConnectionsByToken中,这样就可以利用token来快速找到serverChannel封装的connection。最后监听serverChannel的fd,有事件时回调给InputDispatcher::handleReceiveCallback方法的最后把创建的clientChannel返回给了客户端,就是开头的WMS中。这样在WMS就也能通过clientChannel来获取事件了。

读到这里,这篇“Android事件分发中事件是怎么来的”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: Android事件分发中事件是怎么来的

本文链接: https://lsjlt.com/news/351690.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android事件分发中事件是怎么来的
    本文小编为大家详细介绍“Android事件分发中事件是怎么来的”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android事件分发中事件是怎么来的”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Andriod事件...
    99+
    2023-07-05
  • Andriod事件分发事件怎么来的
    本篇内容主要讲解“Andriod事件分发事件怎么来的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Andriod事件分发事件怎么来的”吧!Android事件分发的事件从何而来事件分发一直以来都是...
    99+
    2023-07-05
  • Android事件分发机制(上) ViewGroup的事件分发
    综述   Android中的事件分发机制也就是View与ViewGroup的对事件的分发与处理。在ViewGroup的内部包含了许多View,而ViewGroup继承自View...
    99+
    2022-06-06
    Android
  • Andriod事件分发事件由来初识
    目录Android事件分发的事件从何而来Activity的事件分发ViewRootImpl事件分发DecorView事件处理Android事件分发的事件从何而来 事件分发一直以来都...
    99+
    2023-03-15
    Android事件分发 Android事件由来
  • Android事件分发的流程是什么
    Android事件分发的流程如下: 事件发生:用户在屏幕上进行触摸或其他操作。 事件捕获:事件首先被传递给顶级父视图(通常是...
    99+
    2023-10-24
    Android
  • android事件分发流程是什么
    Android事件分发流程主要包括以下几个步骤:1. 事件产生:用户在屏幕上进行触摸、点击、滑动等操作时,会产生相应的事件。2. 事...
    99+
    2023-08-15
    android
  • Android中怎么实现 View事件分发
    这篇文章给大家介绍Android中怎么实现 View事件分发,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。(1)ViewGroup.dispatchTouchEvent(event)boolean dispa...
    99+
    2023-05-30
    android view
  • Android事件分发机制(下) View的事件处理
    综述   在上篇文章Android中的事件分发机制(上)——ViewGroup的事件分发中,对ViewGroup的事件分发进行了详细的分析。在文章的最后ViewGroup的di...
    99+
    2022-06-06
    view Android
  • Android 点击事件分发
    Android 点击事件分发Activity中对事件的处理ViewGroup是如何进行事件处理的View的dispatchTouchEvent相...
    99+
    2022-06-06
    事件 Android
  • Android事件分发机制
    事件分发流程相关 一个事件发生后,首先从Acrtivity开始传递,然后一层一层往下传,从上往下调用dispatchTouchEvent方法传递...
    99+
    2022-06-06
    Android
  • 聊聊Android中的事件分发机制
    目录Activity的事件分发机制 ViewGroup的事件分发机制 View的事件分发机制 View事件分发机制的本质就是就是MotionEvent事件的分发过程,即MotionE...
    99+
    2024-04-02
  • Android View的事件分发机制
    一.Android View框架提供了3个对事件的主要操作概念。 1、事件的分发机制,dispatchTouchEvent。主要是parent根据触摸事件的产生位置,以及chi...
    99+
    2022-06-06
    view 事件 Android
  • android中事件分发机制的实现原理是什么
    android中事件分发机制的实现原理是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。android中的事件处理,以及解决滑动冲突问题都离不开事件分发机制,androi...
    99+
    2023-05-30
    android
  • android事件分发与处理的方法是什么
    Android事件分发与处理的方法主要有以下几种:1. 触摸事件分发处理:Android中的触摸事件主要包括按下、移动、抬起等动作。...
    99+
    2023-09-13
    android
  • android事件传递与分发的流程是什么
    在Android中,事件传递与分发的流程如下:1. 事件产生:事件可以由用户触摸屏幕、按下按钮等方式产生。2. 事件分发:事件由系统...
    99+
    2023-10-18
    android
  • Android事件的分发机制详解
    在分析Android事件分发机制前,明确android的两大基础控件类型:View和ViewGroup。View即普通的控件,没有子布局的,如Button、TextView. ...
    99+
    2022-06-06
    Android
  • Android事件分发机制的详解
    Android事件分发机制我们只考虑最重要的四个触摸事件,即:DOWN,MOVE,UP和CANCEL。一个手势(gesture)是一个事件列,以一个DOWN事件开始(当用户触摸屏幕时产生),后跟0个或多个MOVE事件(当用户四处移动手指时产...
    99+
    2023-05-30
    android 事件 分发
  • Android事件分发机制 ViewGroup分析
    目录整体流程源码分析前言: 事件分发从手指触摸屏幕开始,即产生了触摸信息,被底层系统捕获后会传递给Android的输入系统服务IMS,通过Binder把消息发送到activity,a...
    99+
    2024-04-02
  • Android 事件分发机制 讲解
    1、分发事件的组件 分发事件的组件,也称为分发事件者,包括Activity、ViewGroup和View。它们三者的一般结构为: 从上图中可以...
    99+
    2022-06-06
    事件 Android
  • Android怎么开发Input系统触摸事件分发
    本篇内容介绍了“Android怎么开发Input系统触摸事件分发”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!引言Input系统: Inpu...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作