【转】和菜鸟一起学android4.0.3源码之touchscreen配置 调试记录 - Gaojiquan/android_bootable_recovery GitHub Wiki

转载地址:http://www.cnblogs.com/leaven/archive/2012/09/05/2672359.html

记得应该是上上周了,终于毕业了,离开了学校,就得面对现实的社会,以前学校实验室里,老师给了钥匙,那电脑随便用,那元器件随便玩,什么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中看出 来的。

[html] view plaincopy

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

[html] view plaincopy 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

[html] view plaincopy 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

[html] view plaincopy 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

[html] view plaincopy 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

[html] view plaincopy 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

[html] view plaincopy 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

[html] view plaincopy 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() : "");
#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()函数,

[html] view plaincopy uint32_t policyFlags = args->policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
mPolicy->interceptMotionBeforeQueueing(args->eventTime, /byref/ policyFlags);

[html] view plaincopy 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;  
}  

}

⚠️ **GitHub.com Fallback** ⚠️