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/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index edcb805..3539f00 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -148,7 +148,8 @@
                                       output_type_t *outputType,
                                       bool *isSpatialized,
                                       bool *isBitPerfect,
-                                      float *volume) = 0;
+                                      float *volume,
+                                      bool *muted) = 0;
     // indicates to the audio policy manager that the output starts being used by corresponding
     // stream.
     virtual status_t startOutput(audio_port_handle_t portId) = 0;
@@ -197,6 +198,7 @@
     // setting volume for all devices
     virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
                                           int index,
+                                          bool muted,
                                           audio_devices_t device) = 0;
 
     // retrieve current volume index for the specified stream and the
@@ -208,6 +210,7 @@
 
     virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
                                                  int index,
+                                                 bool muted,
                                                  audio_devices_t device) = 0;
     virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
                                                  int &index,
@@ -514,7 +517,7 @@
     // set a stream volume for a particular output. For the same user setting, a given stream type
     // can have different volumes
     // for each output (destination device) it is attached to.
-    virtual status_t setStreamVolume(audio_stream_type_t stream, float volume,
+    virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, bool muted,
                                      audio_io_handle_t output, int delayMs = 0) = 0;
     /**
      * Set volume for given AudioTrack port ids for a particular output.
@@ -522,12 +525,13 @@
      * can have different volumes for each output (destination device) it is attached to.
      * @param ports to consider
      * @param volume to apply
+     * @param muted to apply
      * @param output to consider
      * @param delayMs to use
      * @return NO_ERROR if successful
      */
     virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& ports, float volume,
-            audio_io_handle_t output, int delayMs = 0) = 0;
+            bool muted, audio_io_handle_t output, int delayMs = 0) = 0;
 
     // function enabling to send proprietary informations directly from audio policy manager to
     // audio hardware interface.
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 4dedcd6..0e1d090 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -39,6 +39,7 @@
         "android.media.audiopolicy-aconfig-cc",
         "audioclient-types-aidl-cpp",
         "audiopolicy-types-aidl-cpp",
+        "com.android.media.audio-aconfig-cc",
         "com.android.media.audioserver-aconfig-cc",
         "libaconfig_storage_read_api_cc",
         "libaudioclient_aidl_conversion",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 835fad2..9bceee7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -89,7 +89,9 @@
 class VolumeActivity : public ActivityTracking
 {
 public:
-    bool isMuted() const { return mMuteCount > 0; }
+    bool isMutedInternally() const { return mMuteCount > 0; }
+    bool isMutedByGroup() const { return mMutedByGroup > 0; }
+    void setMutedByGroup(bool mutedByGroup) { mMutedByGroup = mutedByGroup; }
     int getMuteCount() const { return mMuteCount; }
     int incMuteCount() { return ++mMuteCount; }
     int decMuteCount() { return mMuteCount > 0 ? --mMuteCount : -1; }
@@ -107,6 +109,7 @@
 
 private:
     int mMuteCount = 0; /**< mute request counter */
+    bool mMutedByGroup = false; /**< mute from AudioService, does not add to counter */
     float mCurVolumeDb = NAN; /**< current volume in dB. */
     bool mIsVoice = false; /** true if this volume source is used for voice call volume */
 };
@@ -209,16 +212,25 @@
         return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
                     mVolumeActivities.at(vs).getActivityCount() : 0;
     }
-    bool isMuted(VolumeSource vs) const
+    bool isMutedInternally(VolumeSource vs) const
     {
         return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
-                    mVolumeActivities.at(vs).isMuted() : false;
+                    mVolumeActivities.at(vs).isMutedInternally() : false;
     }
     int getMuteCount(VolumeSource vs) const
     {
         return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
                     mVolumeActivities.at(vs).getMuteCount() : 0;
     }
+    bool isMutedByGroup(VolumeSource vs)
+    {
+        return mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
+               mVolumeActivities.at(vs).isMutedByGroup() : false;
+    }
+    bool hasVolumeSource(VolumeSource vs)
+    {
+        return mVolumeActivities.find(vs) != std::end(mVolumeActivities);
+    }
     int incMuteCount(VolumeSource vs)
     {
         return mVolumeActivities[vs].incMuteCount();
@@ -227,10 +239,11 @@
     {
         return mVolumeActivities[vs].decMuteCount();
     }
-    void setCurVolume(VolumeSource vs, float volumeDb, bool isVoiceVolSrc)
+    void setCurVolume(VolumeSource vs, float volumeDb, bool mutedByGroup, bool isVoiceVolSrc)
     {
         // Even if not activity for this source registered, need to create anyway
         mVolumeActivities[vs].setVolume(volumeDb);
+        mVolumeActivities[vs].setMutedByGroup(mutedByGroup);
         mVolumeActivities[vs].setIsVoice(isVoiceVolSrc);
     }
     float getCurVolume(VolumeSource vs) const
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
index fd8b81a..ebfc597 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
@@ -41,6 +41,8 @@
     virtual status_t initVolume(int indexMin, int indexMax) = 0;
     virtual std::vector<audio_attributes_t> getAttributes() const = 0;
     virtual std::vector<audio_stream_type_t> getStreamTypes() const = 0;
+    virtual void setIsMuted(bool isMuted) = 0;
+    virtual bool isMuted() const = 0;
     virtual void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const = 0;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 2c41de4..c417462 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -22,6 +22,7 @@
 #include <AudioPolicyInterface.h>
 #include "AudioOutputDescriptor.h"
 #include "AudioPolicyMix.h"
+#include <com_android_media_audio.h>
 #include "IOProfile.h"
 #include "Volume.h"
 #include "HwModule.h"
@@ -161,7 +162,7 @@
     return false;
 }
 
