diff options
-rw-r--r-- | audio/AudioPolicyManagerBase.cpp | 162 | ||||
-rw-r--r-- | audio/audio_policy_hal.cpp | 30 | ||||
-rw-r--r-- | include/hardware_legacy/AudioPolicyInterface.h | 17 | ||||
-rw-r--r-- | include/hardware_legacy/AudioPolicyManagerBase.h | 18 |
4 files changed, 177 insertions, 50 deletions
diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp index 45df7fe..12df7bd 100644 --- a/audio/AudioPolicyManagerBase.cpp +++ b/audio/AudioPolicyManagerBase.cpp @@ -573,8 +573,9 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, // necassary for a correct control of hardware output routing by startOutput() and stopOutput() outputDesc->changeRefCount(stream, 1); - uint32_t prevDevice = outputDesc->mDevice; + uint32_t prevDevice = outputDesc->device(); setOutputDevice(output, getNewDevice(output)); + uint32_t newDevice = outputDesc->device(); // handle special case for sonification while in call if (isInCall()) { @@ -582,12 +583,15 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, } // apply volume rules for current stream and device if necessary - checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device()); + checkAndSetVolume(stream, + mStreams[stream].getVolumeIndex((audio_devices_t)newDevice), + output, + newDevice); // FIXME: need a delay to make sure that audio path switches to speaker before sound // starts. Should be platform specific? if (stream == AudioSystem::ENFORCED_AUDIBLE && - prevDevice != outputDesc->mDevice) { + prevDevice != newDevice) { usleep(outputDesc->mLatency*4*1000); } @@ -814,18 +818,30 @@ void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream, mStreams[stream].mIndexMax = indexMax; } -status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index) +status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, + int index, + audio_devices_t device) { if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) { return BAD_VALUE; } + if (!audio_is_output_device(device)) { + return BAD_VALUE; + } // Force max volume if stream cannot be muted if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax; - ALOGV("setStreamVolumeIndex() stream %d, index %d", stream, index); - mStreams[stream].mIndexCur = index; + ALOGV("setStreamVolumeIndex() stream %d, device %08x, index %d", + stream, device, index); + + // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and + // clear all device specific values + if (device == AUDIO_DEVICE_OUT_DEFAULT) { + mStreams[stream].mIndexCur.clear(); + } + mStreams[stream].mIndexCur.add(device, index); // compute and apply stream volume on all outputs according to connected device status_t status = NO_ERROR; @@ -838,13 +854,25 @@ status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type s return status; } -status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) +status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, + int *index, + audio_devices_t device) { - if (index == 0) { + if (index == NULL) { return BAD_VALUE; } - ALOGV("getStreamVolumeIndex() stream %d", stream); - *index = mStreams[stream].mIndexCur; + if (!audio_is_output_device(device)) { + return BAD_VALUE; + } + // if device is AUDIO_DEVICE_OUT_DEFAULT, return volume for device corresponding to + // the strategy the stream belongs to. + if (device == AUDIO_DEVICE_OUT_DEFAULT) { + device = (audio_devices_t)getDeviceForStrategy(getStrategy(stream), true); + } + device = getDeviceForVolume(device); + + *index = mStreams[stream].getVolumeIndex(device); + ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index); return NO_ERROR; } @@ -1029,12 +1057,13 @@ status_t AudioPolicyManagerBase::dump(int fd) snprintf(buffer, SIZE, "\nStreams dump:\n"); write(fd, buffer, strlen(buffer)); - snprintf(buffer, SIZE, " Stream Index Min Index Max Index Cur Can be muted\n"); + snprintf(buffer, SIZE, + " Stream Can be muted Index Min Index Max Index Cur [device : index]...\n"); write(fd, buffer, strlen(buffer)); for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) { - snprintf(buffer, SIZE, " %02d", i); - mStreams[i].dump(buffer + 3, SIZE); + snprintf(buffer, SIZE, " %02d ", i); write(fd, buffer, strlen(buffer)); + mStreams[i].dump(fd); } snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n", @@ -1896,31 +1925,35 @@ audio_io_handle_t AudioPolicyManagerBase::getActiveInput() } -AudioPolicyManagerBase::device_category AudioPolicyManagerBase::getDeviceCategory(uint32_t device) +audio_devices_t AudioPolicyManagerBase::getDeviceForVolume(audio_devices_t device) { if (device == 0) { // this happens when forcing a route update and no track is active on an output. // In this case the returned category is not important. - return DEVICE_CATEGORY_SPEAKER; - } - - if (AudioSystem::popCount(device) > 1) { + device = AUDIO_DEVICE_OUT_SPEAKER; + } else if (AudioSystem::popCount(device) > 1) { // Multiple device selection is either: // - speaker + one other device: give priority to speaker in this case. // - one A2DP device + another device: happens with duplicated output. In this case // retain the device on the A2DP output as the other must not correspond to an active // selection if not the speaker. - if (device & AUDIO_DEVICE_OUT_SPEAKER) - return DEVICE_CATEGORY_SPEAKER; - - device &= AUDIO_DEVICE_OUT_ALL_A2DP; + if (device & AUDIO_DEVICE_OUT_SPEAKER) { + device = AUDIO_DEVICE_OUT_SPEAKER; + } else { + device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP); + } } ALOGW_IF(AudioSystem::popCount(device) != 1, - "getDeviceCategory() invalid device combination: %08x", + "getDeviceForVolume() invalid device combination: %08x", device); - switch(device) { + return device; +} + +AudioPolicyManagerBase::device_category AudioPolicyManagerBase::getDeviceCategory(uint32_t device) +{ + switch(getDeviceForVolume((audio_devices_t)device)) { case AUDIO_DEVICE_OUT_EARPIECE: return DEVICE_CATEGORY_EARPIECE; case AUDIO_DEVICE_OUT_WIRED_HEADSET: @@ -1933,6 +1966,7 @@ AudioPolicyManagerBase::device_category AudioPolicyManagerBase::getDeviceCategor case AUDIO_DEVICE_OUT_SPEAKER: case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: + case AUDIO_DEVICE_OUT_AUX_DIGITAL: default: return DEVICE_CATEGORY_SPEAKER; } @@ -2046,7 +2080,10 @@ void AudioPolicyManagerBase::initializeVolumeCurves() } } -float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device) +float AudioPolicyManagerBase::computeVolume(int stream, + int index, + audio_io_handle_t output, + uint32_t device) { float volume = 1.0; AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); @@ -2084,8 +2121,12 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand // by the music application and behave as if music was active if the last music track was // just stopped if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) { - float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device); - float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN; + float musicVol = computeVolume(AudioSystem::MUSIC, + mStreams[AudioSystem::MUSIC].getVolumeIndex((audio_devices_t)device), + output, + (uint32_t)device); + float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? + musicVol : SONIFICATION_HEADSET_VOLUME_MIN; if (volume > minVol) { volume = minVol; ALOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol); @@ -2096,7 +2137,12 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand return volume; } -status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force) +status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, + int index, + audio_io_handle_t output, + uint32_t device, + int delayMs, + bool force) { // do not change actual stream volume if the stream is muted @@ -2156,12 +2202,20 @@ status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_ return NO_ERROR; } -void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs, bool force) +void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, + uint32_t device, + int delayMs, + bool force) { ALOGV("applyStreamVolumes() for output %d and device %x", output, device); for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { - checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs, force); + checkAndSetVolume(stream, + mStreams[stream].getVolumeIndex((audio_devices_t)device), + output, + device, + delayMs, + force); } } @@ -2179,13 +2233,14 @@ void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_ { StreamDescriptor &streamDesc = mStreams[stream]; AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); + uint32_t device = outputDesc->device(); ALOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]); if (on) { if (outputDesc->mMuteCount[stream] == 0) { if (streamDesc.mCanBeMuted) { - checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs); + checkAndSetVolume(stream, 0, output, device, delayMs); } } // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored @@ -2196,7 +2251,11 @@ void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_ return; } if (--outputDesc->mMuteCount[stream] == 0) { - checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs); + checkAndSetVolume(stream, + streamDesc.getVolumeIndex((audio_devices_t)device), + output, + device, + delayMs); } } } @@ -2398,13 +2457,40 @@ status_t AudioPolicyManagerBase::AudioInputDescriptor::dump(int fd) // --- StreamDescriptor class implementation -void AudioPolicyManagerBase::StreamDescriptor::dump(char* buffer, size_t size) +AudioPolicyManagerBase::StreamDescriptor::StreamDescriptor() + : mIndexMin(0), mIndexMax(1), mCanBeMuted(true) +{ + mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0); +} + +int AudioPolicyManagerBase::StreamDescriptor::getVolumeIndex(audio_devices_t device) +{ + device = AudioPolicyManagerBase::getDeviceForVolume(device); + // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT + if (mIndexCur.indexOfKey(device) < 0) { + device = AUDIO_DEVICE_OUT_DEFAULT; + } + return mIndexCur.valueFor(device); +} + +void AudioPolicyManagerBase::StreamDescriptor::dump(int fd) { - snprintf(buffer, size, " %02d %02d %02d %d\n", - mIndexMin, - mIndexMax, - mIndexCur, - mCanBeMuted); + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + snprintf(buffer, SIZE, "%s %02d %02d ", + mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax); + result.append(buffer); + for (size_t i = 0; i < mIndexCur.size(); i++) { + snprintf(buffer, SIZE, "%04x : %02d, ", + mIndexCur.keyAt(i), + mIndexCur.valueAt(i)); + result.append(buffer); + } + result.append("\n"); + + write(fd, result.string(), result.size()); } // --- EffectDescriptor class implementation diff --git a/audio/audio_policy_hal.cpp b/audio/audio_policy_hal.cpp index a0100a8..7d2e1e0 100644 --- a/audio/audio_policy_hal.cpp +++ b/audio/audio_policy_hal.cpp @@ -216,7 +216,8 @@ static int ap_set_stream_volume_index(struct audio_policy *pol, { struct legacy_audio_policy *lap = to_lap(pol); return lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream, - index); + index, + AUDIO_DEVICE_OUT_DEFAULT); } static int ap_get_stream_volume_index(const struct audio_policy *pol, @@ -225,7 +226,30 @@ static int ap_get_stream_volume_index(const struct audio_policy *pol, { const struct legacy_audio_policy *lap = to_clap(pol); return lap->apm->getStreamVolumeIndex((AudioSystem::stream_type)stream, - index); + index, + AUDIO_DEVICE_OUT_DEFAULT); +} + +static int ap_set_stream_volume_index_for_device(struct audio_policy *pol, + audio_stream_type_t stream, + int index, + audio_devices_t device) +{ + struct legacy_audio_policy *lap = to_lap(pol); + return lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream, + index, + device); +} + +static int ap_get_stream_volume_index_for_device(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index, + audio_devices_t device) +{ + const struct legacy_audio_policy *lap = to_clap(pol); + return lap->apm->getStreamVolumeIndex((AudioSystem::stream_type)stream, + index, + device); } static uint32_t ap_get_strategy_for_stream(const struct audio_policy *pol, @@ -320,6 +344,8 @@ static int create_legacy_ap(const struct audio_policy_device *device, lap->policy.init_stream_volume = ap_init_stream_volume; lap->policy.set_stream_volume_index = ap_set_stream_volume_index; lap->policy.get_stream_volume_index = ap_get_stream_volume_index; + lap->policy.set_stream_volume_index_for_device = ap_set_stream_volume_index_for_device; + lap->policy.get_stream_volume_index_for_device = ap_get_stream_volume_index_for_device; lap->policy.get_strategy_for_stream = ap_get_strategy_for_stream; lap->policy.get_devices_for_stream = ap_get_devices_for_stream; lap->policy.get_output_for_effect = ap_get_output_for_effect; diff --git a/include/hardware_legacy/AudioPolicyInterface.h b/include/hardware_legacy/AudioPolicyInterface.h index 1ee0e20..a1c1fd5 100644 --- a/include/hardware_legacy/AudioPolicyInterface.h +++ b/include/hardware_legacy/AudioPolicyInterface.h @@ -128,10 +128,19 @@ public: int indexMin, int indexMax) = 0; - // sets the new stream volume at a level corresponding to the supplied index - virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0; - // retreive current volume index for the specified stream - virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0; + // sets the new stream volume at a level corresponding to the supplied index for the + // supplied device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means + // setting volume for all devices + virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, + int index, + audio_devices_t device) = 0; + + // retrieve current volume index for the specified stream and the + // specified device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means + // querying the volume of the active device. + virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, + int *index, + audio_devices_t device) = 0; // return the strategy corresponding to a given stream type virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0; diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h index 3ab748d..24368e3 100644 --- a/include/hardware_legacy/AudioPolicyManagerBase.h +++ b/include/hardware_legacy/AudioPolicyManagerBase.h @@ -101,8 +101,12 @@ public: virtual void initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax); - virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index); - virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index); + virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, + int index, + audio_devices_t device); + virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, + int *index, + audio_devices_t device); // return the strategy corresponding to a given stream type virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream); @@ -219,14 +223,14 @@ protected: class StreamDescriptor { public: - StreamDescriptor() - : mIndexMin(0), mIndexMax(1), mIndexCur(1), mCanBeMuted(true) {} + StreamDescriptor(); - void dump(char* buffer, size_t size); + int getVolumeIndex(audio_devices_t device); + void dump(int fd); int mIndexMin; // min volume index int mIndexMax; // max volume index - int mIndexCur; // current volume index + KeyedVector<audio_devices_t, int> mIndexCur; // current volume index per device bool mCanBeMuted; // true is the stream can be muted const VolumeCurvePoint *mVolumeCurve[DEVICE_CATEGORY_CNT]; @@ -340,6 +344,8 @@ protected: // returns the category the device belongs to with regard to volume curve management static device_category getDeviceCategory(uint32_t device); + // extract one device relevant for volume control from multiple device selection + static audio_devices_t getDeviceForVolume(audio_devices_t device); AudioPolicyClientInterface *mpClientInterface; // audio policy client interface audio_io_handle_t mHardwareOutput; // hardware output handler |