Android多媒体框架(4)—— AMessage,AHandler和ALooper源码分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/foolish0421/article/details/86763119

AMessage,AHandler和ALooper源码分析

AMessage继承自RefBase类,它有AHandler和ALooper的成员mHandler和mLooper,并且ALooper还是它的友元。成员变量mWhat是消息id,成员变量mTarget指明消息的handler(只用于调试)。成员函数setWhat和setTarget分别设置这两个属性。

void AMessage::setWhat(uint32_t what) {
68    mWhat = what;
69}
70
71uint32_t AMessage::what() const {
72    return mWhat;
73}
74
75void AMessage::setTarget(const sp<const AHandler> &handler) {
76    if (handler == NULL) {
77        mTarget = 0;
78        mHandler.clear();
79        mLooper.clear();
80    } else {
81        mTarget = handler->id();
82        mHandler = handler->getHandler();
83        mLooper = handler->getLooper();
84    }
85}

成员函数what返回mWhat属性。而setTarget方法,如果参数handler等于NULL,就把mTarget生成NULL(0),同时清空mHandler和mLooper队列;否则,mTarget设成handler的id,mHandler和mLooper分别设置成handler中的handler和looper。
AMessage中有一组set函数:

	void setInt32(const char *name, int32_t value);
98    void setInt64(const char *name, int64_t value);
99    void setSize(const char *name, size_t value);
100    void setFloat(const char *name, float value);
101    void setDouble(const char *name, double value);
102    void setPointer(const char *name, void *value);
103    void setString(const char *name, const char *s, ssize_t len = -1);
104    void setString(const char *name, const AString &s);
105    void setObject(const char *name, const sp<RefBase> &obj);
106    void setBuffer(const char *name, const sp<ABuffer> &buffer);
107    void setMessage(const char *name, const sp<AMessage> &obj);
108
109    void setRect(
110            const char *name,
111            int32_t left, int32_t top, int32_t right, int32_t bottom);

用来设置name对应的值。与之对应的又一组find函数:

bool findInt32(const char *name, int32_t *value) const;
116    bool findInt64(const char *name, int64_t *value) const;
117    bool findSize(const char *name, size_t *value) const;
118    bool findFloat(const char *name, float *value) const;
119    bool findDouble(const char *name, double *value) const;
120    bool findPointer(const char *name, void **value) const;
121    bool findString(const char *name, AString *value) const;
122    bool findObject(const char *name, sp<RefBase> *obj) const;
123    bool findBuffer(const char *name, sp<ABuffer> *buffer) const;
124    bool findMessage(const char *name, sp<AMessage> *obj) const;
125
126    // finds any numeric type cast to a float
127    bool findAsFloat(const char *name, float *value) const;
128
129    bool findRect(
130            const char *name,
131            int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;

用来根据name查找对应的值。
这里我们重点分析一下setMessage和findMessage的实现。首先看setMessage的代码:

void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
    Item *item = allocateItem(name);
    item->mType = kTypeMessage;

    if (obj != NULL) { obj->incStrong(this); }
    item->u.refValue = obj.get();
}

首先调用allocateItem,根据name创建一个Item,item的type设置成kTypeMessage。如果参数obj不等于NULL,就增加obj的强引用计数,同时,item中的refValue要设置成参数obj的值。kTypeMessage是一个枚举值,它的定义在AMessage.h中:

enum Type {
167        kTypeInt32,
168        kTypeInt64,
169        kTypeSize,
170        kTypeFloat,
171        kTypeDouble,
172        kTypePointer,
173        kTypeString,
174        kTypeObject,
175        kTypeMessage,
176        kTypeRect,
177        kTypeBuffer,
178    };

这里用到的allocateItem函数的代码是这样的:

AMessage::Item *AMessage::allocateItem(const char *name) {
187    size_t len = strlen(name);
188    size_t i = findItemIndex(name, len);
189    Item *item;
190
191    if (i < mNumItems) {
192        item = &mItems[i];
193        freeItemValue(item);
194    } else {
195        CHECK(mNumItems < kMaxNumItems);
196        i = mNumItems++;
197        item = &mItems[i];
198        item->setName(name, len);
199    }
200
201    return item;
202}

获取name的长度,调用findItemIndex获取那么的index i。如果i小于mNumItems,使item指向mItems的第i个item,然后调用freeItemValue,释放对应的item。如果i大于或等于mNumItems,检查mNumItems是否小于kMaxNumItems。mNumItems的值赋值给i,然后使mNumItems的值加1,item指向mItems的第i个item,设置item的name为参数name。findItemIndex的代码如下:

