標籤:android input inputmapper sync 繼承
前文Linux/Android——Input系統之InputReader (七)介紹到了inputreader的運作流程,如何擷取events到初步的分發,依次分析到InputMapper做第一步的處理.
前文有解析Mapper類型的依賴規則,不做重述.,這裡單以觸控螢幕input_device 對應的SingleTouchInputMapper 為例。
撰寫不易,轉載需註明出處:http://blog.csdn.net/jscese/article/details/43561773本博文來自【 jscese 】的部落格!
SingleTouchInputMapper:
原型定義在InputReader.h 中:
class SingleTouchInputMapper : public TouchInputMapper {public: SingleTouchInputMapper(InputDevice* device); virtual ~SingleTouchInputMapper(); virtual void reset(nsecs_t when); virtual void process(const RawEvent* rawEvent);protected: virtual void syncTouch(nsecs_t when, bool* outHavePointerIds); virtual void configureRawPointerAxes(); virtual bool hasStylus() const;private: SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;};
繼承自TouchInputMapper,函數實現全部放在InputReader.cpp中,先看首先調用進的process:
void SingleTouchInputMapper::process(const RawEvent* rawEvent) { TouchInputMapper::process(rawEvent); //調用父類的process mSingleTouchMotionAccumulator.process(rawEvent); //資料的同步}
繼續跟:
void TouchInputMapper::process(const RawEvent* rawEvent) { mCursorButtonAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); //這三個Accumulator 進一步處理rawEvent ,原型都在InputReader.cpp中,根據rawEvent->code 取出對應資訊 ALOGW("jscese dsp TouchInputMapper::process event type==0x%x, code==0x%x, valude ==0x%x \n",rawEvent->type,rawEvent->code,rawEvent->value); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { sync(rawEvent->when); //同步 }}
上面的幾個process 有興趣可以看下,會依次根據code type抽取對應的資訊儲存,比如CursorMotionAccumulator 中的 mRelX ,mRelY 代表相對座標值
作為我調試的觸摸框來說這裡只在TouchButtonAccumulator中抽取了 BTN_TOUCH 一個按下或者抬起的事件值. ABS_X. ABS_Y 並沒有在這裡讀取。而是在後面的SingleTouchMotionAccumulator::process中.
其它的input 裝置就需要看驅動具體上報的code type了.
TouchInputMapper::sync:
從上面分析可以看到。一個rawEvent過來的時候 都會先經過三個process去抽取資訊,然後才會檢測是否是一個同步sync的rawEent事件,
這也就是為什麼 在驅動中 一次完整的事件上報,總是先report一些button res abs之類的,最後來一個sync!
這個同步函數比較長只留意幾個地方就可以了:
void TouchInputMapper::sync(nsecs_t when) { ALOGW("TouchInputMapper::sync"); // Sync button state. mCurrentButtonState = mTouchButtonAccumulator.getButtonState() | mCursorButtonAccumulator.getButtonState(); // Sync scroll state.... // Sync touch state. bool havePointerIds = true; mCurrentRawPointerData.clear(); syncTouch(when, &havePointerIds);//調用子類的syncTouch,這裡自然調用的是我 觸摸框的 SingleTouchMotionAccumulator的syncTouch,更新ABS 座標值,我這裡是把資料存入到mCurrentRawPointerData中供下面cook... // Reset state that we will compute below. mCurrentFingerIdBits.clear(); mCurrentStylusIdBits.clear(); mCurrentMouseIdBits.clear(); mCurrentCookedPointerData.clear(); // 先清掉... // Cook pointer data. This call populates the mCurrentCookedPointerData structure // with cooked pointer data that has the same ids and indices as the raw data. // The following code can use either the raw or cooked data, as needed. cookPointerData(); //這個函數不跟進去了,太龐大,cook資料,主要是產生 mCurrentCookedPointerData.pointerCoords,mCurrentCookedPointerData.pointerProperties和mCurrentCookedPointerData.idToIndex... dispatchTouches(when, policyFlags); //又進行分發...//一些資料儲存之類的操作}
這裡正常的處理是調用dispatchTouches 函數 ,往裡走是dispatchMotion:
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, const PointerProperties* properties, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { PointerCoords pointerCoords[MAX_POINTERS]; PointerProperties pointerProperties[MAX_POINTERS]; uint32_t pointerCount = 0;... getListener()->notifyMotion(&args); //回調}
這裡是走的signeltouch的所以最終會調用getListener()->notifyMotion(&args),如果是Keydown事件。根據上面的邏輯會在cookPointerData 之前調用synthesizeButtonKeys 依次會調用到context->getListener()->notifyKey(&args);
QueuedInputListener:
上面分析到的notifyMotion最後會調用到這個類中,這個作為inputreader環節的最後交接維護類,回顧一下InputRead的構建,可以看下:
// --- InputReader ---InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) //這裡注意最後一個參數~...{ mQueuedListener = new QueuedInputListener(listener); //構造了一個QueuedinputListener...}
這裡又要看下最開始的構造調用了/frameworks/base/services/input/InputManager.cpp中:
InputManager::InputManager(... mDispatcher = new InputDispatcher(dispatcherPolicy); mReader = new InputReader(eventHub, readerPolicy, mDispatcher); //可以看到這裡傳入的是InputDispatcher ,但是上面直接用的InputListenerInterface ,,直接強制轉換成了 父類指標! 這裡注意一下...}
所以在InputReader中構造QueuedInputListener的時候儲存的是InputDispatcher的父類指標,儲存在私人成員
mInnerListener
// --- QueuedInputListener ---QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) : mInnerListener(innerListener) {}
為什麼這麼做是應為 後續調用的純虛函數。將會交由InputDispatcher 的函數來實現。實現了一個傳遞,C++ 就是這樣,要整個看明白。才知道設計者寫的代碼到底跑到哪裡去了~
往下分析流程就知道我為什麼這麼說了.
回到前面,調用 QueuedInputListener::notifyMotion,將這個notifyMotion push進mArgsQueue 鏈表隊列,然後在loopOnce() 中做完上述一次事件的擷取以及分發處理之後將會調用 mQueuedListener->flush();
void QueuedInputListener::flush() { size_t count = mArgsQueue.size(); for (size_t i = 0; i < count; i++) { NotifyArgs* args = mArgsQueue[i]; args->notify(mInnerListener); //這裡依次調用上面push進來的不同種類notify的notify函數,NotifyConfigurationChangedArgs / NotifyKeyArgs / NotifyMotionArgs / NotifySwitchArgs / NotifyDeviceResetArgs 這幾種 delete args; } mArgsQueue.clear();}
這裡還是單以我做的notifyMotion為例:
void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const { listener->notifyMotion(this);}
就是這裡。又來了一個 notifyMotion調用,這個純虛函數 ,兩個子類QueuedInputListener InputDispatcher 中都有實現,就像上面分析到的,最終是調用到 InputDispatcher 中的notifyMotion !
之後就是InputDispatcher 的處理了,這裡不繼續。後續再說~
Linux/Android——Input系統之InputMapper 處理 (八)