-bool AudioOutputDescriptor::setVolume(float volumeDb, bool /*muted*/,
+bool AudioOutputDescriptor::setVolume(float volumeDb, bool mutedByGroup,
                                       VolumeSource volumeSource,
                                       const StreamTypeVector &/*streams*/,
                                       const DeviceTypeSet& deviceTypes,
@@ -169,7 +170,6 @@
                                       bool force,
                                       bool isVoiceVolSrc)
 {
-
     if (!supportedDevices().containsDeviceAmongTypes(deviceTypes)) {
         ALOGV("%s output ID %d unsupported device %s",
                 __func__, getId(), toString(deviceTypes).c_str());
@@ -177,10 +177,14 @@
     }
     // We actually change the volume if:
     // - the float value returned by computeVolume() changed
+    // - the muted state changed
     // - the force flag is set
-    if (volumeDb != getCurVolume(volumeSource) || force) {
-        ALOGV("%s for volumeSrc %d, volume %f, delay %d", __func__, volumeSource, volumeDb, delayMs);
-        setCurVolume(volumeSource, volumeDb, isVoiceVolSrc);
+    const bool mutedChanged =
+            com_android_media_audio_ring_my_car() && (isMutedByGroup(volumeSource) != mutedByGroup);
+    if (volumeDb != getCurVolume(volumeSource) || mutedChanged  || force) {
+        ALOGV("%s for volumeSrc %d, volume %f, mutedByGroup %d,  delay %d", __func__, volumeSource,
+              volumeDb, mutedByGroup, delayMs);
+        setCurVolume(volumeSource, volumeDb, mutedByGroup, isVoiceVolSrc);
         return true;
     }
     return false;
@@ -497,7 +501,7 @@
 }
 
 void SwAudioOutputDescriptor::setSwMute(
-        bool muted, VolumeSource vs, const StreamTypeVector &streamTypes,
+        bool mutedByGroup, VolumeSource vs, const StreamTypeVector &streamTypes,
         const DeviceTypeSet& deviceTypes, uint32_t delayMs) {
     // volume source active and more than one volume source is active, otherwise, no-op or let
     // setVolume controlling SW and/or HW Gains
@@ -506,11 +510,11 @@
             for (const auto& devicePort : devices()) {
                 if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
                     devicePort->hasGainController(true /*canUseForVolume*/)) {
-                    float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
                     ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
-                          mIoHandle, vs, muted, getActiveVolumeSources().size());
+                          mIoHandle, vs, mutedByGroup, getActiveVolumeSources().size());
                     for (const auto &stream : streamTypes) {
-                        mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+                        mClientInterface->setStreamVolume(stream, Volume::DbToAmpl(0), mutedByGroup,
+                                                          mIoHandle, delayMs);
                     }
                     return;
                 }
@@ -521,11 +525,12 @@
             for (const auto &devicePort: devices()) {
                 if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
                     devicePort->hasGainController(true /*canUseForVolume*/)) {
-                    float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
+                    float volumeAmpl = Volume::DbToAmpl(0);
                     ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
-                          mIoHandle, vs, muted, getActiveVolumeSources().size());
+                          mIoHandle, vs, mutedByGroup, getActiveVolumeSources().size());
                     mClientInterface->setPortsVolume(
-                            getPortsForVolumeSource(vs), volumeAmpl, mIoHandle, delayMs);
+                            getPortsForVolumeSource(vs), Volume::DbToAmpl(0), mutedByGroup,
+                            mIoHandle, delayMs);
                     return;
                 }
             }
@@ -533,7 +538,7 @@
     }
 }
 
