Merge "audiopolicy: rework stream activity for volume management on output"

gugelfrei
Eric Laurent 5 years ago committed by Android (Google) Code Review
commit 0cc7c07a0d

@ -20,6 +20,22 @@
#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.
*/
enum VolumeSource : std::underlying_type<audio_stream_type_t>::type;
static const VolumeSource VOLUME_SOURCE_NONE = static_cast<VolumeSource>(AUDIO_STREAM_DEFAULT);
static inline VolumeSource streamToVolumeSource(audio_stream_type_t stream) {
return static_cast<VolumeSource>(stream);
}
} // namespace android
// Absolute min volume in dB (can be represented in single precision normal float value)
#define VOLUME_MIN_DB (-758)

@ -73,7 +73,7 @@ public:
virtual void dump(String8 *dst, int spaces) const
{
dst->appendFormat("%*s- ActivityCount: %d, StopTime: %" PRId64 " \n", spaces, "",
dst->appendFormat("%*s- ActivityCount: %d, StopTime: %" PRId64 ", ", spaces, "",
getActivityCount(), getStopTime());
}
private:
@ -81,6 +81,37 @@ private:
nsecs_t mStopTime = 0;
};
/**
* @brief VolumeActivity: it tracks the activity for volume policy (volume index, mute,
* memorize previous stop, and store mute if incompatible device with another strategy.
*/
class VolumeActivity : public ActivityTracking
{
public:
bool isMuted() const { return mMuteCount > 0; }
int getMuteCount() const { return mMuteCount; }
int incMuteCount() { return ++mMuteCount; }
int decMuteCount() { return mMuteCount > 0 ? --mMuteCount : -1; }
void dump(String8 *dst, int spaces) const override
{
ActivityTracking::dump(dst, spaces);
dst->appendFormat(", Volume: %.03f, MuteCount: %02d\n", mCurVolumeDb, mMuteCount);
}
void setVolume(float volume) { mCurVolumeDb = volume; }
float getVolume() const { return mCurVolumeDb; }
private:
int mMuteCount = 0; /**< mute request counter */
float mCurVolumeDb = NAN; /**< current volume in dB. */
};
/**
* 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
* done
*/
using VolumeActivities = std::map<VolumeSource, VolumeActivity>;
/**
* @brief The Activity class: it tracks the activity for volume policy (volume index, mute,
* memorize previous stop, and store mute if incompatible device with another strategy.
@ -92,6 +123,10 @@ public:
void setMutedByDevice( bool isMuted) { mIsMutedByDevice = isMuted; }
bool isMutedByDevice() const { return mIsMutedByDevice; }
void dump(String8 *dst, int spaces) const override {
ActivityTracking::dump(dst, spaces);
dst->appendFormat("\n");
}
private:
/**
* strategies muted because of incompatible device selection.
@ -127,15 +162,6 @@ public:
uint32_t delayMs,
bool force);
/**
* Changes the stream active count and mActiveClients only.
* This does not change the client->active() state or the output descriptor's
* global active count.
*/
virtual void changeStreamActiveCount(const sp<TrackClientDescriptor>& client, int delta);
uint32_t streamActiveCount(audio_stream_type_t stream) const
{ return mActiveCount[stream]; }
/**
* @brief setStopTime set the stop time due to the client stoppage or a re routing of this
* client
@ -148,13 +174,61 @@ public:
* Changes the client->active() state and the output descriptor's global active count,
* along with the stream active count and mActiveClients.
* The client must be previously added by the base class addClient().
* In case of duplicating thread, client shall be added on the duplicated thread, not on the
* involved outputs but setClientActive will be called on all output to track strategy and
* active client for a given output.
* Active ref count of the client will be incremented/decremented through setActive API
*/
void setClientActive(const sp<TrackClientDescriptor>& client, bool active);
bool isActive(uint32_t inPastMs = 0) const;
bool isStreamActive(audio_stream_type_t stream,
uint32_t inPastMs = 0,
nsecs_t sysTime = 0) const;
virtual void setClientActive(const sp<TrackClientDescriptor>& client, bool active);
bool isActive(uint32_t inPastMs) const;
bool isActive(VolumeSource volumeSource = VOLUME_SOURCE_NONE,
uint32_t inPastMs = 0,
nsecs_t sysTime = 0) const;
bool isAnyActive(VolumeSource volumeSourceToIgnore) const;
std::vector<VolumeSource> getActiveVolumeSources() const {
std::vector<VolumeSource> activeList;
for (const auto &iter : mVolumeActivities) {
if (iter.second.isActive()) {
activeList.push_back(iter.first);
}
}
return activeList;
}
uint32_t getActivityCount(VolumeSource vs) const
{
return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
mVolumeActivities.at(vs).getActivityCount() : 0;
}
bool isMuted(VolumeSource vs) const
{
return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
mVolumeActivities.at(vs).isMuted() : false;
}
int getMuteCount(VolumeSource vs) const
{
return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
mVolumeActivities.at(vs).getMuteCount() : 0;
}
int incMuteCount(VolumeSource vs)
{
return mVolumeActivities[vs].incMuteCount();
}
int decMuteCount(VolumeSource vs)
{
return mVolumeActivities[vs].decMuteCount();
}
void setCurVolume(VolumeSource vs, float volume)
{
// Even if not activity for this group registered, need to create anyway
mVolumeActivities[vs].setVolume(volume);
}
float getCurVolume(VolumeSource vs) const
{
return mVolumeActivities.find(vs) != std::end(mVolumeActivities) ?
mVolumeActivities.at(vs).getVolume() : NAN;
}
bool isStrategyActive(product_strategy_t ps, uint32_t inPastMs = 0, nsecs_t sysTime = 0) const
{
@ -195,40 +269,36 @@ public:
// it is possible that when a client is removed, we could remove its
// associated active count by calling changeStreamActiveCount(),
// but that would be hiding a problem, so we log fatal instead.
auto it2 = mActiveClients.find(client);
LOG_ALWAYS_FATAL_IF(it2 != mActiveClients.end(),
"%s(%d) removing client portId %d which is active (count %zu)",
__func__, mId, portId, it2->second);
auto clientIter = std::find(begin(mActiveClients), end(mActiveClients), client);
LOG_ALWAYS_FATAL_IF(clientIter != mActiveClients.end(),
"%s(%d) removing client portId %d which is active (count %d)",
__func__, mId, portId, client->getActivityCount());
ClientMapHandler<TrackClientDescriptor>::removeClient(portId);
}
using ActiveClientMap = std::map<sp<TrackClientDescriptor>, size_t /* count */>;
// required for duplicating thread
const ActiveClientMap& getActiveClients() const {
const TrackClientVector& getActiveClients() const {
return mActiveClients;
}
DeviceVector mDevices; /**< current devices this output is routed to */
nsecs_t mStopTime[AUDIO_STREAM_CNT];
int mMuteCount[AUDIO_STREAM_CNT]; // mute request counter
AudioMix *mPolicyMix = nullptr; // non NULL when used by a dynamic policy
protected:
const sp<AudioPort> mPort;
AudioPolicyClientInterface * const mClientInterface;
float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB
uint32_t mActiveCount[AUDIO_STREAM_CNT]; // number of streams of each type active on this output
uint32_t mGlobalActiveCount = 0; // non-client-specific active count
audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
// The ActiveClientMap shows the clients that contribute to the streams counts
// The ActiveClients shows the clients that contribute to the @VolumeSource counts
// and may include upstream clients from a duplicating thread.
// Compare with the ClientMap (mClients) which are external AudioTrack clients of the
// output descriptor (and do not count internal PatchTracks).
ActiveClientMap mActiveClients;
TrackClientVector mActiveClients;
RoutingActivities mRoutingActivities; /**< track routing activity on this ouput.*/
VolumeActivities mVolumeActivities; /**< track volume activity on this ouput.*/
};
// Audio output driven by a software mixer in audio flinger.
@ -250,8 +320,13 @@ public:
virtual bool isFixedVolume(audio_devices_t device);
sp<SwAudioOutputDescriptor> subOutput1() { return mOutput1; }
sp<SwAudioOutputDescriptor> subOutput2() { return mOutput2; }
void changeStreamActiveCount(
const sp<TrackClientDescriptor>& client, int delta) override;
void setClientActive(const sp<TrackClientDescriptor>& client, bool active) override;
void setAllClientsInactive()
{
for (const auto &client : clientsList(true)) {
setClientActive(client, false);
}
}
virtual bool setVolume(float volume,
audio_stream_type_t stream,
audio_devices_t device,
@ -344,25 +419,27 @@ class SwAudioOutputCollection :
public DefaultKeyedVector< audio_io_handle_t, sp<SwAudioOutputDescriptor> >
{
public:
bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
bool isActive(VolumeSource volumeSource, uint32_t inPastMs = 0) const;
/**
* return whether a stream is playing remotely, override to change the definition of
* 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
* For the base implementation, "remotely" means playing during screen mirroring which
* uses an output for playback with a non-empty, non "0" address.
*/
bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
bool isActiveRemotely(VolumeSource volumeSource, uint32_t inPastMs = 0) const;
/**
* return whether a stream is playing, but not on a "remote" device.
* return whether any source contributing to VolumeSource is playing, but not on a "remote"
* device.
* Override to change the definition of a local/remote playback.
* Used for instance by policy manager to alter the speaker playback ("speaker safe" behavior)
* when media plays or not locally.
* For the base implementation, "remotely" means playing during screen mirroring.
*/
bool isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
bool isActiveLocally(VolumeSource volumeSource, uint32_t inPastMs = 0) const;
/**
* @brief isStrategyActiveOnSameModule checks if the given strategy is active (or was active
@ -409,9 +486,21 @@ public:
sp<SwAudioOutputDescriptor> getPrimaryOutput() const;
/**
* return true if any output is playing anything besides the stream to ignore
* @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
*/
bool isAnyOutputActive(audio_stream_type_t streamToIgnore) const;
bool isAnyOutputActive(VolumeSource volumeSourceToIgnore) const
{
for (size_t i = 0; i < size(); i++) {
const sp<AudioOutputDescriptor> &outputDesc = valueAt(i);
if (outputDesc->isAnyActive(volumeSourceToIgnore)) {
return true;
}
}
return false;
}
audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
@ -424,12 +513,24 @@ class HwAudioOutputCollection :
public DefaultKeyedVector< audio_io_handle_t, sp<HwAudioOutputDescriptor> >
{
public:
bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
bool isActive(VolumeSource volumeSource, uint32_t inPastMs = 0) const;
/**
* return true if any output is playing anything besides the stream to ignore
* @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
*/
bool isAnyOutputActive(audio_stream_type_t streamToIgnore) const;
bool isAnyOutputActive(VolumeSource volumeSourceToIgnore) const
{
for (size_t i = 0; i < size(); i++) {
const sp<AudioOutputDescriptor> &outputDesc = valueAt(i);
if (outputDesc->isAnyActive(volumeSourceToIgnore)) {
return true;
}
}
return false;
}
void dump(String8 *dst) const;
};

@ -28,6 +28,7 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <policy.h>
#include <Volume.h>
#include "AudioPatch.h"
#include "EffectDescriptor.h"
@ -62,7 +63,7 @@ public:
mPreferredDeviceId = preferredDeviceId;
}
bool isPreferredDeviceForExclusiveUse() const { return mPreferredDeviceForExclusiveUse; }
void setActive(bool active) { mActive = active; }
virtual void setActive(bool active) { mActive = active; }
bool active() const { return mActive; }
bool hasPreferredDevice(bool activeOnly = false) const {
return mPreferredDeviceId != AUDIO_PORT_HANDLE_NONE && (!activeOnly || mActive);
@ -85,12 +86,13 @@ public:
TrackClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_session_t sessionId,
audio_attributes_t attributes, audio_config_base_t config,
audio_port_handle_t preferredDeviceId, audio_stream_type_t stream,
product_strategy_t strategy, audio_output_flags_t flags,
product_strategy_t strategy, VolumeSource volumeSource,
audio_output_flags_t flags,
bool isPreferredDeviceForExclusiveUse,
std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs) :
ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId,
isPreferredDeviceForExclusiveUse),
mStream(stream), mStrategy(strategy), mFlags(flags),
mStream(stream), mStrategy(strategy), mVolumeSource(volumeSource), mFlags(flags),
mSecondaryOutputs(std::move(secondaryOutputs)) {}
~TrackClientDescriptor() override = default;
@ -104,12 +106,41 @@ public:
const std::vector<wp<SwAudioOutputDescriptor>>& getSecondaryOutputs() const {
return mSecondaryOutputs;
};
VolumeSource volumeSource() const { return mVolumeSource; }
void setActive(bool active) override
{
int delta = active ? 1 : -1;
changeActivityCount(delta);
}
void changeActivityCount(int delta)
{
if (delta > 0) {
mActivityCount += delta;
} else {
LOG_ALWAYS_FATAL_IF(!mActivityCount, "%s(%s) invalid delta %d, inactive client",
__func__, toShortString().c_str(), delta);
LOG_ALWAYS_FATAL_IF(static_cast<int>(mActivityCount) < -delta,
"%s(%s) invalid delta %d, active client count %d",
__func__, toShortString().c_str(), delta, mActivityCount);
mActivityCount += delta;
}
ClientDescriptor::setActive(mActivityCount > 0);
}
uint32_t getActivityCount() const { return mActivityCount; }
private:
const audio_stream_type_t mStream;
const product_strategy_t mStrategy;
const VolumeSource mVolumeSource;
const audio_output_flags_t mFlags;
const std::vector<wp<SwAudioOutputDescriptor>> mSecondaryOutputs;
/**
* required for duplicating thread, prevent from removing active client from an output
* involved in a duplication.
*/
uint32_t mActivityCount = 0;
};
class RecordClientDescriptor: public ClientDescriptor
@ -148,7 +179,8 @@ class SourceClientDescriptor: public TrackClientDescriptor
public:
SourceClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_attributes_t attributes,
const sp<AudioPatch>& patchDesc, const sp<DeviceDescriptor>& srcDevice,
audio_stream_type_t stream, product_strategy_t strategy);
audio_stream_type_t stream, product_strategy_t strategy,
VolumeSource volumeSource);
~SourceClientDescriptor() override = default;
sp<AudioPatch> patchDesc() const { return mPatchDesc; }

