Linux/Android——Input系統之InputMapper 處理 (八)

來源:互聯網
上載者:User

標籤: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 處理 (八)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.