Fix issue 2045911: Camera Shutter tone does not play correctly while listening to music.

Add the possibility to delay routing and volume commands in AudioPolicyClientInterface. The delay is not blocking for the caller.
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 1f726fe..57f8102 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -451,6 +451,7 @@
     status_t get(const String8& key, String8& value);
     status_t getInt(const String8& key, int& value);
     status_t getFloat(const String8& key, float& value);
+    status_t getAt(size_t index, String8& key, String8& value);
 
     size_t size() { return mParameters.size(); }
 
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
index ae17d76..5c3cc8e 100644
--- a/libs/audioflinger/AudioPolicyService.cpp
+++ b/libs/audioflinger/AudioPolicyService.cpp
@@ -16,6 +16,13 @@
 
 #define LOG_TAG "AudioPolicyService"
 //#define LOG_NDEBUG 0
+
+#undef __STRICT_ANSI__
+#define __STDINT_LIMITS
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include <sys/time.h>
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
 #include <cutils/properties.h>
@@ -54,7 +61,7 @@
     char value[PROPERTY_VALUE_MAX];
 
     // start tone playback thread
-    mTonePlaybacThread = new AudioCommandThread();
+    mTonePlaybackThread = new AudioCommandThread();
     // start audio commands thread
     mAudioCommandThread = new AudioCommandThread();
 
@@ -80,8 +87,8 @@
 
 AudioPolicyService::~AudioPolicyService()
 {
-    mTonePlaybacThread->exit();
-    mTonePlaybacThread.clear();
+    mTonePlaybackThread->exit();
+    mTonePlaybackThread.clear();
     mAudioCommandThread->exit();
     mAudioCommandThread.clear();
 
@@ -451,9 +458,9 @@
     return af->closeInput(input);
 }
 
-status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output)
+status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
 {
-    return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output);
+    return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
 }
 
 status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
@@ -465,9 +472,9 @@
 }
 
 
-void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
+void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
 {
-    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs);
+    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
 }
 
 String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
@@ -478,13 +485,13 @@
 
 status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
 {
-    mTonePlaybacThread->startToneCommand(tone, stream);
+    mTonePlaybackThread->startToneCommand(tone, stream);
     return NO_ERROR;
 }
 
 status_t AudioPolicyService::stopTone()
 {
-    mTonePlaybacThread->stopToneCommand();
+    mTonePlaybackThread->stopToneCommand();
     return NO_ERROR;
 }
 
@@ -516,58 +523,72 @@
 
 bool AudioPolicyService::AudioCommandThread::threadLoop()
 {
+    nsecs_t waitTime = INT64_MAX;
+
     mLock.lock();
     while (!exitPending())
     {
         while(!mAudioCommands.isEmpty()) {
-            AudioCommand *command = mAudioCommands[0];
-            mAudioCommands.removeAt(0);
-            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;
+            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);
+                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;
+                case SET_VOLUME: {
+                    VolumeData *data = (VolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
+                    command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
+                case SET_PARAMETERS: {
+                     ParametersData *data = (ParametersData *)command->mParam;
+                     LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
+                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
+                     if (command->mWaitStatus) {
+                         command->mCond.signal();
+                         mWaitWorkCV.wait(mLock);
+                     }
+                     delete data;
+                     }break;
+                default:
+                    LOGW("AudioCommandThread() unknown command %d", command->mCommand);
                 }
-                mLock.lock();
-                }break;
-            case SET_VOLUME: {
-                VolumeData *data = (VolumeData *)command->mParam;
-                LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
-                mCommandStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
-                mCommandCond.signal();
-                mWaitWorkCV.wait(mLock);
-                delete data;
-                }break;
-            case SET_PARAMETERS: {
-                 ParametersData *data = (ParametersData *)command->mParam;
-                 LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
-                 mCommandStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
-                 mCommandCond.signal();
-                 mWaitWorkCV.wait(mLock);
-                 delete data;
-                 }break;
-            default:
-                LOGW("AudioCommandThread() unknown command %d", command->mCommand);
+                delete command;
+                waitTime = INT64_MAX;
+            } else {
+                waitTime = mAudioCommands[0]->mTime - curTime;
+                break;
             }
-            delete command;
         }
         LOGV("AudioCommandThread() going to sleep");
-        mWaitWorkCV.wait(mLock);
+        mWaitWorkCV.waitRelative(mLock, waitTime);
         LOGV("AudioCommandThread() waking up");
     }
     mLock.unlock();
@@ -583,7 +604,8 @@
     data->mType = type;
     data->mStream = stream;
     command->mParam = (void *)data;
-    mAudioCommands.add(command);
+    command->mWaitStatus = false;
+    insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
     mWaitWorkCV.signal();
 }
@@ -594,13 +616,16 @@
     AudioCommand *command = new AudioCommand();
     command->mCommand = STOP_TONE;
     command->mParam = NULL;
-    mAudioCommands.add(command);
+    command->mWaitStatus = false;
+    insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone stop");
     mWaitWorkCV.signal();
 }
 
-status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output)
+status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
 {
+    status_t status = NO_ERROR;
+
     Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_VOLUME;
@@ -609,17 +634,26 @@
     data->mVolume = volume;
     data->mIO = output;
     command->mParam = data;
-    mAudioCommands.add(command);
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    insertCommand_l(command, delayMs);
     LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
     mWaitWorkCV.signal();
-    mCommandCond.wait(mLock);
-    status_t status =  mCommandStatus;
-    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
     return status;
 }
 