inline size_t AMessage::findItemIndex(const char *name, size_t len) const {
151#ifdef DUMP_STATS
152    size_t memchecks = 0;
153#endif
154    size_t i = 0;
155    for (; i < mNumItems; i++) {
156        if (len != mItems[i].mNameLength) {
157            continue;
158        }
159#ifdef DUMP_STATS
160        ++memchecks;
161#endif
162        if (!memcmp(mItems[i].mName, name, len)) {
163            break;
164        }
165    }
166#ifdef DUMP_STATS
167    {
168        Mutex::Autolock _l(gLock);
169        ++gFindItemCalls;
170        gAverageNumItems += mNumItems;
171        gAverageNumMemChecks += memchecks;
172        gAverageNumChecks += i;
173        reportStats();
174    }
175#endif
176    return i;
177}

这是一个内联函数。

· freeItemValue
freeItemValue的代码如下:

void AMessage::freeItemValue(Item *item) {
98    switch (item->mType) {
99        case kTypeString:
100        {
101            delete item->u.stringValue;
102            break;
103        }
104
105        case kTypeObject:
106        case kTypeMessage:
107        case kTypeBuffer:
108        {
109            if (item->u.refValue != NULL) {
110                item->u.refValue->decStrong(this);
111            }
112            break;
113        }
114
115        default:
116            break;
117    }
118}
119

根据item的类型,执行不同的free操作。

· findMessage
下面我们再来分析一下findMessage的代码:

bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
350    const Item *item = findItem(name, kTypeMessage);
351    if (item) {
352        *obj = static_cast<AMessage *>(item->u.refValue);
353        return true;
354    }
355    return false;
356}

比较简单,调用findItem,根据那么,和类型“kTypeMessage”,调用findItem获取item,如果item不为NULL,就把item的refValue转化为AMessage类型的指针,返回true;否则,返回false。
AMessage中,我们最关心的是以下方法:postAndAwaitResponse等。

status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
396    sp<ALooper> looper = mLooper.promote();
397    if (looper == NULL) {
398        ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
399        return -ENOENT;
400    }
401
402    sp<AReplyToken> token = looper->createReplyToken();
403    if (token == NULL) {
404        ALOGE("failed to create reply token");
405        return -ENOMEM;
406    }
407    setObject("replyID", token);
408
409    looper->post(this, 0 /* delayUs */);
410    return looper->awaitResponse(token, response);
411}
412
413status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
414    if (replyToken == NULL) {
415        ALOGW("failed to post reply to a NULL token");
416        return -ENOENT;
417    }
418    sp<ALooper> looper = replyToken->getLooper();
419    if (looper == NULL) {
420        ALOGW("failed to post reply as target looper is gone.");
421        return -ENOENT;
422    }
423    return looper->postReply(replyToken, this);
424}

postAndAwaitResponse方法中,首先通过mLooper的promote方法,获取ALooper的一个强引用计数looper,如果looper为NULL,直接返回ENOMEM。通过looper->createReplyToken()创建AReplyToken的强引用计数token。调用setObject("replyID", token)设置replyID。调用looper->post(this, 0 /* delayUs */)发送消息,然后,looper->awaitResponse(token, response)等待返回。

AHandler类

AHandler类的代码比较简单,其中定义了一个ALooper的弱引用计数mLooper,一个ALooper::handler_id类型的mID。其中的deliverMessage方法代码如下:

void AHandler::deliverMessage(const sp<AMessage> &msg) {
27    onMessageReceived(msg);
28    mMessageCounter++;
29
30    if (mVerboseStats) {
31        uint32_t what = msg->what();
32        ssize_t idx = mMessages.indexOfKey(what);
33        if (idx < 0) {
34            mMessages.add(what, 1);
35        } else {
36            mMessages.editValueAt(idx)++;
37        }
38    }
39}

首先触发本类的onMessageReceived(msg),这是一个纯虚函数,子类中需要有它的具体实现。然后把Message技术mMessageCounter加1。获取message的类型(what)和idx。如果idx小于0,在mMessages中添加一个what类型的消息;否则,编辑idx出的Message。

ALooper类

ALooper类也是RefBase的子类。ALooper中有一个内部的struct LooperThread,继承自Thread,并且,这个struct中有一个指向ALooper类型的指针mLooper。ALooper中的成员变量mThread是一个LooperThread的强引用计数。ALooper的start方法开启Looper,其代码如下:

status_t ALooper::start(
97        bool runOnCallingThread, bool canCallJava, int32_t priority) {
98    if (runOnCallingThread) {
99        {
100            Mutex::Autolock autoLock(mLock);
101
102            if (mThread != NULL || mRunningLocally) {
103                return INVALID_OPERATION;
104            }
105
106            mRunningLocally = true;
107        }
108
109        do {
110        } while (loop());
111
112        return OK;
113    }
114
115    Mutex::Autolock autoLock(mLock);
116
117    if (mThread != NULL || mRunningLocally) {
118        return INVALID_OPERATION;
119    }
120
121    mThread = new LooperThread(this, canCallJava);
122
123    status_t err = mThread->run(
124            mName.empty() ? "ALooper" : mName.c_str(), priority);
125    if (err != OK) {
126        mThread.clear();
127    }
128
129    return err;
130}

