Multimedia Alooper 机制分析

本文深入探讨了Android底层多媒体处理中的ALooper、AHandler和AMessage机制,与普通的Looper机制进行了对比。主要内容包括ALooper线程创建、AHandler与ALooper绑定、AMessage与AHandler的交互以及AMessage的异步和同步发送流程。通过AMessage的键值对形式,传递参数变得灵活便捷。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

android  底层的录制和播放都会用到ALooper,AHandler和AMessage,这个和上一篇讲的looper有什么不一样呢?其实作用是差不多的,只是实现的方式不一样而已。

1、looper线程的创建

status_t ALooper::start(
        bool runOnCallingThread, bool canCallJava, int32_t priority) {
    if (runOnCallingThread) {  //如果传入的参数为true,就会使用当前的线程作为looper线程,否则下面会再创建一个线程作为looper线程
        {
            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;
}
调用ALooper的start()函数后,就会进入loop,也就是一直循环调用loop()函数,如果传入的第一个参数是true,就会让当前线程变成looper线程,否则会创建一个新的looper线程。

   virtual bool threadLoop() {
        return mLooper->loop();
    }
其实就是创建一个普通线程,然后循环调用loop()函数。


2、AHandler和Alooper进行绑定

ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
    return gLooperRoster.registerHandler(this, handler);
}
调用ALooper的registerHandler()接口后就能将AHandler对象和该ALooper对象进行绑定了。

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;
}
gLooperRoster 可以认为它是一个全局变量,主要的作用是管理AHandler和ALooper,返回的handlerID十分重要,L版本之前可以通过这个id找到对应的AHandler。

3、AMessage怎么和AHandler进行绑定

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 对象的时候可以把对应AHandler对象传入进行绑定,或者通过setTarget()函数进行绑定。


4、AMessage从发送到处理流程

1)异步消息,不需要等待执行结果


post()到ALooper后,会把AMessage插入到mEventQueue队列中,此时把Message封装到Event中。

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);
}

上面的post()后,会把Event(AMessage)插入event队列中,如果插在头部,会发一次信号到loop()中。

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;
}
收到信号后,mQueueChangedCondition.waitRelative()会返回true,重新跑一次loop(),这时如果队列中的第一个消息需要马上处理(whenUs > nowUs 不成立),会继续往下跑,从队列中取出第一个消息,并从队列移除,调用event.mMessage->deliver();就走到了后面AHandler的消息处理流程。

2)同步消息,需要等待消息处理完成之后才返回


和异步消息的流程差不多,只不过多了等带AHandler处理完消息后并postReply()后才会往下走,并且得到一个AMessage类型返回结果。AMessage可以保存很多类型的数据,通过<ker,value>的形式,在传递参数时,使用起来十分方便,有兴趣的同学阅读源码深入了解。


对比一下:

Looper 通过epoll_wait()等待事件触发或者超时。

int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

ALooper通过waitRelative()等待信号或者超时。

mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值