Fix issue 2192181: AudioFlinger must provide separated methods to set VOICE_CALL stream volume and down link audio volume.

Added setVoiceVolume() method to AudioSystem, AudioFlinger, IAudioFlinger, AudioPolicyService.
Removed call to AudioHardwareInterface::setVoiceVolume() from AudioFlinger::setStreamVolume().
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index ba8b322..0960c81 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -482,38 +482,17 @@
         }
     }
 
-    status_t ret = NO_ERROR;
-
-    if (stream == AudioSystem::VOICE_CALL ||
-        stream == AudioSystem::BLUETOOTH_SCO) {
-        float hwValue;
-        if (stream == AudioSystem::VOICE_CALL) {
-            hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
-            // offset value to reflect actual hardware volume that never reaches 0
-            // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
-            value = 0.01 + 0.99 * value;
-        } else { // (type == AudioSystem::BLUETOOTH_SCO)
-            hwValue = 1.0f;
-        }
-
-        AutoMutex lock(mHardwareLock);
-        mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
-        ret = mAudioHardware->setVoiceVolume(hwValue);
-        mHardwareStatus = AUDIO_HW_IDLE;
-
-    }
-
     mStreamTypes[stream].volume = value;
 
     if (thread == NULL) {
-        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
            mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
-
+        }
     } else {
         thread->setStreamVolume(stream, value);
     }
 
-    return ret;
+    return NO_ERROR;
 }
 
 status_t AudioFlinger::setStreamMute(int stream, bool muted)
@@ -553,11 +532,6 @@
         volume = mStreamTypes[stream].volume;
     }
 
-    // remove correction applied by setStreamVolume()
-    if (stream == AudioSystem::VOICE_CALL) {
-        volume = (volume - 0.01) / 0.99 ;
-    }
-
     return volume;
 }
 
@@ -644,6 +618,21 @@
     return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
 }
 
+status_t AudioFlinger::setVoiceVolume(float value)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    AutoMutex lock(mHardwareLock);
+    mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
+    status_t ret = mAudioHardware->setVoiceVolume(value);
+    mHardwareStatus = AUDIO_HW_IDLE;
+
+    return ret;
+}
+
 void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
 {
 
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 4bf73ce..56599f6 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -133,6 +133,8 @@
 
     virtual status_t setStreamOutput(uint32_t stream, int output);
 
+    virtual status_t setVoiceVolume(float volume);
+
     // IBinder::DeathRecipient
     virtual     void        binderDied(const wp<IBinder>& who);
 
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
index 5c3cc8e..f71c99c 100644
--- a/libs/audioflinger/AudioPolicyService.cpp
+++ b/libs/audioflinger/AudioPolicyService.cpp
@@ -495,6 +495,10 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
+{
+    return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
+}
 
 // -----------  AudioPolicyService::AudioCommandThread implementation ----------
 
@@ -577,6 +581,16 @@
                      }
                      delete data;
                      }break;
+                case SET_VOICE_VOLUME: {
+                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
+                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
                 default:
                     LOGW("AudioCommandThread() unknown command %d", command->mCommand);
                 }
@@ -597,7 +611,6 @@
 
 void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
 {
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = START_TONE;
     ToneData *data = new ToneData();
@@ -605,6 +618,7 @@
     data->mStream = stream;
     command->mParam = (void *)data;
     command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
     mWaitWorkCV.signal();
@@ -612,11 +626,11 @@
 
 void AudioPolicyService::AudioCommandThread::stopToneCommand()
 {
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = STOP_TONE;
     command->mParam = NULL;
     command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone stop");
     mWaitWorkCV.signal();
@@ -626,7 +640,6 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_VOLUME;
     VolumeData *data = new VolumeData();
@@ -639,6 +652,7 @@
     } else {
         command->mWaitStatus = false;
     }
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command, delayMs);
     LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
     mWaitWorkCV.signal();
@@ -654,7 +668,6 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_PARAMETERS;
     ParametersData *data = new ParametersData();
@@ -666,6 +679,7 @@
     } else {
         command->mWaitStatus = false;
     }
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command, delayMs);
     LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
     mWaitWorkCV.signal();
@@ -677,6 +691,32 @@
     return status;
 }
 
+status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_VOICE_VOLUME;
+    VoiceVolumeData *data = new VoiceVolumeData();
+    data->mVolume = volume;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
+    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)
 {
diff --git a/libs/audioflinger/AudioPolicyService.h b/libs/audioflinger/AudioPolicyService.h
index 56a85e1..11a1214 100644
--- a/libs/audioflinger/AudioPolicyService.h
+++ b/libs/audioflinger/AudioPolicyService.h
@@ -105,6 +105,7 @@
     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();
+    virtual status_t setVoiceVolume(float volume, int delayMs = 0);
 
 private:
                         AudioPolicyService();
@@ -125,7 +126,8 @@
             START_TONE,
             STOP_TONE,
             SET_VOLUME,
-            SET_PARAMETERS
+            SET_PARAMETERS,
+            SET_VOICE_VOLUME
         };
 
         AudioCommandThread ();
@@ -140,6 +142,7 @@
                     void        stopToneCommand();
                     status_t    volumeCommand(int stream, float volume, int output, int delayMs = 0);
                     status_t    parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
+                    status_t    voiceVolumeCommand(float volume, int delayMs = 0);
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
 
     private:
@@ -166,12 +169,17 @@
             float mVolume;
             int mIO;
         };
+
         class ParametersData {
         public:
             int mIO;
             String8 mKeyValuePairs;
         };
 
+        class VoiceVolumeData {
+        public:
+            float mVolume;
+        };
 
         Mutex   mLock;
         Condition mWaitWorkCV;