zoukankan      html  css  js  c++  java
  • 和菜鸟一起学android4.0.3源码之touchscreen配置+调试记录

            记得应该是上上周了,终于毕业了,离开了学校,就得面对现实的社会,以前学校实验室里,老师给了钥匙,那电脑随便用,那元器件随便玩,什么51单片机啊,PIC单片机啊,FPGA啊,arm11啊什么的。想着做什么就直接万用版+电烙铁什么的一起搞定。调试,写程序,焊板子都是自己一手操办啊,多么自由啊。到了公司,可不依你,对于上市公司来说,管理什么的总归还是有些规范化的。
            对于嵌入式,虽然早有所耳闻,大三也玩过arm7,编了几个基于GUI的贪吃蛇啊,黑白棋啊,连连看啊什么的。自己也买来arm11,烧写linux系统,搭建环境,最终也成功完成了hello world驱动模块。待以后有时间再好好整理整理。废话不多说了,既然是anrdroid下的touchscreen的配置,那就专心点,不东扯西扯了。
         都说android4.0.3的touchscreen有了很大的变化,菜鸟也不知道这么庞大的代码,各个功能模块式干嘛的。只能找找资料,瞎折腾了。公司的任务,触摸屏得上了,android的东西,只用鼠标可不好玩啊。开始调试SPI模式的ads7846的电阻屏,板子没有SPI接口,于是就用GPIO模拟SPI的方式来实现SPI的功能,在此要说明下,这个嵌入式的板子就是和51,PIC的板子用起来不一样啊,什么工作队列,什么中断下半部分工作,什么总线啊,I2C啊,SPI啊,I2S啊,USB啊,都这么纠结,顿时觉得学得好少啊,自己又有点懒,什么都想学,至于什么也没学好。调试好驱动后,总算是完成了一半的工作,接着,是否要直接上android去跑呢?android里什么机制都不知道额,虽然一开始android中实现鼠标的时候小研究过android下的input那个框架,不过只是模模糊糊的概念,根本就没有弄清楚。看来得下点功夫啊,要不然怎么混啊。又偏题了,额,正题,正题。。
             直接上android了,突然发现出现了一个小圈圈。向鼠标一样的。貌似触摸屏变成了鼠标了。觉得太怪了,怎么可以这样?肯定那里有问题的,找了好久的资料,终于找到了,原来是android4.0.3,他的touchscreen是需要配置文件的。只要直接创建一个“设备名.idc”的文件,直接放到/system/usr/idc/目录下,就可以了,设备名是驱动中定义的,在android中的Eventhub中也是可以加打印在logcat中看出来的。

     # Basic Parameters
       touch.deviceType = touchScreen
       touch.orientationAware = 1
    
       # Size
       touch.size.calibration = diameter
       touch.size.scale = 10
       touch.size.bias = 0
       touch.size.isSummed = 0
    
       # Pressure
       # Driver reports signal strength as pressure.
       #
       # A normal thumb touch typically registers about 200 signal strength
       # units although we don't expect these values to be accurate.
       touch.pressure.calibration = amplitude
       touch.pressure.scale = 0.005
    
       # Orientation
       touch.orientation.calibration = none
    
    


            但是就知道了这个配置文件,具体那里实现的呢?怎么配置进去的呢?怎么看着你个是touch.deviceType = touchScreen这个决定的。不多说来代码
    frameworks/base/services/input/InputReader.cpp

    void TouchInputMapper::configureParameters() {
        // Use the pointer presentation mode for devices that do not support distinct
        // multitouch.  The spot-based presentation relies on being able to accurately
        // locate two or more fingers on the touch pad.
        mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
                ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
    
        String8 gestureModeString;
        if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
                gestureModeString)) {
            if (gestureModeString == "pointer") {
                mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
            } else if (gestureModeString == "spots") {
                mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
            } else if (gestureModeString != "default") {
                LOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
            }
        }
    
        if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
            // The device is a touch screen.
            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
        } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
            // The device is a pointing device like a track pad.
            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
        } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
                || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
            // The device is a cursor device with a touch pad attached.
            // By default don't use the touch pad to move the pointer.
            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
        } else {
            // The device is a touch pad of unknown purpose.
            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
        }
    
        String8 deviceTypeString;
        if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
                deviceTypeString)) {
            if (deviceTypeString == "touchScreen") {
                mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
            } else if (deviceTypeString == "touchPad") {
                mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
            } else if (deviceTypeString == "pointer") {
                mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
            } else if (deviceTypeString != "default") {
                LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
            }
        }
    
        mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
        getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
                mParameters.orientationAware);
    
        mParameters.associatedDisplayId = -1;
        mParameters.associatedDisplayIsExternal = false;
        if (mParameters.orientationAware
                || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
                || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
            mParameters.associatedDisplayIsExternal =
                    mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
                            && getDevice()->isExternal();
            mParameters.associatedDisplayId = 0;
        }
    }
    
    


         还是英文呢,看到第一行,如果没有配置的话,那就是pointer,pointer不就是鼠标吗?只有定义deviceType为touchScreen,那才是我们要的啊。看来英文真的好重要好重

    要啊。那到底是那里去获取配置文件的呢?不是一般都是EventHub下打开什么文件吗?走,咱们去seesee。
    frameworks/base/services/input/EventHub.cpp

    void EventHub::loadConfigurationLocked(Device* device) {
        device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
                device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
        if (device->configurationFile.isEmpty()) {
            LOGD("No input device configuration file found for device '%s'.",
                    device->identifier.name.string());
        } else {
            status_t status = PropertyMap::load(device->configurationFile,
                    &device->configuration);
            if (status) {
                LOGE("Error loading input device configuration file for device '%s'.  "
                        "Using default configuration.",
                        device->identifier.name.string());
            }
        }
    }
    
    


         原来就是这里去载入配置文件的。然后再进行配置的,接着我们看看那些配置是什么功能?上面的deviceType就不用说了,就是类型是触摸屏而不是touchPad和pointer。

    pointer是鼠标类似的光标,touchPad还没试过,板子上的触摸屏也拆了,也没法跳了。不知道是什么,下次有机会去试试。差不多应该和touchScreen差不多。那么

    touch.size.calibration等一些配置是什么?有什么作用呢?还是代码看起
    frameworks/base/services/input/InputReader.cpp

    void TouchInputMapper::parseCalibration() {
        const PropertyMap& in = getDevice()->getConfiguration();
        Calibration& out = mCalibration;
    
        // Size
        out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
        String8 sizeCalibrationString;
        if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
            if (sizeCalibrationString == "none") {
                out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
            } else if (sizeCalibrationString == "geometric") {
                out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
            } else if (sizeCalibrationString == "diameter") {
                out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
            } else if (sizeCalibrationString == "area") {
                out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
            } else if (sizeCalibrationString != "default") {
                LOGW("Invalid value for touch.size.calibration: '%s'",
                        sizeCalibrationString.string());
            }
        }
    
        out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
                out.sizeScale);
        out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
                out.sizeBias);
        out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
                out.sizeIsSummed);
    
        // Pressure
        out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
        String8 pressureCalibrationString;
        if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
            if (pressureCalibrationString == "none") {
                out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
            } else if (pressureCalibrationString == "physical") {
                out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
            } else if (pressureCalibrationString == "amplitude") {
                out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
            } else if (pressureCalibrationString != "default") {
                LOGW("Invalid value for touch.pressure.calibration: '%s'",
                        pressureCalibrationString.string());
            }
        }
    
        out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
                out.pressureScale);
    
        // Orientation
        out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
        String8 orientationCalibrationString;
        if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
            if (orientationCalibrationString == "none") {
                out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
            } else if (orientationCalibrationString == "interpolated") {
                out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
            } else if (orientationCalibrationString == "vector") {
                out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
            } else if (orientationCalibrationString != "default") {
                LOGW("Invalid value for touch.orientation.calibration: '%s'",
                        orientationCalibrationString.string());
            }
        }
    
        // Distance
        out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
        String8 distanceCalibrationString;
        if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
            if (distanceCalibrationString == "none") {
                out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
            } else if (distanceCalibrationString == "scaled") {
                out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
            } else if (distanceCalibrationString != "default") {
                LOGW("Invalid value for touch.distance.calibration: '%s'",
                        distanceCalibrationString.string());
            }
        }
    
        out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
                out.distanceScale);
    }
    
    


            touch.size.calibration分为了1、geometric 2、diameter 3、area,老师说不懂的单词要查字典,现在都什么年代了,随便谷歌一下,手机也行。什么牛津字典啊的,那都是浮云了。geometric:几何图形?怪怪的,是不是代表不同的触摸的形状?不懂,diameter倒是还好,直径嘛应该是一个触摸的点是以这个为直径的一个圆,至于area嘛,区域,难道是多点的时候?也许吧。touch.pressure.calibration分为了1、physical 2、amplitude 。physical:物理的,是不是理论上的?amplitude是不是幅度就是压力的大小?不懂额。要不再来看看代码?那些配置之后肯定有执行的。不可能简简单单的就是赋值了。找找看
    frameworks/base/services/input/InputReader.cpp

    void TouchInputMapper::cookPointerData() {
        uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
    
        mCurrentCookedPointerData.clear();
        mCurrentCookedPointerData.pointerCount = currentPointerCount;
        mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
        mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
    
        // Walk through the the active pointers and map device coordinates onto
        // surface coordinates and adjust for display orientation.
        for (uint32_t i = 0; i < currentPointerCount; i++) {
            const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
    
            // Size
            float touchMajor, touchMinor, toolMajor, toolMinor, size;
            switch (mCalibration.sizeCalibration) {
            case Calibration::SIZE_CALIBRATION_GEOMETRIC:
            case Calibration::SIZE_CALIBRATION_DIAMETER:
            case Calibration::SIZE_CALIBRATION_AREA:
                if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
                    touchMajor = in.touchMajor;
                    touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
                    toolMajor = in.toolMajor;
                    toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
                    size = mRawPointerAxes.touchMinor.valid
                            ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
                } else if (mRawPointerAxes.touchMajor.valid) {
                    toolMajor = touchMajor = in.touchMajor;
                    toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
                            ? in.touchMinor : in.touchMajor;
                    size = mRawPointerAxes.touchMinor.valid
                            ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
                } else if (mRawPointerAxes.toolMajor.valid) {
                    touchMajor = toolMajor = in.toolMajor;
                    touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
                            ? in.toolMinor : in.toolMajor;
                    size = mRawPointerAxes.toolMinor.valid
                            ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
                } else {
                    LOG_ASSERT(false, "No touch or tool axes.  "
                            "Size calibration should have been resolved to NONE.");
                    touchMajor = 0;
                    touchMinor = 0;
                    toolMajor = 0;
                    toolMinor = 0;
                    size = 0;
                }
    
                if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
                    uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
                    if (touchingCount > 1) {
                        touchMajor /= touchingCount;
                        touchMinor /= touchingCount;
                        toolMajor /= touchingCount;
                        toolMinor /= touchingCount;
                        size /= touchingCount;
                    }
                }
    
                if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
                    touchMajor *= mGeometricScale;
                    touchMinor *= mGeometricScale;
                    toolMajor *= mGeometricScale;
                    toolMinor *= mGeometricScale;
                } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
                    touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
                    touchMinor = touchMajor;
                    toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
                    toolMinor = toolMajor;
                } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
                    touchMinor = touchMajor;
                    toolMinor = toolMajor;
                }
    
                mCalibration.applySizeScaleAndBias(&touchMajor);
                mCalibration.applySizeScaleAndBias(&touchMinor);
                mCalibration.applySizeScaleAndBias(&toolMajor);
                mCalibration.applySizeScaleAndBias(&toolMinor);
                size *= mSizeScale;
                break;
            default:
                touchMajor = 0;
                touchMinor = 0;
                toolMajor = 0;
                toolMinor = 0;
                size = 0;
                break;
            }
    
            // Pressure
            float pressure;
            switch (mCalibration.pressureCalibration) {
            case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
            case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
                pressure = in.pressure * mPressureScale;
                break;
            default:
                pressure = in.isHovering ? 0 : 1;
                break;
            }
    
            // Tilt and Orientation
            float tilt;
            float orientation;
            if (mHaveTilt) {
                float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
                float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
                orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
                tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
            } else {
                tilt = 0;
    
                switch (mCalibration.orientationCalibration) {
                case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
                    orientation = (in.orientation - mOrientationCenter) * mOrientationScale;
                    break;
                case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
                    int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
                    int32_t c2 = signExtendNybble(in.orientation & 0x0f);
                    if (c1 != 0 || c2 != 0) {
                        orientation = atan2f(c1, c2) * 0.5f;
                        float confidence = hypotf(c1, c2);
                        float scale = 1.0f + confidence / 16.0f;
                        touchMajor *= scale;
                        touchMinor /= scale;
                        toolMajor *= scale;
                        toolMinor /= scale;
                    } else {
                        orientation = 0;
                    }
                    break;
                }
                default:
                    orientation = 0;
                }
            }
    
            // Distance
            float distance;
            switch (mCalibration.distanceCalibration) {
            case Calibration::DISTANCE_CALIBRATION_SCALED:
                distance = in.distance * mDistanceScale;
                break;
            default:
                distance = 0;
            }
    
            // X and Y
            // Adjust coords for surface orientation.
            float x, y;
            switch (mSurfaceOrientation) {
            case DISPLAY_ORIENTATION_90:
                x = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
                y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
                orientation -= M_PI_2;
                if (orientation < - M_PI_2) {
                    orientation += M_PI;
                }
                break;
            case DISPLAY_ORIENTATION_180:
                x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
                y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
                break;
            case DISPLAY_ORIENTATION_270:
                x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
                y = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
                orientation += M_PI_2;
                if (orientation > M_PI_2) {
                    orientation -= M_PI;
                }
                break;
            default:
                x = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
                y = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
                break;
            }
    
            // Write output coords.
            PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
            out.clear();
            out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
            out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
            out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
            out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
            out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
            out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
            out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
            out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
            out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
    
            // Write output properties.
            PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
            uint32_t id = in.id;
            properties.clear();
            properties.id = id;
            properties.toolType = in.toolType;
    
            // Write id index.
            mCurrentCookedPointerData.idToIndex[id] = i;
        }
    }

        这数据处理的,cookPointerData,哈哈哈,原来都在这里搞定的啊。TouchMajor and TouchMinor表示了触摸时接触面积的大小范围。这个函数会把驱动上传上来的数据,也就是X、Y坐标转换为android设定的分辨率的一个映射。差不多就这样了。具体,碰到问题了在解决了。
        在此,有时候再讲讲自己调试的时候碰到的一个问题,那就是android电源管理中会把背光给关掉,所以点死了触摸屏还是发现没用。所以调试的时候可以把其中的一个

    policyFlags设置下,不要drop掉,也就是即使背光关掉了也可以有效。
    frameworks/base/services/input/InputDispatcher.cpp

       

     void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
        nsecs_t currentTime = now();
    
        // Reset the key repeat timer whenever we disallow key events, even if the next event
        // is not a key.  This is to ensure that we abort a key repeat if the device is just coming
        // out of sleep.
        if (!mPolicy->isKeyRepeatEnabled()) {
            resetKeyRepeatLocked();
        }
    
        // If dispatching is frozen, do not process timeouts or try to deliver any new events.
        if (mDispatchFrozen) {
    #if DEBUG_FOCUS
            LOGD("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.
        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.
        if (! mPendingEvent) {
            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) {
                    if (mActiveConnections.isEmpty()) {
                        dispatchIdleLocked();
                    }
                    return;
                }
            } else {
                // Inbound queue has at least one entry.
                EventEntry* entry = mInboundQueue.head;
    
                // Throttle the entry if it is a move event and there are no
                // other events behind it in the queue.  Due to movement batching, additional
                // samples may be appended to this event by the time the throttling timeout
                // expires.
                // TODO Make this smarter and consider throttling per device independently.
                if (entry->type == EventEntry::TYPE_MOTION
                        && !isAppSwitchDue
                        && mDispatchEnabled
                        && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
                        && !entry->isInjected()) {
                    MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
                    int32_t deviceId = motionEntry->deviceId;
                    uint32_t source = motionEntry->source;
                    if (! isAppSwitchDue
                            && !motionEntry->next // exactly one event, no successors
                            && (motionEntry->action == AMOTION_EVENT_ACTION_MOVE
                                    || motionEntry->action == AMOTION_EVENT_ACTION_HOVER_MOVE)
                            && deviceId == mThrottleState.lastDeviceId
                            && source == mThrottleState.lastSource) {
                        nsecs_t nextTime = mThrottleState.lastEventTime
                                + mThrottleState.minTimeBetweenEvents;
                        if (currentTime < nextTime) {
                            // Throttle it!
    #if DEBUG_THROTTLING
                            LOGD("Throttling - Delaying motion event for "
                                    "device %d, source 0x%08x by up to %0.3fms.",
                                    deviceId, source, (nextTime - currentTime) * 0.000001);
    #endif
                            if (nextTime < *nextWakeupTime) {
                                *nextWakeupTime = nextTime;
                            }
                            if (mThrottleState.originalSampleCount == 0) {
                                mThrottleState.originalSampleCount =
                                        motionEntry->countSamples();
                            }
                            return;
                        }
                    }
    
    #if DEBUG_THROTTLING
                    if (mThrottleState.originalSampleCount != 0) {
                        uint32_t count = motionEntry->countSamples();
                        LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
                                count - mThrottleState.originalSampleCount,
                                mThrottleState.originalSampleCount, count);
                        mThrottleState.originalSampleCount = 0;
                    }
    #endif
    
                    mThrottleState.lastEventTime = currentTime;
                    mThrottleState.lastDeviceId = deviceId;
                    mThrottleState.lastSource = source;
                }
    
                mInboundQueue.dequeue(entry);
                mPendingEvent = entry;
            }
    
            // Poke user activity for this event.
            if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
                pokeUserActivityLocked(mPendingEvent);
            }
        }
    
        // Now we have an event to dispatch.
        // All events are eventually dequeued and processed this way, even if we intend to drop them.
        LOG_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<ConfigurationChangedEntry*>(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<DeviceResetEntry*>(mPendingEvent);
            done = dispatchDeviceResetLocked(currentTime, typedEntry);
            dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
            break;
        }
    
        case EventEntry::TYPE_KEY: {
            KeyEntry* typedEntry = static_cast<KeyEntry*>(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<MotionEntry*>(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:
            LOG_ASSERT(false);
            break;
        }
    
        if (done) {
            if (dropReason != DROP_REASON_NOT_DROPPED) {
                dropInboundEventLocked(mPendingEvent, dropReason);
            }
    
            releasePendingEventLocked();
            *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
        }
    }
    
    
    

            只要把下面的东西给注释掉就好了,那具体的policyflags是哪里赋值的呢?真心找了我好久的。
    frameworks/base/services/input/InputDispatcher.cpp

      if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
            dropReason = DROP_REASON_POLICY;
        } else if (!mDispatchEnabled) {
            dropReason = DROP_REASON_DISABLED;
        }
    
    


    frameworks/base/services/input/InputDispatcher.cpp 

    void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
    #if DEBUG_INBOUND_EVENT_DETAILS
        LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
                "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, "
                "xPrecision=%f, yPrecision=%f, downTime=%lld",
                args->eventTime, args->deviceId, args->source, args->policyFlags,
                args->action, args->flags, args->metaState, args->buttonState,
                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
        for (uint32_t i = 0; i < args->pointerCount; i++) {
            LOGD("  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->pointerCount, args->pointerProperties)) {
            return;
        }
    
        uint32_t policyFlags = args->policyFlags;
        policyFlags |= POLICY_FLAG_TRUSTED;
        mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
    
        bool needWake;
        { // acquire lock
            mLock.lock();
    
            if (mInputFilterEnabled) {
                mLock.unlock();
    
                MotionEvent event;
                event.initialize(args->deviceId, args->source, args->action, 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();
            }
    
            // Attempt batching and streaming of move events.
            if (args->action == AMOTION_EVENT_ACTION_MOVE
                    || args->action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
                // BATCHING CASE
                //
                // Try to append a move sample to the tail of the inbound queue for this device.
                // Give up if we encounter a non-move motion event for this device since that
                // means we cannot append any new samples until a new motion event has started.
                for (EventEntry* entry = mInboundQueue.tail; entry; entry = entry->prev) {
                    if (entry->type != EventEntry::TYPE_MOTION) {
                        // Keep looking for motion events.
                        continue;
                    }
    
                    MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
                    if (motionEntry->deviceId != args->deviceId
                            || motionEntry->source != args->source) {
                        // Keep looking for this device and source.
                        continue;
                    }
    
                    if (!motionEntry->canAppendSamples(args->action,
                            args->pointerCount, args->pointerProperties)) {
                        // Last motion event in the queue for this device and source is
                        // not compatible for appending new samples.  Stop here.
                        goto NoBatchingOrStreaming;
                    }
    
                    // Do the batching magic.
                    batchMotionLocked(motionEntry, args->eventTime,
                            args->metaState, args->pointerCoords,
                            "most recent motion event for this device and source in the inbound queue");
                    mLock.unlock();
                    return; // done!
                }
    
                // BATCHING ONTO PENDING EVENT CASE
                //
                // Try to append a move sample to the currently pending event, if there is one.
                // We can do this as long as we are still waiting to find the targets for the
                // event.  Once the targets are locked-in we can only do streaming.
                if (mPendingEvent
                        && (!mPendingEvent->dispatchInProgress || !mCurrentInputTargetsValid)
                        && mPendingEvent->type == EventEntry::TYPE_MOTION) {
                    MotionEntry* motionEntry = static_cast<MotionEntry*>(mPendingEvent);
                    if (motionEntry->deviceId == args->deviceId
                            && motionEntry->source == args->source) {
                        if (!motionEntry->canAppendSamples(args->action,
                                args->pointerCount, args->pointerProperties)) {
                            // Pending motion event is for this device and source but it is
                            // not compatible for appending new samples.  Stop here.
                            goto NoBatchingOrStreaming;
                        }
    
                        // Do the batching magic.
                        batchMotionLocked(motionEntry, args->eventTime,
                                args->metaState, args->pointerCoords,
                                "pending motion event");
                        mLock.unlock();
                        return; // done!
                    }
                }
    
                // STREAMING CASE
                //
                // There is no pending motion event (of any kind) for this device in the inbound queue.
                // Search the outbound queue for the current foreground targets to find a dispatched
                // motion event that is still in progress.  If found, then, appen the new sample to
                // that event and push it out to all current targets.  The logic in
                // prepareDispatchCycleLocked takes care of the case where some targets may
                // already have consumed the motion event by starting a new dispatch cycle if needed.
                if (mCurrentInputTargetsValid) {
                    for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
                        const InputTarget& inputTarget = mCurrentInputTargets[i];
                        if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
                            // Skip non-foreground targets.  We only want to stream if there is at
                            // least one foreground target whose dispatch is still in progress.
                            continue;
                        }
    
                        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
                        if (connectionIndex < 0) {
                            // Connection must no longer be valid.
                            continue;
                        }
    
                        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
                        if (connection->outboundQueue.isEmpty()) {
                            // This foreground target has an empty outbound queue.
                            continue;
                        }
    
                        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
                        if (! dispatchEntry->inProgress
                                || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
                                || dispatchEntry->isSplit()) {
                            // No motion event is being dispatched, or it is being split across
                            // windows in which case we cannot stream.
                            continue;
                        }
    
                        MotionEntry* motionEntry = static_cast<MotionEntry*>(
                                dispatchEntry->eventEntry);
                        if (motionEntry->action != args->action
                                || motionEntry->deviceId != args->deviceId
                                || motionEntry->source != args->source
                                || motionEntry->pointerCount != args->pointerCount
                                || motionEntry->isInjected()) {
                            // The motion event is not compatible with this move.
                            continue;
                        }
    
                        if (args->action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
                            if (mLastHoverWindowHandle == NULL) {
    #if DEBUG_BATCHING
                                LOGD("Not streaming hover move because there is no "
                                        "last hovered window.");
    #endif
                                goto NoBatchingOrStreaming;
                            }
    
                            sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(
                                    args->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
                                    args->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
                            if (mLastHoverWindowHandle != hoverWindowHandle) {
    #if DEBUG_BATCHING
                                LOGD("Not streaming hover move because the last hovered window "
                                        "is '%s' but the currently hovered window is '%s'.",
                                        mLastHoverWindowHandle->getName().string(),
                                        hoverWindowHandle != NULL
                                                ? hoverWindowHandle->getName().string() : "<null>");
    #endif
                                goto NoBatchingOrStreaming;
                            }
                        }
    
                        // Hurray!  This foreground target is currently dispatching a move event
                        // that we can stream onto.  Append the motion sample and resume dispatch.
                        motionEntry->appendSample(args->eventTime, args->pointerCoords);
    #if DEBUG_BATCHING
                        LOGD("Appended motion sample onto batch for most recently dispatched "
                                "motion event for this device and source in the outbound queues.  "
                                "Attempting to stream the motion sample.");
    #endif
                        nsecs_t currentTime = now();
                        dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
                                true /*resumeWithAppendedMotionSample*/);
    
                        runCommandsLockedInterruptible();
                        mLock.unlock();
                        return; // done!
                    }
                }
    
    NoBatchingOrStreaming:;
            }
    
            // Just enqueue a new motion event.
            MotionEntry* newEntry = new MotionEntry(args->eventTime,
                    args->deviceId, args->source, policyFlags,
                    args->action, args->flags, args->metaState, args->buttonState,
                    args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                    args->pointerCount, args->pointerProperties, args->pointerCoords);
    
            needWake = enqueueInboundEventLocked(newEntry);
            mLock.unlock();
        } // release lock
    
        if (needWake) {
            mLooper->wake();
        }
    }
    
    


     

    看到了吗?就是这里了,interceptMotionBeforeQueueing()函数,

       

     uint32_t policyFlags = args->policyFlags;
        policyFlags |= POLICY_FLAG_TRUSTED;
        mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
    


     

    void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
        // Policy:
        // - Ignore untrusted events and pass them along.
        // - No special filtering for injected events required at this time.
        // - Filter normal events based on screen state.
        // - For normal events brighten (but do not wake) the screen if currently dim.
        if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
            if (isScreenOn()) {
                policyFlags |= POLICY_FLAG_PASS_TO_USER;
    
                if (!isScreenBright()) {
                    policyFlags |= POLICY_FLAG_BRIGHT_HERE;
                }
            } else {
                JNIEnv* env = jniEnv();
                jint wmActions = env->CallIntMethod(mCallbacksObj,
                            gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
                            policyFlags);
                if (checkAndClearExceptionFromCallback(env,
                        "interceptMotionBeforeQueueingWhenScreenOff")) {
                    wmActions = 0;
                }
    
                policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;
                handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
            }
        } else {
            policyFlags |= POLICY_FLAG_PASS_TO_USER;
        }
    }
    
    


    原来如此呢, if (isScreenOn()) 。搞定,收工,回去睡觉了,哈哈。。。

  • 相关阅读:
    ASP.NET MVC4.0+EF+LINQ+bui+bootstrap+网站+角色权限管理系统(2)
    ASP.NET MVC4.0+EF+LINQ+bui+bootstrap+网站+角色权限管理系统(1)
    ASP.NET MVC4.0+EF+LINQ+bui+bootstrap+网站+角色权限管理系统(开篇)
    时间文本框,入职时间,工龄的换算
    javascript中this的用法
    web的Tomcat8部署文档
    rabbitMQ集群安装部署
    Python实现统计Jenkins multibranch发布的分支及时间等 页面 … 部署文档 跳到banner的尾部 回到标题开始 转至元数据结尾
    centos 7 DNS部署
    MongoDB3.X参数文件
  • 原文地址:https://www.cnblogs.com/wuyida/p/6300096.html
Copyright © 2011-2022 走看看