-bool SwAudioOutputDescriptor::setVolume(float volumeDb, bool muted,
+bool SwAudioOutputDescriptor::setVolume(float volumeDb, bool mutedByGroup,
                                         VolumeSource vs, const StreamTypeVector &streamTypes,
                                         const DeviceTypeSet& deviceTypes,
                                         uint32_t delayMs,
@@ -542,18 +547,22 @@
 {
     StreamTypeVector streams = streamTypes;
     if (!AudioOutputDescriptor::setVolume(
-            volumeDb, muted, vs, streamTypes, deviceTypes, delayMs, force, isVoiceVolSrc)) {
+            volumeDb, mutedByGroup, vs, streamTypes, deviceTypes, delayMs, force, isVoiceVolSrc)) {
         if (hasStream(streamTypes, AUDIO_STREAM_BLUETOOTH_SCO)) {
             VolumeSource callVolSrc = getVoiceSource();
-            if (callVolSrc != VOLUME_SOURCE_NONE && volumeDb != getCurVolume(callVolSrc)) {
-                setCurVolume(callVolSrc, volumeDb, true);
+            const bool mutedChanged =
+                    com_android_media_audio_ring_my_car() && hasVolumeSource(callVolSrc) &&
+                    (isMutedByGroup(callVolSrc) != mutedByGroup);
+            if (callVolSrc != VOLUME_SOURCE_NONE &&
+                (volumeDb != getCurVolume(callVolSrc) || mutedChanged)) {
+                setCurVolume(callVolSrc, volumeDb, mutedByGroup, true);
                 float volumeAmpl = Volume::DbToAmpl(volumeDb);
                 if (audioserver_flags::portid_volume_management()) {
                     mClientInterface->setPortsVolume(getPortsForVolumeSource(callVolSrc),
-                            volumeAmpl, mIoHandle, delayMs);
+                            volumeAmpl, mutedByGroup, mIoHandle, delayMs);
                 } else {
                     mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL,
-                            volumeAmpl, mIoHandle, delayMs);
+                            volumeAmpl, mutedByGroup, mIoHandle, delayMs);
                 }
             }
         }
@@ -580,18 +589,19 @@
                 // Allows to mute SW Gain on AudioFlinger only for volume group with explicit
                 // stream(s)
                 if (!streamTypes.empty() || (getActiveVolumeSources().size() == 1)) {
-                    const bool canMute = muted && (volumeDb != 0.0f) && !streamTypes.empty();
-                    float volumeAmpl = canMute ? 0.0f : Volume::DbToAmpl(0);
+                    const bool canMute = mutedByGroup && !streamTypes.empty();
+                    const float volumeAmpl = Volume::DbToAmpl(0);
                     for (const auto &stream: streams) {
-                        mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+                        mClientInterface->setStreamVolume(stream, volumeAmpl, canMute, mIoHandle,
+                                                          delayMs);
                     }
                 }
             } else {
-                float volumeAmpl = (muted && volumeDb != 0.0f) ? 0.0f : Volume::DbToAmpl(0);
+                float volumeAmpl = Volume::DbToAmpl(0);
                 ALOGV("%s: output: %d, vs: %d, active vs count: %zu", __func__,
                       mIoHandle, vs, getActiveVolumeSources().size());
                 mClientInterface->setPortsVolume(
-                        getPortsForVolumeSource(vs), volumeAmpl, mIoHandle, delayMs);
+                        getPortsForVolumeSource(vs), volumeAmpl, mutedByGroup, mIoHandle, delayMs);
             }
             AudioGains gains = devicePort->getGains();
             int gainMinValueInMb = gains[0]->getMinValueInMb();
@@ -615,26 +625,27 @@
         if (audioserver_flags::portid_volume_management()) {
             if (callVolSrc != VOLUME_SOURCE_NONE) {
                 mClientInterface->setPortsVolume(getPortsForVolumeSource(callVolSrc), volumeAmpl,
-                        mIoHandle, delayMs);
+                                                 mutedByGroup, mIoHandle, delayMs);
             }
         } else {
-            mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle,
-                    delayMs);
+            mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mutedByGroup,
+                                              mIoHandle, delayMs);
         }
         if (callVolSrc != VOLUME_SOURCE_NONE) {
-            setCurVolume(callVolSrc, getCurVolume(vs), true);
+            setCurVolume(callVolSrc, getCurVolume(vs), mutedByGroup, true);
         }
     }
     if (audioserver_flags::portid_volume_management()) {
-        ALOGV("%s output %d for volumeSource %d, volume %f, delay %d active=%d", __func__,
-              mIoHandle, vs, volumeDb, delayMs, isActive(vs));
-        mClientInterface->setPortsVolume(getPortsForVolumeSource(vs), volumeAmpl, mIoHandle,
-                                         delayMs);
+        ALOGV("%s output %d for volumeSource %d, volume %f, mutedByGroup %d, delay %d active=%d",
+              __func__, mIoHandle, vs, volumeDb, mutedByGroup, delayMs, isActive(vs));
+        mClientInterface->setPortsVolume(getPortsForVolumeSource(vs), volumeAmpl, mutedByGroup,
+                                         mIoHandle, delayMs);
     } else {
         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);
+            ALOGV("%s output %d for volumeSource %d, volume %f, mutedByGroup %d delay %d stream=%s",
+                  __func__, mIoHandle, vs, volumeDb, mutedByGroup, delayMs,
+                  toString(stream).c_str());
+            mClientInterface->setStreamVolume(stream, volumeAmpl, mutedByGroup, mIoHandle, delayMs);
         }
     }
     return true;
diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h
index 2e75ff1..e5f7a41 100644
--- a/services/audiopolicy/engine/common/include/VolumeCurve.h
+++ b/services/audiopolicy/engine/common/include/VolumeCurve.h
@@ -179,6 +179,12 @@
     }
     StreamTypeVector getStreamTypes() const override { return mStreams; }
 
+    void setIsMuted(bool isMuted)
+    {
+        mIsMuted = isMuted;
+    }
+    bool isMuted() const { return mIsMuted; }
+
     void dump(String8 *dst, int spaces = 0, bool curvePoints = false) const override;
 
 private:
@@ -187,6 +193,7 @@
     int mIndexMin; /**< min volume index. */
     int mIndexMax; /**< max volume index. */
     const bool mCanBeMuted = true; /**< true is the stream can be muted. */
+    bool mIsMuted = false; /**< true if the stream is currently muted. */
 
     AttributesVector mAttributes;
     StreamTypeVector mStreams; /**< Keep it for legacy. */
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index c9a77a4..27a290f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -45,4 +45,7 @@
         "libparameter",
         "libutils",
     ],
+    defaults: [
+        "aconfig_lib_cc_shared_link.defaults",
+    ],
 }
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index fd40c04..a5f37b0 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -266,6 +266,7 @@
     bool isSpatialized;
     bool isBitPerfect;
     float volume;
+    bool muted;
 
     // TODO b/182392769: use attribution source util
     AttributionSourceState attributionSource;
