Merge "camera2 ndk: Add some null checks before dereferencing captureSequenceId."
diff --git a/camera/OWNERS b/camera/OWNERS
index 18acfee..d6b95da 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -1,6 +1,8 @@
-cychen@google.com
epeev@google.com
etalvala@google.com
+jchowdhary@google.com
shuzhenwang@google.com
yinchiayeh@google.com
+# backup owner
+cychen@google.com
zhijunhe@google.com
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index 819058c..bebfb3b 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -10,7 +10,6 @@
vndk: {
enabled: true,
},
- double_loadable: true,
srcs: [
"MediaCodecsXmlParser.cpp",
diff --git a/media/ndk/OWNERS b/media/ndk/OWNERS
index 11e8340..b015a9b 100644
--- a/media/ndk/OWNERS
+++ b/media/ndk/OWNERS
@@ -1,5 +1,3 @@
marcone@google.com
# For AImage/AImageReader
-etalvala@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av/camera:/OWNERS
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 13243b8..a210a6d 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -543,7 +543,7 @@
__func__, mRecord.handle(), mPlayback.handle());
mRecord.stopTrack();
mPlayback.stopTrack();
- mRecord.track()->clearPeerProxy(); // mRecord stop is synchronous. Break PeerProxy sp<> cycle.
+ mRecord.clearTrackPeer(); // mRecord stop is synchronous. Break PeerProxy sp<> cycle.
mRecord.closeConnections(panel);
mPlayback.closeConnections(panel);
}
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index aba2cc2..181e27c 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -128,6 +128,7 @@
mThread->addPatchTrack(mTrack);
mTrack->setPeerProxy(peer, true /* holdReference */);
}
+ void clearTrackPeer() { if (mTrack) mTrack->clearPeerProxy(); }
void stopTrack() { if (mTrack) mTrack->stop(); }
void swap(Endpoint &other) noexcept {
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index 48b5271..561f100 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -16,19 +16,22 @@
#pragma once
+#include <media/AudioCommonTypes.h>
#include <system/audio.h>
#include <utils/Log.h>
#include <math.h>
namespace android {
+
/**
* VolumeSource is the discriminent for volume management on an output.
* It used to be the stream type by legacy, it may be host volume group or a volume curves if
- * we allow to have more than one curve per volume group.
+ * we allow to have more than one curve per volume group (mandatory to get rid of AudioServer
+ * stream aliases.
*/
-enum VolumeSource : std::underlying_type<audio_stream_type_t>::type;
-static const VolumeSource VOLUME_SOURCE_NONE = static_cast<VolumeSource>(AUDIO_STREAM_DEFAULT);
+enum VolumeSource : std::underlying_type<volume_group_t>::type;
+static const VolumeSource VOLUME_SOURCE_NONE = static_cast<VolumeSource>(VOLUME_GROUP_NONE);
static inline VolumeSource streamToVolumeSource(audio_stream_type_t stream) {
return static_cast<VolumeSource>(stream);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 803cfac..e071fe0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -29,7 +29,7 @@
namespace android {
-class AudioMix;
+class AudioPolicyMix;
class AudioPolicyClientInterface;
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
@@ -53,7 +53,7 @@
void dump(String8 *dst) const override;
audio_io_handle_t mIoHandle = AUDIO_IO_HANDLE_NONE; // input handle
- AudioMix *mPolicyMix = nullptr; // non NULL when used by a dynamic policy
+ wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy
const sp<IOProfile> mProfile; // I/O profile this output derives from
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 704f404..cd54085 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -34,7 +34,7 @@
namespace android {
class IOProfile;
-class AudioMix;
+class AudioPolicyMix;
class AudioPolicyClientInterface;
class ActivityTracking
@@ -107,7 +107,7 @@
};
/**
* Note: volume activities shall be indexed by CurvesId if we want to allow multiple
- * curves per volume group, inferring a mute management or volume balancing between HW and SW is
+ * curves per volume source, inferring a mute management or volume balancing between HW and SW is
* done
*/
using VolumeActivities = std::map<VolumeSource, VolumeActivity>;
@@ -157,7 +157,7 @@
virtual uint32_t latency() { return 0; }
virtual bool isFixedVolume(audio_devices_t device);
virtual bool setVolume(float volumeDb,
- audio_stream_type_t stream,
+ VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
uint32_t delayMs,
bool force);
@@ -221,7 +221,7 @@
}
void setCurVolume(VolumeSource vs, float volumeDb)
{
- // Even if not activity for this group registered, need to create anyway
+ // Even if not activity for this source registered, need to create anyway
mVolumeActivities[vs].setVolume(volumeDb);
}
float getCurVolume(VolumeSource vs) const
@@ -280,8 +280,13 @@
return mActiveClients;
}
+ bool useHwGain() const
+ {
+ return !devices().isEmpty() ? devices().itemAt(0)->hasGainController() : false;
+ }
+
DeviceVector mDevices; /**< current devices this output is routed to */
- AudioMix *mPolicyMix = nullptr; // non NULL when used by a dynamic policy
+ wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy
protected:
const sp<AudioPort> mPort;
@@ -328,7 +333,7 @@
}
}
virtual bool setVolume(float volumeDb,
- audio_stream_type_t stream,
+ VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
uint32_t delayMs,
bool force);
@@ -402,7 +407,7 @@
void dump(String8 *dst) const override;
virtual bool setVolume(float volumeDb,
- audio_stream_type_t stream,
+ VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
uint32_t delayMs,
bool force);
@@ -422,7 +427,7 @@
bool isActive(VolumeSource volumeSource, uint32_t inPastMs = 0) const;
/**
- * return whether any source contributing to VolumeSource is playing remotely, override
+ * return whether any source contributing to VolumeSource is playing remotely, override
* to change the definition of
* local/remote playback, used for instance by notification manager to not make
* media players lose audio focus when not playing locally
@@ -488,8 +493,8 @@
/**
* @brief isAnyOutputActive checks if any output is active (aka playing) except the one(s) that
* hold the volume source to be ignored
- * @param volumeSourceToIgnore source not considered in the activity detection
- * @return true if any output is active for any source except the one to be ignored
+ * @param volumeSourceToIgnore source not to be considered in the activity detection
+ * @return true if any output is active for any volume source except the one to be ignored
*/
bool isAnyOutputActive(VolumeSource volumeSourceToIgnore) const
{
@@ -518,8 +523,8 @@
/**
* @brief isAnyOutputActive checks if any output is active (aka playing) except the one(s) that
* hold the volume source to be ignored
- * @param volumeSourceToIgnore source not considered in the activity detection
- * @return true if any output is active for any source except the one to be ignored
+ * @param volumeSourceToIgnore source not to be considered in the activity detection
+ * @return true if any output is active for any volume source except the one to be ignored
*/
bool isAnyOutputActive(VolumeSource volumeSourceToIgnore) const
{
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index d6f24b2..7a9c26e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -31,24 +31,19 @@
/**
* custom mix entry in mPolicyMixes
*/
-class AudioPolicyMix : public RefBase {
+class AudioPolicyMix : public AudioMix, public RefBase {
public:
- AudioPolicyMix() {}
+ AudioPolicyMix(const AudioMix &mix) : AudioMix(mix) {}
+ AudioPolicyMix(const AudioPolicyMix&) = delete;
+ AudioPolicyMix& operator=(const AudioPolicyMix&) = delete;
- const sp<SwAudioOutputDescriptor> &getOutput() const;
-
- void setOutput(sp<SwAudioOutputDescriptor> &output);
-
- void clearOutput();
-
- android::AudioMix *getMix();
-
- void setMix(const AudioMix &mix);
+ const sp<SwAudioOutputDescriptor> &getOutput() const { return mOutput; }
+ void setOutput(const sp<SwAudioOutputDescriptor> &output) { mOutput = output; }
+ void clearOutput() { mOutput.clear(); }
void dump(String8 *dst, int spaces, int index) const;
private:
- AudioMix mMix; // Audio policy mix descriptor
sp<SwAudioOutputDescriptor> mOutput; // Corresponding output stream
};
@@ -77,21 +72,19 @@
sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
const DeviceVector &availableDeviceTypes,
- AudioMix **policyMix) const;
+ sp<AudioPolicyMix> *policyMix) const;
/**
* @brief try to find a matching mix for a given output descriptor and returns the associated
* output device.
* @param output to be considered
* @param availableOutputDevices list of output devices currently reachable
- * @param policyMix to be returned if any mix matching ouput descriptor
* @return device selected from the mix attached to the output, null pointer otherwise
*/
sp<DeviceDescriptor> getDeviceAndMixForOutput(const sp<SwAudioOutputDescriptor> &output,
- const DeviceVector &availableOutputDevices,
- AudioMix **policyMix = nullptr);
+ const DeviceVector &availableOutputDevices);
- status_t getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix);
+ status_t getInputMixForAttr(audio_attributes_t attr, sp<AudioPolicyMix> *policyMix);
status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
status_t removeUidDeviceAffinities(uid_t uid);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 1fa1123..635de6f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -22,6 +22,7 @@
#include <AudioPolicyInterface.h>
#include "AudioInputDescriptor.h"
#include "AudioGain.h"
+#include "AudioPolicyMix.h"
#include "HwModule.h"
namespace android {
@@ -308,16 +309,17 @@
const int delta = active ? 1 : -1;
mGlobalActiveCount += delta;
+ sp<AudioPolicyMix> policyMix = mPolicyMix.promote();
if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
- if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
+ if ((policyMix != NULL) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
+ mClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
} else if ((oldGlobalActiveCount > 0) && (mGlobalActiveCount == 0)) {
- if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
+ if ((policyMix != NULL) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
+ mClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
MIX_STATE_IDLE);
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index fd33649..1f3dccd 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -19,10 +19,12 @@
#include <AudioPolicyInterface.h>
#include "AudioOutputDescriptor.h"
+#include "AudioPolicyMix.h"
#include "IOProfile.h"
#include "AudioGain.h"
#include "Volume.h"
#include "HwModule.h"
+#include "TypeConverter.h"
#include <media/AudioParameter.h>
#include <media/AudioPolicy.h>
@@ -111,9 +113,10 @@
}
mGlobalActiveCount += delta;
- if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ sp<AudioPolicyMix> policyMix = mPolicyMix.promote();
+ if ((policyMix != NULL) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
if ((oldGlobalActiveCount == 0) || (mGlobalActiveCount == 0)) {
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
+ mClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
mGlobalActiveCount > 0 ? MIX_STATE_MIXING : MIX_STATE_IDLE);
}
}
@@ -150,17 +153,18 @@
}
bool AudioOutputDescriptor::setVolume(float volumeDb,
- audio_stream_type_t stream,
- audio_devices_t device __unused,
+ VolumeSource volumeSource,
+ const StreamTypeVector &/*streams*/,
+ audio_devices_t /*device*/,
uint32_t delayMs,
bool force)
{
// We actually change the volume if:
// - the float value returned by computeVolume() changed
// - the force flag is set
- if (volumeDb != getCurVolume(static_cast<VolumeSource>(stream)) || force) {
- ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volumeDb, delayMs);
- setCurVolume(static_cast<VolumeSource>(stream), volumeDb);
+ if (volumeDb != getCurVolume(volumeSource) || force) {
+ ALOGV("%s for volumeSrc %d, volume %f, delay %d", __func__, volumeSource, volumeDb, delayMs);
+ setCurVolume(volumeSource, volumeDb);
return true;
}
return false;
@@ -389,23 +393,33 @@
}
bool SwAudioOutputDescriptor::setVolume(float volumeDb,
- audio_stream_type_t stream,
+ VolumeSource vs, const StreamTypeVector &streamTypes,
audio_devices_t device,
uint32_t delayMs,
bool force)
{
- if (!AudioOutputDescriptor::setVolume(volumeDb, stream, device, delayMs, force)) {
+ StreamTypeVector streams = streamTypes;
+ if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, device, delayMs, force)) {
return false;
}
+ if (streams.empty()) {
+ streams.push_back(AUDIO_STREAM_MUSIC);
+ }
if (!devices().isEmpty()) {
// Assume first device to check upon Gain Crontroller availability
+ // APM loops on all group, so filter on active group to set the port gain,
+ // let the other groups set the stream volume as per legacy
const auto &devicePort = devices().itemAt(0);
- ALOGV("%s: device %s hasGC %d", __FUNCTION__,
- devicePort->toString().c_str(), devices().itemAt(0)->hasGainController(true));
- if (devicePort->hasGainController(true)) {
+ if (devicePort->hasGainController(true) && isActive(vs)) {
+ ALOGV("%s: device %s has gain controller", __func__, devicePort->toString().c_str());
+ // @todo: here we might be in trouble if the SwOutput has several active clients with
+ // different Volume Source (or if we allow several curves within same volume group)
+ //
// @todo: default stream volume to max (0) when using HW Port gain?
float volumeAmpl = Volume::DbToAmpl(0);
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ for (const auto &stream : streams) {
+ mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ }
AudioGains gains = devicePort->getGains();
int gainMinValueInMb = gains[0]->getMinValueInMb();
@@ -422,11 +436,15 @@
}
}
// Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is enabled
- float volumeAmpl = Volume::DbToAmpl(getCurVolume(static_cast<VolumeSource>(stream)));
- if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
+ float volumeAmpl = Volume::DbToAmpl(getCurVolume(vs));
+ if (hasStream(streams, AUDIO_STREAM_BLUETOOTH_SCO)) {
mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle, delayMs);
}
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ for (const auto &stream : streams) {
+ ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__,
+ mIoHandle, vs, volumeDb, delayMs, toString(stream).c_str());
+ mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ }
return true;
}
@@ -616,12 +634,13 @@
bool HwAudioOutputDescriptor::setVolume(float volumeDb,
- audio_stream_type_t stream,
+ VolumeSource volumeSource, const StreamTypeVector &streams,
audio_devices_t device,
uint32_t delayMs,
bool force)
{
- bool changed = AudioOutputDescriptor::setVolume(volumeDb, stream, device, delayMs, force);
+ bool changed =
+ AudioOutputDescriptor::setVolume(volumeDb, volumeSource, streams, device, delayMs, force);
if (changed) {
// TODO: use gain controller on source device if any to adjust volume
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 23d764e..f7289ca 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -27,51 +27,26 @@
namespace android {
-void AudioPolicyMix::setOutput(sp<SwAudioOutputDescriptor> &output)
-{
- mOutput = output;
-}
-
-const sp<SwAudioOutputDescriptor> &AudioPolicyMix::getOutput() const
-{
- return mOutput;
-}
-
-void AudioPolicyMix::clearOutput()
-{
- mOutput.clear();
-}
-
-void AudioPolicyMix::setMix(const AudioMix &mix)
-{
- mMix = mix;
-}
-
-android::AudioMix *AudioPolicyMix::getMix()
-{
- return &mMix;
-}
-
void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const
{
dst->appendFormat("%*sAudio Policy Mix %d:\n", spaces, "", index + 1);
std::string mixTypeLiteral;
- if (!MixTypeConverter::toString(mMix.mMixType, mixTypeLiteral)) {
- ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMix.mMixType);
+ if (!MixTypeConverter::toString(mMixType, mixTypeLiteral)) {
+ ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMixType);
return;
}
dst->appendFormat("%*s- mix type: %s\n", spaces, "", mixTypeLiteral.c_str());
std::string routeFlagLiteral;
- RouteFlagTypeConverter::maskToString(mMix.mRouteFlags, routeFlagLiteral);
+ RouteFlagTypeConverter::maskToString(mRouteFlags, routeFlagLiteral);
dst->appendFormat("%*s- Route Flags: %s\n", spaces, "", routeFlagLiteral.c_str());
- dst->appendFormat("%*s- device type: %s\n", spaces, "", toString(mMix.mDeviceType).c_str());
+ dst->appendFormat("%*s- device type: %s\n", spaces, "", toString(mDeviceType).c_str());
- dst->appendFormat("%*s- device address: %s\n", spaces, "", mMix.mDeviceAddress.string());
+ dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string());
int indexCriterion = 0;
- for (const auto &criterion : mMix.mCriteria) {
+ for (const auto &criterion : mCriteria) {
dst->appendFormat("%*s- Criterion %d:\n", spaces + 2, "", indexCriterion++);
std::string usageLiteral;
@@ -81,7 +56,7 @@
}
dst->appendFormat("%*s- Usage:%s\n", spaces + 4, "", usageLiteral.c_str());
- if (mMix.mMixType == MIX_TYPE_RECORDERS) {
+ if (mMixType == MIX_TYPE_RECORDERS) {
std::string sourceLiteral;
if (!SourceTypeConverter::toString(criterion.mValue.mSource, sourceLiteral)) {
ALOGE("%s: failed to convert source %d", __FUNCTION__, criterion.mValue.mSource);
@@ -109,12 +84,11 @@
ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
return BAD_VALUE;
}
- sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
- policyMix->setMix(mix);
+ sp<AudioPolicyMix> policyMix = new AudioPolicyMix(mix);
add(address, policyMix);
if (desc != 0) {
- desc->mPolicyMix = policyMix->getMix();
+ desc->mPolicyMix = policyMix;
policyMix->setOutput(desc);
}
return NO_ERROR;
@@ -168,15 +142,14 @@
continue;
}
- AudioMix *mix = policyMix->getMix();
- const bool primaryOutputMix = !is_mix_loopback_render(mix->mRouteFlags);
+ const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
if (primaryOutputMix && primaryDesc != 0) {
ALOGV("%s: Skiping %zu: Primary output already found", __func__, i);
continue; // Primary output already found
}
- switch (mixMatch(mix, i, attributes, uid)) {
+ switch (mixMatch(policyMix.get(), i, attributes, uid)) {
case MixMatchStatus::INVALID_MIX: return BAD_VALUE; // TODO: Do we really want to abort?
case MixMatchStatus::NO_MATCH:
ALOGV("%s: Mix %zu: does not match", __func__, i);
@@ -184,7 +157,7 @@
case MixMatchStatus::MATCH:;
}
- policyDesc->mPolicyMix = mix;
+ policyDesc->mPolicyMix = policyMix;
if (primaryOutputMix) {
primaryDesc = policyDesc;
ALOGV("%s: Mix %zu: set primary desc", __func__, i);
@@ -327,17 +300,13 @@
sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForOutput(
const sp<SwAudioOutputDescriptor> &output,
- const DeviceVector &availableOutputDevices,
- AudioMix **policyMix)
+ const DeviceVector &availableOutputDevices)
{
for (size_t i = 0; i < size(); i++) {
if (valueAt(i)->getOutput() == output) {
- AudioMix *mix = valueAt(i)->getMix();
- if (policyMix != nullptr)
- *policyMix = mix;
// This Desc is involved in a Mix, which has the highest prio
- audio_devices_t deviceType = mix->mDeviceType;
- String8 address = mix->mDeviceAddress;
+ audio_devices_t deviceType = valueAt(i)->mDeviceType;
+ String8 address = valueAt(i)->mDeviceAddress;
ALOGV("%s: device (0x%x, addr=%s) forced by mix",
__FUNCTION__, deviceType, address.c_str());
return availableOutputDevices.getDevice(deviceType, address, AUDIO_FORMAT_DEFAULT);
@@ -347,10 +316,12 @@
}
sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForInputSource(
- audio_source_t inputSource, const DeviceVector &availDevices, AudioMix **policyMix) const
+ audio_source_t inputSource,
+ const DeviceVector &availDevices,
+ sp<AudioPolicyMix> *policyMix) const
{
for (size_t i = 0; i < size(); i++) {
- AudioMix *mix = valueAt(i)->getMix();
+ AudioPolicyMix *mix = valueAt(i).get();
if (mix->mMixType != MIX_TYPE_RECORDERS) {
continue;
}
@@ -365,7 +336,7 @@
auto mixDevice =
availDevices.getDevice(device, mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
if (mixDevice != nullptr) {
- if (policyMix != NULL) {
+ if (policyMix != nullptr) {
*policyMix = mix;
}
return mixDevice;
@@ -377,7 +348,8 @@
return nullptr;
}
-status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix)
+status_t AudioPolicyMixCollection::getInputMixForAttr(
+ audio_attributes_t attr, sp<AudioPolicyMix> *policyMix)
{
if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) {
return BAD_VALUE;
@@ -387,9 +359,8 @@
#ifdef LOG_NDEBUG
ALOGV("getInputMixForAttr looking for address %s\n mixes available:", address.string());
for (size_t i = 0; i < size(); i++) {
- sp<AudioPolicyMix> policyMix = valueAt(i);
- const AudioMix *mix = policyMix->getMix();
- ALOGV("\tmix %zu address=%s", i, mix->mDeviceAddress.string());
+ sp<AudioPolicyMix> audioPolicyMix = valueAt(i);
+ ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
}
#endif
@@ -399,13 +370,14 @@
return BAD_VALUE;
}
sp<AudioPolicyMix> audioPolicyMix = valueAt(index);
- AudioMix *mix = audioPolicyMix->getMix();
- if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ if (audioPolicyMix->mMixType != MIX_TYPE_PLAYERS) {
ALOGW("getInputMixForAttr() bad policy mix type for address %s", address.string());
return BAD_VALUE;
}
- *policyMix = mix;
+ if (policyMix != nullptr) {
+ *policyMix = audioPolicyMix;
+ }
return NO_ERROR;
}
@@ -416,7 +388,7 @@
// for each player mix: add a rule to match or exclude the uid based on the device
for (size_t i = 0; i < size(); i++) {
- const AudioMix *mix = valueAt(i)->getMix();
+ const AudioPolicyMix *mix = valueAt(i).get();
if (mix->mMixType != MIX_TYPE_PLAYERS) {
continue;
}
@@ -445,7 +417,7 @@
// for each player mix: remove existing rules that match or exclude this uid
for (size_t i = 0; i < size(); i++) {
bool foundUidRule = false;
- const AudioMix *mix = valueAt(i)->getMix();
+ const AudioPolicyMix *mix = valueAt(i).get();
if (mix->mMixType != MIX_TYPE_PLAYERS) {
continue;
}
@@ -473,7 +445,7 @@
// for each player mix: find rules that don't exclude this uid, and add the device to the list
for (size_t i = 0; i < size(); i++) {
bool ruleAllowsUid = true;
- const AudioMix *mix = valueAt(i)->getMix();
+ const AudioPolicyMix *mix = valueAt(i).get();
if (mix->mMixType != MIX_TYPE_PLAYERS) {
continue;
}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 6ff8512..cedc78f 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -84,10 +84,6 @@
volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const override;
- StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const override;
-
- AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const override;
-
status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const override;
void dump(String8 *dst) const override;
@@ -112,7 +108,7 @@
VolumeSource toVolumeSource(audio_stream_type_t stream) const
{
- return static_cast<VolumeSource>(stream);
+ return static_cast<VolumeSource>(getVolumeGroupForStreamType(stream));
}
status_t switchVolumeCurve(audio_stream_type_t streamSrc, audio_stream_type_t streamDst);
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 767a8ed..1a2a198 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -152,6 +152,8 @@
volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
+ volume_group_t getDefaultVolumeGroup() const;
+
product_strategy_t getDefault() const;
void dump(String8 *dst, int spaces = 0) const;
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 4fe7b42..07a7e65 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -218,6 +218,9 @@
VolumeCurves *EngineBase::getVolumeCurvesForStreamType(audio_stream_type_t stream) const
{
volume_group_t volGr = mProductStrategies.getVolumeGroupForStreamType(stream);
+ if (volGr == VOLUME_GROUP_NONE) {
+ volGr = mProductStrategies.getDefaultVolumeGroup();
+ }
const auto &iter = mVolumeGroups.find(volGr);
LOG_ALWAYS_FATAL_IF(iter == std::end(mVolumeGroups), "No volume groups for %s",
toString(stream).c_str());
@@ -260,20 +263,6 @@
return mProductStrategies.getVolumeGroupForStreamType(stream);
}
-StreamTypeVector EngineBase::getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const
-{
- // @TODO default music stream to control volume if no group?
- return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
- mVolumeGroups.at(volumeGroup)->getStreamTypes() :
- StreamTypeVector(AUDIO_STREAM_MUSIC);
-}
-
-AttributesVector EngineBase::getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const
-{
- return (mVolumeGroups.find(volumeGroup) != end(mVolumeGroups)) ?
- mVolumeGroups.at(volumeGroup)->getSupportedAttributes() : AttributesVector();
-}
-
status_t EngineBase::listAudioVolumeGroups(AudioVolumeGroupVector &groups) const
{
for (const auto &iter : mVolumeGroups) {
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 16e6690..f74f190 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -270,11 +270,7 @@
return group;
}
}
- product_strategy_t defaultStrategy = getDefault();
- if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
- return VOLUME_GROUP_NONE;
- }
- return at(defaultStrategy)->getDefaultVolumeGroup();
+ return getDefaultVolumeGroup();
}
volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(audio_stream_type_t stream) const
@@ -285,6 +281,12 @@
return group;
}
}
+ ALOGW("%s: no volume group for %s, using default", __func__, toString(stream).c_str());
+ return getDefaultVolumeGroup();
+}
+
+volume_group_t ProductStrategyMap::getDefaultVolumeGroup() const
+{
product_strategy_t defaultStrategy = getDefault();
if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
return VOLUME_GROUP_NONE;
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
index 38f3401..b7fd031 100644
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -169,7 +169,7 @@
* @return selected input device for the audio attributes, may be null if error.
*/
virtual sp<DeviceDescriptor> getInputDeviceForAttributes(
- const audio_attributes_t &attr, AudioMix **mix = nullptr) const = 0;
+ const audio_attributes_t &attr, sp<AudioPolicyMix> *mix = nullptr) const = 0;
/**
* Get the legacy stream type for a given audio attributes.
@@ -283,10 +283,6 @@
*/
virtual volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const = 0;
- virtual StreamTypeVector getStreamTypesForVolumeGroup(volume_group_t volumeGroup) const = 0;
-
- virtual AttributesVector getAllAttributesForVolumeGroup(volume_group_t volumeGroup) const = 0;
-
/**
* @brief listAudioVolumeGroups introspection API to get the Audio Volume Groups, aka
* former stream aliases in Audio Service, defining volume curves attached to one or more
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index 65dc9af..4706d7d 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -36,7 +36,9 @@
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-LOCAL_STATIC_LIBRARIES := libpfw_utility
+LOCAL_STATIC_LIBRARIES := \
+ libpfw_utility \
+ libaudiopolicycomponents
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libpolicy-subsystem
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 89a1694..89aaa84 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -295,7 +295,7 @@
}
sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_t &attr,
- AudioMix **mix) const
+ sp<AudioPolicyMix> *mix) const
{
const auto &policyMixes = getApmObserver()->getAudioPolicyMixCollection();
const auto &availableInputDevices = getApmObserver()->getAvailableInputDevices();
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 5553994..4662e7e 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -62,7 +62,7 @@
bool fromCache = false) const override;
sp<DeviceDescriptor> getInputDeviceForAttributes(
- const audio_attributes_t &attr, AudioMix **mix = nullptr) const override;
+ const audio_attributes_t &attr, sp<AudioPolicyMix> *mix = nullptr) const override;
void updateDeviceSelectionCache() override;
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index f191738..66a6965 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -727,7 +727,7 @@
}
sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_t &attr,
- AudioMix **mix) const
+ sp<AudioPolicyMix> *mix) const
{
const auto &policyMixes = getApmObserver()->getAudioPolicyMixCollection();
const auto &availableInputDevices = getApmObserver()->getAvailableInputDevices();
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index d8a3698..d5dfacc 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -66,7 +66,7 @@
bool fromCache = false) const override;
sp<DeviceDescriptor> getInputDeviceForAttributes(
- const audio_attributes_t &attr, AudioMix **mix = nullptr) const override;
+ const audio_attributes_t &attr, sp<AudioPolicyMix> *mix = nullptr) const override;
void updateDeviceSelectionCache() override;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ea98253..4a0e764 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -217,10 +217,11 @@
&& strncmp(device_address, "0", AUDIO_DEVICE_MAX_ADDRESS_LEN) != 0) {
for (audio_io_handle_t output : outputs) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
- if (desc->mPolicyMix != nullptr
- && desc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS
+ sp<AudioPolicyMix> policyMix = desc->mPolicyMix.promote();
+ if (policyMix != nullptr
+ && policyMix->mMixType == MIX_TYPE_RECORDERS
&& strncmp(device_address,
- desc->mPolicyMix->mDeviceAddress.string(),
+ policyMix->mDeviceAddress.string(),
AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
doCheckForDeviceAndOutputChanges = false;
break;
@@ -968,7 +969,7 @@
}
if (usePrimaryOutputFromPolicyMixes) {
*output = policyDesc->mIoHandle;
- AudioMix *mix = policyDesc->mPolicyMix;
+ sp<AudioPolicyMix> mix = policyDesc->mPolicyMix.promote();
sp<DeviceDescriptor> deviceDesc =
mAvailableOutputDevices.getDevice(mix->mDeviceType,
mix->mDeviceAddress,
@@ -1084,7 +1085,7 @@
new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
sanitizedRequestedPortId, *stream,
mEngine->getProductStrategyForAttributes(resultAttr),
- streamToVolumeSource(*stream),
+ toVolumeSource(resultAttr),
*flags, isRequestedDeviceForExclusiveUse,
std::move(weakSecondaryOutputDescs));
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
@@ -1602,10 +1603,9 @@
(outputDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE);
DeviceVector devices;
- AudioMix *policyMix = NULL;
+ sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
const char *address = NULL;
- if (outputDesc->mPolicyMix != NULL) {
- policyMix = outputDesc->mPolicyMix;
+ if (policyMix != NULL) {
audio_devices_t newDeviceType;
address = policyMix->mDeviceAddress.string();
if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
@@ -1694,8 +1694,9 @@
setOutputDevices(outputDesc, devices, force, 0, NULL, requiresMuteCheck);
// apply volume rules for current stream and device if necessary
- checkAndSetVolume(stream,
- getVolumeCurves(stream).getVolumeIndex(outputDesc->devices().types()),
+ auto &curves = getVolumeCurves(client->attributes());
+ checkAndSetVolume(curves, client->volumeSource(),
+ curves.getVolumeIndex(outputDesc->devices().types()),
outputDesc,
outputDesc->devices().types());
@@ -1775,12 +1776,13 @@
if (outputDesc->getActivityCount(clientVolSrc) == 1) {
// Automatically disable the remote submix input when output is stopped on a
// re routing mix of type MIX_TYPE_RECORDERS
+ sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
if (audio_is_remote_submix_device(outputDesc->devices().types()) &&
- outputDesc->mPolicyMix != NULL &&
- outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+ policyMix != NULL &&
+ policyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputDesc->mPolicyMix->mDeviceAddress,
+ policyMix->mDeviceAddress,
"remote-submix", AUDIO_FORMAT_DEFAULT);
}
}
@@ -1895,7 +1897,7 @@
status_t status = NO_ERROR;
audio_source_t halInputSource;
audio_attributes_t attributes = *attr;
- AudioMix *policyMix = NULL;
+ sp<AudioPolicyMix> policyMix;
sp<DeviceDescriptor> device;
sp<AudioInputDescriptor> inputDesc;
sp<RecordClientDescriptor> clientDesc;
@@ -1992,7 +1994,7 @@
status = BAD_VALUE;
goto error;
}
- if (policyMix != nullptr) {
+ if (policyMix) {
ALOG_ASSERT(policyMix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type");
// there is an external policy, but this input is attached to a mix of recorders,
// meaning it receives audio injected into the framework, so the recorder doesn't
@@ -2044,7 +2046,7 @@
const audio_attributes_t &attributes,
const audio_config_base_t *config,
audio_input_flags_t flags,
- AudioMix *policyMix)
+ const sp<AudioPolicyMix> &policyMix)
{
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
audio_source_t halInputSource = attributes.source;
@@ -2204,10 +2206,11 @@
setInputDevice(input, device, true /* force */);
if (inputDesc->activeCount() == 1) {
+ sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
// if input maps to a dynamic policy with an activity listener, notify of state change
- if ((inputDesc->mPolicyMix != NULL)
- && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
+ if ((policyMix != NULL)
+ && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
@@ -2222,10 +2225,10 @@
// For remote submix (a virtual device), we open only one input per capture request.
if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
String8 address = String8("");
- if (inputDesc->mPolicyMix == NULL) {
+ if (policyMix == NULL) {
address = String8("0");
- } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mDeviceAddress;
+ } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) {
+ address = policyMix->mDeviceAddress;
}
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -2262,10 +2265,11 @@
if (inputDesc->isActive()) {
setInputDevice(input, getNewInputDevice(inputDesc), false /* force */);
} else {
+ sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
// if input maps to a dynamic policy with an activity listener, notify of state change
- if ((inputDesc->mPolicyMix != NULL)
- && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
+ if ((policyMix != NULL)
+ && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
MIX_STATE_IDLE);
}
@@ -2273,10 +2277,10 @@
// used by a policy mix of type MIX_TYPE_RECORDERS
if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
String8 address = String8("");
- if (inputDesc->mPolicyMix == NULL) {
+ if (policyMix == NULL) {
address = String8("0");
- } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mDeviceAddress;
+ } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) {
+ address = policyMix->mDeviceAddress;
}
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -2384,107 +2388,27 @@
int index,
audio_devices_t device)
{
- auto &curves = getVolumeCurves(stream);
- // VOICE_CALL and BLUETOOTH_SCO stream have minVolumeIndex > 0 but
- // can be muted directly by an app that has MODIFY_PHONE_STATE permission.
- if (((index < curves.getVolumeIndexMin()) &&
- !((stream == AUDIO_STREAM_VOICE_CALL || stream == AUDIO_STREAM_BLUETOOTH_SCO) &&
- index == 0)) ||
- (index > curves.getVolumeIndexMax())) {
+ auto attributes = mEngine->getAttributesForStreamType(stream);
+ auto volumeGroup = mEngine->getVolumeGroupForStreamType(stream);
+ if (volumeGroup == VOLUME_GROUP_NONE) {
+ ALOGE("%s: no group matching with stream %s", __FUNCTION__, toString(stream).c_str());
return BAD_VALUE;
}
- if (!audio_is_output_device(device)) {
- return BAD_VALUE;
- }
-
- // Force max volume if stream cannot be muted
- if (!curves.canBeMuted()) index = curves.getVolumeIndexMax();
-
- ALOGV("setStreamVolumeIndex() stream %d, device %08x, index %d",
- stream, device, index);
-
- // update other private stream volumes which follow this one
- for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
- if (!streamsMatchForvolume(stream, (audio_stream_type_t)curStream)) {
- continue;
- }
- auto &curCurves = getVolumeCurves(static_cast<audio_stream_type_t>(curStream));
- curCurves.addCurrentVolumeIndex(device, index);
- }
-
- // update volume on all outputs and streams matching the following:
- // - The requested stream (or a stream matching for volume control) is active on the output
- // - The device (or devices) selected by the engine for this stream includes
- // the requested device
- // - For non default requested device, currently selected device on the output is either the
- // requested device or one of the devices selected by the engine for this stream
- // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME), apply volume only if
- // no specific device volume value exists for currently selected device.
- status_t status = NO_ERROR;
- for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- audio_devices_t curDevice = desc->devices().types();
- for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
- if (!(streamsMatchForvolume(stream, (audio_stream_type_t)curStream))) {
- continue;
- }
- if (!(desc->isActive(streamToVolumeSource((audio_stream_type_t)curStream)) || isInCall())) {
- continue;
- }
- audio_devices_t curStreamDevice = Volume::getDeviceForVolume(
- mEngine->getOutputDevicesForStream((audio_stream_type_t)curStream,
- false /*fromCache*/).types());
- if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) &&
- ((curStreamDevice & device) == 0)) {
- continue;
- }
- bool applyVolume;
- if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
- curStreamDevice |= device;
- applyVolume = (Volume::getDeviceForVolume(curDevice) & curStreamDevice) != 0;
- } else {
- applyVolume = !curves.hasVolumeIndexForDevice(curStreamDevice);
- }
- // rescale index before applying to curStream as ranges may be different for
- // stream and curStream
- int idx = rescaleVolumeIndex(index, stream, (audio_stream_type_t)curStream);
- if (applyVolume) {
- //FIXME: workaround for truncated touch sounds
- // delayed volume change for system stream to be removed when the problem is
- // handled by system UI
- status_t volStatus = checkAndSetVolume(
- (audio_stream_type_t)curStream, idx, desc, curDevice,
- (stream == AUDIO_STREAM_SYSTEM) ?
- TOUCH_SOUND_FIXED_DELAY_MS : 0);
- if (volStatus != NO_ERROR) {
- status = volStatus;
- }
- }
- }
- }
- return status;
+ ALOGV("%s: stream %s attributes=%s", __func__,
+ toString(stream).c_str(), toString(attributes).c_str());
+ return setVolumeGroupIndex(getVolumeCurves(stream), volumeGroup, index, device, attributes);
}
status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,
- int *index,
- audio_devices_t device)
+ int *index,
+ audio_devices_t device)
{
- if (index == NULL) {
- return BAD_VALUE;
- }
- if (!audio_is_output_device(device)) {
- return BAD_VALUE;
- }
// if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
// stream by the engine.
if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
device = mEngine->getOutputDevicesForStream(stream, true /*fromCache*/).types();
}
- device = Volume::getDeviceForVolume(device);
-
- *index = getVolumeCurves(stream).getVolumeIndex(device);
- ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index);
- return NO_ERROR;
+ return getVolumeIndex(getVolumeCurves(stream), *index, device);
}
status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attr,
@@ -2497,18 +2421,25 @@
ALOGD("%s: could not find group matching with %s", __FUNCTION__, toString(attr).c_str());
return BAD_VALUE;
}
- ALOGD("%s: FOUND group %d matching with %s", __FUNCTION__, volumeGroup, toString(attr).c_str());
+ ALOGV("%s: group %d matching with %s", __FUNCTION__, volumeGroup, toString(attr).c_str());
return setVolumeGroupIndex(getVolumeCurves(attr), volumeGroup, index, device, attr);
}
status_t AudioPolicyManager::setVolumeGroupIndex(IVolumeCurves &curves, volume_group_t group,
int index,
audio_devices_t device,
- const audio_attributes_t /*attributes*/)
+ const audio_attributes_t attributes)
{
ALOGVV("%s: group=%d", __func__, group);
status_t status = NO_ERROR;
- setVolumeCurveIndex(group, index, device, curves);
+ VolumeSource vs = toVolumeSource(group);
+ product_strategy_t strategy = mEngine->getProductStrategyForAttributes(attributes);
+
+ status = setVolumeCurveIndex(index, device, curves);
+ if (status != NO_ERROR) {
+ ALOGE("%s failed to set curve index for group %d device 0x%X", __func__, group, device);
+ return status;
+ }
// update volume on all outputs and streams matching the following:
// - The requested stream (or a stream matching for volume control) is active on the output
// - The device (or devices) selected by the engine for this stream includes
@@ -2517,21 +2448,116 @@
// requested device or one of the devices selected by the engine for this stream
// - For default requested device (AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME), apply volume only if
// no specific device volume value exists for currently selected device.
- // @TODO
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ audio_devices_t curDevice = Volume::getDeviceForVolume(desc->devices().types());
+
+ // Inter / intra volume group priority management: Loop on strategies arranged by priority
+ // If a higher priority strategy is active, and the output is routed to a device with a
+ // HW Gain management, do not change the volume
+ bool applyVolume = false;
+ if (desc->useHwGain()) {
+ if (!(desc->isActive(group) || isInCall())) {
+ continue;
+ }
+ for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
+ auto activeClients = desc->clientsList(true /*activeOnly*/, productStrategy,
+ false /*preferredDevice*/);
+ if (activeClients.empty()) {
+ continue;
+ }
+ bool isPreempted = false;
+ bool isHigherPriority = productStrategy < strategy;
+ for (const auto &client : activeClients) {
+ if (isHigherPriority && (client->volumeSource() != vs)) {
+ ALOGV("%s: Strategy=%d (\nrequester:\n"
+ " group %d, volumeGroup=%d attributes=%s)\n"
+ " higher priority source active:\n"
+ " volumeGroup=%d attributes=%s) \n"
+ " on output %zu, bailing out", __func__, productStrategy,
+ group, group, toString(attributes).c_str(),
+ client->volumeSource(), toString(client->attributes()).c_str(), i);
+ applyVolume = false;
+ isPreempted = true;
+ break;
+ }
+ // However, continue for loop to ensure no higher prio clients running on output
+ if (client->volumeSource() == vs) {
+ applyVolume = true;
+ }
+ }
+ if (isPreempted || applyVolume) {
+ break;
+ }
+ }
+ if (!applyVolume) {
+ continue; // next output
+ }
+ status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevice,
+ (vs == toVolumeSource(AUDIO_STREAM_SYSTEM)?
+ TOUCH_SOUND_FIXED_DELAY_MS : 0));
+ if (volStatus != NO_ERROR) {
+ status = volStatus;
+ }
+ continue;
+ }
+ for (auto curVolGroup : getVolumeGroups()) {
+ VolumeSource curVolSrc = toVolumeSource(curVolGroup);
+ if (!(curVolSrc == vs || isInCall())) {
+ continue;
+ }
+ if (!(desc->isActive(vs) || isInCall())) {
+ continue;
+ }
+ audio_devices_t curSrcDevice;
+ auto &curCurves = getVolumeCurves(curVolSrc);
+ auto curCurvAttrs = curCurves.getAttributes();
+ if (!curCurvAttrs.empty() && curCurvAttrs.front() != defaultAttr) {
+ auto attr = curCurvAttrs.front();
+ curSrcDevice = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
+ } else if (!curCurves.getStreamTypes().empty()) {
+ auto stream = curCurves.getStreamTypes().front();
+ curSrcDevice = mEngine->getOutputDevicesForStream(stream, false).types();
+ } else {
+ ALOGE("%s: Invalid src %d: no valid attributes nor stream",__func__, curVolSrc);
+ continue;
+ }
+ curSrcDevice = Volume::getDeviceForVolume(curSrcDevice);
+ if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) && ((curDevice & device) == 0)) {
+ continue;
+ }
+ if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
+ curSrcDevice |= device;
+ applyVolume = (curDevice & curSrcDevice) != 0;
+ } else {
+ applyVolume = !curves.hasVolumeIndexForDevice(curSrcDevice);
+ }
+ if (applyVolume) {
+ //FIXME: workaround for truncated touch sounds
+ // delayed volume change for system stream to be removed when the problem is
+ // handled by system UI
+ status_t volStatus = checkAndSetVolume(
+ curCurves, curVolSrc, index, desc, curDevice,
+ ((vs == toVolumeSource(AUDIO_STREAM_SYSTEM))?
+ TOUCH_SOUND_FIXED_DELAY_MS : 0));
+ if (volStatus != NO_ERROR) {
+ status = volStatus;
+ }
+ }
+ }
+ }
mpClientInterface->onAudioVolumeGroupChanged(group, 0 /*flags*/);
return status;
}
-status_t AudioPolicyManager::setVolumeCurveIndex(volume_group_t volumeGroup,
- int index,
+status_t AudioPolicyManager::setVolumeCurveIndex(int index,
audio_devices_t device,
IVolumeCurves &volumeCurves)
{
// VOICE_CALL stream has minVolumeIndex > 0 but can be muted directly by an
// app that has MODIFY_PHONE_STATE permission.
- // If voice is member of the volume group, it will contaminate all the member of this group
- auto streams = mEngine->getStreamTypesForVolumeGroup(volumeGroup);
- if (((index < volumeCurves.getVolumeIndexMin()) && !(hasVoiceStream(streams) && index == 0)) ||
+ bool hasVoice = hasVoiceStream(volumeCurves.getStreamTypes());
+ if (((index < volumeCurves.getVolumeIndexMin()) && !(hasVoice && index == 0)) ||
(index > volumeCurves.getVolumeIndexMax())) {
ALOGD("%s: wrong index %d min=%d max=%d", __FUNCTION__, index,
volumeCurves.getVolumeIndexMin(), volumeCurves.getVolumeIndexMax());
@@ -2544,7 +2570,7 @@
// Force max volume if stream cannot be muted
if (!volumeCurves.canBeMuted()) index = volumeCurves.getVolumeIndexMax();
- ALOGD("%s device %08x, index %d", __FUNCTION__ , device, index);
+ ALOGV("%s device %08x, index %d", __FUNCTION__ , device, index);
volumeCurves.addCurrentVolumeIndex(device, index);
return NO_ERROR;
}
@@ -2706,19 +2732,12 @@
bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
- bool active = false;
- for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT && !active; curStream++) {
- if (!streamsMatchForvolume(stream, (audio_stream_type_t)curStream)) {
- continue;
- }
- active = mOutputs.isActive(streamToVolumeSource((audio_stream_type_t)curStream), inPastMs);
- }
- return active;
+ return mOutputs.isActive(toVolumeSource(stream), inPastMs);
}
bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
{
- return mOutputs.isActiveRemotely(streamToVolumeSource((audio_stream_type_t)stream), inPastMs);
+ return mOutputs.isActiveRemotely(toVolumeSource(stream), inPastMs);
}
bool AudioPolicyManager::isSourceActive(audio_source_t source) const
@@ -3747,11 +3766,11 @@
struct audio_patch dummyPatch = {};
sp<AudioPatch> patchDesc = new AudioPatch(&dummyPatch, uid);
- sp<SourceClientDescriptor> sourceDesc = new SourceClientDescriptor(
- *portId, uid, *attributes, patchDesc, srcDevice,
- mEngine->getStreamTypeForAttributes(*attributes),
- mEngine->getProductStrategyForAttributes(*attributes),
- streamToVolumeSource(mEngine->getStreamTypeForAttributes(*attributes)));
+ sp<SourceClientDescriptor> sourceDesc =
+ new SourceClientDescriptor(*portId, uid, *attributes, patchDesc, srcDevice,
+ mEngine->getStreamTypeForAttributes(*attributes),
+ mEngine->getProductStrategyForAttributes(*attributes),
+ toVolumeSource(*attributes));
status_t status = connectAudioSource(sourceDesc);
if (status == NO_ERROR) {
@@ -3916,7 +3935,7 @@
float AudioPolicyManager::getStreamVolumeDB(
audio_stream_type_t stream, int index, audio_devices_t device)
{
- return computeVolume(stream, index, device);
+ return computeVolume(getVolumeCurves(stream), toVolumeSource(stream), index, device);
}
status_t AudioPolicyManager::getSurroundFormats(unsigned int *numSurroundFormats,
@@ -4582,7 +4601,7 @@
sp<AudioPolicyMix> policyMix;
if (mPolicyMixes.getAudioPolicyMix(address, policyMix) == NO_ERROR) {
policyMix->setOutput(desc);
- desc->mPolicyMix = policyMix->getMix();
+ desc->mPolicyMix = policyMix;
} else {
ALOGW("checkOutputsForDevice() cannot find policy for address %s",
address.string());
@@ -5292,11 +5311,10 @@
// mute/unmute AUDIO_STREAM_TTS on all outputs
ALOGV("\t muting %d", mute);
uint32_t maxLatency = 0;
+ auto ttsVolumeSource = toVolumeSource(AUDIO_STREAM_TTS);
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- setStreamMute(AUDIO_STREAM_TTS, mute/*on*/,
- desc,
- 0 /*delay*/, AUDIO_DEVICE_NONE);
+ setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, AUDIO_DEVICE_NONE);
const uint32_t latency = desc->latency() * 2;
if (latency > maxLatency) {
maxLatency = latency;
@@ -5380,15 +5398,12 @@
if (muteWaitMs < tempMuteWaitMs) {
muteWaitMs = tempMuteWaitMs;
}
-
- for (const auto &productStrategy : productStrategies) {
- if (outputDesc->isStrategyActive(productStrategy)) {
- // make sure that we do not start the temporary mute period too early in case of
- // delayed device change
- setStrategyMute(productStrategy, true, outputDesc, delayMs);
- setStrategyMute(productStrategy, false, outputDesc, delayMs + tempMuteDurationMs,
+ for (const auto &activeVs : outputDesc->getActiveVolumeSources()) {
+ // make sure that we do not start the temporary mute period too early in case of
+ // delayed device change
+ setVolumeSourceMute(activeVs, true, outputDesc, delayMs);
+ setVolumeSourceMute(activeVs, false, outputDesc, delayMs + tempMuteDurationMs,
devices.types());
- }
}
}
@@ -5612,51 +5627,51 @@
return NULL;
}
-float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
+float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
+ VolumeSource volumeSource,
int index,
audio_devices_t device)
{
- auto &curves = getVolumeCurves(stream);
float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
// handle the case of accessibility active while a ringtone is playing: if the ringtone is much
// louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
// exploration of the dialer UI. In this situation, bring the accessibility volume closer to
// the ringtone volume
- if ((stream == AUDIO_STREAM_ACCESSIBILITY)
- && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState())
- && isStreamActive(AUDIO_STREAM_RING, 0)) {
- const float ringVolumeDB = computeVolume(AUDIO_STREAM_RING, index, device);
- return ringVolumeDB - 4 > volumeDb ? ringVolumeDB - 4 : volumeDb;
+ const auto callVolumeSrc = toVolumeSource(AUDIO_STREAM_VOICE_CALL);
+ const auto ringVolumeSrc = toVolumeSource(AUDIO_STREAM_RING);
+ const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC);
+ const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM);
+
+ if (volumeSource == toVolumeSource(AUDIO_STREAM_ACCESSIBILITY)
+ && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
+ mOutputs.isActive(ringVolumeSrc, 0)) {
+ auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
+ const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, device);
+ return ringVolumeDb - 4 > volumeDb ? ringVolumeDb - 4 : volumeDb;
}
// in-call: always cap volume by voice volume + some low headroom
- if ((stream != AUDIO_STREAM_VOICE_CALL) &&
- (isInCall() || mOutputs.isActiveLocally(streamToVolumeSource(AUDIO_STREAM_VOICE_CALL)))) {
- switch (stream) {
- case AUDIO_STREAM_SYSTEM:
- case AUDIO_STREAM_RING:
- case AUDIO_STREAM_MUSIC:
- case AUDIO_STREAM_ALARM:
- case AUDIO_STREAM_NOTIFICATION:
- case AUDIO_STREAM_ENFORCED_AUDIBLE:
- case AUDIO_STREAM_DTMF:
- case AUDIO_STREAM_ACCESSIBILITY: {
- int voiceVolumeIndex = getVolumeCurves(AUDIO_STREAM_VOICE_CALL).getVolumeIndex(device);
- const float maxVoiceVolDb =
- computeVolume(AUDIO_STREAM_VOICE_CALL, voiceVolumeIndex, device)
+ if ((volumeSource != callVolumeSrc && (isInCall() ||
+ mOutputs.isActiveLocally(callVolumeSrc))) &&
+ (volumeSource == toVolumeSource(AUDIO_STREAM_SYSTEM) ||
+ volumeSource == ringVolumeSrc || volumeSource == musicVolumeSrc ||
+ volumeSource == alarmVolumeSrc ||
+ volumeSource == toVolumeSource(AUDIO_STREAM_NOTIFICATION) ||
+ volumeSource == toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE) ||
+ volumeSource == toVolumeSource(AUDIO_STREAM_DTMF) ||
+ volumeSource == toVolumeSource(AUDIO_STREAM_ACCESSIBILITY))) {
+ auto &voiceCurves = getVolumeCurves(callVolumeSrc);
+ int voiceVolumeIndex = voiceCurves.getVolumeIndex(device);
+ const float maxVoiceVolDb =
+ computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, device)
+ IN_CALL_EARPIECE_HEADROOM_DB;
- if (volumeDb > maxVoiceVolDb) {
- ALOGV("computeVolume() stream %d at vol=%f overriden by stream %d at vol=%f",
- stream, volumeDb, AUDIO_STREAM_VOICE_CALL, maxVoiceVolDb);
- volumeDb = maxVoiceVolDb;
- }
- } break;
- default:
- break;
+ if (volumeDb > maxVoiceVolDb) {
+ ALOGV("%s volume source %d at vol=%f overriden by volume group %d at vol=%f", __func__,
+ volumeSource, volumeDb, callVolumeSrc, maxVoiceVolDb);
+ volumeDb = maxVoiceVolDb;
}
}
-
// if a headset is connected, apply the following rules to ring tones and notifications
// to avoid sound level bursts in user's ears:
// - always attenuate notifications volume by 6dB
@@ -5664,19 +5679,17 @@
// speaker is part of the select devices
// - if music is playing, always limit the volume to current music volume,
// with a minimum threshold at -36dB so that notification is always perceived.
- if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AUDIO_DEVICE_OUT_WIRED_HEADSET |
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
- AUDIO_DEVICE_OUT_USB_HEADSET |
- AUDIO_DEVICE_OUT_HEARING_AID)) &&
- ((stream == AUDIO_STREAM_ALARM || stream == AUDIO_STREAM_RING)
- || (stream == AUDIO_STREAM_NOTIFICATION)
- || (stream == AUDIO_STREAM_SYSTEM)
- || ((stream == AUDIO_STREAM_ENFORCED_AUDIBLE) &&
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) ==
- AUDIO_POLICY_FORCE_NONE))) &&
- getVolumeCurves(stream).canBeMuted()) {
+ if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+ AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+ AUDIO_DEVICE_OUT_USB_HEADSET | AUDIO_DEVICE_OUT_HEARING_AID)) &&
+ ((volumeSource == alarmVolumeSrc ||
+ volumeSource == ringVolumeSrc) ||
+ (volumeSource == toVolumeSource(AUDIO_STREAM_NOTIFICATION)) ||
+ (volumeSource == toVolumeSource(AUDIO_STREAM_SYSTEM)) ||
+ ((volumeSource == toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE)) &&
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) &&
+ curves.canBeMuted()) {
+
// 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
// just stopped
@@ -5686,29 +5699,29 @@
audio_devices_t musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
nullptr, true /*fromCache*/).types();
- float musicVolDB = computeVolume(AUDIO_STREAM_MUSIC,
- getVolumeCurves(AUDIO_STREAM_MUSIC).getVolumeIndex(musicDevice),
- musicDevice);
- float minVolDB = (musicVolDB > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
- musicVolDB : SONIFICATION_HEADSET_VOLUME_MIN_DB;
- if (volumeDb > minVolDB) {
- volumeDb = minVolDB;
- ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDB, musicVolDB);
+ auto &musicCurves = getVolumeCurves(AUDIO_STREAM_MUSIC);
+ float musicVolDb = computeVolume(musicCurves, musicVolumeSrc,
+ musicCurves.getVolumeIndex(musicDevice), musicDevice);
+ float minVolDb = (musicVolDb > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
+ musicVolDb : SONIFICATION_HEADSET_VOLUME_MIN_DB;
+ if (volumeDb > minVolDb) {
+ volumeDb = minVolDb;
+ ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDb, musicVolDb);
}
if (device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)) {
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)) {
// on A2DP, also ensure notification volume is not too low compared to media when
// intended to be played
if ((volumeDb > -96.0f) &&
- (musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
- ALOGV("computeVolume increasing volume for stream=%d device=0x%X from %f to %f",
- stream, device,
- volumeDb, musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
- volumeDb = musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
+ (musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
+ ALOGV("%s increasing volume for volume source=%d device=0x%X from %f to %f",
+ __func__, volumeSource, device, volumeDb,
+ musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
+ volumeDb = musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
}
}
} else if ((Volume::getDeviceForVolume(device) != AUDIO_DEVICE_OUT_SPEAKER) ||
- (stream != AUDIO_STREAM_ALARM && stream != AUDIO_STREAM_RING)) {
+ (!(volumeSource == alarmVolumeSrc || volumeSource == ringVolumeSrc))) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
}
}
@@ -5742,58 +5755,61 @@
return (int)(minDst + ((srcIndex - minSrc) * (maxDst - minDst)) / (maxSrc - minSrc));
}
-status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
+status_t AudioPolicyManager::checkAndSetVolume(IVolumeCurves &curves,
+ VolumeSource volumeSource,
int index,
const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
int delayMs,
bool force)
{
- // do not change actual stream volume if the stream is muted
- if (outputDesc->isMuted(streamToVolumeSource(stream))) {
- ALOGVV("%s() stream %d muted count %d", __func__, stream, outputDesc->getMuteCount(stream));
+ // do not change actual attributes volume if the attributes is muted
+ if (outputDesc->isMuted(volumeSource)) {
+ ALOGVV("%s: volume source %d muted count %d active=%d", __func__, volumeSource,
+ outputDesc->getMuteCount(volumeSource), outputDesc->isActive(volumeSource));
return NO_ERROR;
}
+ VolumeSource callVolSrc = toVolumeSource(AUDIO_STREAM_VOICE_CALL);
+ VolumeSource btScoVolSrc = toVolumeSource(AUDIO_STREAM_BLUETOOTH_SCO);
+ bool isVoiceVolSrc = callVolSrc == volumeSource;
+ bool isBtScoVolSrc = btScoVolSrc == volumeSource;
+
audio_policy_forced_cfg_t forceUseForComm =
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
// do not change in call volume if bluetooth is connected and vice versa
- if ((stream == AUDIO_STREAM_VOICE_CALL && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
- (stream == AUDIO_STREAM_BLUETOOTH_SCO && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO)) {
- ALOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
- stream, forceUseForComm);
+ // if sco and call follow same curves, bypass forceUseForComm
+ if ((callVolSrc != btScoVolSrc) &&
+ ((isVoiceVolSrc && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
+ (isBtScoVolSrc && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO))) {
+ ALOGV("%s cannot set volume group %d volume with force use = %d for comm", __func__,
+ volumeSource, forceUseForComm);
return INVALID_OPERATION;
}
-
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->devices().types();
}
- float volumeDb = computeVolume(stream, index, device);
+ float volumeDb = computeVolume(curves, volumeSource, index, device);
if (outputDesc->isFixedVolume(device) ||
// Force VoIP volume to max for bluetooth SCO
- ((stream == AUDIO_STREAM_VOICE_CALL || stream == AUDIO_STREAM_BLUETOOTH_SCO) &&
- (device & AUDIO_DEVICE_OUT_ALL_SCO) != 0)) {
+ ((isVoiceVolSrc || isBtScoVolSrc) && (device & AUDIO_DEVICE_OUT_ALL_SCO) != 0)) {
volumeDb = 0.0f;
}
+ outputDesc->setVolume(volumeDb, volumeSource, curves.getStreamTypes(), device, delayMs, force);
- outputDesc->setVolume(volumeDb, stream, device, delayMs, force);
-
- if (stream == AUDIO_STREAM_VOICE_CALL ||
- stream == AUDIO_STREAM_BLUETOOTH_SCO) {
+ if (isVoiceVolSrc || isBtScoVolSrc) {
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)getVolumeCurves(stream).getVolumeIndexMax();
+ if (isVoiceVolSrc) {
+ voiceVolume = (float)index/(float)curves.getVolumeIndexMax();
} else {
voiceVolume = 1.0;
}
-
if (voiceVolume != mLastVoiceVolume) {
mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
mLastVoiceVolume = voiceVolume;
}
}
-
return NO_ERROR;
}
@@ -5803,14 +5819,10 @@
bool force)
{
ALOGVV("applyStreamVolumes() for device %08x", device);
-
- for (int stream = 0; stream < AUDIO_STREAM_FOR_POLICY_CNT; stream++) {
- checkAndSetVolume((audio_stream_type_t)stream,
- getVolumeCurves((audio_stream_type_t)stream).getVolumeIndex(device),
- outputDesc,
- device,
- delayMs,
- force);
+ for (const auto &volumeGroup : mEngine->getVolumeGroups()) {
+ auto &curves = getVolumeCurves(toVolumeSource(volumeGroup));
+ checkAndSetVolume(curves, toVolumeSource(volumeGroup),
+ curves.getVolumeIndex(device), outputDesc, device, delayMs, force);
}
}
@@ -5820,43 +5832,54 @@
int delayMs,
audio_devices_t device)
{
- for (auto stream: mEngine->getStreamTypesForProductStrategy(strategy)) {
- ALOGVV("%s() stream %d, mute %d, output ID %d", __FUNCTION__, stream, on,
- outputDesc->getId());
- setStreamMute(stream, on, outputDesc, delayMs, device);
+ std::vector<VolumeSource> sourcesToMute;
+ for (auto attributes: mEngine->getAllAttributesForProductStrategy(strategy)) {
+ ALOGVV("%s() attributes %s, mute %d, output ID %d", __func__,
+ toString(attributes).c_str(), on, outputDesc->getId());
+ VolumeSource source = toVolumeSource(attributes);
+ if (std::find(begin(sourcesToMute), end(sourcesToMute), source) == end(sourcesToMute)) {
+ sourcesToMute.push_back(source);
+ }
}
+ for (auto source : sourcesToMute) {
+ setVolumeSourceMute(source, on, outputDesc, delayMs, device);
+ }
+
}
-void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
- bool on,
- const sp<AudioOutputDescriptor>& outputDesc,
- int delayMs,
- audio_devices_t device)
+void AudioPolicyManager::setVolumeSourceMute(VolumeSource volumeSource,
+ bool on,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ int delayMs,
+ audio_devices_t device,
+ bool activeOnly)
{
+ if (activeOnly && !outputDesc->isActive(volumeSource)) {
+ return;
+ }
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->devices().types();
}
-
- ALOGVV("setStreamMute() stream %d, mute %d, mMuteCount %d device %04x",
- stream, on, outputDesc->getMuteCount(stream), device);
- auto &curves = getVolumeCurves(stream);
+ auto &curves = getVolumeCurves(volumeSource);
if (on) {
- if (!outputDesc->isMuted(streamToVolumeSource(stream))) {
+ if (!outputDesc->isMuted(volumeSource)) {
if (curves.canBeMuted() &&
- ((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) ||
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) {
- checkAndSetVolume(stream, 0, outputDesc, device, delayMs);
+ (volumeSource != toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE) ||
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) ==
+ AUDIO_POLICY_FORCE_NONE))) {
+ checkAndSetVolume(curves, volumeSource, 0, outputDesc, device, delayMs);
}
}
- // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
- outputDesc->incMuteCount(streamToVolumeSource(stream));
+ // increment mMuteCount after calling checkAndSetVolume() so that volume change is not
+ // ignored
+ outputDesc->incMuteCount(volumeSource);
} else {
- if (!outputDesc->isMuted(streamToVolumeSource(stream))) {
- ALOGV("setStreamMute() unmuting non muted stream!");
+ if (!outputDesc->isMuted(volumeSource)) {
+ ALOGV("%s unmuting non muted attributes!", __func__);
return;
}
- if (outputDesc->decMuteCount(streamToVolumeSource(stream)) == 0) {
- checkAndSetVolume(stream,
+ if (outputDesc->decMuteCount(volumeSource) == 0) {
+ checkAndSetVolume(curves, volumeSource,
curves.getVolumeIndex(device),
outputDesc,
device,
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 3a31e1e..1fc61e5 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -174,8 +174,7 @@
status_t setVolumeGroupIndex(IVolumeCurves &volumeCurves, volume_group_t group, int index,
audio_devices_t device, const audio_attributes_t attributes);
- status_t setVolumeCurveIndex(volume_group_t volumeGroup,
- int index,
+ status_t setVolumeCurveIndex(int index,
audio_devices_t device,
IVolumeCurves &volumeCurves);
@@ -358,6 +357,30 @@
return mDefaultOutputDevice;
}
+ std::vector<volume_group_t> getVolumeGroups() const
+ {
+ return mEngine->getVolumeGroups();
+ }
+
+ VolumeSource toVolumeSource(volume_group_t volumeGroup) const
+ {
+ return static_cast<VolumeSource>(volumeGroup);
+ }
+ VolumeSource toVolumeSource(const audio_attributes_t &attributes) const
+ {
+ return toVolumeSource(mEngine->getVolumeGroupForAttributes(attributes));
+ }
+ VolumeSource toVolumeSource(audio_stream_type_t stream) const
+ {
+ return toVolumeSource(mEngine->getVolumeGroupForStreamType(stream));
+ }
+ IVolumeCurves &getVolumeCurves(VolumeSource volumeSource)
+ {
+ auto *curves = mEngine->getVolumeCurvesForVolumeGroup(
+ static_cast<volume_group_t>(volumeSource));
+ ALOG_ASSERT(curves != nullptr, "No curves for volume source %d", volumeSource);
+ return *curves;
+ }
IVolumeCurves &getVolumeCurves(const audio_attributes_t &attr)
{
auto *curves = mEngine->getVolumeCurvesForAttributes(attr);
@@ -395,7 +418,8 @@
// compute the actual volume for a given stream according to the requested index and a particular
// device
- virtual float computeVolume(audio_stream_type_t stream,
+ virtual float computeVolume(IVolumeCurves &curves,
+ VolumeSource volumeSource,
int index,
audio_devices_t device);
@@ -404,7 +428,8 @@
audio_stream_type_t srcStream,
audio_stream_type_t dstStream);
// check that volume change is permitted, compute and send new volume to audio hardware
- virtual status_t checkAndSetVolume(audio_stream_type_t stream, int index,
+ virtual status_t checkAndSetVolume(IVolumeCurves &curves,
+ VolumeSource volumeSource, int index,
const sp<AudioOutputDescriptor>& outputDesc,
audio_devices_t device,
int delayMs = 0, bool force = false);
@@ -428,12 +453,22 @@
int delayMs = 0,
audio_devices_t device = AUDIO_DEVICE_NONE);
- // Mute or unmute the stream on the specified output
- void setStreamMute(audio_stream_type_t stream,
- bool on,
- const sp<AudioOutputDescriptor>& outputDesc,
- int delayMs = 0,
- audio_devices_t device = (audio_devices_t)0);
+ /**
+ * @brief setVolumeSourceMute Mute or unmute the volume source on the specified output
+ * @param volumeSource to be muted/unmute (may host legacy streams or by extension set of
+ * audio attributes)
+ * @param on true to mute, false to umute
+ * @param outputDesc on which the client following the volume group shall be muted/umuted
+ * @param delayMs
+ * @param device
+ * @param activeOnly if true, mute only if the volume group is active on the output.
+ */
+ void setVolumeSourceMute(VolumeSource volumeSource,
+ bool on,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ int delayMs = 0,
+ audio_devices_t device = AUDIO_DEVICE_NONE,
+ bool activeOnly = false);
audio_mode_t getPhoneState();
@@ -799,7 +834,7 @@
const audio_attributes_t &attributes,
const audio_config_base_t *config,
audio_input_flags_t flags,
- AudioMix *policyMix);
+ const sp<AudioPolicyMix> &policyMix);
// event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
// returns 0 if no mute/unmute event happened, the largest latency of the device where
diff --git a/services/camera/OWNERS b/services/camera/OWNERS
index 18acfee..f112576 100644
--- a/services/camera/OWNERS
+++ b/services/camera/OWNERS
@@ -1,6 +1 @@
-cychen@google.com
-epeev@google.com
-etalvala@google.com
-shuzhenwang@google.com
-yinchiayeh@google.com
-zhijunhe@google.com
+include platform/frameworks/av/camera:/OWNERS