分析Android代码的时候被内部使用的mutex搞的很晕,经常找不到对应的lock和unlock的地方在bool AudioPolicyService::AudioCommandThread::threadLoop()函数刚进去的地方就把mLock给lock上了,搞不懂写代码人的用意,也没找到unlock的地方,见下面红色字体部分,在处理START_TONE和STOP_TONE的时候为何会先unlock再lock请大家帮忙看看,谢谢bool AudioPolicyService::AudioCommandThread::threadLoop()
{
    nsecs_t waitTime = INT64_MAX;    mLock.lock();
    while (!exitPending())
    {
        while(!mAudioCommands.isEmpty()) {
            nsecs_t curTime = systemTime();
            // commands are sorted by increasing time stamp: execute them from index 0 and up
            if (mAudioCommands[0]->mTime <= curTime) {
                AudioCommand *command = mAudioCommands[0];
                mAudioCommands.removeAt(0);
                mLastCommand = *command;                switch (command->mCommand) {
                case START_TONE: {
                    mLock.unlock();
                    ToneData *data = (ToneData *)command->mParam;
                    LOGV("AudioCommandThread() processing start tone %d on stream %d",
                            data->mType, data->mStream);
                    if (mpToneGenerator != NULL)
                        delete mpToneGenerator;
                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
                    mpToneGenerator->startTone(data->mType);
                    delete data;
                    mLock.lock();
                    }break;
                case STOP_TONE: {
                    mLock.unlock();
                    LOGV("AudioCommandThread() processing stop tone");
                    if (mpToneGenerator != NULL) {
                        mpToneGenerator->stopTone();
                        delete mpToneGenerator;
                        mpToneGenerator = NULL;
                    }
                    mLock.lock();
                    }break;
                 default:
                    LOGW("AudioCommandThread() unknown command %d", command->mCommand);
                }
                delete command;
                waitTime = INT64_MAX;
            } else {
                waitTime = mAudioCommands[0]->mTime - curTime;
                break;
            }
        }
        // release delayed commands wake lock
        if (mName != "" && mAudioCommands.isEmpty()) {
            release_wake_lock(mName.string());
        }
        LOGV("AudioCommandThread() going to sleep");
        mWaitWorkCV.waitRelative(mLock, waitTime);
        LOGV("AudioCommandThread() waking up");
    }
    mLock.unlock();
    return false;
}