@@ -273,7 +274,7 @@
     attributionSource.token = sp<BBinder>::make();
     if (mManager->getOutputForAttr(&attr, output, AUDIO_SESSION_NONE, &stream, attributionSource,
             &config, &flags, selectedDeviceId, portId, {}, &outputType, &isSpatialized,
-            &isBitPerfect, &volume) != OK) {
+            &isBitPerfect, &volume, &muted) != OK) {
         return false;
     }
     if (*output == AUDIO_IO_HANDLE_NONE || *portId == AUDIO_PORT_HANDLE_NONE) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c1c4a28..3633732 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1512,7 +1512,8 @@
                                               output_type_t *outputType,
                                               bool *isSpatialized,
                                               bool *isBitPerfect,
-                                              float *volume)
+                                              float *volume,
+                                              bool *muted)
 {
     // The supplied portId must be AUDIO_PORT_HANDLE_NONE
     if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -1569,6 +1570,7 @@
     outputDesc->addClient(clientDesc);
 
     *volume = Volume::DbToAmpl(outputDesc->getCurVolume(toVolumeSource(resultAttr)));
+    *muted = outputDesc->isMutedByGroup(toVolumeSource(resultAttr));
 
     ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
           *output, requestedPortId, *selectedDeviceId, *portId);
@@ -2617,8 +2619,7 @@
         auto &curves = getVolumeCurves(client->attributes());
         if (NO_ERROR != checkAndSetVolume(curves, client->volumeSource(),
                           curves.getVolumeIndex(outputDesc->devices().types()),
-                          outputDesc,
-                          outputDesc->devices().types(), 0 /*delay*/,
+                          outputDesc, outputDesc->devices().types(), 0 /*delay*/,
                           outputDesc->useHwGain() /*force*/)) {
             // request AudioService to reinitialize the volume curves asynchronously
             ALOGE("checkAndSetVolume failed, requesting volume range init");
@@ -3591,6 +3592,7 @@
 
 status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
                                                   int index,
+                                                  bool muted,
                                                   audio_devices_t device)
 {
     auto attributes = mEngine->getAttributesForStreamType(stream);
@@ -3600,7 +3602,7 @@
     }
     ALOGV("%s: stream %s attributes=%s, index %d , device 0x%X", __func__,
           toString(stream).c_str(), toString(attributes).c_str(), index, device);
-    return setVolumeIndexForAttributes(attributes, index, device);
+    return setVolumeIndexForAttributes(attributes, index, muted, device);
 }
 
 status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,
@@ -3619,6 +3621,7 @@
 
 status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
                                                          int index,
+                                                         bool muted,
                                                          audio_devices_t device)
 {
     // Get Volume group matching the Audio Attributes
@@ -3638,7 +3641,8 @@
             toVolumeSource(AUDIO_STREAM_VOICE_CALL, false) : vs;
     product_strategy_t strategy = mEngine->getProductStrategyForAttributes(attributes);
 
-    status = setVolumeCurveIndex(index, device, curves);
+
+    status = setVolumeCurveIndex(index, muted, device, curves);
     if (status != NO_ERROR) {
         ALOGE("%s failed to set curve index for group %d device 0x%X", __func__, group, device);
         return status;
@@ -3700,8 +3704,9 @@
         // HW Gain management, do not change the volume
         if (desc->useHwGain()) {
             applyVolume = false;
+            bool swMute = com_android_media_audio_ring_my_car() ? curves.isMuted() : (index == 0);
             // If the volume source is active with higher priority source, ensure at least Sw Muted
-            desc->setSwMute((index == 0), vs, curves.getStreamTypes(), curDevices, 0 /*delayMs*/);
+            desc->setSwMute(swMute, vs, curves.getStreamTypes(), curDevices, 0 /*delayMs*/);
             for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
                 auto activeClients = desc->clientsList(true /*activeOnly*/, productStrategy,
                                                        false /*preferredDevice*/);
@@ -3739,8 +3744,7 @@
         //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(
-                    curves, vs, index, desc, curDevices,
+        status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevices,
                     ((vs == toVolumeSource(AUDIO_STREAM_SYSTEM, false))?
                          TOUCH_SOUND_FIXED_DELAY_MS : 0));
         if (volStatus != NO_ERROR) {
@@ -3769,6 +3773,7 @@
 }
 
 status_t AudioPolicyManager::setVolumeCurveIndex(int index,
+                                                 bool muted,
                                                  audio_devices_t device,
                                                  IVolumeCurves &volumeCurves)
 {
@@ -3788,8 +3793,9 @@
     // Force max volume if stream cannot be muted
     if (!volumeCurves.canBeMuted()) index = volumeCurves.getVolumeIndexMax();
 
-    ALOGV("%s device %08x, index %d", __FUNCTION__ , device, index);
+    ALOGV("%s device %08x, index %d, muted %d", __FUNCTION__ , device, index, muted);
     volumeCurves.addCurrentVolumeIndex(device, index);
+    volumeCurves.setIsMuted(muted);
     return NO_ERROR;
 }
 
@@ -7898,7 +7904,8 @@
         }
         for (size_t i = 0; i < mOutputs.size(); i++) {
             sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-            setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, DeviceTypeSet());
+            setVolumeSourceMutedInternally(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/,
+                                           DeviceTypeSet());
             const uint32_t latency = desc->latency() * 2;
             if (desc->isActive(latency * 2) && latency > maxLatency) {
                 maxLatency = latency;
@@ -7992,9 +7999,10 @@
         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());
+            setVolumeSourceMutedInternally(activeVs, true, outputDesc, delayMs);
+            setVolumeSourceMutedInternally(activeVs, false, outputDesc,
+                                           delayMs + tempMuteDurationMs,
+                                           devices.types());
         }
     }
 
