Android input 系统之一:InputReader线程

Android input 系统之一 :InputReader线程

touch事件处理流程:

底层触摸事件上报至framework层,事件未分发之前的数据读取与处理流程:

"InputReader 线程"

bool InputReaderThread::threadLoop()						frameworks/native/services/inputflinger/InputReader.cpp
void InputReader::loopOnce()
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); //从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256
    size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize)	frameworks/native/services/inputflinger/EventHub.cpp
        scanDevicesLocked();//扫描设备,会把dev/input下所有可用的输入设备打开并储存到Device结构体中
        int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); //从设备不断读取事件,放入到readBuffer
        //将input_event信息, 封装成"RawEvent"
            >>(event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL + nsecs_t(iev.time.tv_usec) * 1000LL;
            event->deviceId = deviceId;
            event->type = iev.type;
            event->code = iev.code;
            event->value = iev.value;
            event += 1;
            capacity -= 1;)
        return event - buffer; //返回所读取的事件个数

        processEventsLocked(mEventBuffer, count);//事件处理
        void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count)
>>>>>>> "if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {"
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
            void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count)   
                device->process(rawEvents, count);
                void InputDevice::process(const RawEvent* rawEvents, size_t count)
                      mapper->process(rawEvent);//调用具体mapper来处理( 以MultiTouch为例 )
                        SwitchInputMapper::process(const RawEvent* rawEvent);
                        KeyboardInputMapper::process(const RawEvent* rawEvent);
                        CursorInputMapper::process(const RawEvent* rawEvent);
                        RotaryEncoderInputMapper::process(const RawEvent* rawEvent);
                        TouchInputMapper::process(const RawEvent* rawEvent);
                        SingleTouchInputMapper::process(const RawEvent* rawEvent);
                        ExternalStylusInputMapper::process(const RawEvent* rawEvent);
                        JoystickInputMapper::process(const RawEvent* rawEvent);
                        MultiTouchInputMapper::process(const RawEvent* rawEvent);
                            >>TouchInputMapper::process(rawEvent); 
                            >>mMultiTouchMotionAccumulator.process(rawEvent);
                            void TouchInputMapper::process(const RawEvent* rawEvent)//由于多点触摸屏中没有Button,Scroll,因此这里不做处理
                                mCursorButtonAccumulator.process(rawEvent);
                                mCursorScrollAccumulator.process(rawEvent);
                                mTouchButtonAccumulator.process(rawEvent);
                                //多点触摸的前几个点是不会执行sync的,所有点上报完后input_sync()上报的
                                    sync(rawEvent->when);   //同步
                                    void TouchInputMapper::sync(nsecs_t when)   
                                         syncTouch(when, next);
                                         processRawTouches(false /*timeout*/);
                                             cookAndDispatch(mCurrentRawState.when);
                                             void TouchInputMapper::cookAndDispatch(nsecs_t when)
                   >>>>>>>>>>>>>>>>>>>>>>>>  "if (mDeviceMode == DEVICE_MODE_DIRECT) {
                                                                                          //touchScreen:触摸屏,覆盖在LCD屏上,可以操作各种图标
                                                                                          //stylus(笔尖),gestrue(手势),mouse(鼠标)
                                                                                          //touchPad:触摸板,不是覆盖在LCD屏上,需要在LCD屏上显示一个光标以便定位。"
                            // touchScreen:触摸屏,覆盖在LCD屏上,可以操作各种图标
                            // touchPad:触摸板,不是覆盖在LCD屏上,需要在LCD屏上显示一个光标以便定位。
                            // pointer:和touchPad类似,但是多一些手势功能
                            // default:由系统根据某些算法来确定类型。

                                                 cookPointerData();//将原始的输入事件(坐标)转变为屏幕坐标
                                                 void TouchInputMapper::cookPointerData()                                                   
                                                                   //驱动上报touch信息时,不仅仅会上报坐标点,同时还会有tracking_id,pressure ,touch_major等属性值;
                                                                   //属性值会在cookPointerData函数中经过简单计算然后再上报,例如坐标转换、压力值归一化

                                                 dispatchPointerUsage(when, policyFlags, pointerUsage);
                                                 void TouchInputMapper::dispatchPointerUsage
                                                     case POINTER_USAGE_GESTURES:
                                                     dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); 
                                                         dispatchMotion();  
                                                         void TouchInputMapper::dispatchMotion
                                                             getListener()->notifyMotion(&args);    //getListener()=mReader->mQueuedListener.get()=InputListenerInterface
                                                                 void QueuedInputListener::notifyMotion     frameworks/native/services/inputflinger/InputListener.cpp
                                                                     mArgsQueue.push(new NotifyMotionArgs(*args));  //InputListenerInterface::notifyMotion, NotifyArgs=mArgsQueue
                                                                         //look at mQueuedListener->flush();

                        >>>>>>>>>>>>>>>>>>>>>>> " }else{"
                                                 if (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches && mPointerController != NULL){
                                                     if (!mCurrentMotionAborted) {  

                                                     dispatchButtonRelease(when, policyFlags);
                                                     dispatchHoverExit(when, policyFlags);
                                                     dispatchTouches(when, policyFlags);
                                                     dispatchHoverEnterAndMove(when, policyFlags);
                                                     dispatchButtonPress(when, policyFlags);
                                                     dispatchMotion(...);
                                                         getListener()->notifyMotion(&args);  //getListener()=mReader->mQueuedListener.get()=InputListenerInterface
                                                             mArgsQueue.push(new NotifyMotionArgs(*args));    //InputListenerInterface::notifyMotion, NotifyArgs=mArgsQueue
                                                                 //look at mQueuedListener->flush();
                                                     }
                                                 }    

        
