記得應該是上上周了,終於畢業了,離開了學校,就得面對現實的社會,以前學校實驗室里,老師給了鑰匙,那電腦隨便用,那元器件隨便玩,什么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()) 。搞定,收工,回去睡覺了,哈哈。。。