@@ -8507,7 +8515,7 @@
     static std::set<IVolumeCurves*> invalidCurvesReported;
 
     // do not change actual attributes volume if the attributes is muted
-    if (outputDesc->isMuted(volumeSource)) {
+    if (!com_android_media_audio_ring_my_car() && outputDesc->isMutedInternally(volumeSource)) {
         ALOGVV("%s: volume source %d muted count %d active=%d", __func__, volumeSource,
                outputDesc->getMuteCount(volumeSource), outputDesc->isActive(volumeSource));
         return NO_ERROR;
@@ -8549,7 +8557,13 @@
                     || isSingleDeviceType(deviceTypes, audio_is_ble_out_device)))) {
         volumeDb = 0.0f;
     }
-    const bool muted = (index == 0) && (volumeDb != 0.0f);
+
+    bool muted;
+    if (!com_android_media_audio_ring_my_car()) {
+        muted = (index == 0) && (volumeDb != 0.0f);
+    } else {
+        muted = curves.isMuted();
+    }
     outputDesc->setVolume(volumeDb, muted, volumeSource, curves.getStreamTypes(),
             deviceTypes, delayMs, force, isVoiceVolSrc);
 
@@ -8564,6 +8578,11 @@
 void AudioPolicyManager::setVoiceVolume(
         int index, IVolumeCurves &curves, bool voiceVolumeManagedByHost, int delayMs) {
     float voiceVolume;
+
+    if (com_android_media_audio_ring_my_car() && curves.isMuted()) {
+        index = 0;
+    }
+
     // Force voice volume to max or mute for Bluetooth SCO/BLE as other attenuations are managed
     // by the headset
     if (voiceVolumeManagedByHost) {
@@ -8617,8 +8636,7 @@
     ALOGVV("applyStreamVolumes() for device %s", dumpDeviceTypes(deviceTypes).c_str());
     for (const auto &volumeGroup : mEngine->getVolumeGroups()) {
         auto &curves = getVolumeCurves(toVolumeSource(volumeGroup));
-        checkAndSetVolume(curves, toVolumeSource(volumeGroup),
-                          curves.getVolumeIndex(deviceTypes),
+        checkAndSetVolume(curves, toVolumeSource(volumeGroup), curves.getVolumeIndex(deviceTypes),
                           outputDesc, deviceTypes, delayMs, force);
     }
 }
@@ -8641,23 +8659,23 @@
         }
     }
     for (auto source : sourcesToMute) {
-        setVolumeSourceMute(source, on, outputDesc, delayMs, deviceTypes);
+        setVolumeSourceMutedInternally(source, on, outputDesc, delayMs, deviceTypes);
     }
 
 }
 
-void AudioPolicyManager::setVolumeSourceMute(VolumeSource volumeSource,
-                                             bool on,
-                                             const sp<AudioOutputDescriptor>& outputDesc,
-                                             int delayMs,
-                                             DeviceTypeSet deviceTypes)
+void AudioPolicyManager::setVolumeSourceMutedInternally(VolumeSource volumeSource,
+                                                        bool on,
+                                                        const sp<AudioOutputDescriptor>& outputDesc,
+                                                        int delayMs,
+                                                        DeviceTypeSet deviceTypes)
 {
     if (deviceTypes.empty()) {
         deviceTypes = outputDesc->devices().types();
     }
     auto &curves = getVolumeCurves(volumeSource);
     if (on) {
-        if (!outputDesc->isMuted(volumeSource)) {
+        if (!outputDesc->isMutedInternally(volumeSource)) {
             if (curves.canBeMuted() &&
                     (volumeSource != toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE, false) ||
                      (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) ==
@@ -8669,7 +8687,7 @@
         // ignored
         outputDesc->incMuteCount(volumeSource);
     } else {
-        if (!outputDesc->isMuted(volumeSource)) {
+        if (!outputDesc->isMutedInternally(volumeSource)) {
             ALOGV("%s unmuting non muted attributes!", __func__);
             return;
         }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 9ad2ea5..20f7b12 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -129,7 +129,8 @@
                                   output_type_t *outputType,
                                   bool *isSpatialized,
                                   bool *isBitPerfect,
-                                  float *volume) override;
+                                  float *volume,
+                                  bool *muted) override;
         virtual status_t startOutput(audio_port_handle_t portId);
         virtual status_t stopOutput(audio_port_handle_t portId);
         virtual bool releaseOutput(audio_port_handle_t portId);
@@ -169,6 +170,7 @@
         virtual void initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax);
         virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
                                               int index,
+                                              bool muted,
                                               audio_devices_t device);
         virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
                                               int *index,
@@ -176,6 +178,7 @@
 
         virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
                                                      int index,
+                                                     bool muted,
                                                      audio_devices_t device);
         virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
                                                      int &index,
@@ -185,6 +188,7 @@
         virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
 
         status_t setVolumeCurveIndex(int index,
+                                     bool muted,
                                      audio_devices_t device,
                                      IVolumeCurves &volumeCurves);
 
@@ -650,7 +654,8 @@
                              DeviceTypeSet deviceTypes = DeviceTypeSet());
 
         /**
-         * @brief setVolumeSourceMute Mute or unmute the volume source on the specified output
+         * @brief setVolumeSourceMutedInternally 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
@@ -658,11 +663,11 @@
          * @param delayMs
          * @param device
          */
