Audio/audioflinger/AudioPolicyService.cpp
// insertCommand_l() must be called with mLock held
insertCommand_l() must be called with mLock held
insertCommand_l () must be called with mLock held
void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
{
    ssize_t i;  
    Vector <AudioCommand *> removedCommands;
    nsecs_t time = 0;
    command->mTime = systemTime() + milliseconds(delayMs);
    if (mName != "" && mAudioCommands.isEmpty()) {
        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
    }
    for (i = mAudioCommands.size()-1; i >= 0; i--) {
        AudioCommand *command2 = mAudioCommands[i];
        if (command2->mTime <= command->mTime) break;
        if (command2->mCommand != command->mCommand) continue;
        switch (command->mCommand) {
        case SET_PARAMETERS: {
            ParametersData *data = (ParametersData *)command->mParam;
            ParametersData *data2 = (ParametersData *)command2->mParam;
            if (data->mIO != data2->mIO) break;
            ALOGV("Comparing parameter command %s to new command %s",
                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
            AudioParameter param = AudioParameter(data->mKeyValuePairs);
            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
            for (size_t j = 0; j < param.size(); j++) {
                String8 key;
                String8 value;
                param.getAt(j, key, value);
                for (size_t k = 0; k < param2.size(); k++) {
                    String8 key2;
                    String8 value2;
                    param2.getAt(k, key2, value2);
                    if (key2 == key) {
                        param2.remove(key2);
                        ALOGV("Filtering out parameter %s", key2.string());
                        break;
                    }
                }
            }
            if (param2.size() == 0) {
                removedCommands.add(command2);
            } else {
                data2->mKeyValuePairs = param2.toString();
            }
            time = command2->mTime;
        } break;
        case SET_VOLUME: {
            VolumeData *data = (VolumeData *)command->mParam;
            VolumeData *data2 = (VolumeData *)command2->mParam;
            if (data->mIO != data2->mIO) break;
            if (data->mStream != data2->mStream) break;
            ALOGV("Filtering out volume command on output %d for stream %d",
                    data->mIO, data->mStream);
            removedCommands.add(command2);
            time = command2->mTime;
        } break;
        case START_TONE:
        case STOP_TONE:
        default:
            break;
        }
    }
    for (size_t j = 0; j < removedCommands.size(); j++) {
        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
            if (mAudioCommands[k] == removedCommands[j]) {
                ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
                mAudioCommands.removeAt(k);
                break;
            }
        }
    }
    removedCommands.clear();
    if (delayMs == 0 && time == 0) {
        command->mWaitStatus = true;
    } else {
        command->mWaitStatus = false;
    }
    if (time != 0) {
        command->mTime = time;
    }
    ALOGV("inserting command: %d at index %d, num commands %d",
            command->mCommand, (int)i+1, mAudioCommands.size());
    mAudioCommands.insertAt(command, i + 1);
}
void AudioPolicyService :: AudioCommandThread :: insertCommand_l ( AudioCommand * command , int delayMs ) { ssize_t i ; Vector < AudioCommand * > removedCommands ; nsecs_t time = 0 ; command -> mTime = systemTime ( ) + milliseconds ( delayMs ) ; if ( mName != " " && mAudioCommands . isEmpty ( ) ) { acquire_wake_lock ( PARTIAL_WAKE_LOCK , mName . string ( ) ) ; } for ( i = mAudioCommands . size ( ) - 1 ; i >= 0 ; i -- ) { AudioCommand * command2 = mAudioCommands [ i ] ; if ( command2 -> mTime <= command -> mTime ) break ; if ( command2 -> mCommand != command -> mCommand ) continue ; switch ( command -> mCommand ) { case SET_PARAMETERS : { ParametersData * data = ( ParametersData * ) command -> mParam ; ParametersData * data2 = ( ParametersData * ) command2 -> mParam ; if ( data -> mIO != data2 -> mIO ) break ; ALOGV ( " " , data2 -> mKeyValuePairs . string ( ) , data -> mKeyValuePairs . string ( ) ) ; AudioParameter param = AudioParameter ( data -> mKeyValuePairs ) ; AudioParameter param2 = AudioParameter ( data2 -> mKeyValuePairs ) ; for ( size_t j = 0 ; j < param . size ( ) ; j ++ ) { String8 key ; String8 value ; param . getAt ( j , key , value ) ; for ( size_t k = 0 ; k < param2 . size ( ) ; k ++ ) { String8 key2 ; String8 value2 ; param2 . getAt ( k , key2 , value2 ) ; if ( key2 == key ) { param2 . remove ( key2 ) ; ALOGV ( " " , key2 . string ( ) ) ; break ; } } } if ( param2 . size ( ) == 0 ) { removedCommands . add ( command2 ) ; } else { data2 -> mKeyValuePairs = param2 . toString ( ) ; } time = command2 -> mTime ; } break ; case SET_VOLUME : { VolumeData * data = ( VolumeData * ) command -> mParam ; VolumeData * data2 = ( VolumeData * ) command2 -> mParam ; if ( data -> mIO != data2 -> mIO ) break ; if ( data -> mStream != data2 -> mStream ) break ; ALOGV ( " " , data -> mIO , data -> mStream ) ; removedCommands . add ( command2 ) ; time = command2 -> mTime ; } break ; case START_TONE : case STOP_TONE : default : break ; } } for ( size_t j = 0 ; j < removedCommands . size ( ) ; j ++ ) { for ( size_t k = i + 1 ; k < mAudioCommands . size ( ) ; k ++ ) { if ( mAudioCommands [ k ] == removedCommands [ j ] ) { ALOGV ( " " , mAudioCommands [ k ] -> mCommand ) ; mAudioCommands . removeAt ( k ) ; break ; } } } removedCommands . clear ( ) ; if ( delayMs == 0 && time == 0 ) { command -> mWaitStatus = true ; } else { command -> mWaitStatus = false ; } if ( time != 0 ) { command -> mTime = time ; } ALOGV ( " " , command -> mCommand , ( int ) i + 1 , mAudioCommands . size ( ) ) ; mAudioCommands . insertAt ( command , i + 1 ) ; }
insertCommand_l() must be called with mLock held
insertCommand_l () must be called with mLock held
// not size_t because i will count down to -1 // acquire wake lock to make sure delayed commands are processed // check same pending commands with later time stamps and eliminate them // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands // if all keys have been filtered out, remove the command. // otherwise, update the key value pairs // remove filtered commands // removed commands always have time stamps greater than current command // wait for status only if delay is 0 and command time was not modified above // update command time if modified above // insert command at the right place according to its time stamp