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

其他教程   发布日期:2023年08月29日   浏览次数:466

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

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

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

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

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

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

调用WMS中的成员mInputManager

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

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

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

调用的mNative的方法

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

  1. public InputManagerService(Context context) {
  2. this(new Injector(context, DisplayThread.get().getLooper()));
  3. }
  4. @VisibleForTesting
  5. InputManagerService(Injector injector) {
  6. // The static association map is accessed by both java and native code, so it must be
  7. // initialized before initializing the native service.
  8. mStaticAssociations = loadStaticInputPortAssociations();
  9. mContext = injector.getContext();
  10. mHandler = new InputManagerHandler(injector.getLooper());
  11. mNative = injector.getNativeService(this);
  12. ....
  13. }
  14. //frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java
  15. NativeInputManagerService getNativeService(InputManagerService service) {
  16. return new NativeInputManagerService.NativeImpl(service, mContext, mLooper.getQueue());
  17. }

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

  1. //frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
  2. base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
  3. const std::string& name) {
  4. ATRACE_CALL();
  5. return mInputManager->getDispatcher().createInputChannel(name);
  6. }

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

  1. InputManager* im = new InputManager(this, this);
  2. mInputManager = im;

看看InputManager怎么初始化

  1. InputManager::InputManager(
  2. const sp<InputReaderPolicyInterface>& readerPolicy,
  3. const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
  4. mDispatcher = createInputDispatcher(dispatcherPolicy);
  5. mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
  6. mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
  7. mReader = createInputReader(readerPolicy, *mBlocker);
  8. }

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

  1. //frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
  2. Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
  3. if (DEBUG_CHANNEL_CREATION) {
  4. ALOGD("channel '%s' ~ createInputChannel", name.c_str());
  5. }
  6. std::unique_ptr<InputChannel> serverChannel;
  7. std::unique_ptr<InputChannel> clientChannel;
  8. //调用创建了一个serverChannel和一个clientChannel
  9. status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
  10. if (result) {
  11. return base::Error(result) << "Failed to open input channel pair with name " << name;
  12. }
  13. { // acquire lock
  14. std::scoped_lock _l(mLock);
  15. const sp<IBinder>& token = serverChannel->getConnectionToken();
  16. int fd = serverChannel->getFd();
  17. sp<Connection> connection =
  18. new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);
  19. if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
  20. ALOGE("Created a new connection, but the token %p is already known", token.get());
  21. }
  22. mConnectionsByToken.emplace(token, connection);
  23. std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
  24. this, std::placeholders::_1, token);
  25. mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
  26. } // release lock
  27. // Wake the looper because some connections have changed.
  28. mLooper->wake();
  29. return clientChannel;
  30. }

createInputChannel干了3件事

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

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

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

首先看下openInputChannelPair

  1. //frameworks/native/libs/input/InputTransport.cpp
  2. status_t InputChannel::openInputChannelPair(const std::string& name,
  3. std::unique_ptr<InputChannel>& outServerChannel,
  4. std::unique_ptr<InputChannel>& outClientChannel) {
  5. int sockets[2];
  6. //真正创建了socket
  7. if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
  8. status_t result = -errno;
  9. ALOGE("channel '%s' ~ Could not create socket pair. errno=%s(%d)", name.c_str(),
  10. strerror(errno), errno);
  11. outServerChannel.reset();
  12. outClientChannel.reset();
  13. return result;
  14. }
  15. //设置了socket传输的大小为32k
  16. int bufferSize = SOCKET_BUFFER_SIZE;
  17. setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
  18. setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
  19. setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
  20. setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
  21. sp<IBinder> token = new BBinder();
  22. std::string serverChannelName = name + " (server)";
  23. android::base::unique_fd serverFd(sockets[0]);
  24. outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
  25. std::string clientChannelName = name + " (client)";
  26. android::base::unique_fd clientFd(sockets[1]);
  27. outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
  28. return OK;
  29. }

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

回到createInputChannel中

  1. const sp<IBinder>& token = serverChannel->getConnectionToken();
  2. int fd = serverChannel->getFd();//拿到socket fd
  3. sp<Connection> connection =
  4. new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);
  5. if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
  6. ALOGE("Created a new connection, but the token %p is already known", token.get());
  7. }
  8. mConnectionsByToken.emplace(token, connection);
  9. std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
  10. this, std::placeholders::_1, token);
  11. 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事件分发中事件是怎么来的的详细内容,更多关于Android事件分发中事件是怎么来的的资料请关注九品源码其它相关文章!