Android MultiMedia框架——ALooper AHandler AMessage
基于Android 9.0源码分析
在分析meidacodec framework层代码有看到ALooper、AHandler、AMessage这几个类,这主要分析下其内部原理
代码路径:frameworks/av/media/libstagefright/foundation/
ALooper
首先看下ALooper使用示例
mLooper = new ALooper;
mLooper->setName("MediaCodec_looper");
mLooper->start(
false, // runOnCallingThread
true, // canCallJava
ANDROID_PRIORITY_VIDEO);
1 初始化
ALooper::ALooper()
: mRunningLocally(false) {
// clean up stale AHandlers. Doing it here instead of in the destructor avoids
// the side effect of objects being deleted from the unregister function recursively.
gLooperRoster.unregisterStaleHandlers();
}
mRunningLocally用来区分ALooper执行线程是否在调用线程,start函数会进行复制;
清理过时的AHandler;
2 start
status_t ALooper::start(
bool runOnCallingThread, bool canCallJava, int32_t priority) {
if (runOnCallingThread) {
{
Mutex::Autolock autoLock(mLock);
if (mThread != NULL || mRunningLocally) {
return INVALID_OPERATION;
}
mRunningLocally = true;
}
do {
} while (loop());
return OK;
}
Mutex::Autolock autoLock(mLock);
if (mThread != NULL || mRunningLocally) {
return INVALID_OPERATION;
}
mThread = new LooperThread(this, canCallJava);
status_t err = mThread->run(
mName.empty() ? "ALooper" : mName.c_str(), priority);
if (err != OK) {
mThread.clear();
}
return err;
}
runOnCallingThread参数用来区分ALooper执行时在调用者线程还是新创建线程;
runOnCallingThread为ture,则在调用者线程进行loop循环;
runOnCallingThread为false,创建LooperThread,并调用其run方法;
接着看下LooperThread
struct ALooper::LooperThread : public Thread {
LooperThread(ALooper *looper, bool canCallJava)
: Thread(canCallJava),
mLooper(looper),
mThreadId(NULL) {
}
virtual bool threadLoop() {
return mLooper->loop();
}
//.........
}
LooperThread继承于Thread类,其run函数会调用到threadLoop函数中;
threadLoop会调用ALooper的loop函数,进行消息的分发;
3 loop
先看下ALooper类的一些变量
private:
friend struct AMessage; // post()
//封装消息 结构体
struct Event {
int64_t mWhenUs;
sp<AMessage> mMessage;
};
Mutex mLock; //锁
Condition mQueueChangedCondition;
AString mName;
//event队列
List<Event> mEventQueue;
struct LooperThread;
sp<LooperThread> mThread; //新建的运行线程
bool mRunningLocally; //是否在调用者线程运行
Event结构体封装了AMessage及对应的时间,mEventQueue则对应接收到的消息队列。
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;
}
mEventQueue如果内部空,没有元素则进行阻塞等待;
mEventQueue不为空,则获取第一个元素的时间,如果时间大于当前时间则表示没有到时间,则阻塞指定时间并返回;
如果whenUs不大于当前时间,则表示应该执行第一个任务了;
取出第一个event,并从mEventQueue中擦除,执行message deliver函数,稍后分析deliver;
ALooper loop函数负责从mEventQueue获取事件,并进行分发;
AMessage
先看使用示例
sp<AMessage> msg = new AMessage(kWhatInit, this);
msg->setMessage("on-frame-rendered", notify);
msg->post()
接着看下AMessage内部实现
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();
}
}
初始化AMessage,设置其what值,并且和handler、Looper绑定关系。
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;
}
post获取ALooper指针,调用其post函数,将AMessage封装成Event,添加到mEventQueue队列中。
看下Amessage 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);
}
deliver中获取AHandler指针,并将消息分发给AHandler处理;
AHandler
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)++;
}
}
}
AHandler接收到消息,调用onMessageReceived函数进行处理,类似java 中handleMessage。
C++层和java层区别(AHandler 和Handler区别)
- 都实现了线程间通信机制
- ALooper在start时,确定其执行线程是在调用者线程,还是新建线程,而Looper则在初始化(prepare)时确定其执行线程为本线程;
- C++层发送消息可以等待获取回应,java层不能阻塞获取回应。
————————————————
版权声明:本文为博主「zpy_公众号_码农修仙儿」的原创文章