安卓異步消息處理機制源碼流程

1.源碼流程貼圖

1.1源碼例子部分代碼貼圖

NuPlayerDriver::NuPlayerDriver(pid_t pid)
    : mState(STATE_IDLE),
      mIsAsyncPrepare(false),
      mAsyncResult(UNKNOWN_ERROR),
      mSetSurfaceInProgress(false),
      mDurationUs(-1),
      mPositionUs(-1),
      mSeekInProgress(false),
      mLooper(new ALooper),
      mPlayerFlags(0),
      mAtEOS(false),
      mLooping(false),
      mAutoLoop(false) {
    ALOGV("NuPlayerDriver(%p)", this);
    mLooper->setName("NuPlayerDriver Looper");

    mLooper->start(
            false, /* runOnCallingThread */
            true,  /* canCallJava */
            PRIORITY_AUDIO);

    mPlayer = AVNuFactory::get()->createNuPlayer(pid);
    mLooper->registerHandler(mPlayer);

    mPlayer->setDriver(this);
}

主要部分:

      mLooper(new ALooper),    
      mLooper->start(
            false, /* runOnCallingThread */
            true,  /* canCallJava */
            PRIORITY_AUDIO);
      mLooper->registerHandler(mPlayer);

  其中mLooper(new ALooper) 和mLooper->start創建一個線程,該線程不斷地執行mLooper的loop函數,每執行一次loop函數就會從線程中由mLooper維護的事件鏈表取出首端事件,然後判斷該事件的時間戳,如果該事件的時間戳小於或者等於當前系統的時間,則調用該事件消息的deliver函數將該事件的消息派發出去。
  現在完成了這樣一個創建,還沒有向事件鏈表中添加任何事件。

下面貼出mLooper調用registerHandler函數的具體流程
==>
mLooper->registerHandler(mPlayer);

==>
ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
    return gLooperRoster.registerHandler(this, handler);
}

==>
ALooper::handler_id ALooperRoster::registerHandler(
        const sp<ALooper> looper, const sp<AHandler> &handler) {
    Mutex::Autolock autoLock(mLock);

    if (handler->id() != 0) {
        CHECK(!"A handler must only be registered once.");
        return INVALID_OPERATION;
    }

    HandlerInfo info;
    info.mLooper = looper;
    info.mHandler = handler;
    ALooper::handler_id handlerID = mNextHandlerID++;
    mHandlers.add(handlerID, info);

    handler->setID(handlerID, looper);

    return handlerID;
}

==>
handler->setID(handlerID, looper);

==>
inline void setID(ALooper::handler_id id, wp<ALooper> looper) {
    mID = id;
    mLooper = looper;
}

  由ALooper調用其registerHandler函數來完成註冊,整個註冊過程除了將ALooper和AHandler綁定成一對兒,然後給予一個唯一的鍵值,存儲在全局對象gLooperRoster的mHandlers容器中,還通過調用handler->setID(handlerID, looper)將這個鍵值和 looper的引用保存在handler中。
  將鍵值和 looper的引用保存在handler中這很重要,因爲只有擁有ALooper的引用,才能調用ALooper提供的post接口將事件添加到ALooper維護的事件鏈表中。
  這樣以來,一個經過註冊的AHandler對象,將擁有一個非零的鍵值用來標識自己和與自己綁定在一起的ALooper對象,並且該AHandler對象含有該ALooper對象的引用,後續會通過這個引用來調用ALooper對象的post接口向ALooper對象維護的事件鏈表中。

1.2創建一個消息

==>
void NuPlayer::start() {
    (new AMessage(kWhatStart, this))->post();
}

==>
AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
    : mWhat(what),
      mNumItems(0) {
    setTarget(handler);
}

==>
void AMessage::setTarget(const sp<const AHandler> &handler) {
    if (handler == NULL) {
        mTarget = 0;
        mHandler.clear();
        mLooper.clear();
    } else {
        mTarget = handler->id();
        mHandler = handler->getHandler();
        mLooper = handler->getLooper();
    }
}

==>
struct AHandler : public RefBase {
    wp<ALooper> getLooper() const {
        return mLooper;
    }

    wp<AHandler> getHandler() const {
        // allow getting a weak reference to a const handler
        return const_cast<AHandler *>(this);
    }
};

  創建消息的時候需要兩個參數,一個是消息名,另一個是經過註冊的消息處理者(AHandler),this這裏是NuPlayer對象,也是前面的創建的mPlayer,是一個AHandler對象。
  設置好了消息名後,然後調用setTarget(handler)函數,設置mTarget,mHandler,mLooper這些成員變量的值。其中mHandler和mLooper是一對兒經過註冊的AHandler,ALooper對兒,mTarget是標識這一對兒的鍵值。
  整個流程完成賦值後,形成的格局是:
  有一對兒綁定在一起的AHandler,,ALooper跟據標識這一對兒的鍵值存儲在全局對象gLooperRoster的mHandlers容器中。
  然後這個經過註冊的AHandler對象作爲參數值來創建一個消息AMessage對象。這個AMessage對象通過傳遞的AHandler對象得到了這個AHandler對象的引用,並且獲取到了他的handler ID 和ALooper對象的引用。
  這樣以來這個AMessage對象和AHandler對象都擁有了ALooper對象的引用引用,這樣就可以通過調用ALooper對象的post函數來向ALooper對象維護的事件鏈表中添加事件。同時AMessage對象也擁有了AHandler對象的引用,這樣就可以調用AHandler對象的函數來對該消息進行處理。

