APM: forward mute state in APM to AF
With ring_my_car we pass the mute state together with the actual index
to AudioFlinger
Flag: com.android.media.audio.ring_my_car
Test: dumpsys + logs
Bug: 319515324
Change-Id: I7b219f9c4917b58a84fd51c0431098a77896887a
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0d5d61f..fada5b0 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -629,6 +629,7 @@
bool isSpatialized;
bool isBitPerfect;
float volume;
+ bool muted;
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
&streamType, adjAttributionSource,
@@ -637,7 +638,8 @@
AUDIO_OUTPUT_FLAG_DIRECT),
deviceId, &portId, &secondaryOutputs, &isSpatialized,
&isBitPerfect,
- &volume);
+ &volume,
+ &muted);
if (ret != NO_ERROR) {
config->sample_rate = fullConfig.sample_rate;
config->channel_mask = fullConfig.channel_mask;
@@ -1097,6 +1099,7 @@
bool isSpatialized = false;
bool isBitPerfect = false;
float volume;
+ bool muted;
audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
std::vector<int> effectIds;
@@ -1157,7 +1160,7 @@
lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
adjAttributionSource, &input.config, input.flags,
&output.selectedDeviceId, &portId, &secondaryOutputs,
- &isSpatialized, &isBitPerfect, &volume);
+ &isSpatialized, &isBitPerfect, &volume, &muted);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
@@ -1214,7 +1217,7 @@
if (effectThread == nullptr) {
effectChain = getOrphanEffectChain_l(sessionId);
}
- ALOGV("createTrack() sessionId: %d volume: %f", sessionId, volume);
+ ALOGV("createTrack() sessionId: %d volume: %f muted %d", sessionId, volume, muted);
output.sampleRate = input.config.sample_rate;
output.frameCount = input.frameCount;
@@ -1229,7 +1232,7 @@
input.sharedBuffer, sessionId, &output.flags,
callingPid, adjAttributionSource, input.clientInfo.clientTid,
&lStatus, portId, input.audioTrackCallback, isSpatialized,
- isBitPerfect, &output.afTrackFlags, volume);
+ isBitPerfect, &output.afTrackFlags, volume, muted);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
@@ -1653,7 +1656,7 @@
}
status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output)
+ bool muted, audio_io_handle_t output)
{
// check calling permissions
if (!settingsAllowed()) {
@@ -1675,14 +1678,14 @@
if (volumeInterface == NULL) {
return BAD_VALUE;
}
- volumeInterface->setStreamVolume(stream, value);
+ volumeInterface->setStreamVolume(stream, value, muted);
return NO_ERROR;
}
status_t AudioFlinger::setPortsVolume(
- const std::vector<audio_port_handle_t>& ports, float volume, audio_io_handle_t output)
-{
+ const std::vector<audio_port_handle_t> &ports, float volume, bool muted,
+ audio_io_handle_t output) {
for (const auto& port : ports) {
if (port == AUDIO_PORT_HANDLE_NONE) {
return BAD_VALUE;
@@ -1697,12 +1700,12 @@
audio_utils::lock_guard lock(mutex());
IAfPlaybackThread *thread = checkPlaybackThread_l(output);
if (thread != nullptr) {
- return thread->setPortsVolume(ports, volume);
+ return thread->setPortsVolume(ports, volume, muted);
}
const sp<IAfMmapThread> mmapThread = checkMmapThread_l(output);
if (mmapThread != nullptr && mmapThread->isOutput()) {
IAfMmapPlaybackThread *mmapPlaybackThread = mmapThread->asIAfMmapPlaybackThread().get();
- return mmapPlaybackThread->setPortsVolume(ports, volume);
+ return mmapPlaybackThread->setPortsVolume(ports, volume, muted);
}
return BAD_VALUE;
}
@@ -4097,7 +4100,8 @@
0ns /* timeout */,
frameCountToBeReady,
track->getSpeed(),
- 1.f /* volume */);
+ 1.f /* volume */,
+ track->getPortMute() /* muted */);
status = patchTrack->initCheck();
if (status != NO_ERROR) {
ALOGE("Secondary output patchTrack init failed: %d", status);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ace74ee..7274b59 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -93,12 +93,12 @@
status_t getMasterBalance(float* balance) const final EXCLUDES_AudioFlinger_Mutex;
status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+ bool muted, audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
status_t setStreamMute(audio_stream_type_t stream, bool muted) final
EXCLUDES_AudioFlinger_Mutex;
status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
- audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+ bool muted, audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
status_t setMode(audio_mode_t mode) final EXCLUDES_AudioFlinger_Mutex;
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
index abb8f2f..a13819c 100644
--- a/services/audioflinger/IAfThread.h
+++ b/services/audioflinger/IAfThread.h
@@ -481,7 +481,8 @@
bool isSpatialized,
bool isBitPerfect,
audio_output_flags_t* afTrackFlags,
- float volume)
+ float volume,
+ bool muted)
REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
virtual status_t addTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
@@ -558,8 +559,8 @@
virtual void setTracksInternalMute(std::map<audio_port_handle_t, bool>* tracksInternalMute)
EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t> &portIds, float volume,
+ bool muted) EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfDirectOutputThread : public virtual IAfPlaybackThread {
@@ -700,8 +701,8 @@
virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ bool muted) EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfMmapCaptureThread : public virtual IAfMmapThread {
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
index 2049adc..1b10f81 100644
--- a/services/audioflinger/IAfTrack.h
+++ b/services/audioflinger/IAfTrack.h
@@ -291,14 +291,15 @@
float speed = 1.0f,
bool isSpatialized = false,
bool isBitPerfect = false,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
static constexpr std::string_view getLogHeader() {
using namespace std::literals;
return "Type Id Active Client(pid/uid) Session Port Id S Flags "
" Format Chn mask SRate "
"ST Usg CT "
- " G db L dB R dB VS dB PortVol dB "
+ " G db L dB R dB VS dB PortVol dB PortMuted"
" Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
" Latency\n"sv;
}
@@ -476,12 +477,13 @@
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
static constexpr std::string_view getLogHeader() {
using namespace std::literals;
return "Client(pid/uid) Session Port Id"
- " Format Chn mask SRate Flags Usg/Src PortVol dB\n"sv;
+ " Format Chn mask SRate Flags Usg/Src PortVol dB PortMuted\n"sv;
};
// protected by MMapThread::mLock
@@ -610,7 +612,8 @@
* the lowest possible latency
* even if it might glitch. */
float speed = 1.0f,
- float volume = 1.0f);
+ float volume = 1.0f,
+ bool muted = false);
};
class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 442dd80..30bbd5d 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -36,7 +36,8 @@
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
~MmapTrack() override;
status_t initCheck() const final;
@@ -71,7 +72,11 @@
void setPortVolume(float volume) override {
mVolume = volume;
}
+ void setPortMute(bool muted) override {
+ mMuteState.muteFromPortVolume = muted;
+ }
float getPortVolume() const override { return mVolume; }
+ bool getPortMute() const override { return mMuteState.muteFromPortVolume; }
private:
DISALLOW_COPY_AND_ASSIGN(MmapTrack);
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index d0b96de..be59299 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -650,7 +650,8 @@
{} /*timeout*/,
frameCountToBeReady,
1.0f /*speed*/,
- 1.0f /*volume*/);
+ 1.0f /*volume*/,
+ false /*muted*/);
status = mPlayback.checkTrack(tempPatchTrack.get());
if (status != NO_ERROR) {
return status;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 84758a4..70bab6a 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -97,7 +97,8 @@
float speed = 1.0f,
bool isSpatialized = false,
bool isBitPerfect = false,
- float volume = 0.0f);
+ float volume = 0.0f,
+ bool muted = false);
~Track() override;
status_t initCheck() const final;
void appendDumpHeader(String8& result) const final;
@@ -226,7 +227,9 @@
// VolumePortInterface implementation
void setPortVolume(float volume) override;
+ void setPortMute(bool muted) override;
float getPortVolume() const override { return mVolume; }
+ bool getPortMute() const override { return mMuteState.load().muteFromPortVolume; }
protected:
@@ -410,9 +413,9 @@
// TODO: replace PersistableBundle with own struct
// access these two variables only when holding player thread lock.
std::unique_ptr<os::PersistableBundle> mMuteEventExtras;
- mute_state_t mMuteState;
- bool mInternalMute = false;
- std::atomic<float> mVolume = 0.0f;
+ std::atomic<mute_state_t> mMuteState;
+ bool mInternalMute = false;
+ std::atomic<float> mVolume = 0.0f;
}; // end of Track
@@ -510,7 +513,8 @@
* the lowest possible latency
* even if it might glitch. */
float speed = 1.0f,
- float volume = 1.0f);
+ float volume = 1.0f,
+ bool muted = false);
~PatchTrack() override;
size_t framesReady() const final;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ae102fc..1c0b749 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2405,7 +2405,8 @@
bool isSpatialized,
bool isBitPerfect,
audio_output_flags_t *afTrackFlags,
- float volume)
+ float volume,
+ bool muted)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2734,7 +2735,7 @@
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
sessionId, creatorPid, attributionSource, trackFlags,
IAfTrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
- speed, isSpatialized, isBitPerfect, volume);
+ speed, isSpatialized, isBitPerfect, volume, muted);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
if (lStatus != NO_ERROR) {
@@ -2842,10 +2843,14 @@
}
}
-void PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value, bool muted)
{
+ ALOGV("%s: stream %d value %f muted %d", __func__, stream, value, muted);
audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].volume = value;
+ if (com_android_media_audio_ring_my_car()) {
+ mStreamTypes[stream].mute = muted;
+ }
broadcast_l();
}
@@ -2863,13 +2868,14 @@
}
status_t PlaybackThread::setPortsVolume(
- const std::vector<audio_port_handle_t>& portIds, float volume) {
+ const std::vector<audio_port_handle_t>& portIds, float volume, bool muted) {
audio_utils::lock_guard _l(mutex());
for (const auto& portId : portIds) {
for (size_t i = 0; i < mTracks.size(); i++) {
sp<IAfTrack> track = mTracks[i].get();
if (portId == track->portId()) {
track->setPortVolume(volume);
+ track->setPortMute(muted);
break;
}
}
@@ -5859,7 +5865,7 @@
volume = masterVolume * mStreamTypes[track->streamType()].volume;
}
} else {
- if (track->isPlaybackRestricted()) {
+ if (track->isPlaybackRestricted() || track->getPortMute()) {
volume = 0.f;
} else {
volume = masterVolume * track->getPortVolume();
@@ -5883,7 +5889,8 @@
mStreamTypes[track->streamType()].mute,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ /*muteFromPortVolume=*/false});
} else {
track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{masterVolume == 0.f,
@@ -5891,7 +5898,8 @@
/* muteFromStreamMuted= */ false,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ track->getPortMute()});
}
vlf *= volume;
vrf *= volume;
@@ -6055,7 +6063,7 @@
}
} else {
v = masterVolume * track->getPortVolume();
- if (track->isPlaybackRestricted()) {
+ if (track->isPlaybackRestricted() || track->getPortMute()) {
v = 0;
}
}
@@ -6085,7 +6093,8 @@
mStreamTypes[track->streamType()].mute,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ /*muteFromPortVolume=*/false});
} else {
track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{masterVolume == 0.f,
@@ -6093,7 +6102,8 @@
/* muteFromStreamMuted= */ false,
track->isPlaybackRestricted(),
vlf == 0.f && vrf == 0.f,
- vh == 0.f});
+ vh == 0.f,
+ track->getPortMute()});
}
// now apply the master volume and stream type volume and shaper volume
vlf *= v * vh;
@@ -6851,7 +6861,8 @@
mStreamTypes[track->streamType()].mute,
track->isPlaybackRestricted(),
clientVolumeMute,
- shaperVolume == 0.f});
+ shaperVolume == 0.f,
+ /*muteFromPortVolume=*/false});
} else {
if (mMasterMute || track->isPlaybackRestricted()) {
left = right = 0;
@@ -6879,7 +6890,8 @@
/* muteFromStreamMuted= */ false,
track->isPlaybackRestricted(),
clientVolumeMute,
- shaperVolume == 0.f});
+ shaperVolume == 0.f,
+ track->getPortMute()});
}
if (lastTrack) {
@@ -7981,8 +7993,9 @@
return;
}
if (!audioserver_flags::portid_volume_management()) {
- thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
+ thread->setStreamVolume(AUDIO_STREAM_PATCH, /*volume=*/1.0f, /*muted=*/false);
}
+
mOutputTracks.add(outputTrack);
ALOGV("addOutputTrack() track %p, on thread %p", outputTrack.get(), thread);
updateWaitTime_l();
@@ -10486,6 +10499,7 @@
const auto localSessionId = mSessionId;
auto localAttr = mAttr;
float volume = 0.0f;
+ bool muted = false;
if (isOutput()) {
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = mSampleRate;
@@ -10510,7 +10524,8 @@
&secondaryOutputs,
&isSpatialized,
&isBitPerfect,
- &volume);
+ &volume,
+ &muted);
mutex().lock();
mAttr = localAttr;
ALOGD_IF(!secondaryOutputs.empty(),
@@ -10580,7 +10595,7 @@
mChannelMask, mSessionId, isOutput(),
client.attributionSource,
IPCThreadState::self()->getCallingPid(), portId,
- volume);
+ volume, muted);
if (!isOutput()) {
track->setSilenced_l(isClientSilenced_l(portId));
}
@@ -11238,10 +11253,14 @@
}
}
-void MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value, bool muted)
{
+ ALOGV("%s: stream %d value %f muted %d", __func__, stream, value, muted);
audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].volume = value;
+ if (com_android_media_audio_ring_my_car()) {
+ mStreamTypes[stream].mute = muted;
+ }
if (stream == mStreamType) {
broadcast_l();
}
@@ -11263,12 +11282,13 @@
}
status_t MmapPlaybackThread::setPortsVolume(
- const std::vector<audio_port_handle_t>& portIds, float volume) {
+ const std::vector<audio_port_handle_t>& portIds, float volume, bool muted) {
audio_utils::lock_guard _l(mutex());
for (const auto& portId : portIds) {
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
if (portId == track->portId()) {
track->setPortVolume(volume);
+ track->setPortMute(muted);
break;
}
}
@@ -11326,7 +11346,11 @@
// will be broadcasted to all tracks. Thus, take arbitrarily first track volume.
size_t numtracks = mActiveTracks.size();
if (numtracks) {
- volume = mMasterVolume * mActiveTracks[0]->getPortVolume();
+ if (mActiveTracks[0]->getPortMute()) {
+ volume = 0;
+ } else {
+ volume = mMasterVolume * mActiveTracks[0]->getPortVolume();
+ }
}
}
}
@@ -11370,7 +11394,8 @@
// TODO(b/241533526): adjust logic to include mute from AppOps
false /*muteFromPlaybackRestricted*/,
false /*muteFromClientVolume*/,
- false /*muteFromVolumeShaper*/});
+ false /*muteFromVolumeShaper*/,
+ false /*muteFromPortVolume*/});
} else {
track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
/*muteState=*/{mMasterMute,
@@ -11379,7 +11404,8 @@
// TODO(b/241533526): adjust logic to include mute from AppOps
false /*muteFromPlaybackRestricted*/,
false /*muteFromClientVolume*/,
- false /*muteFromVolumeShaper*/});
+ false /*muteFromVolumeShaper*/,
+ track->getPortMute()});
}
}
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index a13340d..0c5a2c3 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1020,11 +1020,12 @@
void setMasterVolume(float value) final;
void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex;
void setMasterMute(bool muted) final;
- void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamVolume(audio_stream_type_t stream, float value, bool muted) final
+ EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
- status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ bool muted) final EXCLUDES_ThreadBase_Mutex;
void setVolumeForOutput_l(float left, float right) const final;
@@ -1051,7 +1052,8 @@
bool isSpatialized,
bool isBitPerfect,
audio_output_flags_t* afTrackFlags,
- float volume) final
+ float volume,
+ bool muted) final
REQUIRES(audio_utils::AudioFlinger_Mutex);
bool isTrackActive(const sp<IAfTrack>& track) const final {
@@ -2405,11 +2407,13 @@
// Needs implementation?
void setMasterBalance(float /* value */) final EXCLUDES_ThreadBase_Mutex {}
void setMasterMute(bool muted) final EXCLUDES_ThreadBase_Mutex;
- void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+
+ void setStreamVolume(audio_stream_type_t stream, float value, bool muted) final
+ EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
- status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
- final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ bool muted) final EXCLUDES_ThreadBase_Mutex;
void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b08b0b7..980ef22 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -728,7 +728,8 @@
float speed,
bool isSpatialized,
bool isBitPerfect,
- float volume) {
+ float volume,
+ bool muted) {
return sp<Track>::make(thread,
client,
streamType,
@@ -750,7 +751,8 @@
speed,
isSpatialized,
isBitPerfect,
- volume);
+ volume,
+ muted);
}
// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
@@ -776,7 +778,8 @@
float speed,
bool isSpatialized,
bool isBitPerfect,
- float volume)
+ float volume,
+ bool muted)
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -860,11 +863,13 @@
}
populateUsageAndContentTypeFromStreamType();
+ setPortMute(muted);
// Audio patch and call assistant volume are always max
if (mAttr.usage == AUDIO_USAGE_CALL_ASSISTANT
|| mAttr.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
mVolume = 1.0f;
+ setPortMute(false);
}
mServerLatencySupported = checkServerLatencySupported(format, flags);
@@ -1084,7 +1089,7 @@
result.appendFormat("%7s %7u/%7u %7u %7u %2s 0x%03X "
"%08X %08X %6u "
"%2u %3x %2x "
- "%5.2g %5.2g %5.2g %5.2g%c %11.2g "
+ "%5.2g %5.2g %5.2g %5.2g%c %11.2g %12s"
"%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
active ? "yes" : "no",
mClient ? mClient->pid() : getpid() ,
@@ -1108,6 +1113,7 @@
20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
20.0 * log10(mVolume),
+ getPortMute() ? "true" : "false",
mCblk->mServer,
bufferSizeInFrames,
@@ -1614,8 +1620,25 @@
if (mType != TYPE_PATCH) {
// Do not recursively propagate a PatchTrack setPortVolume to
// downstream PatchTracks.
- forEachTeePatchTrack_l([volume](const auto& patchTrack) {
- patchTrack->setPortVolume(volume); });
+ forEachTeePatchTrack_l([volume](const auto &patchTrack) {
+ patchTrack->setPortVolume(volume);
+ });
+ }
+}
+
+void Track::setPortMute(bool muted) {
+ mute_state_t newMuteState = mMuteState.load();
+ if (newMuteState.muteFromPortVolume == muted) {
+ return;
+ }
+ newMuteState.muteFromPortVolume = muted;
+ mMuteState.store(newMuteState);
+ if (mType != TYPE_PATCH) {
+ // Do not recursively propagate a PatchTrack setPortVolume to
+ // downstream PatchTracks.
+ forEachTeePatchTrack_l([muted](const auto &patchTrack) {
+ patchTrack->setPortMute(muted);
+ });
}
}
@@ -1720,8 +1743,8 @@
}
if (result == OK) {
- ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
- static_cast<int>(mMuteState), static_cast<int>(muteState));
+ ALOGI("%s(%d): processed mute state for port ID %d from %#x to %#x", __func__, id(),
+ mPortId, static_cast<int>(mMuteState.load()), static_cast<int>(muteState));
mMuteState = muteState;
} else {
ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
@@ -2498,7 +2521,8 @@
* the lowest possible latency
* even if it might glitch. */
float speed,
- float volume)
+ float volume,
+ bool muted)
{
return sp<PatchTrack>::make(
playbackThread,
@@ -2513,7 +2537,8 @@
timeout,
frameCountToBeReady,
speed,
- volume);
+ volume,
+ muted);
}
PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
@@ -2528,14 +2553,15 @@
const Timeout& timeout,
size_t frameCountToBeReady,
float speed,
- float volume)
+ float volume,
+ bool muted)
: Track(playbackThread, NULL, streamType,
AUDIO_ATTRIBUTES_INITIALIZER,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed,
- false /*isSpatialized*/, false /*isBitPerfect*/, volume),
+ false /*isSpatialized*/, false /*isBitPerfect*/, volume, muted),
PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
true /*clientInServer*/) : nullptr,
playbackThread, timeout)
@@ -3519,7 +3545,8 @@
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId,
- float volume)
+ float volume,
+ bool muted)
{
return sp<MmapTrack>::make(
thread,
@@ -3532,7 +3559,8 @@
attributionSource,
creatorPid,
portId,
- volume);
+ volume,
+ muted);
}
MmapTrack::MmapTrack(IAfThreadBase* thread,
@@ -3545,7 +3573,8 @@
const AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId,
- float volume)
+ float volume,
+ bool muted)
: TrackBase(thread, NULL, attr, sampleRate, format,
channelMask, (size_t)0 /* frameCount */,
nullptr /* buffer */, (size_t)0 /* bufferSize */,
@@ -3559,12 +3588,14 @@
mUid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid))),
mSilenced(false), mSilencedNotified(false), mVolume(volume)
{
+ mMuteState.muteFromPortVolume = muted;
// Once this item is logged by the server, the client can add properties.
mTrackMetrics.logConstructor(creatorPid, uid(), id());
if (isOut && (attr.usage == AUDIO_USAGE_CALL_ASSISTANT
|| attr.usage == AUDIO_USAGE_VIRTUAL_SOURCE)) {
// Audio patch and call assistant volume are always max
mVolume = 1.0f;
+ mMuteState.muteFromPortVolume = false;
}
}
@@ -3662,6 +3693,7 @@
if (isOut()) {
result.appendFormat("%4x %2x", mAttr.usage, mAttr.content_type);
result.appendFormat("%11.2g", 20.0 * log10(mVolume));
+ result.appendFormat("%12s", mMuteState.muteFromPortVolume ? "true" : "false");
} else {
result.appendFormat("%7x", mAttr.source);
}
diff --git a/services/audioflinger/datapath/VolumeInterface.h b/services/audioflinger/datapath/VolumeInterface.h
index 1564fe1..02b6ade 100644
--- a/services/audioflinger/datapath/VolumeInterface.h
+++ b/services/audioflinger/datapath/VolumeInterface.h
@@ -25,7 +25,7 @@
virtual void setMasterVolume(float value) = 0;
virtual void setMasterBalance(float balance) = 0;
virtual void setMasterMute(bool muted) = 0;
- virtual void setStreamVolume(audio_stream_type_t stream, float value) = 0;
+ virtual void setStreamVolume(audio_stream_type_t stream, float value, bool muted) = 0;
virtual void setStreamMute(audio_stream_type_t stream, bool muted) = 0;
// TODO(b/290699744) add "get" prefix for getter below.
virtual float streamVolume(audio_stream_type_t stream) const = 0;
diff --git a/services/audioflinger/datapath/VolumePortInterface.h b/services/audioflinger/datapath/VolumePortInterface.h
index fb1c463..fe3b782 100644
--- a/services/audioflinger/datapath/VolumePortInterface.h
+++ b/services/audioflinger/datapath/VolumePortInterface.h
@@ -23,7 +23,10 @@
class VolumePortInterface : public virtual RefBase {
public:
virtual void setPortVolume(float volume) = 0;
+ virtual void setPortMute(bool mute) = 0;
virtual float getPortVolume() const = 0;
+ /** Returns the muted state defined by the volume group which is playing on this port. */
+ virtual bool getPortMute() const = 0;
};
} // namespace android