如果runOnCallingThread为true(在调用线程运行),首先使用mLock加同步锁,如果mThread为NULL,或者mRunningLocally为true(在本地线程运行),直接返回INVALID_OPERATION。将mRunningLocally设为true。执行一个无限循环,直到loop方法返回false为止。返回OK。如果runOnCallingThread为false,先用mLock加同步锁,如果mThread为NULL,或者mRunningLocally为true(在本地线程运行),直接返回INVALID_OPERATION。生成一个新的LooperThread,赋值给mThread。调用mThread的run方法。如果run方法返回的状态不是OK,需要调用clear方法。
loop方法的代码如下:

bool ALooper::loop() {
195    Event event;
196
197    {
198        Mutex::Autolock autoLock(mLock);
199        if (mThread == NULL && !mRunningLocally) {
200            return false;
201        }
202        if (mEventQueue.empty()) {
203            mQueueChangedCondition.wait(mLock);
204            return true;
205        }
206        int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
207        int64_t nowUs = GetNowUs();
208
209        if (whenUs > nowUs) {
210            int64_t delayUs = whenUs - nowUs;
211            mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
212
213            return true;
214        }
215
216        event = *mEventQueue.begin();
217        mEventQueue.erase(mEventQueue.begin());
218    }
219
220    event.mMessage->deliver();
221
222    // NOTE: It's important to note that at this point our "ALooper" object
223    // may no longer exist (its final reference may have gone away while
224    // delivering the message). We have made sure, however, that loop()
225    // won't be called again.
226
227    return true;
228}

首先加同步锁。如果mThread为NULL,或者mRunningLocally为false(非本地线程执行),返回false。如果mEventQueue列表为空,等待解锁,并且返回true。获取mEventQueue中的一个元素的mWhenUs属性(当时的微秒数)whenUs,以及当前的微秒数nowUs,如果whenUs大于nowUs,whenUs减去nowUs的差值delayUs。等待一个delayUs * 1000的相对时间后解锁,并返回true。获取mQueue中的第一个event,并且从mQueue中移除这个event。调用event.mMessage->deliver()投递消息到handler,返回true。
mEventQueue中的Event从何而来呢?是通过post方法加入的。post方法的代码如下:

void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
169    Mutex::Autolock autoLock(mLock);
170
171    int64_t whenUs;
172    if (delayUs > 0) {
173        whenUs = GetNowUs() + delayUs;
174    } else {
175        whenUs = GetNowUs();
176    }
177
178    List<Event>::iterator it = mEventQueue.begin();
179    while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {
180        ++it;
181    }
182
183    Event event;
184    event.mWhenUs = whenUs;
185    event.mMessage = msg;
186
187    if (it == mEventQueue.begin()) {
188        mQueueChangedCondition.signal();
189    }
190
191    mEventQueue.insert(it, event);
192}

首先要加同步锁,得到whenUs的值,通过迭代器遍历mEventQueue,在mEventQueue中找到mWhenUs大于whenUs的Event的位置。创建新Event,event的mWhenUs就是之前的whenUs,mMessage是参数msg。如果找到的位置位于mEventQueue的开始,直接调用mQueueChangedCondition.signal()激活解锁。把event插入到前面找到的位置。
ALooper中还有个重要的方法stop:

status_t ALooper::stop() {
133    sp<LooperThread> thread;
134    bool runningLocally;
135
136    {
137        Mutex::Autolock autoLock(mLock);
138
139        thread = mThread;
140        runningLocally = mRunningLocally;
141        mThread.clear();
142        mRunningLocally = false;
143    }
144
145    if (thread == NULL && !runningLocally) {
146        return INVALID_OPERATION;
147    }
148
149    if (thread != NULL) {
150        thread->requestExit();
151    }
152
153    mQueueChangedCondition.signal();
154    {
155        Mutex::Autolock autoLock(mRepliesLock);
156        mRepliesCondition.broadcast();
157    }
158
159    if (!runningLocally && !thread->isCurrentThread()) {
160        // If not running locally and this thread _is_ the looper thread,
161        // the loop() function will return and never be called again.
162        thread->requestExitAndWait();
163    }
164
165    return OK;
166}

首先加同步锁,调用mThread的clear,恢复mRunningLocally为false。如果thread为NULL,或者mRunningLocally为false,返回INVALID_OPERATION。stop主要做一些退出前的清理操作。

猜你喜欢

转载自blog.csdn.net/foolish0421/article/details/86763119