1.3發用消息

==>
void NuPlayer::start() {
    (new AMessage(kWhatStart, this))->post();
}

==>
status_t AMessage::post(int64_t delayUs) {
    sp<ALooper> looper = mLooper.promote();
    if (looper == NULL) {
        ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
        return -ENOENT;
    }

    looper->post(this, delayUs);
    return OK;
}

==>
void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
    Mutex::Autolock autoLock(mLock);

    int64_t whenUs;
    if (delayUs > 0) {
        whenUs = GetNowUs() + delayUs;
    } else {
        whenUs = GetNowUs();
    }

    List<Event>::iterator it = mEventQueue.begin();
    while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {
        ++it;
    }

    Event event;
    event.mWhenUs = whenUs;
    event.mMessage = msg;

    if (it == mEventQueue.begin()) {
        mQueueChangedCondition.signal();
    }

    mEventQueue.insert(it, event);
}

  通過調用該AMessage對象擁有的ALooper對象引用調用其post函數來向ALooper對象維護的事件鏈表添加消息。

1.4消息派發(deliver)

==>
bool ALooper::loop() {
    Event event;

    {
        Mutex::Autolock autoLock(mLock);
        if (mThread == NULL && !mRunningLocally) {
            return false;
        }
        if (mEventQueue.empty()) {
            mQueueChangedCondition.wait(mLock);
            return true;
        }
        int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
        int64_t nowUs = GetNowUs();

        if (whenUs > nowUs) {
            int64_t delayUs = whenUs - nowUs;
            mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);

            return true;
        }

        event = *mEventQueue.begin();
        mEventQueue.erase(mEventQueue.begin());
    }

    event.mMessage->deliver();

    // NOTE: It's important to note that at this point our "ALooper" object
    // may no longer exist (its final reference may have gone away while
    // delivering the message). We have made sure, however, that loop()
    // won't be called again.

    return true;
}

==>
event.mMessage->deliver();

==>
void AMessage::deliver() {
    sp<AHandler> handler = mHandler.promote();
    if (handler == NULL) {
        ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
        return;
    }

    handler->deliverMessage(this);
}

  通過AMessage對象擁有的AHandler對象的引用,然後調用AHandler對象對象的deliverMessage函數將消息派發出去。

1.5消息處理

==>
handler->deliverMessage(this);

==>
namespace android {

void AHandler::deliverMessage(const sp<AMessage> &msg) {
    onMessageReceived(msg);
    mMessageCounter++;

    if (mVerboseStats) {
        uint32_t what = msg->what();
        ssize_t idx = mMessages.indexOfKey(what);
        if (idx < 0) {
            mMessages.add(what, 1);
        } else {
            mMessages.editValueAt(idx)++;
        }
    }
}

}  // namespace android

==>
onMessageReceived(msg);

  handler->deliverMessage函數裏調用了onMessageReceived(msg);
  onMessageReceived在AHandler裏是純虛函數,NuPlayer繼承自AHandler並且重寫了onMessageReceived。所以通過虛函數機制最終是在NuPlayer的onMessageReceived函數裏對msg進行處理的

  下面貼出安卓N版本AHandler.h的原文

#ifndef A_HANDLER_H_

#define A_HANDLER_H_

#include <media/stagefright/foundation/ALooper.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>

namespace android {

struct AMessage;

struct AHandler : public RefBase {
    AHandler()
        : mID(0),
          mVerboseStats(false),
          mMessageCounter(0) {
    }

    ALooper::handler_id id() const {
        return mID;
    }

    sp<ALooper> looper() const {
        return mLooper.promote();
    }

    wp<ALooper> getLooper() const {
        return mLooper;
    }

    wp<AHandler> getHandler() const {
        // allow getting a weak reference to a const handler
        return const_cast<AHandler *>(this);
    }

protected:
    virtual void onMessageReceived(const sp<AMessage> &msg) = 0;

private:
    friend struct AMessage;      // deliverMessage()
    friend struct ALooperRoster; // setID()

    ALooper::handler_id mID;
    wp<ALooper> mLooper;

    inline void setID(ALooper::handler_id id, wp<ALooper> looper) {
        mID = id;
        mLooper = looper;
    }

    bool mVerboseStats;
    uint32_t mMessageCounter;
    KeyedVector<uint32_t, uint32_t> mMessages;

    void deliverMessage(const sp<AMessage> &msg);

    DISALLOW_EVIL_CONSTRUCTORS(AHandler);
};

}  // namespace android

#endif  // A_HANDLER_H_

2.總結

  整體來說安卓N版本里異步消息處理機制較安卓M版本有了很大的變化,不過涉及到的還是ALooper,AHandler,AMessage這三個。只不過在實現機理上有了不小的變化。
  我覺得N版本這個實現機理上還是比較好的,但是容易繞糊塗。
  對這個版本的實現機理做個小結:
  ALooper提供post函數用來向事件鏈表裏添加消息,AHandler提供函數deliverMessage來完成消息派發。兩個函數調用都是發生在AMessage提供的post和deliver函數裏的。因此問題的關鍵就是這個中間者需要擁有ALooper,AHandler的引用這樣就可以在自己的post和deliver函數裏裏分被調用ALooper提供的post函數和AHandler提供函數deliverMessage來完成事件的添加和消息的派發。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章