>>>>>>>>>>> "} else {"
            case EventHubInterface::DEVICE_ADDED:
            addDeviceLocked(rawEvent->when, rawEvent->deviceId);
            void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId)
            InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
            InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes)
                
            //添加键盘类设备InputMapper
            if (keyboardSource != 0) {
                device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
            }

            //添加鼠标类设备InputMapper
           if (classes & INPUT_DEVICE_CLASS_CURSOR) {
               device->addMapper(new CursorInputMapper(device));
           }

           //添加触摸屏设备InputMapper
           if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
               device->addMapper(new MultiTouchInputMapper(device));
           }
           
           device->configure(when, &mConfig, 0);//依次调用了inputDevice::configure()和TouchInputMapper::configure()两个函数,
                                                //去获取监听设备的配置信息(包括在驱动中配置的TP分辨率)和display信息。值得注意的是,
                                                //上面提到的设备配置信息仅会在这里更新一次;如果配置出现异常将无法恢复,直到再次开关机
                void InputDevice::configure
                    mapper->configure(when, config, changes);
                        void TouchInputMapper::configure
                             configureSurface(when, &resetNeeded);//主要是根据当前显示视图的旋转角度来分别计算TP坐标到显示坐标的转换系数。
                                                                  //当手机竖直放置时(旋转角度为0),X轴转换系数= (LCD_width) / (TP_X_max) , Y轴转换系数 =(LCD_height) /(TP_Y_max)
           }



>>>>>>>>>  "mQueuedListener->flush();"     //QueuedInputListeners=mQueuedListener
           void QueuedInputListener::flush()
               args->notify(mInnerListener);   //NotifyKeyArgs:NotifyArgs=args
               void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener)
                   listener->notifyKey(this);   //InputDispatcher:InputDispatcherInterface:InputListenerInterface
                       void InputDispatcher::notifyKey(const NotifyKeyArgs* args)     frameworks/native/services/inputflinger/InputDispatcher.cpp
                           event.initialize()   //KeyEvent event; & 将NotifyKeyArgs转换为KeyEvent
                               void KeyEvent::initialize                              frameworks/native/libs/input/Input.cpp
                           mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);            //intercept=拦截, //mPolicy=NativeInputManager =>PhoneWindowManager
                                                                                                          "//mPolicy是指NativeInputManager对象"
                          调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程,调用链:

                              //IMS.interceptKeyBeforeQueueing
                              //InputMonitor.interceptKeyBeforeQueueing (继承IMS.WindowManagerCallbacks)
                              //PhoneWindowManager.interceptKeyBeforeQueueing (继承WindowManagerPolicy)

                           void NativeInputManager::interceptMotionBeforeQueueing                       frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
                                JNIEnv* env = jniEnv(); // 调用Java层的IMS.interceptKeyBeforeQueueing    
                                jint wmActions = env->CallIntMethod(mServiceObj,gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,when, policyFlags);
                                private int interceptMotionBeforeQueueingNonInteractive //native callback       frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
   
                               virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&)        //定义fameworks/native/services/inputflinger/tests/InputDispatcher_test.cpp
                               public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)     "frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java "
                                                                                                          // https://blog.csdn.net/qidabing/article/details/73614621
                                                                                                          //Android7.0 PowerManagerService亮灭屏分析(一)
                           bool needWake;
                           //当inputEventObj不为空, 则事件被filter所拦截
                           if (!mPolicy->filterInputEvent(&event, policyFlags)) {
                               return;
                           }
                           NativeInputManager::filterInputEvent                                           frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
                           bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags)
                               JNIEnv* env = jniEnv();
                               
                              if (!inputEventObj) {
                                 return true; // 当inputEventObj为空, 则走事件正常的分发流程
                              }
                              //当inputEventObj不为空,则调用Java层的IMS.filterInputEvent()
                              jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent, inputEventObj, policyFlags);
                                  final boolean filterInputEvent(InputEvent event, int policyFlags)      frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
                           

                           needWake = enqueueInboundEventLocked(newEntry);  //将newEntry即本次keyevent送到队列中
                           bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry)             frameworks/native/services/inputflinger/InputDispatcher.cpp
                               mInboundQueue.enqueueAtTail(entry); //将该事件放入mInboundQueue队列尾部
                               switch (entry->type) {
                                   case EventEntry::TYPE_KEY: 
                                       //其中APP_SWITCH_TIMEOUT=500ms
                                       mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
                                   case EventEntry::TYPE_MOTION: 
                                       //当前App无响应且用户希望切换到其他应用窗口,则drop该窗口事件,并处理其他窗口事件
                                       //查询可触摸的窗口
                                       sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);  // InputDispatcher.cpp
                                            //从前台到后台来遍历查询可触摸的窗口

                           
                           if (needWake) {                                                                            
                               mLooper->wake();  }  //唤醒InputDispatcher线程, EVENT_REPORT_SIGN1_WAKE1 如果需要唤醒mLooper则马上唤醒,唤醒后事件将立马进行分发 & InputDispatcher::mLooper

你可能感兴趣的:(Android)