美文网首页Android开发经验谈Android开发Android技术知识
Android:播放系统效果音导致ANR问题分析

Android:播放系统效果音导致ANR问题分析

作者: 我在等你回复可你没回 | 来源:发表于2019-07-01 14:39 被阅读27次

    最近遇到一个问题,在疯狂点击按钮后,手机出现ANR

    步骤一:通过查看ANR的log,发现AudioTrack占用了将近100%的CPU

    步骤二:分析AudioTrack的代码

    通过AudioTrack的PID,确认到这个AudioTrack属于system_server。
    而这个AudioTrack是在播放按钮的效果音。

    步骤三:分析AudioTrack的代码是否存在循环

    bool AudioTrack::AudioTrackThread::threadLoop()
    {
        ..................
            if (mPaused) {
                mMyCond.wait(mMyLock);
                // caller will check for exitPending()
                return true;
            }
        nsecs_t ns = mReceiver.processAudioBuffer();
       ...................
    }
    

    通过加log发现,AudioTrack线程在threadLoop中疯狂的循环,这个就是导致CPU占用高的原因。我关闭掉系统效果音之后,ANR就没法复现了。
    理论上,这个threadLoop()会在mMyCond.wait停下来,但是现在没有停下来,说明mPaused变量一直没false,说明AudioTrack::stop函数一直没有被调用。

    步骤四:寻找AudioTrack::stop的入口

    最后发现是在SoundPool.cpp的run函数中调用stop的

    int SoundPool::run()
    {
        mRestartLock.lock();
        while (!mQuit) {
            mCondition.wait(mRestartLock);
            ALOGV("awake");
            if (mQuit) break;
            while (!mStop.empty()) {
                SoundChannel* channel;
                ALOGV("Getting channel from stop list");
                List<SoundChannel* >::iterator iter = mStop.begin();
                channel = *iter;
                  this, channel->mChannelID);
                mStop.erase(iter);
                mRestartLock.unlock();
                if (channel != 0) {
                    Mutex::Autolock lock(&mLock);
                    channel->stop();   //这里去stop
                }
                mRestartLock.lock();
                if (mQuit) break;
            }
    
            while (!mRestart.empty()) {
                SoundChannel* channel;
                ALOGV("Getting channel from list");
                List<SoundChannel*>::iterator iter = mRestart.begin();
                channel = *iter;
                mRestart.erase(iter);
                mRestartLock.unlock();
                if (channel != 0) {
                    Mutex::Autolock lock(&mLock);
                    channel->nextEvent();
                }
                mRestartLock.lock();
                if (mQuit) break;
            }
        }
        mStop.clear();
        mRestart.clear();
        mCondition.signal();
        mRestartLock.unlock();
        ALOGV("goodbye");
        return 0;
    }
    

    那为什么没有调用到channel->stop,最后分析发现卡在了mCondition.wait中,而通过分析发现下面函数的signal已经调用了,但却没有唤醒

    void SoundPool::addToStopList(SoundChannel* channel)
    {
        Mutex::Autolock lock(&mRestartLock);
        if (!mQuit) {
            mStop.push_back(channel);
            mCondition.signal();
            KPOC_LOGE("addToStopList.signal mQuit= %d",mQuit);
        }
    }
    

    这种情况,我分析是cpu占用过高了,导致唤醒非常地慢。当然这个只是猜测。

    接下来能做什么?对比processAudioBuffer的流程。查看R状态死锁。

    相关文章

      网友评论

        本文标题:Android:播放系统效果音导致ANR问题分析

        本文链接:https://www.haomeiwen.com/subject/mtpgcctx.html