diff options
8 files changed, 473 insertions, 246 deletions
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h new file mode 100755 index 0000000..a4cc759 --- /dev/null +++ b/services/audiopolicy/common/include/Volume.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <system/audio.h> +#include <utils/Log.h> + +class VolumeCurvePoint +{ +public: + int mIndex; + float mDBAttenuation; +}; + +class Volume +{ +public: + /** + * 4 points to define the volume attenuation curve, each characterized by the volume + * index (from 0 to 100) at which they apply, and the attenuation in dB at that index. + * we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl() + * + * @todo shall become configurable + */ + enum { + VOLMIN = 0, + VOLKNEE1 = 1, + VOLKNEE2 = 2, + VOLMAX = 3, + + VOLCNT = 4 + }; + + /** + * device categories used for volume curve management. + */ + enum device_category { + DEVICE_CATEGORY_HEADSET, + DEVICE_CATEGORY_SPEAKER, + DEVICE_CATEGORY_EARPIECE, + DEVICE_CATEGORY_EXT_MEDIA, + DEVICE_CATEGORY_CNT + }; + + /** + * extract one device relevant for volume control from multiple device selection + * + * @param[in] device for which the volume category is associated + * + * @return subset of device required to limit the number of volume category per device + */ + static audio_devices_t getDeviceForVolume(audio_devices_t device) + { + if (device == AUDIO_DEVICE_NONE) { + // this happens when forcing a route update and no track is active on an output. + // In this case the returned category is not important. + device = AUDIO_DEVICE_OUT_SPEAKER; + } else if (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. + // - HDMI-CEC system audio mode only output: give priority to available item in order. + if (device & AUDIO_DEVICE_OUT_SPEAKER) { + device = AUDIO_DEVICE_OUT_SPEAKER; + } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) { + device = AUDIO_DEVICE_OUT_HDMI_ARC; + } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) { + device = AUDIO_DEVICE_OUT_AUX_LINE; + } else if (device & AUDIO_DEVICE_OUT_SPDIF) { + device = AUDIO_DEVICE_OUT_SPDIF; + } else { + device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP); + } + } + + /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/ + if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) + device = AUDIO_DEVICE_OUT_SPEAKER; + + ALOGW_IF(popcount(device) != 1, + "getDeviceForVolume() invalid device combination: %08x", + device); + + return device; + } + + /** + * returns the category the device belongs to with regard to volume curve management + * + * @param[in] device to check upon the category to whom it belongs to. + * + * @return device category. + */ + static device_category getDeviceCategory(audio_devices_t device) + { + switch(getDeviceForVolume(device)) { + case AUDIO_DEVICE_OUT_EARPIECE: + return DEVICE_CATEGORY_EARPIECE; + case AUDIO_DEVICE_OUT_WIRED_HEADSET: + case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: + case AUDIO_DEVICE_OUT_BLUETOOTH_SCO: + case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: + return DEVICE_CATEGORY_HEADSET; + case AUDIO_DEVICE_OUT_LINE: + case AUDIO_DEVICE_OUT_AUX_DIGITAL: + /*USB? Remote submix?*/ + return DEVICE_CATEGORY_EXT_MEDIA; + case AUDIO_DEVICE_OUT_SPEAKER: + case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: + case AUDIO_DEVICE_OUT_USB_ACCESSORY: + case AUDIO_DEVICE_OUT_USB_DEVICE: + case AUDIO_DEVICE_OUT_REMOTE_SUBMIX: + default: + return DEVICE_CATEGORY_SPEAKER; + } + } + +}; diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk index 85f33bb..71ba1cb 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.mk +++ b/services/audiopolicy/common/managerdefinitions/Android.mk @@ -5,6 +5,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ src/DeviceDescriptor.cpp \ src/AudioGain.cpp \ + src/StreamDescriptor.cpp \ src/HwModule.cpp \ src/IOProfile.cpp \ src/AudioPort.cpp \ diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h index f638c8e..944fadc 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h @@ -16,70 +16,43 @@ #pragma once +#include <Volume.h> #include <utils/Errors.h> #include <utils/RefBase.h> #include <system/audio.h> -#include <utils/KeyedVector.h> namespace android { -class VolumeCurvePoint -{ -public: - int mIndex; - float mDBAttenuation; -}; - class StreamDescriptor; class ApmGains { public : - // 4 points to define the volume attenuation curve, each characterized by the volume - // index (from 0 to 100) at which they apply, and the attenuation in dB at that index. - // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl() - enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4}; - - // device categories used for volume curve management. - enum device_category { - DEVICE_CATEGORY_HEADSET, - DEVICE_CATEGORY_SPEAKER, - DEVICE_CATEGORY_EARPIECE, - DEVICE_CATEGORY_EXT_MEDIA, - DEVICE_CATEGORY_CNT - }; - - // returns the category the device belongs to with regard to volume curve management - static ApmGains::device_category getDeviceCategory(audio_devices_t device); - - // extract one device relevant for volume control from multiple device selection - static audio_devices_t getDeviceForVolume(audio_devices_t device); - static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, int indexInUi); // default volume curve - static const VolumeCurvePoint sDefaultVolumeCurve[ApmGains::VOLCNT]; + static const VolumeCurvePoint sDefaultVolumeCurve[Volume::VOLCNT]; // default volume curve for media strategy - static const VolumeCurvePoint sDefaultMediaVolumeCurve[ApmGains::VOLCNT]; + static const VolumeCurvePoint sDefaultMediaVolumeCurve[Volume::VOLCNT]; // volume curve for non-media audio on ext media outputs (HDMI, Line, etc) - static const VolumeCurvePoint sExtMediaSystemVolumeCurve[ApmGains::VOLCNT]; + static const VolumeCurvePoint sExtMediaSystemVolumeCurve[Volume::VOLCNT]; // volume curve for media strategy on speakers - static const VolumeCurvePoint sSpeakerMediaVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT]; + static const VolumeCurvePoint sSpeakerMediaVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT]; // volume curve for sonification strategy on speakers - static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT]; - static const VolumeCurvePoint sDefaultSystemVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT]; - static const VolumeCurvePoint sHeadsetSystemVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sDefaultVoiceVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sLinearVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sSilentVolumeCurve[ApmGains::VOLCNT]; - static const VolumeCurvePoint sFullScaleVolumeCurve[ApmGains::VOLCNT]; + static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT]; + static const VolumeCurvePoint sDefaultSystemVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[Volume::VOLCNT]; + static const VolumeCurvePoint sHeadsetSystemVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sDefaultVoiceVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sLinearVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sSilentVolumeCurve[Volume::VOLCNT]; + static const VolumeCurvePoint sFullScaleVolumeCurve[Volume::VOLCNT]; // default volume curves per stream and device category. See initializeVolumeCurves() - static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][ApmGains::DEVICE_CATEGORY_CNT]; + static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][Volume::DEVICE_CATEGORY_CNT]; }; @@ -98,22 +71,4 @@ public: bool mUseInChannelMask; }; - -// stream descriptor used for volume control -class StreamDescriptor -{ -public: - StreamDescriptor(); - - int getVolumeIndex(audio_devices_t device); - void dump(int fd); - - int mIndexMin; // min volume index - int mIndexMax; // max 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[ApmGains::DEVICE_CATEGORY_CNT]; -}; - }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h new file mode 100644 index 0000000..84db5ab --- /dev/null +++ b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <Volume.h> +#include <utils/KeyedVector.h> +#include <utils/StrongPointer.h> +#include <utils/SortedVector.h> +#include <hardware/audio.h> + +namespace android { + +// stream descriptor used for volume control +class StreamDescriptor +{ +public: + StreamDescriptor(); + + int getVolumeIndex(audio_devices_t device) const; + bool canBeMuted() const { return mCanBeMuted; } + void clearCurrentVolumeIndex(); + void addCurrentVolumeIndex(audio_devices_t device, int index); + int getVolumeIndexMin() const { return mIndexMin; } + int getVolumeIndexMax() const { return mIndexMax; } + void setVolumeIndexMin(int volIndexMin); + void setVolumeIndexMax(int volIndexMax); + + void dump(int fd) const; + + void setVolumeCurvePoint(Volume::device_category deviceCategory, const VolumeCurvePoint *point); + const VolumeCurvePoint *getVolumeCurvePoint(Volume::device_category deviceCategory) const + { + return mVolumeCurve[deviceCategory]; + } + +private: + const VolumeCurvePoint *mVolumeCurve[Volume::DEVICE_CATEGORY_CNT]; + KeyedVector<audio_devices_t, int> mIndexCur; /**< current volume index per device. */ + int mIndexMin; /**< min volume index. */ + int mIndexMax; /**< max volume index. */ + bool mCanBeMuted; /**< true is the stream can be muted. */ +}; + +/** + * stream descriptors collection for volume control + */ +class StreamDescriptorCollection : public DefaultKeyedVector<audio_stream_type_t, StreamDescriptor> +{ +public: + StreamDescriptorCollection(); + + void clearCurrentVolumeIndex(audio_stream_type_t stream); + void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device, int index); + + bool canBeMuted(audio_stream_type_t stream); + + status_t dump(int fd) const; + + void setVolumeCurvePoint(audio_stream_type_t stream, + Volume::device_category deviceCategory, + const VolumeCurvePoint *point); + + const VolumeCurvePoint *getVolumeCurvePoint(audio_stream_type_t stream, + Volume::device_category deviceCategory) const; + + void setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin); + void setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax); + +}; + +}; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp index ebd3548..ffe22ed 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp @@ -25,6 +25,7 @@ #endif #include "AudioGain.h" +#include "StreamDescriptor.h" #include <utils/Log.h> #include <utils/String8.h> @@ -33,38 +34,38 @@ namespace android { const VolumeCurvePoint -ApmGains::sDefaultVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sDefaultVolumeCurve[Volume::VOLCNT] = { {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sDefaultMediaVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sDefaultMediaVolumeCurve[Volume::VOLCNT] = { {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sExtMediaSystemVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sExtMediaSystemVolumeCurve[Volume::VOLCNT] = { {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f} }; const VolumeCurvePoint -ApmGains::sSpeakerMediaVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = { {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT] = { +ApmGains::sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT] = { {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sSpeakerSonificationVolumeCurve[Volume::VOLCNT] = { {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT] = { +ApmGains::sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT] = { {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f} }; @@ -74,47 +75,47 @@ ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT] = { // The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset. const VolumeCurvePoint -ApmGains::sDefaultSystemVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sDefaultSystemVolumeCurve[Volume::VOLCNT] = { {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f} }; const VolumeCurvePoint -ApmGains::sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT] = { +ApmGains::sDefaultSystemVolumeCurveDrc[Volume::VOLCNT] = { {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f} }; const VolumeCurvePoint -ApmGains::sHeadsetSystemVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sHeadsetSystemVolumeCurve[Volume::VOLCNT] = { {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f} }; const VolumeCurvePoint -ApmGains::sDefaultVoiceVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = { {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sSpeakerVoiceVolumeCurve[Volume::VOLCNT] = { {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sLinearVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sLinearVolumeCurve[Volume::VOLCNT] = { {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f} }; const VolumeCurvePoint -ApmGains::sSilentVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sSilentVolumeCurve[Volume::VOLCNT] = { {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f} }; const VolumeCurvePoint -ApmGains::sFullScaleVolumeCurve[ApmGains::VOLCNT] = { +ApmGains::sFullScaleVolumeCurve[Volume::VOLCNT] = { {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f} }; const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT] - [ApmGains::DEVICE_CATEGORY_CNT] = { + [Volume::DEVICE_CATEGORY_CNT] = { { // AUDIO_STREAM_VOICE_CALL ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER @@ -197,93 +198,27 @@ const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT] }; //static -audio_devices_t ApmGains::getDeviceForVolume(audio_devices_t device) -{ - if (device == AUDIO_DEVICE_NONE) { - // this happens when forcing a route update and no track is active on an output. - // In this case the returned category is not important. - device = AUDIO_DEVICE_OUT_SPEAKER; - } else if (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. - // - HDMI-CEC system audio mode only output: give priority to available item in order. - if (device & AUDIO_DEVICE_OUT_SPEAKER) { - device = AUDIO_DEVICE_OUT_SPEAKER; - } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) { - device = AUDIO_DEVICE_OUT_HDMI_ARC; - } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) { - device = AUDIO_DEVICE_OUT_AUX_LINE; - } else if (device & AUDIO_DEVICE_OUT_SPDIF) { - device = AUDIO_DEVICE_OUT_SPDIF; - } else { - device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP); - } - } - - /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/ - if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) - device = AUDIO_DEVICE_OUT_SPEAKER; - - ALOGW_IF(popcount(device) != 1, - "getDeviceForVolume() invalid device combination: %08x", - device); - - return device; -} - -//static -ApmGains::device_category ApmGains::getDeviceCategory(audio_devices_t device) -{ - switch(getDeviceForVolume(device)) { - case AUDIO_DEVICE_OUT_EARPIECE: - return ApmGains::DEVICE_CATEGORY_EARPIECE; - case AUDIO_DEVICE_OUT_WIRED_HEADSET: - case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: - case AUDIO_DEVICE_OUT_BLUETOOTH_SCO: - case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: - case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: - case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: - return ApmGains::DEVICE_CATEGORY_HEADSET; - case AUDIO_DEVICE_OUT_LINE: - case AUDIO_DEVICE_OUT_AUX_DIGITAL: - /*USB? Remote submix?*/ - return ApmGains::DEVICE_CATEGORY_EXT_MEDIA; - case AUDIO_DEVICE_OUT_SPEAKER: - case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: - case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: - case AUDIO_DEVICE_OUT_USB_ACCESSORY: - case AUDIO_DEVICE_OUT_USB_DEVICE: - case AUDIO_DEVICE_OUT_REMOTE_SUBMIX: - default: - return ApmGains::DEVICE_CATEGORY_SPEAKER; - } -} - -//static float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, int indexInUi) { - ApmGains::device_category deviceCategory = ApmGains::getDeviceCategory(device); - const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory]; + Volume::device_category deviceCategory = Volume::getDeviceCategory(device); + const VolumeCurvePoint *curve = streamDesc.getVolumeCurvePoint(deviceCategory); // the volume index in the UI is relative to the min and max volume indices for this stream type - int nbSteps = 1 + curve[ApmGains::VOLMAX].mIndex - - curve[ApmGains::VOLMIN].mIndex; - int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) / - (streamDesc.mIndexMax - streamDesc.mIndexMin); + int nbSteps = 1 + curve[Volume::VOLMAX].mIndex - + curve[Volume::VOLMIN].mIndex; + int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) / + (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin()); // find what part of the curve this index volume belongs to, or if it's out of bounds int segment = 0; - if (volIdx < curve[ApmGains::VOLMIN].mIndex) { // out of bounds + if (volIdx < curve[Volume::VOLMIN].mIndex) { // out of bounds return 0.0f; - } else if (volIdx < curve[ApmGains::VOLKNEE1].mIndex) { + } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) { segment = 0; - } else if (volIdx < curve[ApmGains::VOLKNEE2].mIndex) { + } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) { segment = 1; - } else if (volIdx <= curve[ApmGains::VOLMAX].mIndex) { + } else if (volIdx <= curve[Volume::VOLMAX].mIndex) { segment = 2; } else { // out of bounds return 1.0f; @@ -406,43 +341,4 @@ void AudioGain::dump(int fd, int spaces, int index) const write(fd, result.string(), result.size()); } - -// --- StreamDescriptor class implementation - -StreamDescriptor::StreamDescriptor() - : mIndexMin(0), mIndexMax(1), mCanBeMuted(true) -{ - mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0); -} - -int StreamDescriptor::getVolumeIndex(audio_devices_t device) -{ - device = ApmGains::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 StreamDescriptor::dump(int fd) -{ - 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()); -} - }; // namespace android diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp new file mode 100644 index 0000000..b682e2c --- /dev/null +++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "APM::Volumes" +//#define LOG_NDEBUG 0 + +//#define VERY_VERBOSE_LOGGING +#ifdef VERY_VERBOSE_LOGGING +#define ALOGVV ALOGV +#else +#define ALOGVV(a...) do { } while(0) +#endif + +#include "StreamDescriptor.h" +#include <utils/Log.h> +#include <utils/String8.h> + +namespace android { + +// --- StreamDescriptor class implementation + +StreamDescriptor::StreamDescriptor() + : mIndexMin(0), mIndexMax(1), mCanBeMuted(true) +{ + mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0); +} + +int StreamDescriptor::getVolumeIndex(audio_devices_t device) const +{ + device = Volume::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 StreamDescriptor::clearCurrentVolumeIndex() +{ + mIndexCur.clear(); +} + +void StreamDescriptor::addCurrentVolumeIndex(audio_devices_t device, int index) +{ + mIndexCur.add(device, index); +} + +void StreamDescriptor::setVolumeIndexMin(int volIndexMin) +{ + mIndexMin = volIndexMin; +} + +void StreamDescriptor::setVolumeIndexMax(int volIndexMax) +{ + mIndexMax = volIndexMax; +} + +void StreamDescriptor::setVolumeCurvePoint(Volume::device_category deviceCategory, + const VolumeCurvePoint *point) +{ + mVolumeCurve[deviceCategory] = point; +} + +void StreamDescriptor::dump(int fd) const +{ + 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()); +} + +StreamDescriptorCollection::StreamDescriptorCollection() +{ + for (size_t stream = 0 ; stream < AUDIO_STREAM_CNT; stream++) { + add(static_cast<audio_stream_type_t>(stream), StreamDescriptor()); + } +} + +bool StreamDescriptorCollection::canBeMuted(audio_stream_type_t stream) +{ + return valueAt(stream).canBeMuted(); +} + +void StreamDescriptorCollection::clearCurrentVolumeIndex(audio_stream_type_t stream) +{ + editValueAt(stream).clearCurrentVolumeIndex(); +} + +void StreamDescriptorCollection::addCurrentVolumeIndex(audio_stream_type_t stream, + audio_devices_t device, int index) +{ + editValueAt(stream).addCurrentVolumeIndex(device, index); +} + +void StreamDescriptorCollection::setVolumeCurvePoint(audio_stream_type_t stream, + Volume::device_category deviceCategory, + const VolumeCurvePoint *point) +{ + editValueAt(stream).setVolumeCurvePoint(deviceCategory, point); +} + +const VolumeCurvePoint *StreamDescriptorCollection::getVolumeCurvePoint(audio_stream_type_t stream, + Volume::device_category deviceCategory) const +{ + return valueAt(stream).getVolumeCurvePoint(deviceCategory); +} + +void StreamDescriptorCollection::setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin) +{ + return editValueAt(stream).setVolumeIndexMin(volIndexMin); +} + +void StreamDescriptorCollection::setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax) +{ + return editValueAt(stream).setVolumeIndexMax(volIndexMax); +} + +status_t StreamDescriptorCollection::dump(int fd) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + + snprintf(buffer, SIZE, "\nStreams dump:\n"); + write(fd, buffer, strlen(buffer)); + 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 < size(); i++) { + snprintf(buffer, SIZE, " %02zu ", i); + write(fd, buffer, strlen(buffer)); + valueAt(i).dump(fd); + } + + return NO_ERROR; +} + +}; // namespace android diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 5341559..a95d7b9 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -437,18 +437,18 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) // force routing command to audio hardware when starting a call // even if no device change is needed force = true; - for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) { - mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = - ApmGains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]; + for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) { + mStreams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<Volume::device_category>(j), + ApmGains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]); } } else if (isStateInCall(oldState) && !isStateInCall(state)) { ALOGV(" Exiting call in setPhoneState()"); // force routing command to audio hardware when exiting a call // even if no device change is needed force = true; - for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) { - mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = - ApmGains::sVolumeProfiles[AUDIO_STREAM_DTMF][j]; + for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) { + mStreams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<Volume::device_category>(j), + ApmGains::sVolumeProfiles[AUDIO_STREAM_DTMF][j]); } } else if (isStateInCall(state) && (state != oldState)) { ALOGV(" Switching between telephony and VoIP in setPhoneState()"); @@ -1565,12 +1565,12 @@ void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax); return; } - mStreams[stream].mIndexMin = indexMin; - mStreams[stream].mIndexMax = indexMax; + mStreams.editValueFor(stream).setVolumeIndexMin(indexMin); + mStreams.editValueFor(stream).setVolumeIndexMax(indexMax); //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now if (stream == AUDIO_STREAM_MUSIC) { - mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMin = indexMin; - mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMax = indexMax; + mStreams.editValueFor(AUDIO_STREAM_ACCESSIBILITY).setVolumeIndexMin(indexMin); + mStreams.editValueFor(AUDIO_STREAM_ACCESSIBILITY).setVolumeIndexMax(indexMax); } } @@ -1579,7 +1579,8 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, audio_devices_t device) { - if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) { + if ((index < mStreams[stream].getVolumeIndexMin()) || + (index > mStreams[stream].getVolumeIndexMax())) { return BAD_VALUE; } if (!audio_is_output_device(device)) { @@ -1587,7 +1588,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, } // Force max volume if stream cannot be muted - if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax; + if (!mStreams.canBeMuted(stream)) index = mStreams[stream].getVolumeIndexMax(); ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d", stream, device, index); @@ -1595,9 +1596,9 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, // 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.clearCurrentVolumeIndex(stream); } - mStreams[stream].mIndexCur.add(device, index); + mStreams.addCurrentVolumeIndex(stream, device, index); // update volume on all outputs whose current device is also selected by the same // strategy as the device specified by the caller @@ -1607,7 +1608,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE; if (stream == AUDIO_STREAM_MUSIC) { - mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexCur.add(device, index); + mStreams.addCurrentVolumeIndex(AUDIO_STREAM_ACCESSIBILITY, device, index); accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/); } if ((device != AUDIO_DEVICE_OUT_DEFAULT) && @@ -1616,8 +1617,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, } status_t status = NO_ERROR; for (size_t i = 0; i < mOutputs.size(); i++) { - audio_devices_t curDevice = - ApmGains::getDeviceForVolume(mOutputs.valueAt(i)->device()); + audio_devices_t curDevice = Volume::getDeviceForVolume(mOutputs.valueAt(i)->device()); if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & strategyDevice) != 0)) { status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice); if (volStatus != NO_ERROR) { @@ -1647,7 +1647,7 @@ status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream, if (device == AUDIO_DEVICE_OUT_DEFAULT) { device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/); } - device = ApmGains::getDeviceForVolume(device); + device = Volume::getDeviceForVolume(device); *index = mStreams[stream].getVolumeIndex(device); ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index); @@ -1901,18 +1901,7 @@ status_t AudioPolicyManager::dump(int fd) mHwModules.dump(fd); mOutputs.dump(fd); mInputs.dump(fd); - - snprintf(buffer, SIZE, "\nStreams dump:\n"); - write(fd, buffer, strlen(buffer)); - 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 < AUDIO_STREAM_CNT; i++) { - snprintf(buffer, SIZE, " %02zu ", i); - write(fd, buffer, strlen(buffer)); - mStreams[i].dump(fd); - } - + mStreams.dump(fd); mEffects.dump(fd); mAudioPatches.dump(fd); @@ -4682,26 +4671,27 @@ audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t input void AudioPolicyManager::initializeVolumeCurves() { for (int i = 0; i < AUDIO_STREAM_CNT; i++) { - for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) { - mStreams[i].mVolumeCurve[j] = - ApmGains::sVolumeProfiles[i][j]; + for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) { + mStreams.setVolumeCurvePoint(static_cast<audio_stream_type_t>(i), + static_cast<Volume::device_category>(j), + ApmGains::sVolumeProfiles[i][j]); } } // Check availability of DRC on speaker path: if available, override some of the speaker curves if (mSpeakerDrcEnabled) { - mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] = - ApmGains::sDefaultSystemVolumeCurveDrc; - mStreams[AUDIO_STREAM_RING].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] = - ApmGains::sSpeakerSonificationVolumeCurveDrc; - mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] = - ApmGains::sSpeakerSonificationVolumeCurveDrc; - mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] = - ApmGains::sSpeakerSonificationVolumeCurveDrc; - mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] = - ApmGains::sSpeakerMediaVolumeCurveDrc; - mStreams[AUDIO_STREAM_ACCESSIBILITY].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] = - ApmGains::sSpeakerMediaVolumeCurveDrc; + mStreams.setVolumeCurvePoint(AUDIO_STREAM_SYSTEM, Volume::DEVICE_CATEGORY_SPEAKER, + ApmGains::sDefaultSystemVolumeCurveDrc); + mStreams.setVolumeCurvePoint(AUDIO_STREAM_RING, Volume::DEVICE_CATEGORY_SPEAKER, + ApmGains::sSpeakerSonificationVolumeCurveDrc); + mStreams.setVolumeCurvePoint(AUDIO_STREAM_ALARM, Volume::DEVICE_CATEGORY_SPEAKER, + ApmGains::sSpeakerSonificationVolumeCurveDrc); + mStreams.setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, Volume::DEVICE_CATEGORY_SPEAKER, + ApmGains::sSpeakerSonificationVolumeCurveDrc); + mStreams.setVolumeCurvePoint(AUDIO_STREAM_MUSIC, Volume::DEVICE_CATEGORY_SPEAKER, + ApmGains::sSpeakerMediaVolumeCurveDrc); + mStreams.setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, Volume::DEVICE_CATEGORY_SPEAKER, + ApmGains::sSpeakerMediaVolumeCurveDrc); } } @@ -4712,7 +4702,7 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream, { float volume = 1.0; sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); - StreamDescriptor &streamDesc = mStreams[stream]; + const StreamDescriptor &streamDesc = mStreams[stream]; if (device == AUDIO_DEVICE_NONE) { device = outputDesc->device(); @@ -4735,7 +4725,7 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream, || (stream == AUDIO_STREAM_SYSTEM) || ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) && (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) && - streamDesc.mCanBeMuted) { + mStreams.canBeMuted(stream)) { volume *= SONIFICATION_HEADSET_VOLUME_FACTOR; // when the phone is ringing we must consider that music could have been paused just before // by the music application and behave as if music was active if the last music track was @@ -4817,7 +4807,7 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream, float voiceVolume; // Force voice volume to max for bluetooth SCO as volume is managed by the headset if (stream == AUDIO_STREAM_VOICE_CALL) { - voiceVolume = (float)index/(float)mStreams[stream].mIndexMax; + voiceVolume = (float)index/(float)mStreams[stream].getVolumeIndexMax(); } else { voiceVolume = 1.0; } @@ -4874,7 +4864,7 @@ void AudioPolicyManager::setStreamMute(audio_stream_type_t stream, int delayMs, audio_devices_t device) { - StreamDescriptor &streamDesc = mStreams[stream]; + const StreamDescriptor &streamDesc = mStreams[stream]; sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); if (device == AUDIO_DEVICE_NONE) { device = outputDesc->device(); @@ -4885,7 +4875,7 @@ void AudioPolicyManager::setStreamMute(audio_stream_type_t stream, if (on) { if (outputDesc->mMuteCount[stream] == 0) { - if (streamDesc.mCanBeMuted && + if (streamDesc.canBeMuted() && ((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) || (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) { checkAndSetVolume(stream, 0, output, device, delayMs); diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index b881aaa..d7301f5 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -39,6 +39,7 @@ #include <AudioPolicyMix.h> #include <EffectDescriptor.h> #include <SoundTriggerSession.h> +#include <StreamDescriptor.h> namespace android { @@ -435,10 +436,10 @@ protected: int mPhoneState; // current phone state audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT]; // current forced use configuration - StreamDescriptor mStreams[AUDIO_STREAM_CNT]; // stream descriptors for volume control - bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected + StreamDescriptorCollection mStreams; // stream descriptors for volume control + bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected audio_devices_t mDeviceForStrategy[NUM_STRATEGIES]; - float mLastVoiceVolume; // last voice volume value sent to audio HAL + float mLastVoiceVolume; // last voice volume value sent to audio HAL EffectDescriptorCollection mEffects; // list of registered audio effects bool mA2dpSuspended; // true if A2DP output is suspended |