@ -34,16 +34,8 @@ namespace android {
AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
AudioPolicyClientInterface *clientInterface)
: mPort(port)
, mClientInterface(clientInterface)
: mPort(port), mClientInterface(clientInterface)
{
// clear usage count for all stream types
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
mActiveCount[i] = 0;
mCurVolume[i] = -1.0;
mMuteCount[i] = 0;
mStopTime[i] = 0;
}
if (mPort.get() != nullptr) {
mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
if (mPort->mGains.size() > 0) {
@ -85,124 +77,73 @@ bool AudioOutputDescriptor::sharesHwModuleWith(
return hasSameHwModuleAs(outputDesc);
}
void AudioOutputDescriptor::changeStreamActiveCount(const sp<TrackClientDescriptor>& client,
int delta)
{
if (delta == 0) return;
const audio_stream_type_t stream = client->stream();
if ((delta + (int)mActiveCount[stream]) < 0) {
// any mismatched active count will abort.
LOG_ALWAYS_FATAL("%s(%s) invalid delta %d, active stream count %d",
__func__, client->toShortString().c_str(), delta, mActiveCount[stream]);
// mActiveCount[stream] = 0;
// return;
}
mActiveCount[stream] += delta;
mRoutingActivities[client->strategy()].changeActivityCount(delta);
if (delta > 0) {
mActiveClients[client] += delta;
} else {
auto it = mActiveClients.find(client);
if (it == mActiveClients.end()) { // client not found!
LOG_ALWAYS_FATAL("%s(%s) invalid delta %d, inactive client",
__func__, client->toShortString().c_str(), delta);
} else if (it->second < -delta) { // invalid delta!
LOG_ALWAYS_FATAL("%s(%s) invalid delta %d, active client count %zu",
__func__, client->toShortString().c_str(), delta, it->second);
}
it->second += delta;
if (it->second == 0) {
(void)mActiveClients.erase(it);
}
}
ALOGV("%s stream %d, count %d", __FUNCTION__, stream, mActiveCount[stream]);
}
void AudioOutputDescriptor::setStopTime(const sp<TrackClientDescriptor>& client, nsecs_t sysTime)
{
mStopTime[client->stream()] = sysTime;
mVolumeActivities[client->volumeSource()].setStopTime(sysTime);
mRoutingActivities[client->strategy()].setStopTime(sysTime);
}
void AudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
{
LOG_ALWAYS_FATAL_IF(getClient(client->portId()) == nullptr,
"%s(%d) does not exist on output descriptor", __func__, client->portId());
if (active == client->active()) {
ALOGW("%s(%s): ignored active: %d, current stream count %d",
__func__, client->toShortString().c_str(),
active, mActiveCount[client->stream()]);
auto clientIter = std::find(begin(mActiveClients), end(mActiveClients), client);
if (active == (clientIter != end(mActiveClients))) {
ALOGW("%s(%s): ignored active: %d, current stream count %d", __func__,
client->toShortString().c_str(), active,
mRoutingActivities.at(client->strategy()).getActivityCount());
return;
}
if (active) {
mActiveClients.push_back(client);
} else {
mActiveClients.erase(clientIter);
}
const int delta = active ? 1 : -1;
changeStreamActiveCount(client, delta);
// If ps is unknown, it is time to track it!
mRoutingActivities[client->strategy()].changeActivityCount(delta);
mVolumeActivities[client->volumeSource()].changeActivityCount(delta);
// Handle non-client-specific activity ref count
int32_t oldGlobalActiveCount = mGlobalActiveCount;
if (!active && mGlobalActiveCount < 1) {
ALOGW("%s(%s): invalid deactivation with globalRefCount %d",
__func__, client->toShortString().c_str(), mGlobalActiveCount);
__func__, client->toShortString().c_str(), mGlobalActiveCount);
mGlobalActiveCount = 1;
}
mGlobalActiveCount += delta;
if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
if ((oldGlobalActiveCount == 0) || (mGlobalActiveCount == 0)) {
mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
} else if ((oldGlobalActiveCount > 0) && (mGlobalActiveCount == 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
MIX_STATE_IDLE);
mGlobalActiveCount > 0 ? MIX_STATE_MIXING : MIX_STATE_IDLE);
}
}
client->setActive(active);
}
bool AudioOutputDescriptor::isActive(VolumeSource vs, uint32_t inPastMs, nsecs_t sysTime) const
{
return (vs == VOLUME_SOURCE_NONE) ?
isActive(inPastMs) : (mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
mVolumeActivities.at(vs).isActive(inPastMs, sysTime) : false);
}
bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
{
nsecs_t sysTime = 0;
if (inPastMs != 0) {
sysTime = systemTime();
}
for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
if (i == AUDIO_STREAM_PATCH) {
for (const auto &iter : mVolumeActivities) {
if (iter.first == streamToVolumeSource(AUDIO_STREAM_PATCH)) {
continue;
}
if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
if (iter.second.isActive(inPastMs, sysTime)) {
return true;
}
}
return false;
}
bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
uint32_t inPastMs,
nsecs_t sysTime) const
{
if (mActiveCount[stream] != 0) {
return true;
}
if (inPastMs == 0) {
return false;
}
if (sysTime == 0) {
sysTime = systemTime();
}
if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) {
return true;
}
return false;
}
bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
{
return false;
@ -217,9 +158,9 @@ bool AudioOutputDescriptor::setVolume(float volume,
// We actually change the volume if:
// - the float value returned by computeVolume() changed
// - the force flag is set
if (volume != mCurVolume[stream] || force) {
if (volume != getCurVolume(static_cast<VolumeSource>(stream)) || force) {
ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs);
mCurVolume[stream] = volume;
setCurVolume(static_cast<VolumeSource>(stream), volume);
return true;
}
return false;
@ -266,6 +207,13 @@ TrackClientVector AudioOutputDescriptor::clientsList(bool activeOnly, product_st
return clients;
}
bool AudioOutputDescriptor::isAnyActive(VolumeSource volumeSourceToIgnore) const
{
return std::find_if(begin(mActiveClients), end(mActiveClients),
[&volumeSourceToIgnore](const auto &client) {
return client->volumeSource() != volumeSourceToIgnore; }) != end(mActiveClients);
}
void AudioOutputDescriptor::dump(String8 *dst) const
{
dst->appendFormat(" ID: %d\n", mId);
@ -274,20 +222,22 @@ void AudioOutputDescriptor::dump(String8 *dst) const
dst->appendFormat(" Channels: %08x\n", mChannelMask);
dst->appendFormat(" Devices: %s\n", devices().toString().c_str());
dst->appendFormat(" Global active count: %u\n", mGlobalActiveCount);
dst->append(" Stream volume activeCount muteCount\n");
for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
dst->appendFormat(" %02d %.03f %02d %02d\n",
i, mCurVolume[i], streamActiveCount((audio_stream_type_t)i), mMuteCount[i]);
for (const auto &iter : mRoutingActivities) {
dst->appendFormat(" Product Strategy id: %d", iter.first);
iter.second.dump(dst, 4);
}
for (const auto &iter : mVolumeActivities) {
dst->appendFormat(" Volume Activities id: %d", iter.first);
iter.second.dump(dst, 4);
}
dst->append(" AudioTrack Clients:\n");
ClientMapHandler<TrackClientDescriptor>::dump(dst);
dst->append("\n");
if (mActiveClients.size() > 0) {
if (!mActiveClients.empty()) {
dst->append(" AudioTrack active (stream) clients:\n");
size_t index = 0;
for (const auto& clientPair : mActiveClients) {
dst->appendFormat(" Refcount: %zu", clientPair.second);
clientPair.first->dump(dst, 2, index++);
for (const auto& client : mActiveClients) {
client->dump(dst, 2, index++);
}
dst->append(" \n");
}
@ -388,15 +338,14 @@ uint32_t SwAudioOutputDescriptor::latency()
}
}
void SwAudioOutputDescriptor::changeStreamActiveCount(const sp<TrackClientDescriptor>& client,
int delta)
void SwAudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
{
// forward usage count change to attached outputs
if (isDuplicated()) {
mOutput1->changeStreamActiveCount(client, delta);
mOutput2->changeStreamActiveCount(client, delta);
mOutput1->setClientActive(client, active);
mOutput2->setClientActive(client, active);
}
AudioOutputDescriptor::changeStreamActiveCount(client, delta);
AudioOutputDescriptor::setClientActive(client, active);
}
bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
@ -445,19 +394,16 @@ bool SwAudioOutputDescriptor::setVolume(float volume,
uint32_t delayMs,
bool force)
{
bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
if (changed) {
// Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
// enabled
float volume = Volume::DbToAmpl(mCurVolume[stream]);
if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
mClientInterface->setStreamVolume(
AUDIO_STREAM_VOICE_CALL, volume, mIoHandle, delayMs);
}
mClientInterface->setStreamVolume(stream, volume, mIoHandle, delayMs);
if (!AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force)) {
return false;
}
return changed;
// 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) {
mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle, delayMs);
}
mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
return true;
}
status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
@ -660,24 +606,24 @@ bool HwAudioOutputDescriptor::setVolume(float volume,
}
// SwAudioOutputCollection implementation
bool SwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
bool SwAudioOutputCollection::isActive(VolumeSource volumeSource, uint32_t inPastMs) const
{
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < this->size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
if (outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
return true;
}
}
return false;
}
bool SwAudioOutputCollection::isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs) const
bool SwAudioOutputCollection::isActiveLocally(VolumeSource volumeSource, uint32_t inPastMs) const
{
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < this->size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
if (outputDesc->isStreamActive(stream, inPastMs, sysTime)
if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
&& ((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
return true;
}
@ -685,14 +631,13 @@ bool SwAudioOutputCollection::isStreamActiveLocally(audio_stream_type_t stream,
return false;
}
bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
uint32_t inPastMs) const
bool SwAudioOutputCollection::isActiveRemotely(VolumeSource volumeSource, uint32_t inPastMs) const
{
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
if (((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
// do not consider re routing (when the output is going to a dynamic policy)
// as "remote playback"
if (outputDesc->mPolicyMix == NULL) {
@ -775,22 +720,6 @@ sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_
return NULL;
}
bool SwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
{
for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
if (s == (size_t) streamToIgnore) {
continue;
}
for (size_t i = 0; i < size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
if (outputDesc->streamActiveCount((audio_stream_type_t)s)!= 0) {
return true;
}
}
}
return false;
}
sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputForClient(audio_port_handle_t portId)
{
for (size_t i = 0; i < size(); i++) {
@ -825,34 +754,18 @@ void SwAudioOutputCollection::dump(String8 *dst) const
}
// HwAudioOutputCollection implementation
bool HwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
bool HwAudioOutputCollection::isActive(VolumeSource volumeSource, uint32_t inPastMs) const
{
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < this->size(); i++) {
const sp<HwAudioOutputDescriptor> outputDesc = this->valueAt(i);
if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
if (outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
return true;
}
}
return false;
}
bool HwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
{
for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
if (s == (size_t) streamToIgnore) {
continue;
}
for (size_t i = 0; i < size(); i++) {
const sp<HwAudioOutputDescriptor> outputDesc = valueAt(i);
if (outputDesc->streamActiveCount((audio_stream_type_t)s) != 0) {
return true;
}
}
}
return false;
}
void HwAudioOutputCollection::dump(String8 *dst) const
{
dst->append("\nOutputs dump:\n");

@ -20,6 +20,7 @@
#include <sstream>
#include <utils/Log.h>
#include <utils/String8.h>
#include <TypeConverter.h>
#include "AudioGain.h"
#include "AudioOutputDescriptor.h"
#include "AudioPatch.h"
@ -45,6 +46,7 @@ void ClientDescriptor::dump(String8 *dst, int spaces, int index) const
mPortId, mSessionId, mUid);
dst->appendFormat("%*s- Format: %08x Sampling rate: %d Channels: %08x\n", spaces, "",
mConfig.format, mConfig.sample_rate, mConfig.channel_mask);
dst->appendFormat("%*s- Attributes: %s\n", spaces, "", toString(mAttributes).c_str());
dst->appendFormat("%*s- Preferred Device Id: %08x\n", spaces, "", mPreferredDeviceId);
dst->appendFormat("%*s- State: %s\n", spaces, "", mActive ? "Active" : "Inactive");
}
@ -53,6 +55,7 @@ void TrackClientDescriptor::dump(String8 *dst, int spaces, int index) const
{
ClientDescriptor::dump(dst, spaces, index);
dst->appendFormat("%*s- Stream: %d flags: %08x\n", spaces, "", mStream, mFlags);
dst->appendFormat("%*s- Refcount: %d\n", spaces, "", mActivityCount);
}
std::string TrackClientDescriptor::toShortString() const
@ -82,10 +85,10 @@ void RecordClientDescriptor::dump(String8 *dst, int spaces, int index) const
SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t uid,
audio_attributes_t attributes, const sp<AudioPatch>& patchDesc,
const sp<DeviceDescriptor>& srcDevice, audio_stream_type_t stream,
product_strategy_t strategy) :
product_strategy_t strategy, VolumeSource volumeSource) :
TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
AUDIO_CONFIG_BASE_INITIALIZER, AUDIO_PORT_HANDLE_NONE,
stream, strategy, AUDIO_OUTPUT_FLAG_NONE, false,
stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false,
{} /* Sources do not support secondary outputs*/),
mPatchDesc(patchDesc), mSrcDevice(srcDevice)
{

@ -224,16 +224,16 @@ DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t ps) const
audio_devices_t devices = AUDIO_DEVICE_NONE;
if (ps == getProductStrategyForStream(AUDIO_STREAM_NOTIFICATION) &&
!is_state_in_call(getPhoneState()) &&
!outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
outputs.isStreamActive(AUDIO_STREAM_MUSIC,
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
!outputs.isActiveRemotely(streamToVolumeSource(AUDIO_STREAM_MUSIC),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) &&
outputs.isActive(streamToVolumeSource(AUDIO_STREAM_MUSIC),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
product_strategy_t strategyForMedia =
getProductStrategyForStream(AUDIO_STREAM_MUSIC);
devices = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
} else if (ps == getProductStrategyForStream(AUDIO_STREAM_ACCESSIBILITY) &&
(outputs.isStreamActive(AUDIO_STREAM_RING) ||
outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
(outputs.isActive(streamToVolumeSource(AUDIO_STREAM_RING)) ||
outputs.isActive(streamToVolumeSource(AUDIO_STREAM_ALARM)))) {
// do not route accessibility prompts to a digital output currently configured with a
// compressed format as they would likely not be mixed and dropped.
// Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.

@ -182,16 +182,17 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
break;
case STRATEGY_SONIFICATION_RESPECTFUL:
if (isInCall() || outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)) {
if (isInCall() || outputs.isActiveLocally(streamToVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
device = getDeviceForStrategyInt(
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
outputDeviceTypesToIgnore);
} else {
bool media_active_locally =
outputs.isStreamActiveLocally(
AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
|| outputs.isStreamActiveLocally(
AUDIO_STREAM_ACCESSIBILITY, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
outputs.isActiveLocally(streamToVolumeSource(AUDIO_STREAM_MUSIC),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
|| outputs.isActiveLocally(
streamToVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
// routing is same as media without the "remote" device
device = getDeviceForStrategyInt(STRATEGY_MEDIA,
availableOutputDevices,
@ -324,7 +325,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
case STRATEGY_SONIFICATION:
// If incall, just select the STRATEGY_PHONE device
if (isInCall() || outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)) {
if (isInCall() ||
outputs.isActiveLocally(streamToVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
device = getDeviceForStrategyInt(
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
outputDeviceTypesToIgnore);
@ -397,8 +399,8 @@ audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
}
availableOutputDevices =
availableOutputDevices.getDevicesFromTypeMask(availableOutputDevicesType);
if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
if (outputs.isActive(streamToVolumeSource(AUDIO_STREAM_RING)) ||
outputs.isActive(streamToVolumeSource(AUDIO_STREAM_ALARM))) {
return getDeviceForStrategyInt(
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
outputDeviceTypesToIgnore);

@ -1078,6 +1078,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
sanitizedRequestedPortId, *stream,
mEngine->getProductStrategyForAttributes(resultAttr),
streamToVolumeSource(*stream),
*flags, isRequestedDeviceForExclusiveUse,
std::move(weakSecondaryOutputDescs));
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
@ -1569,11 +1570,13 @@ status_t AudioPolicyManager::startSource(const sp<SwAudioOutputDescriptor>& outp
*delayMs = 0;
audio_stream_type_t stream = client->stream();
auto clientVolSrc = client->volumeSource();
auto clientStrategy = client->strategy();
auto clientAttr = client->attributes();
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
if (!mTtsOutputAvailable && mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
if (!mTtsOutputAvailable && mOutputs.isAnyOutputActive(
streamToVolumeSource(AUDIO_STREAM_TTS) /*sourceToIgnore*/)) {
return INVALID_OPERATION;
} else {
beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@ -1628,7 +1631,7 @@ status_t AudioPolicyManager::startSource(const sp<SwAudioOutputDescriptor>& outp
selectOutputForMusicEffects();
}
if (outputDesc->streamActiveCount(stream) == 1 || !devices.isEmpty()) {
if (outputDesc->getActivityCount(clientVolSrc) == 1 || !devices.isEmpty()) {
// starting an output being rerouted?
if (devices.isEmpty()) {
devices = getNewOutputDevices(outputDesc, false /*fromCache*/);
@ -1754,11 +1757,12 @@ status_t AudioPolicyManager::stopSource(const sp<SwAudioOutputDescriptor>& outpu
{
// always handle stream stop, check which stream type is stopping
audio_stream_type_t stream = client->stream();
auto clientVolSrc = client->volumeSource();
handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT);
if (outputDesc->streamActiveCount(stream) > 0) {
if (outputDesc->streamActiveCount(stream) == 1) {
if (outputDesc->getActivityCount(clientVolSrc) > 0) {
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
if (audio_is_remote_submix_device(outputDesc->devices().types()) &&
@ -1780,7 +1784,7 @@ status_t AudioPolicyManager::stopSource(const sp<SwAudioOutputDescriptor>& outpu
outputDesc->setClientActive(client, false);
// store time at which the stream was stopped - see isStreamActive()
if (outputDesc->streamActiveCount(stream) == 0 || forceDeviceUpdate) {
if (outputDesc->getActivityCount(clientVolSrc) == 0 || forceDeviceUpdate) {
outputDesc->setStopTime(client, systemTime());
DeviceVector newDevices = getNewOutputDevices(outputDesc, false /*fromCache*/);
// delay the device switch by twice the latency because stopOutput() is executed when
@ -2411,7 +2415,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
if (!(streamsMatchForvolume(stream, (audio_stream_type_t)curStream))) {
continue;
}
if (!(desc->isStreamActive((audio_stream_type_t)curStream) || isInCall())) {
if (!(desc->isActive(streamToVolumeSource((audio_stream_type_t)curStream)) || isInCall())) {
continue;
}
audio_devices_t curStreamDevice = Volume::getDeviceForVolume(
@ -2499,7 +2503,7 @@ audio_io_handle_t AudioPolicyManager::selectOutputForMusicEffects()
for (audio_io_handle_t output : outputs) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
if (activeOnly && !desc->isStreamActive(AUDIO_STREAM_MUSIC)) {
if (activeOnly && !desc->isActive(streamToVolumeSource(AUDIO_STREAM_MUSIC))) {
continue;
}
ALOGV("selectOutputForMusicEffects activeOnly %d output %d flags 0x%08x",
@ -2593,14 +2597,14 @@ bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inP
if (!streamsMatchForvolume(stream, (audio_stream_type_t)curStream)) {
continue;
}
active = mOutputs.isStreamActive((audio_stream_type_t)curStream, inPastMs);
active = mOutputs.isActive(streamToVolumeSource((audio_stream_type_t)curStream), inPastMs);
}
return active;
}
bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
{
return mOutputs.isStreamActiveRemotely(stream, inPastMs);
return mOutputs.isActiveRemotely(streamToVolumeSource((audio_stream_type_t)stream), inPastMs);
}
bool AudioPolicyManager::isSourceActive(audio_source_t source) const
@ -3630,10 +3634,11 @@ status_t AudioPolicyManager::startAudioSource(const struct audio_port_config *so
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));
sp<SourceClientDescriptor> sourceDesc = new SourceClientDescriptor(
*portId, uid, *attributes, patchDesc, srcDevice,
mEngine->getStreamTypeForAttributes(*attributes),
mEngine->getProductStrategyForAttributes(*attributes),
streamToVolumeSource(mEngine->getStreamTypeForAttributes(*attributes)));
status_t status = connectAudioSource(sourceDesc);
if (status == NO_ERROR) {
@ -4708,37 +4713,31 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
{
ALOGV("closeOutput(%d)", output);
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc == NULL) {
sp<SwAudioOutputDescriptor> closingOutput = mOutputs.valueFor(output);
if (closingOutput == NULL) {
ALOGW("closeOutput() unknown output %d", output);
return;
}
mPolicyMixes.closeOutput(outputDesc);
mPolicyMixes.closeOutput(closingOutput);
// look for duplicated outputs connected to the output being removed.
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i);
if (dupOutputDesc->isDuplicated() &&
(dupOutputDesc->mOutput1 == outputDesc ||
dupOutputDesc->mOutput2 == outputDesc)) {
sp<SwAudioOutputDescriptor> outputDesc2;
if (dupOutputDesc->mOutput1 == outputDesc) {
outputDesc2 = dupOutputDesc->mOutput2;
} else {
outputDesc2 = dupOutputDesc->mOutput1;
}
sp<SwAudioOutputDescriptor> dupOutput = mOutputs.valueAt(i);
if (dupOutput->isDuplicated() &&
(dupOutput->mOutput1 == closingOutput || dupOutput->mOutput2 == closingOutput)) {
sp<SwAudioOutputDescriptor> remainingOutput =
dupOutput->mOutput1 == closingOutput ? dupOutput->mOutput2 : dupOutput->mOutput1;
// As all active tracks on duplicated output will be deleted,
// and as they were also referenced on the other output, the reference
// count for their stream type must be adjusted accordingly on
// the other output.
const bool wasActive = outputDesc2->isActive();
for (const auto &clientPair : dupOutputDesc->getActiveClients()) {
outputDesc2->changeStreamActiveCount(clientPair.first, -clientPair.second);
}
const bool wasActive = remainingOutput->isActive();
// Note: no-op on the closing output where all clients has already been set inactive
dupOutput->setAllClientsInactive();
// stop() will be a no op if the output is still active but is needed in case all
// active streams refcounts where cleared above
if (wasActive) {
outputDesc2->stop();
remainingOutput->stop();
}
audio_io_handle_t duplicatedOutput = mOutputs.keyAt(i);
ALOGV("closeOutput() closing also duplicated output %d", duplicatedOutput);
@ -4750,7 +4749,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
nextAudioPortGeneration();
ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
ssize_t index = mAudioPatches.indexOfKey(closingOutput->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
(void) /*status_t status*/ mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@ -4758,7 +4757,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
mpClientInterface->onAudioPatchListUpdate();
}
outputDesc->close();
closingOutput->close();
removeOutput(output);
mPreviousOutputs = mOutputs;
@ -5109,7 +5108,7 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre
devices.merge(curDevices);
for (audio_io_handle_t output : getOutputsForDevices(curDevices, mOutputs)) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc->isStreamActive((audio_stream_type_t)curStream)) {
if (outputDesc->isActive(streamToVolumeSource((audio_stream_type_t)curStream))) {
activeDevices.merge(outputDesc->devices());
}
}
@ -5523,7 +5522,7 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
// in-call: always cap volume by voice volume + some low headroom
if ((stream != AUDIO_STREAM_VOICE_CALL) &&
(isInCall() || mOutputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL))) {
(isInCall() || mOutputs.isActiveLocally(streamToVolumeSource(AUDIO_STREAM_VOICE_CALL)))) {
switch (stream) {
case AUDIO_STREAM_SYSTEM:
case AUDIO_STREAM_RING:
@ -5641,9 +5640,8 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
bool force)
{
// do not change actual stream volume if the stream is muted
if (outputDesc->mMuteCount[stream] != 0) {
ALOGVV("checkAndSetVolume() stream %d muted count %d",
stream, outputDesc->mMuteCount[stream]);
if (outputDesc->isMuted(streamToVolumeSource(stream))) {
ALOGVV("%s() stream %d muted count %d", __func__, stream, outputDesc->getMuteCount(stream));
return NO_ERROR;
}
audio_policy_forced_cfg_t forceUseForComm =
@ -5730,10 +5728,10 @@ void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
}
ALOGVV("setStreamMute() stream %d, mute %d, mMuteCount %d device %04x",
stream, on, outputDesc->mMuteCount[stream], device);
stream, on, outputDesc->getMuteCount(stream), device);
if (on) {
if (outputDesc->mMuteCount[stream] == 0) {
if (!outputDesc->isMuted(streamToVolumeSource(stream))) {
if (mVolumeCurves->canBeMuted(stream) &&
((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) ||
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) {
@ -5741,13 +5739,13 @@ void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
}
}
// increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
outputDesc->mMuteCount[stream]++;
outputDesc->incMuteCount(streamToVolumeSource(stream));
} else {
if (outputDesc->mMuteCount[stream] == 0) {
if (!outputDesc->isMuted(streamToVolumeSource(stream))) {
ALOGV("setStreamMute() unmuting non muted stream!");
return;
}
if (--outputDesc->mMuteCount[stream] == 0) {
if (outputDesc->decMuteCount(streamToVolumeSource(stream)) == 0) {
checkAndSetVolume(stream,
mVolumeCurves->getVolumeIndex(stream, device),
outputDesc,

Loading…
Cancel
Save