-status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs)
+status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
 {
+    status_t status = NO_ERROR;
+
     Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_PARAMETERS;
@@ -627,15 +661,102 @@
     data->mIO = ioHandle;
     data->mKeyValuePairs = keyValuePairs;
     command->mParam = data;
-    mAudioCommands.add(command);
-    LOGV("AudioCommandThread() adding set parameter string %s, io %d", keyValuePairs.string(), ioHandle);
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
     mWaitWorkCV.signal();
-    mCommandCond.wait(mLock);
-    status_t status =  mCommandStatus;
-    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
     return status;
 }
 
+// insertCommand_l() must be called with mLock held
+void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
+{
+    ssize_t i;
+    Vector <AudioCommand *> removedCommands;
+
+    command->mTime = systemTime() + milliseconds(delayMs);
+
+    // check same pending commands with later time stamps and eliminate them
+    for (i = mAudioCommands.size()-1; i >= 0; i--) {
+        AudioCommand *command2 = mAudioCommands[i];
+        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
+        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;
+            LOGV("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);
+                      LOGV("Filtering out parameter %s", key2.string());
+                      break;
+                  }
+               }
+            }
+            // if all keys have been filtered out, remove the command.
+            // otherwise, update the key value pairs
+            if (param2.size() == 0) {
+                removedCommands.add(command2);
+            } else {
+                data2->mKeyValuePairs = param2.toString();
+            }
+        } 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;
+            LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
+            removedCommands.add(command2);
+        } break;
+        case START_TONE:
+        case STOP_TONE:
+        default:
+            break;
+        }
+    }
+
+    // remove filtered commands
+    for (size_t j = 0; j < removedCommands.size(); j++) {
+        // removed commands always have time stamps greater than current command
+        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
+            if (mAudioCommands[k] == removedCommands[j]) {
+                LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
+                mAudioCommands.removeAt(k);
+                break;
+            }
+        }
+    }
+    removedCommands.clear();
+
+    // insert command at the right place according to its time stamp
+    LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
+    mAudioCommands.insertAt(command, i + 1);
+}
+
 void AudioPolicyService::AudioCommandThread::exit()
 {
     LOGV("AudioCommandThread::exit");
diff --git a/libs/audioflinger/AudioPolicyService.h b/libs/audioflinger/AudioPolicyService.h
index 3909fa4..56a85e1 100644
--- a/libs/audioflinger/AudioPolicyService.h
+++ b/libs/audioflinger/AudioPolicyService.h
@@ -20,6 +20,7 @@
 #include <media/IAudioPolicyService.h>
 #include <hardware_legacy/AudioPolicyInterface.h>
 #include <media/ToneGenerator.h>
+#include <utils/Vector.h>
 
 namespace android {
 
@@ -98,9 +99,9 @@
                                     uint32_t *pChannels,
                                     uint32_t acoustics);
     virtual status_t closeInput(audio_io_handle_t input);
-    virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output);
+    virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs = 0);
     virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
-    virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
+    virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
     virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
     virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
     virtual status_t stopTone();
@@ -116,6 +117,7 @@
     // For audio config commands, it is necessary because audio flinger requires that the calling process (user)
     // has permission to modify audio settings.
     class AudioCommandThread : public Thread {
+        class AudioCommand;
     public:
 
         // commands for tone AudioCommand
@@ -136,15 +138,20 @@
                     void        exit();
                     void        startToneCommand(int type = 0, int stream = 0);
                     void        stopToneCommand();
-                    status_t    volumeCommand(int stream, float volume, int output);
-                    status_t    parametersCommand(int ioHandle, const String8& keyValuePairs);
+                    status_t    volumeCommand(int stream, float volume, int output, int delayMs = 0);
+                    status_t    parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
+                    void        insertCommand_l(AudioCommand *command, int delayMs = 0);
 
     private:
         // descriptor for requested tone playback event
         class AudioCommand {
         public:
             int mCommand;   // START_TONE, STOP_TONE ...
-            void *mParam;
+            nsecs_t mTime;  // time stamp
+            Condition mCond; // condition for status return
+            status_t mStatus; // command status
+            bool mWaitStatus; // true if caller is waiting for status
+            void *mParam;     // command parameter (ToneData, VolumeData, ParametersData)
         };
 
         class ToneData {
@@ -168,9 +175,7 @@
 
         Mutex   mLock;
         Condition mWaitWorkCV;
-        Vector<AudioCommand *> mAudioCommands;    // list of pending tone events
-        Condition              mCommandCond;
-        status_t               mCommandStatus;
+        Vector <AudioCommand *> mAudioCommands; // list of pending commands
         ToneGenerator *mpToneGenerator;     // the tone generator
     };
 
@@ -182,7 +187,7 @@
                         // connection stated our routing
     AudioPolicyInterface* mpPolicyManager;          // the platform specific policy manager
     sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
-    sp <AudioCommandThread> mTonePlaybacThread;     // tone playback thread
+    sp <AudioCommandThread> mTonePlaybackThread;     // tone playback thread
 };
 
 }; // namespace android
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 98b55e9..bd1b2d7 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -883,5 +883,15 @@
     return result;
 }
 
+status_t AudioParameter::getAt(size_t index, String8& key, String8& value)
+{
+    if (mParameters.size() > index) {
+        key = mParameters.keyAt(index);
+        value = mParameters.valueAt(index);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
 }; // namespace android