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;