Change audio flinger to user HAL master mute if available

(cherry picked from commit 91de9b56282d126ffb36344266af5fee3cefcfdd)

> Change audio flinger to user HAL master mute if available
>
> Hand merge from ics-aah
>
> > Change audio flinger to user HAL master mute if available: DO NOT MERGE
> >
> > Replicate the pattern used for HAL master volume support to make use
> > of master mute support if the HAL supports it.  This is part of the
> > change needed to address bug 6828363.  Because of the divergences
> > between ICS and master, this change will need to be merged by hand.
> >
> > Signed-off-by: John Grossman <johngro@google.com>
> > Change-Id: I6d83be524021d273d093bcb117b8f2fe57c23685
>
> Change-Id: I32280582905c969aaec2bb166ec5c61df82d737a
> Signed-off-by: John Grossman <johngro@google.com>

Change-Id: I5cd709187221d307fe25c5117ccaadca5f6b197b
Signed-off-by: John Grossman <johngro@google.com>
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d65a2b6..41ae70e 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -219,6 +219,8 @@
       mMasterVolumeSW(1.0f),
       mMasterVolumeSupportLvl(MVS_NONE),
       mMasterMute(false),
+      mMasterMuteSW(false),
+      mMasterMuteSupportLvl(MMS_NONE),
       mNextUniqueId(1),
       mMode(AUDIO_MODE_INVALID),
       mBtNrecIsOff(false)
@@ -699,16 +701,40 @@
 
 status_t AudioFlinger::setMasterMute(bool muted)
 {
+    status_t ret = initCheck();
+    if (ret != NO_ERROR) {
+        return ret;
+    }
+
     // check calling permissions
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
 
+    bool swmm = muted;
+
+    // when hw supports master mute, don't mute in sw mixer
+    if (MMS_NONE != mMasterMuteSupportLvl) {
+        for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+            AutoMutex lock(mHardwareLock);
+            audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
+
+            mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
+            if (NULL != dev->set_master_mute) {
+                dev->set_master_mute(dev, muted);
+            }
+            mHardwareStatus = AUDIO_HW_IDLE;
+        }
+
+        swmm = false;
+    }
+
     Mutex::Autolock _l(mLock);
     // This is an optimization, so PlaybackThread doesn't have to look at the one from AudioFlinger
-    mMasterMute = muted;
+    mMasterMute   = muted;
+    mMasterMuteSW = swmm;
     for (size_t i = 0; i < mPlaybackThreads.size(); i++)
-        mPlaybackThreads.valueAt(i)->setMasterMute(muted);
+        mPlaybackThreads.valueAt(i)->setMasterMute(swmm);
 
     return NO_ERROR;
 }
@@ -731,6 +757,12 @@
     return masterMute_l();
 }
 
+bool AudioFlinger::masterMuteSW() const
+{
+    Mutex::Autolock _l(mLock);
+    return masterMuteSW_l();
+}
+
 float AudioFlinger::masterVolume_l() const
 {
     if (MVS_FULL == mMasterVolumeSupportLvl) {
@@ -750,6 +782,24 @@
     return mMasterVolume;
 }
 
+bool AudioFlinger::masterMute_l() const
+{
+    if (MMS_FULL == mMasterMuteSupportLvl) {
+        bool ret_val;
+        AutoMutex lock(mHardwareLock);
+
+        mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
+        assert(NULL != mPrimaryHardwareDev);
+        assert(NULL != mPrimaryHardwareDev->get_master_mute);
+
+        mPrimaryHardwareDev->get_master_mute(mPrimaryHardwareDev, &ret_val);
+        mHardwareStatus = AUDIO_HW_IDLE;
+        return ret_val;
+    }
+
+     return mMasterMute;
+}
+
 status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
         audio_io_handle_t output)
 {
@@ -1503,7 +1553,7 @@
         mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
         // Assumes constructor is called by AudioFlinger with it's mLock held,
         // but it would be safer to explicitly pass initial masterMute as parameter
-        mMasterMute(audioFlinger->masterMute_l()),
+        mMasterMute(audioFlinger->masterMuteSW_l()),
         // mStreamTypes[] initialized in constructor body
         mOutput(output),
         // Assumes constructor is called by AudioFlinger with it's mLock held,
@@ -6863,10 +6913,13 @@
             mHardwareStatus = AUDIO_HW_SET_MODE;
             outHwDev->set_mode(outHwDev, mMode);
 
-            // Determine the level of master volume support the primary audio HAL has,
-            // and set the initial master volume at the same time.
+            // Determine the level of master volume/master mute support the primary
+            // audio HAL has, and set the initial master volume/mute state at the same
+            // time.
             float initialVolume = 1.0;
+            bool initialMute = false;
             mMasterVolumeSupportLvl = MVS_NONE;
+            mMasterMuteSupportLvl = MMS_NONE;
 
             mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
             if ((NULL != outHwDev->get_master_volume) &&
@@ -6882,20 +6935,44 @@
                 (NO_ERROR != outHwDev->set_master_volume(outHwDev, initialVolume))) {
                 mMasterVolumeSupportLvl = MVS_NONE;
             }
-            // now that we have a primary device, initialize master volume on other devices
+
+            mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
+            if ((NULL != outHwDev->get_master_mute) &&
+                (NO_ERROR == outHwDev->get_master_mute(outHwDev, &initialMute))) {
+                mMasterMuteSupportLvl = MMS_FULL;
+            } else {
+                mMasterMuteSupportLvl = MMS_SETONLY;
+                initialMute = 0;
+            }
+
+            mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
+            if ((NULL == outHwDev->set_master_mute) ||
+                (NO_ERROR != outHwDev->set_master_mute(outHwDev, initialMute))) {
+                mMasterMuteSupportLvl = MMS_NONE;
+            }
+
+            // now that we have a primary device, initialize master volume/mute
+            // on other devices
             for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
                 audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
 
                 if ((dev != mPrimaryHardwareDev) &&
                     (NULL != dev->set_master_volume)) {
+                    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
                     dev->set_master_volume(dev, initialVolume);
                 }
+
+                if (NULL != dev->set_master_mute) {
+                    mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
+                    dev->set_master_mute(dev, initialMute);
+                }
             }