-        void setVolumeSourceMute(VolumeSource volumeSource,
-                                 bool on,
-                                 const sp<AudioOutputDescriptor>& outputDesc,
-                                 int delayMs = 0,
-                                 DeviceTypeSet deviceTypes = DeviceTypeSet());
+        void setVolumeSourceMutedInternally(VolumeSource volumeSource,
+                                            bool on,
+                                            const sp<AudioOutputDescriptor>& outputDesc,
+                                            int delayMs = 0,
+                                            DeviceTypeSet deviceTypes = DeviceTypeSet());
 
         audio_mode_t getPhoneState();
 
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 363dfa7..3ed247b 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -186,21 +186,19 @@
 }
 
 status_t AudioPolicyService::AudioPolicyClient::setStreamVolume(audio_stream_type_t stream,
-                     float volume, audio_io_handle_t output,
-                     int delay_ms)
+                     float volume, bool muted, audio_io_handle_t output, int delay_ms)
 {
-    return mAudioPolicyService->setStreamVolume(stream, volume, output,
-                                               delay_ms);
+    return mAudioPolicyService->setStreamVolume(stream, volume, muted, output, delay_ms);
 }
 
 status_t AudioPolicyService::AudioPolicyClient::setPortsVolume(
-        const std::vector<audio_port_handle_t> &ports, float volume, audio_io_handle_t output,
-        int delayMs)
+        const std::vector<audio_port_handle_t> &ports, float volume, bool muted,
+        audio_io_handle_t output, int delayMs)
 {
     if (ports.empty()) {
         return NO_ERROR;
     }
-    return mAudioPolicyService->setPortsVolume(ports, volume, output, delayMs);
+    return mAudioPolicyService->setPortsVolume(ports, volume, muted, output, delayMs);
 }
 
 void AudioPolicyService::AudioPolicyClient::setParameters(audio_io_handle_t io_handle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 24ab6a1..84b6c53 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -430,6 +430,7 @@
     bool isSpatialized = false;
     bool isBitPerfect = false;
     float volume;
+    bool muted;
     status_t result = mAudioPolicyManager->getOutputForAttr(&attr, &output, session,
                                                             &stream,
                                                             attributionSource,
@@ -439,7 +440,8 @@
                                                             &outputType,
                                                             &isSpatialized,
                                                             &isBitPerfect,
-                                                            &volume);
+                                                            &volume,
+                                                            &muted);
 
     // FIXME: Introduce a way to check for the the telephony device before opening the output
     if (result == NO_ERROR) {
@@ -504,6 +506,7 @@
         _aidl_return->attr = VALUE_OR_RETURN_BINDER_STATUS(
                 legacy2aidl_audio_attributes_t_AudioAttributes(attr));
         _aidl_return->volume = volume;
+        _aidl_return->muted = muted;
     } else {
         _aidl_return->configBase.format = VALUE_OR_RETURN_BINDER_STATUS(
                 legacy2aidl_audio_format_t_AudioFormatDescription(config.format));
@@ -1170,7 +1173,7 @@
 
 Status AudioPolicyService::setStreamVolumeIndex(AudioStreamType streamAidl,
                                                 const AudioDeviceDescription& deviceAidl,
-                                                int32_t indexAidl) {
+                                                int32_t indexAidl, bool muted) {
     audio_stream_type_t stream = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioStreamType_audio_stream_type_t(streamAidl));
     int index = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int>(indexAidl));
@@ -1192,6 +1195,7 @@
     AutoCallerClear acc;
     return binderStatusFromStatusT(mAudioPolicyManager->setStreamVolumeIndex(stream,
                                                                              index,
+                                                                             muted,
                                                                              device));
 }
 
@@ -1220,7 +1224,7 @@
 
 Status AudioPolicyService::setVolumeIndexForAttributes(
         const media::audio::common::AudioAttributes& attrAidl,
-        const AudioDeviceDescription& deviceAidl, int32_t indexAidl) {
+        const AudioDeviceDescription& deviceAidl, int32_t indexAidl, bool muted) {
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     int index = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int>(indexAidl));
@@ -1240,7 +1244,7 @@
     audio_utils::lock_guard _l(mMutex);
     AutoCallerClear acc;
     return binderStatusFromStatusT(
-            mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, device));
+            mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, muted, device));
 }
 
 Status AudioPolicyService::getVolumeIndexForAttributes(
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 7b7275e..697924d 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1817,6 +1817,7 @@
                     ul.unlock();
                     command->mStatus = AudioSystem::setStreamVolume(data->mStream,
                                                                     data->mVolume,
+                                                                    data->mIsMuted,
                                                                     data->mIO);
                     ul.lock();
                     }break;
@@ -1827,6 +1828,7 @@
                     ul.unlock();
                     command->mStatus = AudioSystem::setPortsVolume(data->mPorts,
                                                                    data->mVolume,
+                                                                   data->mMuted,
                                                                    data->mIO);
                     ul.lock();
                     } break;
@@ -2147,6 +2149,7 @@
 
 status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
                                                                float volume,
