• android中输入系统之内核到InputManagerService过程(源码)


    愿每一份努力都不会被辜负-陈

    总体流程

    在Android中,Touch事件的分发分服务端和应用端。在服务端由WindowManagerService(借助InputManagerService)负责采集和分发的,在应用端则
    是由ViewRootlmpl(内部有一个mView变量指向View树的根,负责控制View树的Ul绘制和事件消息的分发)负责分发的。当输入设备可用时,比如触屏,Linux内核会在/dev/input中创建对应的设备节点,输入事件所产生的原始信息会被Linux内核中的输入子系统采集,原始信息由Kernel Space的驱动层一直传递到User Space的设备节点。IMS所做的工作就是监听/dev/input下的所有的设备节点,当设备节点有数据时会将数据进行加工处理并找到合适的Window,将输入事件派发给它。

    总体来说分为以下三个流程:事件采集,事件中转以及事件分发。

    在这里插入图片描述

    事件的本质

    事件的本质其实就是一个个文件,事件产生后由Linux系统将数据保存到dev/input文件夹下。

    我们可以通过命令来获取输入事件的信息:

    adb shell getevent
    adb shell input event 4
    adb shell getevent -t -I
    
    
    • 1
    • 2
    • 3
    • 4

    Linux-Posix函数(关键函数用到)

    • ePoll

      被公认为Linux2.6下性能最好的多路l/O就绪通知方法。

      epoll只有epoll_create,epoll_ctl,epoll_wait 3个系统调用。

      epoll create:当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽(无限的创建文件夹同样会导致fd被耗尽)。
      epoll _ctl:epol的事件注册函数,它不同于select(是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。
      epoll wait:收集在epoll监控的事件中已经发送的事件。参数events是分配好的epoll event结构体数组,epoll将会把发生的事件赋值到levents数组中(events不可以是空指针,内核只负责把数据复制到这个events数组中,不会去帮助我们在用户态中分配内存)。maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll create(时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。如果函数调用成功,返回对应/O上已准备好的文件描述符数目,如返回0表示已超时

      具体参考:https://blog.csdn.net/xiajun07061225/article/details/9250579

    • iNotify

      它是一个内核用于通知用户空间程序文件系统变化的机制

      int fd = inotify init ():每一个inotify实例对应一个独立的排序的队列

      inotify add watch:fd是 inotify init0返回的文件描述符,path是被监视的目标的路径名(即文件名或目录名),mask是事件掩码,在头文件linux/inotify.h中定义了每一位代表的事件。可以使用同样的方式来修改事件掩码,即改变希望被通知的inotify 事件。Wd是watch描述符。

      具体用法参考:https://blog.csdn.net/breakout_alex/article/details/89028868

    • socketpair

      socketpairO函数用于创建一对无名的、相互连接的套接子。

      具体使用参考:https://blog.csdn.net/weixin_40039738/article/details/81095013

    • fd

      linux中,每一个进程在内核中,都对应有一个“打开文件”数组,存放指向文件对象的指针,而fd是这个数组的下标。
      我们对文件进行操作时,系统调用,将fd传入内核,内核通过fd找到文件,对文件进行操作。
      既然是数组下标,fd的类型为int,<0为非法值,>=0为合法值。在ilinux中,一个进程默认可以打开的文件数为1024个,fd的范围为0~1023。可以通
      过设置,改变最大值。
      在linux中,值为0、1、2的fd,分别代表标准输入、标准输出、标准错误输出。

    从内核到IMS过程

    源码流程

    在这里插入图片描述

    EventHub

    • INotify

      INotify是Linux提供的一种文件系统变化通知机制,什么叫文件系统变化?创建,删除,读写通通叫做变化,使用如下代码就可以将某个目录加入到INotify中。

      int inotifyFd = inotify init();
      int wd =inotify_add_watch(inotifyFd,"/dev/input", IN_CREATE|IN_DELETE):
      
      • 1
      • 2

      上述两行代码就将”/dev/input”加入到了INotify中,这样,对于外部输入设备的插拔就可以很好的被检测到了。可不幸的是,INotify发现文件系统变化后不
      会主动告诉别人,它需要主动通过reado函数读取inotifyFd描述符来获取具体变化信息。也就是说,你插入了鼠标,INotify马上就知道了这个信息,并且将
      信息更新到了inotifyFd描述符对应的对象当中

    • Eventhub

      EventHub 通过读取/dev/input/下的相关文件来判断是否有新事件,并通知InputReader。

      Epoll可以用来监听多个描述符的可读写inotifyFd状态,什么意思呢?比如说上面说到了外部输入设备插拔可以被INotify检测到,并且将相信信息写入到inotifyFd对用的对象中,但是我没法知道INotify什么时候捕获到了这些信息。而Epoll可以监听inotifyFd对应的对象内容是否有变化,一旦有变化马上能进行处理,平常大部分时间没监听到变化时睡大觉(其实Android中的Handler中的消息队列用到了epoll机制)。

      epoll wait大部分时间处于阻塞状态(这点和socket等待连接很相似),一旦/dev/input/evento节点有变化(即产生了输入事件),epoll wait会执行完毕

      //frameworks/native/services/inputflinger/EventHub.cpp
      EventHub::EventHub(void) :
              mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
              mOpeningDevices(0), mClosingDevices(0),
              mNeedToSendFinishedDeviceScan(false),
              mNeedToReopenDevices(false), mNeedToScanDevices(true),
              mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
          acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
      
           //创建epoll列表
          mEpollFd = epoll_create(EPOLL_SIZE_HINT);
          LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
      
           //初始化盘符并且监听。
          mINotifyFd = inotify_init();
          int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
          LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",
                  DEVICE_PATH, errno);
      
          struct epoll_event eventItem;
          memset(&eventItem, 0, sizeof(eventItem));
          eventItem.events = EPOLLIN;
          eventItem.data.u32 = EPOLL_ID_INOTIFY;
           //epoll监听mINotifyFd。
          result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
          LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);
      
          int wakeFds[2];
          result = pipe(wakeFds);
          LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
      
          mWakeReadPipeFd = wakeFds[0];
          mWakeWritePipeFd = wakeFds[1];
      
          result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
          LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
                  errno);
      
          result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
          LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
                  errno);
      
          eventItem.data.u32 = EPOLL_ID_WAKE;
          result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
          LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
                  errno);
      
          int major, minor;
          getLinuxRelease(&major, &minor);
          // EPOLLWAKEUP was introduced in kernel 3.5
          mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52

    IMS概述

    • InputReaderThread

      InputReader会不断的循环读取EventHub中的原始输入事件。

    • InputDispatcherThread

      InputDispatcher中保存了WMS中的所有的Window信息(WMS会将窗口的信息实时的更新到InputDispatcher中),这样InputDispatcher就可以将输入事
      件派发给合适的Window

    整体流程源码分析

    1. 由SystemServer启动一个IMS进程进程,然后进行各个对象的初始化

      SystemServer开启其他服务(这个在之前的博客有详细介绍)

      //com/android/server/SystemServer.java 
      private void startOtherServices() {
            ......
              traceBeginAndSlog("StartInputManagerService");
              inputManager = new InputManagerService(context);
              traceEnd();
          
          //将inputManager与WindowManagerService关联
             wm = WindowManagerService.main(context, inputManager,
                          mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                          !mFirstBoot, mOnlyCore, new PhoneWindowManager());
          //注册wms服务
                  ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                          DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
          //注册ims服务
                  ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                          /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            ......
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

      InputManagerService的构造方法

          public InputManagerService(Context context) {
              this.mContext = context;
              this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
      
              mUseDevInputEventForAudioJack =
                      context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
              Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                      + mUseDevInputEventForAudioJack);
              //调用到jni的初始化方法。
              mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
      
              String doubleTouchGestureEnablePath = context.getResources().getString(
                      R.string.config_doubleTouchGestureEnableFile);
              mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
                  new File(doubleTouchGestureEnablePath);
      
              LocalServices.addService(InputManagerInternal.class, new LocalService());
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    2. 同步会在native层进行初始化,开启一个InputManager对象,开启两个线程,一个Reader线程用来读取触摸信号,一个Dispatcher用来转发信息,EventHub负责采集底层信号。

      通过jni调用到nativeInit方法。

      //frameworks/base/services/core/jni/com_android_server_input_InputManagerService
         
      static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
              jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
          sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
          if (messageQueue == NULL) {
              jniThrowRuntimeException(env, "MessageQueue is not initialized.");
              return 0;
          }
      
          //初始化InputManager
          NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
                  messageQueue->getLooper());
          im->incStrong(0);
          return reinterpret_cast<jlong>(im);
      } 
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      创建NativeInputManager对象

      ///frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
      NativeInputManager::NativeInputManager(jobject contextObj,
              jobject serviceObj, const sp& looper) :
              mLooper(looper), mInteractive(true) {
          JNIEnv* env = jniEnv();
      
          mContextObj = env->NewGlobalRef(contextObj);
          mServiceObj = env->NewGlobalRef(serviceObj);
      
          {
              AutoMutex _l(mLock);
              mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
              mLocked.pointerSpeed = 0;
              mLocked.pointerGesturesEnabled = true;
              mLocked.showTouches = false;
              mLocked.pointerCapture = false;
          }
          mInteractive = true;
      
           //注意此处创建了EventHub
          sp eventHub = new EventHub();
          //并把EventHub作为参数传入到InputManager中
          mInputManager = new InputManager(eventHub, this, this);
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25

      InputManager构造方法

      /frameworks/native/services/inputflinger/InputManager.cpp
      InputManager::InputManager(
              const sp& eventHub,
              const sp& readerPolicy,
              const sp& dispatcherPolicy) {
          //创建InputDispatcher对象
          mDispatcher = new InputDispatcher(dispatcherPolicy);
          //创建InputReader对象,InputReader在创建之初就与InputDispatcher产生了紧密的关联,后面会使用nQueuedListener->flush()通知事件。
      
          mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
          //初始化
          initialize();
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      initialize()初始化

      ///frameworks/native/services/inputflinger/InputManager.cpp
      void InputManager::initialize() {
          //创建绣程“InputReader”
          mReaderThread = new InputReaderThread(mReader);
          //创建线程”InputDispatcher“
          mDispatcherThread = new InputDispatcherThread(mDispatcher);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      InputReader构造方法

      //frameworks/native/services/inputflinger/InputReader.cpp
      InputReader::InputReader(const sp<EventHubInterface>& eventHub,
              const sp<InputReaderPolicyInterface>& policy,
              const sp<InputListenerInterface>& listener) :
              mContext(this), mEventHub(eventHub), mPolicy(policy),
              mGlobalMetaState(0), mGeneration(1),
              mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
              mConfigurationChangesToRefresh(0) {
          //创建Listener回调,这个后面会调用nQueuedListener->flush(),记住这个listener是一个InputDispatcher
          mQueuedListener = new QueuedInputListener(listener);
      
          { // acquire lock
              AutoMutex _l(mLock);
      
              refreshConfigurationLocked(0);
              updateGlobalMetaStateLocked();
          } // release lock
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

      InputDispatcher构造方法

      //frameworks/native/services/inputflinger/InputDispatcher.cpp
      InputDispatcher::InputDispatcher(const sp& policy) :
          mPolicy(policy),
          mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
          mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
          mNextUnblockedEvent(NULL),
          mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
          mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
          mLooper = new Looper(false);
      
          mKeyRepeatState.lastKeyEntry = NULL;
      
          policy->getDispatcherConfiguration(&mConfig);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    3. 通过IMS.start启动上面两个线程流程

      inputManager.start()

      //com/android/server/SystemServer.java
      traceBeginAndSlog("StartInputManager");
                  inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
                  inputManager.start();
                  traceEnd();
      
      • 1
      • 2
      • 3
      • 4
      • 5

      InputManagerService.start

      //com/android/server/input/InputManagerService.java 
      public void start() {
              Slog.i(TAG, "Starting input manager");
            //jni 开启inputmanager
              nativeStart(mPtr);
      
              // Add ourself to the Watchdog monitors.
              Watchdog.getInstance().addMonitor(this);
      
              registerPointerSpeedSettingObserver();
              registerShowTouchesSettingObserver();
              registerAccessibilityLargePointerSettingObserver();
      
              mContext.registerReceiver(new BroadcastReceiver() {
                  @Override
                  public void onReceive(Context context, Intent intent) {
                      updatePointerSpeedFromSettings();
                      updateShowTouchesFromSettings();
                      updateAccessibilityLargePointerFromSettings();
                  }
              }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
      
              updatePointerSpeedFromSettings();
              updateShowTouchesFromSettings();
              updateAccessibilityLargePointerFromSettings();
          }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27

      nativeStart()

      ///frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
      static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
          NativeInputManager* im = reinterpret_cast(ptr);
      
          status_t result = im->getInputManager()->start();
          if (result) {
              jniThrowRuntimeException(env, "Input manager could not be started.");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      ///frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
      status_t InputManager::start() {
          status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
          if (result) {
              ALOGE("Could not start InputDispatcher thread due to error %d.", result);
              return result;
          }
      
          result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
          if (result) {
              ALOGE("Could not start InputReader thread due to error %d.", result);
      
              mDispatcherThread->requestExit();
              return result;
          }
      
          return OK;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    4. InputRerader线程处理过程

      InputRender线程运行。

      ///frameworks/native/services/inputflinger/InputReader.cpp
      bool InputReaderThread::threadLoop() {
          mReader->loopOnce();
          return true;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5

      处理事件

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void InputReader::loopOnce() {
          int32_t oldGeneration;
          int32_t timeoutMillis;
          bool inputDevicesChanged = false;
          Vector inputDevices;
          { // acquire lock
              AutoMutex _l(mLock);
      
              oldGeneration = mGeneration;
              timeoutMillis = -1;
      
              uint32_t changes = mConfigurationChangesToRefresh;
              if (changes) {
                  mConfigurationChangesToRefresh = 0;
                  timeoutMillis = 0;
                  refreshConfigurationLocked(changes);
              } else if (mNextTimeout != LLONG_MAX) {
                  nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
                  timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
              }
          } // release lock
      
      	//内部有一个epoll_wait()  挂起
      	//唤醒由linux驱动去更改dev/input下的文件造成  inotify+epoll,从Eventhub中读取事件,这里注意因为之前将的EventHub.getEvent中有epoll wait进行阻塞,若FD发生改变则执行后面代码
          //通过EventHub的getEvents函数获取事件信息,并存放到mEventBuffer中。
      
          size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
      
          { // acquire lock
              AutoMutex _l(mLock);
              mReaderIsAliveCondition.broadcast();
      
              if (count) {
      			//处理事件信息,如果有事件信息,则进行加工处理。
                  processEventsLocked(mEventBuffer, count);
              }
      
              if (mNextTimeout != LLONG_MAX) {
                  nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
                  if (now >= mNextTimeout) {
      #if DEBUG_RAW_EVENTS
                      ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
      #endif
                      mNextTimeout = LLONG_MAX;
                      timeoutExpiredLocked(now);
                  }
              }
      
              if (oldGeneration != mGeneration) {
                  inputDevicesChanged = true;
                  getInputDevicesLocked(inputDevices);
              }
          } // release lock
      
          // Send out a message that the describes the changed input devices.
          if (inputDevicesChanged) {
              mPolicy->notifyInputDevicesChanged(inputDevices);
          }
      
          // Flush queued events out to the listener.
          // This must happen outside of the lock because the listener could potentially call
          // back into the InputReader's methods, such as getScanCodeState, or become blocked
          // on another thread similarly waiting to acquire the InputReader lock thereby
          // resulting in a deadlock.  This situation is actually quite plausible because the
          // listener is actually the input dispatcher, which calls into the window manager,
          // which occasionally calls into the input reader.
          mQueuedListener->flush();
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69

      处理事件信息:processEventsLocked

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
          //遍历所有事件
          for (const RawEvent* rawEvent = rawEvents; count;) {
              int32_t type = rawEvent->type;
              size_t batchSize = 1;
              //事件类型分为原始输入事件和设备事件,这里时对原始输入事件的处理。
              if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
                  int32_t deviceId = rawEvent->deviceId;
                  while (batchSize < count) {
                      if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                              || rawEvent[batchSize].deviceId != deviceId) {
                          break;
                      }
                      batchSize += 1;
                  }
      #if DEBUG_RAW_EVENTS
                  ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
      #endif
                  //手动注意,继续调用。,处理deviceId所对应的设备的原始输入事件。
                  processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
              } else {
                  //对设备事件进行处理。
                  switch (rawEvent->type) {
                  case EventHubInterface::DEVICE_ADDED:
                      addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                      break;
                  case EventHubInterface::DEVICE_REMOVED:
                      removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                      break;
                  case EventHubInterface::FINISHED_DEVICE_SCAN:
                      handleConfigurationChangedLocked(rawEvent->when);
                      break;
                  default:
                      ALOG_ASSERT(false); // can't happen
                      break;
                  }
              }
              count -= batchSize;
              rawEvent += batchSize;
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43

      继续调用processEventsForDeviceLocked:

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void InputReader::processEventsForDeviceLocked(int32_t deviceId,
              const RawEvent* rawEvents, size_t count) {
          //从mDevices中获取对应的deviceIndex
          ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
          if (deviceIndex < 0) {
              ALOGW("Discarding event for unknown deviceId %d.", deviceId);
              return;
          }
      
          //查找设备
          InputDevice* device = mDevices.valueAt(deviceIndex);
          if (device->isIgnored()) {
              //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
              return;
          }
      
          device->process(rawEvents, count);
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20

      调用inputDevice.process()

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void InputDevice::process(const RawEvent* rawEvents, size_t count) {
          // Process all of the events in order for each mapper.
          // We cannot simply ask each mapper to process them in bulk because mappers may
          // have side-effects that must be interleaved.  For example, joystick movement events and
          // gamepad button presses are handled by different mappers but they should be dispatched
          // in the order received.
          size_t numMappers = mMappers.size();
          //遍历处理该InputDevice的所有事件
          for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
      #if DEBUG_RAW_EVENTS
              ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
                      rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
                      rawEvent->when);
      #endif
      
              //mDropUntilNextSync默认值为false,如果设备的输入事件的缓冲区溢出,这个值为true
              if (mDropUntilNextSync) {
                  if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
                      mDropUntilNextSync = false;
      #if DEBUG_RAW_EVENTS
                      ALOGD("Recovered from input event buffer overrun.");
      #endif
                  } else {
      #if DEBUG_RAW_EVENTS
                      ALOGD("Dropped input event while waiting for next input sync.");
      #endif
                  }
              } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
                  ALOGI("Detected input event buffer overrun for device %s.", getName().string());
                  mDropUntilNextSync = true;
                  reset(rawEvent->when);
              } else {
                  for (size_t i = 0; i < numMappers; i++) {
                      InputMapper* mapper = mMappers[i];
                      mapper->process(rawEvent);
                  }
              }
              --count;
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42

      交给对应的设备处理 mapper->process(rawEvent),这里需要注意,InputMapper有很多的子类,我们要找触摸事件的相关处理就是找到TouchlnputMapper

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void TouchInputMapper::process(const RawEvent* rawEvent) {
          mCursorButtonAccumulator.process(rawEvent);
          mCursorScrollAccumulator.process(rawEvent);
          mTouchButtonAccumulator.process(rawEvent);
      
          if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
              sync(rawEvent->when);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      继续sync

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void TouchInputMapper::sync(nsecs_t when) {
          const RawState* last = mRawStatesPending.isEmpty() ?
                  &mCurrentRawState : &mRawStatesPending.top();
      
          // Push a new state.
          mRawStatesPending.push();
          RawState* next = &mRawStatesPending.editTop();
          next->clear();
          next->when = when;
      
          // Sync button state.
          next->buttonState = mTouchButtonAccumulator.getButtonState()
                  | mCursorButtonAccumulator.getButtonState();
      
          // Sync scroll
          next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
          next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
          mCursorScrollAccumulator.finishSync();
      
          // Sync touch
          syncTouch(when, next);
      
          // Assign pointer ids.
          if (!mHavePointerIds) {
              assignPointerIds(last, next);
          }
      
      #if DEBUG_RAW_EVENTS
          ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
                  "hovering ids 0x%08x -> 0x%08x",
                  last->rawPointerData.pointerCount,
                  next->rawPointerData.pointerCount,
                  last->rawPointerData.touchingIdBits.value,
                  next->rawPointerData.touchingIdBits.value,
                  last->rawPointerData.hoveringIdBits.value,
                  next->rawPointerData.hoveringIdBits.value);
      #endif
      
          processRawTouches(false /*timeout*/);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41

      processRawTouches(最终的目的是找到数据的最终去向)

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void TouchInputMapper::processRawTouches(bool timeout) {
          if (mDeviceMode == DEVICE_MODE_DISABLED) {
              // Drop all input if the device is disabled.
              mCurrentRawState.clear();
              mRawStatesPending.clear();
              return;
          }
      
          // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
          // valid and must go through the full cook and dispatch cycle. This ensures that anything
          // touching the current state will only observe the events that have been dispatched to the
          // rest of the pipeline.
          const size_t N = mRawStatesPending.size();
          size_t count;
          for(count = 0; count < N; count++) {
              const RawState& next = mRawStatesPending[count];
      
              // A failure to assign the stylus id means that we're waiting on stylus data
              // and so should defer the rest of the pipeline.
              if (assignExternalStylusId(next, timeout)) {
                  break;
              }
      
              // All ready to go.
              clearStylusDataPendingFlags();
              mCurrentRawState.copyFrom(next);
              if (mCurrentRawState.when < mLastRawState.when) {
                  mCurrentRawState.when = mLastRawState.when;
              }
              cookAndDispatch(mCurrentRawState.when);
          }
          if (count != 0) {
              mRawStatesPending.removeItemsAt(0, count);
          }
      
          if (mExternalStylusDataPending) {
              if (timeout) {
                  nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
                  clearStylusDataPendingFlags();
                  mCurrentRawState.copyFrom(mLastRawState);
      #if DEBUG_STYLUS_FUSION
                  ALOGD("Timeout expired, synthesizing event with new stylus data");
      #endif
                  //手动注意
                  cookAndDispatch(when);
              } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
                  mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
                  getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52

      cookAndDispatch

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void TouchInputMapper::cookAndDispatch(nsecs_t when) {
          // Always start with a clean state.
          mCurrentCookedState.clear();
      
          // Apply stylus buttons to current raw state.
          applyExternalStylusButtonState(when);
      
          // Handle policy on initial down or hover events.
          bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
                  && mCurrentRawState.rawPointerData.pointerCount != 0;
      
          uint32_t policyFlags = 0;
          bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
          if (initialDown || buttonsPressed) {
              // If this is a touch screen, hide the pointer on an initial down.
              if (mDeviceMode == DEVICE_MODE_DIRECT) {
                  getContext()->fadePointer();
              }
      
              if (mParameters.wake) {
                  policyFlags |= POLICY_FLAG_WAKE;
              }
          }
      
          // Consume raw off-screen touches before cooking pointer data.
          // If touches are consumed, subsequent code will not receive any pointer data.
          if (consumeRawTouches(when, policyFlags)) {
              mCurrentRawState.rawPointerData.clear();
          }
      
          // Cook pointer data.  This call populates the mCurrentCookedState.cookedPointerData structure
          // with cooked pointer data that has the same ids and indices as the raw data.
          // The following code can use either the raw or cooked data, as needed.
          cookPointerData();
      
          // Apply stylus pressure to current cooked state.
          applyExternalStylusTouchState(when);
      
          // Synthesize key down from raw buttons if needed.
          synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
                  policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
      
          // Dispatch the touches either directly or by translation through a pointer on screen.
          if (mDeviceMode == DEVICE_MODE_POINTER) {
              for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
                      !idBits.isEmpty(); ) {
                  uint32_t id = idBits.clearFirstMarkedBit();
                  const RawPointerData::Pointer& pointer =
                          mCurrentRawState.rawPointerData.pointerForId(id);
                  if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
                          || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
                      mCurrentCookedState.stylusIdBits.markBit(id);
                  } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
                          || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
                      mCurrentCookedState.fingerIdBits.markBit(id);
                  } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
                      mCurrentCookedState.mouseIdBits.markBit(id);
                  }
              }
              for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
                      !idBits.isEmpty(); ) {
                  uint32_t id = idBits.clearFirstMarkedBit();
                  const RawPointerData::Pointer& pointer =
                          mCurrentRawState.rawPointerData.pointerForId(id);
                  if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
                          || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
                      mCurrentCookedState.stylusIdBits.markBit(id);
                  }
              }
      
              // Stylus takes precedence over all tools, then mouse, then finger.
              PointerUsage pointerUsage = mPointerUsage;
              if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
                  mCurrentCookedState.mouseIdBits.clear();
                  mCurrentCookedState.fingerIdBits.clear();
                  pointerUsage = POINTER_USAGE_STYLUS;
              } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
                  mCurrentCookedState.fingerIdBits.clear();
                  pointerUsage = POINTER_USAGE_MOUSE;
              } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
                      isPointerDown(mCurrentRawState.buttonState)) {
                  pointerUsage = POINTER_USAGE_GESTURES;
              }
      
              dispatchPointerUsage(when, policyFlags, pointerUsage);
          } else {
              if (mDeviceMode == DEVICE_MODE_DIRECT
                      && mConfig.showTouches && mPointerController != NULL) {
                  mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
                  mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
      
                  mPointerController->setButtonState(mCurrentRawState.buttonState);
                  mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
                          mCurrentCookedState.cookedPointerData.idToIndex,
                          mCurrentCookedState.cookedPointerData.touchingIdBits);
              }
      
              if (!mCurrentMotionAborted) {
                  dispatchButtonRelease(when, policyFlags);
                  dispatchHoverExit(when, policyFlags);
                  //手动注意,分发消息
                  dispatchTouches(when, policyFlags);
                  dispatchHoverEnterAndMove(when, policyFlags);
                  dispatchButtonPress(when, policyFlags);
              }
      
              if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
                  mCurrentMotionAborted = false;
              }
          }
      
          // Synthesize key up from raw buttons if needed.
          synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
                  policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
      
          // Clear some transient state.
          mCurrentRawState.rawVScroll = 0;
          mCurrentRawState.rawHScroll = 0;
      
          // Copy current touch to last touch in preparation for the next cycle.
          mLastRawState.copyFrom(mCurrentRawState);
          mLastCookedState.copyFrom(mCurrentCookedState);
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118
      • 119
      • 120
      • 121
      • 122
      • 123
      • 124
      • 125

      dispatchTouches

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
          BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
          BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
          int32_t metaState = getContext()->getGlobalMetaState();
          int32_t buttonState = mCurrentCookedState.buttonState;
      
          if (currentIdBits == lastIdBits) {
              if (!currentIdBits.isEmpty()) {
                  // No pointer id changes so this is a move event.
                  // The listener takes care of batching moves so we don't have to deal with that here.
                  dispatchMotion(when, policyFlags, mSource,
                          AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
                          AMOTION_EVENT_EDGE_FLAG_NONE,
                          mCurrentCookedState.deviceTimestamp,
                          mCurrentCookedState.cookedPointerData.pointerProperties,
                          mCurrentCookedState.cookedPointerData.pointerCoords,
                          mCurrentCookedState.cookedPointerData.idToIndex,
                          currentIdBits, -1,
                          mOrientedXPrecision, mOrientedYPrecision, mDownTime);
              }
          } else {
              // There may be pointers going up and pointers going down and pointers moving
              // all at the same time.
              BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
              BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
              BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
              BitSet32 dispatchedIdBits(lastIdBits.value);
      
              // Update last coordinates of pointers that have moved so that we observe the new
              // pointer positions at the same time as other pointers that have just gone up.
              bool moveNeeded = updateMovedPointers(
                      mCurrentCookedState.cookedPointerData.pointerProperties,
                      mCurrentCookedState.cookedPointerData.pointerCoords,
                      mCurrentCookedState.cookedPointerData.idToIndex,
                      mLastCookedState.cookedPointerData.pointerProperties,
                      mLastCookedState.cookedPointerData.pointerCoords,
                      mLastCookedState.cookedPointerData.idToIndex,
                      moveIdBits);
              if (buttonState != mLastCookedState.buttonState) {
                  moveNeeded = true;
              }
      
              // Dispatch pointer up events.
              while (!upIdBits.isEmpty()) {
                  uint32_t upId = upIdBits.clearFirstMarkedBit();
      
                  //手动注意。
                  dispatchMotion(when, policyFlags, mSource,
                          AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
                          mCurrentCookedState.deviceTimestamp,
                          mLastCookedState.cookedPointerData.pointerProperties,
                          mLastCookedState.cookedPointerData.pointerCoords,
                          mLastCookedState.cookedPointerData.idToIndex,
                          dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
                  dispatchedIdBits.clearBit(upId);
              }
      
              // Dispatch move events if any of the remaining pointers moved from their old locations.
              // Although applications receive new locations as part of individual pointer up
              // events, they do not generally handle them except when presented in a move event.
              if (moveNeeded && !moveIdBits.isEmpty()) {
                  ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
                  dispatchMotion(when, policyFlags, mSource,
                          AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
                          mCurrentCookedState.deviceTimestamp,
                          mCurrentCookedState.cookedPointerData.pointerProperties,
                          mCurrentCookedState.cookedPointerData.pointerCoords,
                          mCurrentCookedState.cookedPointerData.idToIndex,
                          dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
              }
      
              // Dispatch pointer down events using the new pointer locations.
              while (!downIdBits.isEmpty()) {
                  uint32_t downId = downIdBits.clearFirstMarkedBit();
                  dispatchedIdBits.markBit(downId);
      
                  if (dispatchedIdBits.count() == 1) {
                      // First pointer is going down.  Set down time.
                      mDownTime = when;
                  }
      
                  dispatchMotion(when, policyFlags, mSource,
                          AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
                          mCurrentCookedState.deviceTimestamp,
                          mCurrentCookedState.cookedPointerData.pointerProperties,
                          mCurrentCookedState.cookedPointerData.pointerCoords,
                          mCurrentCookedState.cookedPointerData.idToIndex,
                          dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92

      dispatchMotion

      ///frameworks/native/services/inputflinger/InputReader.cpp
      void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
              int32_t action, int32_t actionButton, int32_t flags,
              int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
              const PointerProperties* properties, const PointerCoords* coords,
              const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
              float xPrecision, float yPrecision, nsecs_t downTime) {
          PointerCoords pointerCoords[MAX_POINTERS];
          PointerProperties pointerProperties[MAX_POINTERS];
          uint32_t pointerCount = 0;
          while (!idBits.isEmpty()) {
              uint32_t id = idBits.clearFirstMarkedBit();
              uint32_t index = idToIndex[id];
              pointerProperties[pointerCount].copyFrom(properties[index]);
              pointerCoords[pointerCount].copyFrom(coords[index]);
      
              if (changedId >= 0 && id == uint32_t(changedId)) {
                  action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
              }
      
              pointerCount += 1;
          }
      
          ALOG_ASSERT(pointerCount != 0);
      
          if (changedId >= 0 && pointerCount == 1) {
              // Replace initial down and final up action.
              // We can compare the action without masking off the changed pointer index
              // because we know the index is 0.
              if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
                  action = AMOTION_EVENT_ACTION_DOWN;
              } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
                  action = AMOTION_EVENT_ACTION_UP;
              } else {
                  // Can't happen.
                  ALOG_ASSERT(false);
              }
          }
      
          NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
                  action, actionButton, flags, metaState, buttonState, edgeFlags,
                  mViewport.displayId, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
                  xPrecision, yPrecision, downTime);
          getListener()->notifyMotion(&args);
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46

      getListener()->notifyMotion(&args);.当前这个getListener实际获取是mQueuedListener=new QueuedlnputListener(listener);实例

      InputReader::InputReader(const sp& eventHub,
              const sp& policy,
              const sp& listener) :
              mContext(this), mEventHub(eventHub), mPolicy(policy),
              mGlobalMetaState(0), mGeneration(1),
              mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
              mConfigurationChangesToRefresh(0) {
          mQueuedListener = new QueuedInputListener(listener);
      
          { // acquire lock
              AutoMutex _l(mLock);
      
              refreshConfigurationLocked(0);
              updateGlobalMetaStateLocked();
          } // release lock
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      InputLintener.cpp.QueuedlnputListenernotifyMotion这里我们实际可以看到他就是往一个队列当中添加数据,实际上是我们将触摸相关的事件进行包装之后,将其加入到一个ArgsQueue队列,到此,我们已经将数据加入到参数队列中。

      ///frameworks/native/services/inputflinger/InputListener.cpp
      void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
          mArgsQueue.push(new NotifyMotionArgs(*args));
      }
      
      • 1
      • 2
      • 3
      • 4

      这时我们在回到上面loopOnce()方法中processEventsLocked调用之后,发现当前mQueueListener->flush的调用

          // Flush queued events out to the listener.
          // This must happen outside of the lock because the listener could potentially call
          // back into the InputReader's methods, such as getScanCodeState, or become blocked
          // on another thread similarly waiting to acquire the InputReader lock thereby
          // resulting in a deadlock.  This situation is actually quite plausible because the
          // listener is actually the input dispatcher, which calls into the window manager,
          // which occasionally calls into the input reader.
          mQueuedListener->flush();
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      flush()

      遍历整个mArgsQueue数组,在input架构中NotifyArgs的实现子类主要有以下几类

      • NotifyConfigurationChangedArgs
      • NotifyKeyArgs
      • NotifyMotionArgs 通知motion事件
      • NotifySwitchArgs
      • NotifvDeviceResetAras
      ///frameworks/native/services/inputflinger/InputListener.cpp
      void QueuedInputListener::flush() {
          size_t count = mArgsQueue.size();
          for (size_t i = 0; i < count; i++) {
              NotifyArgs* args = mArgsQueue[i];
              args->notify(mInnerListener);
              delete args;
          }
          mArgsQueue.clear();
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      上面的listener根据溯源可以看到是lnputDispatcher,是调用InputDispatcher中的notifyMotion,这里就完成了向InputDispatcher的信息传递

      void NotifyMotionArgs::notify(const sp& listener) const {
      	//实际上就是在调用InputDispatcher.notifyMotion
          listener->notifyMotion(this);
      }
      
      
      InputReader::InputReader(const sp& eventHub,
              const sp& policy,
              const sp& listener) ://注意listener
              mContext(this), mEventHub(eventHub), mPolicy(policy),
              mGlobalMetaState(0), mGeneration(1),
              mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
              mConfigurationChangesToRefresh(0) {
          mQueuedListener = new QueuedInputListener(listener);//注意这个listener
      
          { // acquire lock
              AutoMutex _l(mLock);
      
              refreshConfigurationLocked(0);
              updateGlobalMetaStateLocked();
          } // release lock
      }
      
      
      InputManager::InputManager(
              const sp& eventHub,
              const sp& readerPolicy,
              const sp& dispatcherPolicy) {
          mDispatcher = new InputDispatcher(dispatcherPolicy);
          mReader = new InputReader(eventHub, readerPolicy, mDispatcher);//注意这个listener实际就是dispatcher
          initialize();
      }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34

      10.执行notifyMotion中的唤醒操作InputDispatcher.cpp

      ///frameworks/native/services/inputflinger/InputDispatcher.cpp
      void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
      #if DEBUG_INBOUND_EVENT_DETAILS
          ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
                  "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
                  "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
                  args->eventTime, args->deviceId, args->source, args->policyFlags,
                  args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
                  args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
          for (uint32_t i = 0; i < args->pointerCount; i++) {
              ALOGD("  Pointer %d: id=%d, toolType=%d, "
                      "x=%f, y=%f, pressure=%f, size=%f, "
                      "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
                      "orientation=%f",
                      i, args->pointerProperties[i].id,
                      args->pointerProperties[i].toolType,
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
                      args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
          }
      #endif
          if (!validateMotionEvent(args->action, args->actionButton,
                      args->pointerCount, args->pointerProperties)) {
              return;
          }
      
          uint32_t policyFlags = args->policyFlags;
          policyFlags |= POLICY_FLAG_TRUSTED;
      
          android::base::Timer t;
          mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
          if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
              ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
                      std::to_string(t.duration().count()).c_str());
          }
      
          bool needWake;
          { // acquire lock
              mLock.lock();
      
              if (shouldSendMotionToInputFilterLocked(args)) {
                  mLock.unlock();
      
                  MotionEvent event;
                  event.initialize(args->deviceId, args->source, args->action, args->actionButton,
                          args->flags, args->edgeFlags, args->metaState, args->buttonState,
                          0, 0, args->xPrecision, args->yPrecision,
                          args->downTime, args->eventTime,
                          args->pointerCount, args->pointerProperties, args->pointerCoords);
      
                  policyFlags |= POLICY_FLAG_FILTERED;
                  if (!mPolicy->filterInputEvent(&event, policyFlags)) {
                      return; // event was consumed by the filter
                  }
      
                  mLock.lock();
              }
      
              // Just enqueue a new motion event.
              MotionEntry* newEntry = new MotionEntry(args->eventTime,
                      args->deviceId, args->source, policyFlags,
                      args->action, args->actionButton, args->flags,
                      args->metaState, args->buttonState,
                      args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                      args->displayId,
                      args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
      
              needWake = enqueueInboundEventLocked(newEntry);
              mLock.unlock();
          } // release lock
      
          if (needWake) {//注意这里唤醒looper。
              mLooper->wake();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
    5. .InputDispatcher线程处理过程

      InputDispatcher线程开启

      ///frameworks/native/services/inputflinger/InputDispatcher.cpp
      bool InputDispatcherThread::threadLoop() {
          mDispatcher->dispatchOnce();
          return true;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5

      dispatchOnce()轮询

      pollOnce这里是等待被唤醒,进入epoll wait等待状态,当发生以下任一情况则退出等待状态:
      callback:通过回调方法来唤醒;
      timeout:到达nextWakeupTime时间,超时唤醒;
      wake:主动调用Looper的wake0方法;

      ///frameworks/native/services/inputflinger/InputDispatcher.cpp
      void InputDispatcher::dispatchOnce() {
          nsecs_t nextWakeupTime = LONG_LONG_MAX;
          { // acquire lock
              AutoMutex _l(mLock);
              mDispatcherIsAliveCondition.broadcast();
      
              // Run a dispatch loop if there are no pending commands.
              // The dispatch loop might enqueue commands to run afterwards.
              if (!haveCommandsLocked()) {
                  dispatchOnceInnerLocked(&nextWakeupTime);
              }
      
              // Run all pending commands if there are any.
              // If any commands were run then force the next poll to wake up immediately.
              if (runCommandsLockedInterruptible()) {
                  nextWakeupTime = LONG_LONG_MIN;
              }
          } // release lock
      
          // Wait for callback or timeout or wake.  (make sure we round up, not down)
          nsecs_t currentTime = now();
          int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
          mLooper->pollOnce(timeoutMillis);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
       
    dispatchOnceInnerLocked
       
       ```c++
       ///frameworks/native/services/inputflinger/InputDispatcher.cpp
       void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
           nsecs_t currentTime = now();
       
           // Reset the key repeat timer whenever normal dispatch is suspended while the
           // device is in a non-interactive state.  This is to ensure that we abort a key
           // repeat if the device is just coming out of sleep.
           if (!mDispatchEnabled) {
               resetKeyRepeatLocked();
           }
       
           // If dispatching is frozen, do not process timeouts or try to deliver any new events.
           //如果InputDispatcher被冻结,则不进行派发操作。
           if (mDispatchFrozen) {
       #if DEBUG_FOCUS
               ALOGD("Dispatch frozen.  Waiting some more.");
       #endif
               return;
           }
       
           // Optimize latency of app switches.
           // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
           // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
           //如果isAppSwitchDue为true,则说明没有及时相应Home键操作。
           bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
           if (mAppSwitchDueTime < *nextWakeupTime) {
               *nextWakeupTime = mAppSwitchDueTime;
           }
       
           // Ready to start a new event.
           // If we don't already have a pending event, go grab one.
           //如果还没有待分发的事件,则在mInboundQueue中取出一个事件。
           if (! mPendingEvent) {
               //如果mInboundQueue为空,并且没有待分发的事件就return。
               if (mInboundQueue.isEmpty()) {
                   if (isAppSwitchDue) {
                       // The inbound queue is empty so the app switch key we were waiting
                       // for will never arrive.  Stop waiting for it.
                       resetPendingAppSwitchLocked(false);
                       isAppSwitchDue = false;
                   }
       
                   // Synthesize a key repeat if appropriate.
                   if (mKeyRepeatState.lastKeyEntry) {
                       if (currentTime >= mKeyRepeatState.nextRepeatTime) {
                           mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
                       } else {
                           if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
                               *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
                           }
                       }
                   }
       
                   // Nothing to do if there is no pending event.
                   if (!mPendingEvent) {
                       return;
                   }
               } else {
                   // Inbound queue has at least one entry.
                   //如果mInboundQueue不为空,则取队列头部的EventEntry赋值给mPendingEvent
                   mPendingEvent = mInboundQueue.dequeueAtHead();
                   traceInboundQueueLengthLocked();
               }
       
               // Poke user activity for this event.
               if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
                   pokeUserActivityLocked(mPendingEvent);
               }
       
               // Get ready to dispatch the event.
               resetANRTimeoutsLocked();
           }
       
           // Now we have an event to dispatch.
           // All events are eventually dequeued and processed this way, even if we intend to drop them.
           ALOG_ASSERT(mPendingEvent != NULL);
           bool done = false;
           DropReason dropReason = DROP_REASON_NOT_DROPPED;
           if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
               dropReason = DROP_REASON_POLICY;
           } else if (!mDispatchEnabled) {
               dropReason = DROP_REASON_DISABLED;
           }
       
           if (mNextUnblockedEvent == mPendingEvent) {
               mNextUnblockedEvent = NULL;
           }
       
           switch (mPendingEvent->type) {
           case EventEntry::TYPE_CONFIGURATION_CHANGED: {
               ConfigurationChangedEntry* typedEntry =
                       static_cast(mPendingEvent);
               done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
               dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
               break;
           }
       
           case EventEntry::TYPE_DEVICE_RESET: {
               DeviceResetEntry* typedEntry =
                       static_cast(mPendingEvent);
               done = dispatchDeviceResetLocked(currentTime, typedEntry);
               dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
               break;
           }
       
           case EventEntry::TYPE_KEY: {
               KeyEntry* typedEntry = static_cast(mPendingEvent);
               if (isAppSwitchDue) {
                   if (isAppSwitchKeyEventLocked(typedEntry)) {
                       resetPendingAppSwitchLocked(true);
                       isAppSwitchDue = false;
                   } else if (dropReason == DROP_REASON_NOT_DROPPED) {
                       dropReason = DROP_REASON_APP_SWITCH;
                   }
               }
               if (dropReason == DROP_REASON_NOT_DROPPED
                       && isStaleEventLocked(currentTime, typedEntry)) {
                   dropReason = DROP_REASON_STALE;
               }
               if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
                   dropReason = DROP_REASON_BLOCKED;
               }
               done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
               break;
           }
       
           case EventEntry::TYPE_MOTION: {
               MotionEntry* typedEntry = static_cast(mPendingEvent);
               //没有及时响应窗口切换操作
               if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
                   dropReason = DROP_REASON_APP_SWITCH;
               }
               //事件过期
               if (dropReason == DROP_REASON_NOT_DROPPED
                       && isStaleEventLocked(currentTime, typedEntry)) {
                   dropReason = DROP_REASON_STALE;
               }
               //阻碍其他窗口获取事件
               if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
                   dropReason = DROP_REASON_BLOCKED;
               }
               //手动注意
               done = dispatchMotionLocked(currentTime, typedEntry,
                       &dropReason, nextWakeupTime);
               break;
           }
       
           default:
               ALOG_ASSERT(false);
               break;
           }
       
           if (done) {
            if (dropReason != DROP_REASON_NOT_DROPPED) {
                   dropInboundEventLocked(mPendingEvent, dropReason);
            }
               mLastDropReason = dropReason;
       
               //释放本次事件处理对象
            releasePendingEventLocked();
               //使InputDispatcher能够快速处理下一个分发事件。
               *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
           }
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168

    dispatchMotionLocked

    这里两条线,
    1.findTouchedWindowTargetLocked 负责找到要分发的Window
    2.dispatchEventLocked 负责具体分发目标

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    bool InputDispatcher::dispatchMotionLocked(
            nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
        // Preprocessing.
        if (! entry->dispatchInProgress) {
            //标记当前已经进入分发流程
            entry->dispatchInProgress = true;
    
            logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
        }
    
        //如果事件是需要丢弃的,则返回true,不会为该事件寻找合适的窗口
        // Clean up if dropping the event.
        if (*dropReason != DROP_REASON_NOT_DROPPED) {
            setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
                    ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
            return true;
        }
    
        bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
    
        // Identify targets.
        Vector inputTargets;
    
        bool conflictingPointerActions = false;
        int32_t injectionResult;
        if (isPointerEvent) {
            //处理触摸形式的事件,
            // Pointer event.  (eg. touchscreen)负责找到要分发的Window
            injectionResult = findTouchedWindowTargetsLocked(currentTime,
                    entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
        } else {
            //处理非触摸形式的事件 比如轨迹球。
            // Non touch event.  (eg. trackball)负责找到要分发的Window
            injectionResult = findFocusedWindowTargetsLocked(currentTime,
                    entry, inputTargets, nextWakeupTime);
        }
        //输入事件被挂起,说明找到了窗口并且窗口无响应。
        if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
            return false;
        }
    
        setInjectionResultLocked(entry, injectionResult);
        //输入事件没有分发成功,说明没有找到合适的窗口。
        if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
            if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
                CancelationOptions::Mode mode(isPointerEvent ?
                        CancelationOptions::CANCEL_POINTER_EVENTS :
                     CancelationOptions::CANCEL_NON_POINTER_EVENTS);
                CancelationOptions options(mode, "input event injection failed");
             synthesizeCancelationEventsForMonitorsLocked(options);
            }
         return true;
        }
    
        //将分发的目标添加到inputTargets列表中。
        addMonitoringTargetsLocked(inputTargets);
    
        // Dispatch the motion.
        if (conflictingPointerActions) {
            CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
                    "conflicting pointer actions");
            synthesizeCancelationEventsForAllConnectionsLocked(options);
        }
        //将事件分发给inputTargets列表的目标。
        dispatchEventLocked(currentTime, entry, inputTargets);//负责具体分发目标
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    我们先分析findTouchedWindowTargetLocked这条线。

    这是一个很长的方法,省略一些无关的代码。大体是判断这个事件的类型,获取能够处理这个事件的forceground window,如果这个window不能够继续处理事件,就是说这个window的主线程被某些耗时操作占据,handleTargetsNotReadyLocked这个方法主要是判定当前的window是否发生ANR如果没有则处理下面的addWindowTargetLocked。

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
            const MotionEntry* entry, Vector& inputTargets, nsecs_t* nextWakeupTime,
            bool* outConflictingPointerActions) {
    
    ......
        //确保所有触摸过的前台窗口都为新的输入做好了准备
          for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
            const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
            if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
                // Check whether the window is ready for more input.
                //检查窗口是否准备好接收更多的输入。
                std::string reason = checkWindowReadyForMoreInputLocked(currentTime,
                        touchedWindow.windowHandle, entry, "touched");
                if (!reason.empty()) {
                    //如果窗口没有准备好,则将原因赋值给injectionResult
                    injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
                            NULL, touchedWindow.windowHandle, nextWakeupTime, reason.c_str());
                    goto Unresponsive;
                }
            }
        }  
        ......
            
            
              // Success!  Output targets.窗口检查成功
        injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
    
        //遍历mTempTouchState中的窗口
        for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
            const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
           //为每个mTempTouchState中的窗口生成inputTargets
            addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                    touchedWindow.pointerIds, inputTargets);
        }
    
        // Drop the outside or hover touch windows since we will not care about them
        // in the next iteration.
        //在下一次迭代中,删除外部窗口或悬停触摸窗口
        mTempTouchState.filterNonAsIsTouchWindows();
        ......
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    addWindowTargetLocked这里主要的目的是将inputChannel添加至InputTarget中

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    void InputDispatcher::addWindowTargetLocked(const sp& windowHandle,
            int32_t targetFlags, BitSet32 pointerIds, Vector& inputTargets) {
        inputTargets.push();
    
        const InputWindowInfo* windowInfo = windowHandle->getInfo();
        InputTarget& target = inputTargets.editTop();
        target.inputChannel = windowInfo->inputChannel;
        target.flags = targetFlags;
        target.xOffset = - windowInfo->frameLeft;
        target.yOffset = - windowInfo->frameTop;
        target.scaleFactor = windowInfo->scaleFactor;
        target.pointerIds = pointerIds;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    我们在看看另一条线dispatchEventLocked(向目标窗口发送事件)

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
            EventEntry* eventEntry, const Vector& inputTargets) {
    #if DEBUG_DISPATCH_CYCLE
        ALOGD("dispatchEventToCurrentInputTargets");
    #endif
    
        ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
    
        pokeUserActivityLocked(eventEntry);
    
        //遍历inputTargets列表
        for (size_t i = 0; i < inputTargets.size(); i++) {
            const InputTarget& inputTarget = inputTargets.itemAt(i);
    
            //根据inputTarget内部的inputChannel来获取Connection的索引。
            ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
            if (connectionIndex >= 0) {
                //获取mConnectionsByFd容器中的Connection
                sp connection = mConnectionsByFd.valueAt(connectionIndex);
                //手动注意
                //根据inputTarget开始事件发送循环。
                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().c_str());
    #endif
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    prepareDispatchCycleLocked

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
            const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    #if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
                "xOffset=%f, yOffset=%f, scaleFactor=%f, "
                "pointerIds=0x%x",
                connection->getInputChannelName().c_str(), inputTarget->flags,
                inputTarget->xOffset, inputTarget->yOffset,
                inputTarget->scaleFactor, inputTarget->pointerIds.value);
    #endif
    
        // Skip this event if the connection status is not normal.
        // We don't want to enqueue additional outbound events if the connection is broken.
        if (connection->status != Connection::STATUS_NORMAL) {
    #if DEBUG_DISPATCH_CYCLE
            ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
                    connection->getInputChannelName().c_str(), connection->getStatusLabel());
    #endif
            return;
        }
    
        // Split a motion event if needed.
        if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
            ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);
    
            MotionEntry* originalMotionEntry = static_cast(eventEntry);
            if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
                MotionEntry* splitMotionEntry = splitMotionEvent(
                        originalMotionEntry, inputTarget->pointerIds);
                if (!splitMotionEntry) {
                    return; // split event was dropped
                }
    #if DEBUG_FOCUS
                ALOGD("channel '%s' ~ Split motion event.",
                        connection->getInputChannelName().c_str());
                logOutboundMotionDetailsLocked("  ", splitMotionEntry);
    #endif
                //手动注意
                enqueueDispatchEntriesLocked(currentTime, connection,
                        splitMotionEntry, inputTarget);
                splitMotionEntry->release();
                return;
            }
        }
    
        // Not splitting.  Enqueue dispatch entries for the event as is.
        enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    enqueueDispatchEntriesLocked

    该方法主要功能:

    • 根据dispatchMode来决定是否需要加入outboundQueue队列;

    • 根据EventEntry,来生成DispatchEntry事件;

    • 将dispatchEntry加入到connection的outbound队列.

      执行到这里,其实等于又做了一次搬运的工作,将InputDispatcher中mlnboundQueue中的事件取出后,找到目标window后,封装dispatchEntry加入到connection的outbound队列.

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
            const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
        bool wasEmpty = connection->outboundQueue.isEmpty();
    
        //手动注意
        // Enqueue dispatch entries for the requested modes.
        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);
    
        // If the outbound queue was previously empty, start the dispatch cycle going.
        if (wasEmpty && !connection->outboundQueue.isEmpty()) {
            startDispatchCycleLocked(currentTime, connection);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    startDispatchCycleLocked

    startDispatchCycleLocked的主要功能:从outboundQueue中取出事件,重新放入waitQueue队列

    startDispatchCycleLocked触发时机:当起初connection.outboundQueue等于空,经enqueueDispatchEntryLocked处理后,outboundQueue不等于空。

    ///frameworks/native/services/inputflinger/InputDispatcher.cpp
    void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
            const sp& connection) {
    #if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ startDispatchCycle",
                connection->getInputChannelName().c_str());
    #endif
    
        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;
            switch (eventEntry->type) {
            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: {
                MotionEntry* motionEntry = static_cast(eventEntry);
    
                PointerCoords scaledCoords[MAX_POINTERS];
                const PointerCoords* usingCoords = motionEntry->pointerCoords;
    
                // Set the X and Y offset depending on the input source.
                float xOffset, yOffset;
                if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                        && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
                    float scaleFactor = dispatchEntry->scaleFactor;
                    xOffset = dispatchEntry->xOffset * scaleFactor;
                    yOffset = dispatchEntry->yOffset * scaleFactor;
                    if (scaleFactor != 1.0f) {
                        for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                            scaledCoords[i] = motionEntry->pointerCoords[i];
                            scaledCoords[i].scale(scaleFactor);
                        }
                        usingCoords = scaledCoords;
                    }
                } else {
                    xOffset = 0.0f;
                    yOffset = 0.0f;
    
                    // We don't want the dispatch target to know.
                    if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
                        for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                            scaledCoords[i].clear();
                        }
                        usingCoords = scaledCoords;
                    }
                }
    
                //手动注意
                // Publish the motion event.
                status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
                        motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
                        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;
            }
    
            // Check the result.
            if (status) {
                if (status == WOULD_BLOCK) {
                    if (connection->waitQueue.isEmpty()) {
                        ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
                                "This is unexpected because the wait queue is empty, so the pipe "
                                "should be empty and we shouldn't have any problems writing an "
                                "event to it, status=%d", connection->getInputChannelName().c_str(),
                                status);
                        abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
                    } else {
                        // Pipe is full and we are waiting for the app to finish process some events
                        // before sending more events to it.
    #if DEBUG_DISPATCH_CYCLE
                        ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
                                "waiting for the application to catch up",
                                connection->getInputChannelName().c_str());
    #endif
                        connection->inputPublisherBlocked = true;
                    }
                } else {
                    ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
                            "status=%d", connection->getInputChannelName().c_str(), status);
                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
                }
                return;
            }
    
            // Re-enqueue the event on the wait queue.
            connection->outboundQueue.dequeue(dispatchEntry);
            traceOutboundQueueLengthLocked(connection);
            connection->waitQueue.enqueueAtTail(dispatchEntry);
            traceWaitQueueLengthLocked(connection);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118

    至此调用了connection的inputPublisher的publishMotionEvent方法将事件分发消耗。

    ///frameworks/native/services/inputflinger/InputTransport.cpp
    status_t InputPublisher::publishMotionEvent(
            uint32_t seq,
            int32_t deviceId,
            int32_t source,
            int32_t displayId,
            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) {
    #if DEBUG_TRANSPORT_ACTIONS
        ALOGD("channel '%s' publisher ~ 
              publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
                "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
                "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
                "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
                "pointerCount=%" PRIu32,
                mChannel->getName().c_str(), seq,
                deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState,
                xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
    #endif
    
        if (!seq) {
            ALOGE("Attempted to publish a motion event with sequence number 0.");
            return BAD_VALUE;
        }
    
        if (pointerCount > MAX_POINTERS || pointerCount < 1) {
            ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %" PRIu32 ".",
                    mChannel->getName().c_str(), pointerCount);
            return BAD_VALUE;
        }
    
        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.displayId = displayId;
        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]);
        }
        //最后将消息发送
        return mChannel->sendMessage(&msg);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
  • 相关阅读:
    Java中级编程大师班<第一篇:初识数据结构与算法(1)>
    Tiktok抖音最新无人互动直播项目:猜成语V4版(带语音感谢用户送礼物功能)源代码解析
    河北2022中国农民丰收节 国稻种芯:主会场活动在塔元庄举行
    Gartner 存储与数据保护技术 Hype Cycle 解读|SmartX 趋势分享
    QT航空客运订票系统
    Linux关机命令、选项和原理详解
    Leetcode81. Search in Rotated Sorted Array II
    MyBatis动态设置要连接的数据库地址,用户名,密码
    并发编程系列 - ReadWriteLock
    2022年Vue.js面试题汇总及答案【建议收藏】
  • 原文地址:https://blog.csdn.net/chendeshan330/article/details/126755928