+
             mHardwareStatus = AUDIO_HW_IDLE;
-            mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
-                                    ? initialVolume
-                                    : 1.0;
+            mMasterVolumeSW = initialVolume;
             mMasterVolume   = initialVolume;
+            mMasterMuteSW   = initialMute;
+            mMasterMute     = initialMute;
         }
         return id;
     }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 2b6d00f..1bef42c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -124,6 +124,7 @@
     virtual     float       masterVolume() const;
     virtual     float       masterVolumeSW() const;
     virtual     bool        masterMute() const;
+    virtual     bool        masterMuteSW() const;
 
     virtual     status_t    setStreamVolume(audio_stream_type_t stream, float value,
                                             audio_io_handle_t output);
@@ -1911,6 +1912,27 @@
         MVS_FULL,
     };
 
+    enum master_mute_support {
+        // MMS_NONE:
+        // Audio HAL has no support for master mute, either setting or getting.
+        // All master mute control must be implemented in SW by the
+        // AudioFlinger mixing core.
+        MMS_NONE,
+
+        // MMS_SETONLY:
+        // Audio HAL has support for setting master mute, but not for getting
+        // master mute.  AudioFlinger needs to keep track of the last set
+        // master mute in addition to needing to set an initial, default,
+        // master mute at HAL load time.
+        MMS_SETONLY,
+
+        // MMS_FULL:
+        // Audio HAL has support both for setting and getting master mute.
+        // AudioFlinger should send all set and get master mute requests
+        // directly to the HAL.
+        MMS_FULL,
+    };
+
     class AudioHwDevice {
     public:
         AudioHwDevice(const char *moduleName, audio_hw_device_t *hwDevice) :
@@ -1957,6 +1979,8 @@
         AUDIO_HW_GET_INPUT_BUFFER_SIZE, // get_input_buffer_size
         AUDIO_HW_GET_MASTER_VOLUME,     // get_master_volume
         AUDIO_HW_GET_PARAMETER,         // get_parameters
+        AUDIO_HW_SET_MASTER_MUTE,       // set_master_mute
+        AUDIO_HW_GET_MASTER_MUTE,       // get_master_mute
     };
 
     mutable     hardware_call_state                 mHardwareStatus;    // for dump only
@@ -1969,7 +1993,10 @@
                 float                               mMasterVolume;
                 float                               mMasterVolumeSW;
                 master_volume_support               mMasterVolumeSupportLvl;
+
                 bool                                mMasterMute;
+                bool                                mMasterMuteSW;
+                master_mute_support                 mMasterMuteSupportLvl;
 
                 DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> >    mRecordThreads;
 
@@ -1983,7 +2010,8 @@
 
                 float       masterVolume_l() const;
                 float       masterVolumeSW_l() const  { return mMasterVolumeSW; }
-                bool        masterMute_l() const    { return mMasterMute; }
+                bool        masterMute_l() const;
+                bool        masterMuteSW_l() const    { return mMasterMuteSW; }
                 audio_module_handle_t loadHwModule_l(const char *name);
 
                 Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session