+                                                               bool muted,
                                                                audio_io_handle_t output,
                                                                int delayMs)
 {
@@ -2155,6 +2158,7 @@
     sp<VolumeData> data = new VolumeData();
     data->mStream = stream;
     data->mVolume = volume;
+    data->mIsMuted = muted;
     data->mIO = output;
     command->mParam = data;
     command->mWaitStatus = true;
@@ -2164,14 +2168,15 @@
 }
 
 status_t AudioPolicyService::AudioCommandThread::volumePortsCommand(
-        const std::vector<audio_port_handle_t> &ports, float volume, audio_io_handle_t output,
-        int delayMs)
+        const std::vector<audio_port_handle_t> &ports, float volume, bool muted,
+        audio_io_handle_t output, int delayMs)
 {
     sp<AudioCommand> command = new AudioCommand();
     command->mCommand = SET_PORTS_VOLUME;
     sp<VolumePortsData> data = new VolumePortsData();
     data->mPorts = ports;
     data->mVolume = volume;
+    data->mMuted = muted;
     data->mIO = output;
     command->mParam = data;
     command->mWaitStatus = true;
@@ -2675,17 +2680,18 @@
 
 int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
                                         float volume,
+                                        bool muted,
                                         audio_io_handle_t output,
                                         int delayMs)
 {
-    return (int)mAudioCommandThread->volumeCommand(stream, volume,
+    return (int)mAudioCommandThread->volumeCommand(stream, volume, muted,
                                                    output, delayMs);
 }
 
 int AudioPolicyService::setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
-                                       audio_io_handle_t output, int delayMs)
+                                       bool muted, audio_io_handle_t output, int delayMs)
 {
-    return (int)mAudioCommandThread->volumePortsCommand(ports, volume, output, delayMs);
+    return (int)mAudioCommandThread->volumePortsCommand(ports, volume, muted, output, delayMs);
 }
 
 int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c47b5e9..2ce82c0 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -136,13 +136,13 @@
                                     int32_t indexMax) override;
     binder::Status setStreamVolumeIndex(AudioStreamType stream,
                                         const AudioDeviceDescription& device,
-                                        int32_t index) override;
+                                        int32_t index, bool muted) override;
     binder::Status getStreamVolumeIndex(AudioStreamType stream,
                                         const AudioDeviceDescription& device,
                                         int32_t* _aidl_return) override;
     binder::Status setVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
                                                const AudioDeviceDescription& device,
-                                               int32_t index) override;
+                                               int32_t index, bool muted) override;
     binder::Status getVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
                                                const AudioDeviceDescription& device,
                                                int32_t* _aidl_return) override;
@@ -353,6 +353,7 @@
 
     virtual status_t setStreamVolume(audio_stream_type_t stream,
                                      float volume,
+                                     bool muted,
                                      audio_io_handle_t output,
                                      int delayMs = 0);
 
@@ -364,12 +365,13 @@
      *
      * @param ports to consider
      * @param volume to set
+     * @param muted to set
      * @param output to consider
      * @param delayMs to use
      * @return NO_ERROR if successful
      */
     virtual status_t setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
-            audio_io_handle_t output, int delayMs = 0);
+            bool muted, audio_io_handle_t output, int delayMs = 0);
     virtual status_t setVoiceVolume(float volume, int delayMs = 0);
 
     void doOnNewAudioModulesAvailable();
@@ -625,10 +627,10 @@
         virtual     bool        threadLoop();
 
                     void        exit();
-                    status_t    volumeCommand(audio_stream_type_t stream, float volume,
+                    status_t    volumeCommand(audio_stream_type_t stream, float volume, bool muted,
                                             audio_io_handle_t output, int delayMs = 0);
                     status_t    volumePortsCommand(const std::vector<audio_port_handle_t> &ports,
-                            float volume, audio_io_handle_t output, int delayMs = 0);
+                            float volume, bool muted, audio_io_handle_t output, int delayMs = 0);
                     status_t    parametersCommand(audio_io_handle_t ioHandle,
                                             const char *keyValuePairs, int delayMs = 0);
                     status_t    voiceVolumeCommand(float volume, int delayMs = 0);
@@ -700,6 +702,7 @@
         public:
             audio_stream_type_t mStream;
             float mVolume;
+            bool mIsMuted;
             audio_io_handle_t mIO;
         };
 
@@ -707,13 +710,15 @@
         public:
             std::vector<audio_port_handle_t> mPorts;
             float mVolume;
+            bool mMuted;
             audio_io_handle_t mIO;
             std::string dumpPorts() {
-                return std::string("volume ") + std::to_string(mVolume) + " on IO " +
-                        std::to_string(mIO) + " and ports " +
-                        std::accumulate(std::begin(mPorts), std::end(mPorts), std::string{},
-                                       [] (const std::string& ls, int rs) {
-                                return ls + std::to_string(rs) + " "; });
+                return std::string("volume ") + std::to_string(mVolume) + std::string("muted ") +
+                       std::to_string(mMuted) + " on IO " + std::to_string(mIO) + " and ports " +
+                       std::accumulate(std::begin(mPorts), std::end(mPorts), std::string{},
+                                       [](const std::string &ls, int rs) {
+                                           return ls + std::to_string(rs) + " ";
+                                       });
             }
         };
 
@@ -854,9 +859,10 @@
         // misc control functions
         //
 
-        // set a stream volume for a particular output. For the same user setting, a given stream type can have different volumes
-        // for each output (destination device) it is attached to.
-        virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, audio_io_handle_t output, int delayMs = 0);
+        // set a stream volume for a particular output. For the same user setting, a given stream
+        // type can have different volumes for each output (destination device) it is attached to.
+        virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, bool muted,
+                audio_io_handle_t output, int delayMs = 0);
         /**
          * Set a volume on port(s) for a particular output. For the same user setting, a volume
          * group (and associated given port of the client's track) can have different volumes for
@@ -864,12 +870,13 @@
          *
          * @param ports to consider
          * @param volume to set
+         * @param muted to set
          * @param output to consider
          * @param delayMs to use
          * @return NO_ERROR if successful
          */
         status_t setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
-                audio_io_handle_t output, int delayMs = 0) override;
+                bool muted, audio_io_handle_t output, int delayMs = 0) override;
 
         // function enabling to send proprietary informations directly from audio policy manager to audio hardware interface.
         virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 154b063..182dc61 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -29,7 +29,6 @@
         "libbase",
         "libbinder",
         "libcutils",
-        "libcutils",
         "libhidlbase",
         "liblog",
         "libmedia_helper",
@@ -41,6 +40,7 @@
     static_libs: [
         "android.media.audiopolicy-aconfig-cc",
         "audioclient-types-aidl-cpp",
+        "com.android.media.audio-aconfig-cc",
         "com.android.media.audioserver-aconfig-cc",
         "libaudiopolicycomponents",
         "libflagtest",
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 9ddfd6c..5290da2 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -56,11 +56,13 @@
     status_t closeInput(audio_io_handle_t /*input*/) override { return NO_INIT; }
     status_t setStreamVolume(audio_stream_type_t /*stream*/,
                              float /*volume*/,
+                             bool /*muted*/,
                              audio_io_handle_t /*output*/,
                              int /*delayMs*/) override { return NO_INIT; }
 
-    status_t setPortsVolume(const std::vector<audio_port_handle_t>& /*ports*/, float /*volume*/,
-            audio_io_handle_t /*output*/, int /*delayMs*/) override { return NO_INIT; }
+    status_t setPortsVolume(const std::vector<audio_port_handle_t> & /*ports*/, float /*volume*/,
+                            bool /*muted*/, audio_io_handle_t /*output*/,
+                            int /*delayMs*/) override { return NO_INIT; }
 
     void setParameters(audio_io_handle_t /*ioHandle*/,
                        const String8& /*keyValuePairs*/,
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 39f9b8a..d83a277 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -310,11 +310,13 @@
     bool isSpatialized;
     bool isBitPerfectInternal;
     float volume;
+    bool muted;
     AttributionSourceState attributionSource = createAttributionSourceState(uid);
     ASSERT_EQ(OK, mManager->getOutputForAttr(
                     &attr, output, session, &stream, attributionSource, &config, &flags,
                     selectedDeviceId, portId, {}, &outputType, &isSpatialized,
-                    isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect, &volume));
+                    isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect, &volume,
+                    &muted));
     ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
     ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
 }
@@ -2107,6 +2109,7 @@
     bool mIsSpatialized;
     bool mIsBitPerfect;
     float mVolume;
+    bool mMuted;
 };
 
 TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingLoopbackDapMixFails) {
@@ -2125,7 +2128,8 @@
               mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
                                          createAttributionSourceState(testUid), &audioConfig,
                                          &outputFlags, &mSelectedDeviceId, &mPortId, {},
-                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+                                         &mMuted));
 }
 
 TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting,
@@ -2144,7 +2148,8 @@
               mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
                                          createAttributionSourceState(testUid), &audioConfig,
                                          &outputFlags, &mSelectedDeviceId, &mPortId, {},
-                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+                                         &mMuted));
 }
 
 TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting,
@@ -2175,7 +2180,8 @@
               mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
                                          createAttributionSourceState(testUid), &audioConfig,
                                          &outputFlags, &mSelectedDeviceId, &mPortId, {},
-                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+                                         &mMuted));
     ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
     auto outputDesc = mManager->getOutputs().valueFor(mOutput);
     ASSERT_NE(nullptr, outputDesc);
@@ -2191,7 +2197,8 @@
               mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
                                          createAttributionSourceState(testUid), &audioConfig,
                                          &outputFlags, &mSelectedDeviceId, &mPortId, {},
-                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+                                         &mMuted));
     ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
     outputDesc = mManager->getOutputs().valueFor(mOutput);
     ASSERT_NE(nullptr, outputDesc);
@@ -2220,7 +2227,8 @@
               mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
                                          createAttributionSourceState(testUid), &audioConfig,
                                          &outputFlags, &mSelectedDeviceId, &mPortId, {},
-                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
+                                         &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume,
+                                         &mMuted));
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -3978,11 +3986,12 @@
     bool isSpatialized;
     bool isBitPerfect;
     float volume;
+    bool muted;
     EXPECT_EQ(expected,
               mManager->getOutputForAttr(&sMediaAttr, &mBitPerfectOutput, AUDIO_SESSION_NONE,
                                          &stream, attributionSource, &config, &flags,
                                          &mSelectedDeviceId, &mBitPerfectPortId, {}, &outputType,
-                                         &isSpatialized, &isBitPerfect, &volume));
+                                         &isSpatialized, &isBitPerfect, &volume, &muted));
 }
 
 class AudioPolicyManagerTestBitPerfect : public AudioPolicyManagerTestBitPerfectBase {