audio_mutex: Update mutex order

Add new mutex attributes template class to configure
mutex from generated audio mutex information.

Test: validated through dynamic mutex order checking on CTS tests
Bug: 306277363
Bug: 307629326
Change-Id: If35fae81ed1f4e20e758a1cd4ee51cbd27414e1c
diff --git a/audio_utils/include/audio_utils/mutex.h b/audio_utils/include/audio_utils/mutex.h
index 38afadb..8e9b5a6 100644
--- a/audio_utils/include/audio_utils/mutex.h
+++ b/audio_utils/include/audio_utils/mutex.h
@@ -28,6 +28,267 @@
 
 namespace android::audio_utils {
 
+// Define global capabilities for thread-safety annotation.
+//
+// These can be manually modified, or
+// compile generate_mutex_order.cpp in the tests directory
+// to generate this.
+
+// --- Begin generated section
+
+// Lock order
+enum class MutexOrder : uint32_t {
+    kEffectHandle_Mutex = 0,
+    kEffectBase_PolicyMutex = 1,
+    kAudioFlinger_Mutex = 2,
+    kAudioFlinger_HardwareMutex = 3,
+    kDeviceEffectManager_Mutex = 4,
+    kPatchCommandThread_Mutex = 5,
+    kThreadBase_Mutex = 6,
+    kAudioFlinger_ClientMutex = 7,
+    kMelReporter_Mutex = 8,
+    kEffectChain_Mutex = 9,
+    kDeviceEffectProxy_ProxyMutex = 10,
+    kEffectBase_Mutex = 11,
+    kAudioFlinger_UnregisteredWritersMutex = 12,
+    kAsyncCallbackThread_Mutex = 13,
+    kConfigEvent_Mutex = 14,
+    kOutputTrack_TrackMetadataMutex = 15,
+    kPassthruPatchRecord_ReadMutex = 16,
+    kPatchCommandThread_ListenerMutex = 17,
+    kPlaybackThread_AudioTrackCbMutex = 18,
+    kMediaLogNotifier_Mutex = 19,
+    kOtherMutex = 20,
+    kSize = 21,
+};
+
+// Lock by name
+inline constexpr const char* const gMutexNames[] = {
+    "EffectHandle_Mutex",
+    "EffectBase_PolicyMutex",
+    "AudioFlinger_Mutex",
+    "AudioFlinger_HardwareMutex",
+    "DeviceEffectManager_Mutex",
+    "PatchCommandThread_Mutex",
+    "ThreadBase_Mutex",
+    "AudioFlinger_ClientMutex",
+    "MelReporter_Mutex",
+    "EffectChain_Mutex",
+    "DeviceEffectProxy_ProxyMutex",
+    "EffectBase_Mutex",
+    "AudioFlinger_UnregisteredWritersMutex",
+    "AsyncCallbackThread_Mutex",
+    "ConfigEvent_Mutex",
+    "OutputTrack_TrackMetadataMutex",
+    "PassthruPatchRecord_ReadMutex",
+    "PatchCommandThread_ListenerMutex",
+    "PlaybackThread_AudioTrackCbMutex",
+    "MediaLogNotifier_Mutex",
+    "OtherMutex",
+};
+
+// Forward declarations
+class AudioMutexAttributes;
+template <typename T> class mutex_impl;
+using mutex = mutex_impl<AudioMutexAttributes>;
+
+// Capabilities in priority order
+// (declaration only, value is nullptr)
+inline mutex* EffectHandle_Mutex;
+inline mutex* EffectBase_PolicyMutex
+        ACQUIRED_AFTER(android::audio_utils::EffectHandle_Mutex);
+inline mutex* AudioFlinger_Mutex
+        ACQUIRED_AFTER(android::audio_utils::EffectBase_PolicyMutex);
+inline mutex* AudioFlinger_HardwareMutex
+        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_Mutex);
+inline mutex* DeviceEffectManager_Mutex
+        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_HardwareMutex);
+inline mutex* PatchCommandThread_Mutex
+        ACQUIRED_AFTER(android::audio_utils::DeviceEffectManager_Mutex);
+inline mutex* ThreadBase_Mutex
+        ACQUIRED_AFTER(android::audio_utils::PatchCommandThread_Mutex);
+inline mutex* AudioFlinger_ClientMutex
+        ACQUIRED_AFTER(android::audio_utils::ThreadBase_Mutex);
+inline mutex* MelReporter_Mutex
+        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_ClientMutex);
+inline mutex* EffectChain_Mutex
+        ACQUIRED_AFTER(android::audio_utils::MelReporter_Mutex);
+inline mutex* DeviceEffectProxy_ProxyMutex
+        ACQUIRED_AFTER(android::audio_utils::EffectChain_Mutex);
+inline mutex* EffectBase_Mutex
+        ACQUIRED_AFTER(android::audio_utils::DeviceEffectProxy_ProxyMutex);
+inline mutex* AudioFlinger_UnregisteredWritersMutex
+        ACQUIRED_AFTER(android::audio_utils::EffectBase_Mutex);
+inline mutex* AsyncCallbackThread_Mutex
+        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_UnregisteredWritersMutex);
+inline mutex* ConfigEvent_Mutex
+        ACQUIRED_AFTER(android::audio_utils::AsyncCallbackThread_Mutex);
+inline mutex* OutputTrack_TrackMetadataMutex
+        ACQUIRED_AFTER(android::audio_utils::ConfigEvent_Mutex);
+inline mutex* PassthruPatchRecord_ReadMutex
+        ACQUIRED_AFTER(android::audio_utils::OutputTrack_TrackMetadataMutex);
+inline mutex* PatchCommandThread_ListenerMutex
+        ACQUIRED_AFTER(android::audio_utils::PassthruPatchRecord_ReadMutex);
+inline mutex* PlaybackThread_AudioTrackCbMutex
+        ACQUIRED_AFTER(android::audio_utils::PatchCommandThread_ListenerMutex);
+inline mutex* MediaLogNotifier_Mutex
+        ACQUIRED_AFTER(android::audio_utils::PlaybackThread_AudioTrackCbMutex);
+inline mutex* OtherMutex
+        ACQUIRED_AFTER(android::audio_utils::MediaLogNotifier_Mutex);
+
+// Exclusion by capability
+#define EXCLUDES_BELOW_OtherMutex
+#define EXCLUDES_OtherMutex \
+    EXCLUDES(android::audio_utils::OtherMutex) \
+    EXCLUDES_BELOW_OtherMutex
+
+#define EXCLUDES_BELOW_MediaLogNotifier_Mutex \
+    EXCLUDES_OtherMutex
+#define EXCLUDES_MediaLogNotifier_Mutex \
+    EXCLUDES(android::audio_utils::MediaLogNotifier_Mutex) \
+    EXCLUDES_BELOW_MediaLogNotifier_Mutex
+
+#define EXCLUDES_BELOW_PlaybackThread_AudioTrackCbMutex \
+    EXCLUDES_MediaLogNotifier_Mutex
+#define EXCLUDES_PlaybackThread_AudioTrackCbMutex \
+    EXCLUDES(android::audio_utils::PlaybackThread_AudioTrackCbMutex) \
+    EXCLUDES_BELOW_PlaybackThread_AudioTrackCbMutex
+
+#define EXCLUDES_BELOW_PatchCommandThread_ListenerMutex \
+    EXCLUDES_PlaybackThread_AudioTrackCbMutex
+#define EXCLUDES_PatchCommandThread_ListenerMutex \
+    EXCLUDES(android::audio_utils::PatchCommandThread_ListenerMutex) \
+    EXCLUDES_BELOW_PatchCommandThread_ListenerMutex
+
+#define EXCLUDES_BELOW_PassthruPatchRecord_ReadMutex \
+    EXCLUDES_PatchCommandThread_ListenerMutex
+#define EXCLUDES_PassthruPatchRecord_ReadMutex \
+    EXCLUDES(android::audio_utils::PassthruPatchRecord_ReadMutex) \
+    EXCLUDES_BELOW_PassthruPatchRecord_ReadMutex
+
+#define EXCLUDES_BELOW_OutputTrack_TrackMetadataMutex \
+    EXCLUDES_PassthruPatchRecord_ReadMutex
+#define EXCLUDES_OutputTrack_TrackMetadataMutex \
+    EXCLUDES(android::audio_utils::OutputTrack_TrackMetadataMutex) \
+    EXCLUDES_BELOW_OutputTrack_TrackMetadataMutex
+
+#define EXCLUDES_BELOW_ConfigEvent_Mutex \
+    EXCLUDES_OutputTrack_TrackMetadataMutex
+#define EXCLUDES_ConfigEvent_Mutex \
+    EXCLUDES(android::audio_utils::ConfigEvent_Mutex) \
+    EXCLUDES_BELOW_ConfigEvent_Mutex
+
+#define EXCLUDES_BELOW_AsyncCallbackThread_Mutex \
+    EXCLUDES_ConfigEvent_Mutex
+#define EXCLUDES_AsyncCallbackThread_Mutex \
+    EXCLUDES(android::audio_utils::AsyncCallbackThread_Mutex) \
+    EXCLUDES_BELOW_AsyncCallbackThread_Mutex
+
+#define EXCLUDES_BELOW_AudioFlinger_UnregisteredWritersMutex \
+    EXCLUDES_AsyncCallbackThread_Mutex
+#define EXCLUDES_AudioFlinger_UnregisteredWritersMutex \
+    EXCLUDES(android::audio_utils::AudioFlinger_UnregisteredWritersMutex) \
+    EXCLUDES_BELOW_AudioFlinger_UnregisteredWritersMutex
+
+#define EXCLUDES_BELOW_EffectBase_Mutex \
+    EXCLUDES_AudioFlinger_UnregisteredWritersMutex
+#define EXCLUDES_EffectBase_Mutex \
+    EXCLUDES(android::audio_utils::EffectBase_Mutex) \
+    EXCLUDES_BELOW_EffectBase_Mutex
+
+#define EXCLUDES_BELOW_DeviceEffectProxy_ProxyMutex \
+    EXCLUDES_EffectBase_Mutex
+#define EXCLUDES_DeviceEffectProxy_ProxyMutex \
+    EXCLUDES(android::audio_utils::DeviceEffectProxy_ProxyMutex) \
+    EXCLUDES_BELOW_DeviceEffectProxy_ProxyMutex
+
+#define EXCLUDES_BELOW_EffectChain_Mutex \
+    EXCLUDES_DeviceEffectProxy_ProxyMutex
+#define EXCLUDES_EffectChain_Mutex \
+    EXCLUDES(android::audio_utils::EffectChain_Mutex) \
+    EXCLUDES_BELOW_EffectChain_Mutex
+
+#define EXCLUDES_BELOW_MelReporter_Mutex \
+    EXCLUDES_EffectChain_Mutex
+#define EXCLUDES_MelReporter_Mutex \
+    EXCLUDES(android::audio_utils::MelReporter_Mutex) \
+    EXCLUDES_BELOW_MelReporter_Mutex
+
+#define EXCLUDES_BELOW_AudioFlinger_ClientMutex \
+    EXCLUDES_MelReporter_Mutex
+#define EXCLUDES_AudioFlinger_ClientMutex \
+    EXCLUDES(android::audio_utils::AudioFlinger_ClientMutex) \
+    EXCLUDES_BELOW_AudioFlinger_ClientMutex
+
+#define EXCLUDES_BELOW_ThreadBase_Mutex \
+    EXCLUDES_AudioFlinger_ClientMutex
+#define EXCLUDES_ThreadBase_Mutex \
+    EXCLUDES(android::audio_utils::ThreadBase_Mutex) \
+    EXCLUDES_BELOW_ThreadBase_Mutex
+
+#define EXCLUDES_BELOW_PatchCommandThread_Mutex \
+    EXCLUDES_ThreadBase_Mutex
+#define EXCLUDES_PatchCommandThread_Mutex \
+    EXCLUDES(android::audio_utils::PatchCommandThread_Mutex) \
+    EXCLUDES_BELOW_PatchCommandThread_Mutex
+
+#define EXCLUDES_BELOW_DeviceEffectManager_Mutex \
+    EXCLUDES_PatchCommandThread_Mutex
+#define EXCLUDES_DeviceEffectManager_Mutex \
+    EXCLUDES(android::audio_utils::DeviceEffectManager_Mutex) \
+    EXCLUDES_BELOW_DeviceEffectManager_Mutex
+
+#define EXCLUDES_BELOW_AudioFlinger_HardwareMutex \
+    EXCLUDES_DeviceEffectManager_Mutex
+#define EXCLUDES_AudioFlinger_HardwareMutex \
+    EXCLUDES(android::audio_utils::AudioFlinger_HardwareMutex) \
+    EXCLUDES_BELOW_AudioFlinger_HardwareMutex
+
+#define EXCLUDES_BELOW_AudioFlinger_Mutex \
+    EXCLUDES_AudioFlinger_HardwareMutex
+#define EXCLUDES_AudioFlinger_Mutex \
+    EXCLUDES(android::audio_utils::AudioFlinger_Mutex) \
+    EXCLUDES_BELOW_AudioFlinger_Mutex
+
+#define EXCLUDES_BELOW_EffectBase_PolicyMutex \
+    EXCLUDES_AudioFlinger_Mutex
+#define EXCLUDES_EffectBase_PolicyMutex \
+    EXCLUDES(android::audio_utils::EffectBase_PolicyMutex) \
+    EXCLUDES_BELOW_EffectBase_PolicyMutex
+
+#define EXCLUDES_BELOW_EffectHandle_Mutex \
+    EXCLUDES_EffectBase_PolicyMutex
+#define EXCLUDES_EffectHandle_Mutex \
+    EXCLUDES(android::audio_utils::EffectHandle_Mutex) \
+    EXCLUDES_BELOW_EffectHandle_Mutex
+
+#define EXCLUDES_AUDIO_ALL \
+    EXCLUDES_EffectHandle_Mutex
+
+// --- End generated section
+
+/**
+ * AudioMutexAttributes is a collection of types and constexpr configuration
+ * used for the Android audio mutex.
+ *
+ * A different AudioMutexAttributes configuration will instantiate a completely
+ * independent set of mutex strategies, statics and thread locals,
+ * for a different type of mutexes.
+ */
+
+class AudioMutexAttributes {
+public:
+    // Order types, name arrays.
+    using order_t = MutexOrder;
+    static constexpr auto& order_names_ = gMutexNames;
+    static constexpr size_t order_size_ = (size_t)MutexOrder::kSize;
+    static constexpr order_t order_default_ = MutexOrder::kOtherMutex;
+
+    // verify order information
+    static_assert(std::size(order_names_) == order_size_);
+    static_assert((size_t)order_default_ < order_size_);
+};
+
 // audio_utils::mutex, audio_utils::lock_guard, audio_utils::unique_lock,
 // and audio_utils::condition_variable are method compatible versions
 // of std::mutex, std::lock_guard, std::unique_lock, and std::condition_variable
@@ -37,12 +298,21 @@
 // is inefficient.  One is better off making a custom timed implementation using
 // pthread_mutex_timedlock() on the mutex::native_handle().
 
-class CAPABILITY("mutex") mutex {
+extern bool mutex_get_enable_flag();
+
+template <typename Attributes>
+class CAPABILITY("mutex") mutex_impl {
 public:
     // We use composition here.
     // No copy/move ctors as the member std::mutex has it deleted.
-    mutex() {
-        if (!get_enable_flag()) return;
+    mutex_impl(typename Attributes::order_t order = Attributes::order_default_)
+        : order_(order)
+    {
+        LOG_ALWAYS_FATAL_IF((size_t)order >= Attributes::order_size_,
+                "mutex order %u is equal to or greater than order limit:%zu",
+                order, Attributes::order_size_);
+
+        if (!mutex_get_enable_flag()) return;
 
         pthread_mutexattr_t attr;
         int ret = pthread_mutexattr_init(&attr);
@@ -58,12 +328,16 @@
         }
 
         // use of the native_handle() is implementation defined.
-        auto handle = m_.native_handle();
+        const auto handle = m_.native_handle();
         ret = pthread_mutex_init(handle, &attr);
         if (ret != 0) {
             ALOGW("%s, pthread_mutex_init returned %d", __func__, ret);
         }
-        ALOGV("%s: audio_mutex initialized: %d", __func__, ret);
+        ALOGV("%s: audio_mutex initialized: ret:%d  order:%u", __func__, ret, order_);
+    }
+
+    ~mutex_impl() {
+        // Note: std::mutex behavior is undefined if released holding ownership.
     }
 
     auto native_handle() {
@@ -98,8 +372,9 @@
     }
 
 private:
-    static bool get_enable_flag();
+
     std::mutex m_;
+    const typename Attributes::order_t order_;
 };
 
 // audio_utils::lock_guard only works with the defined mutex.
@@ -278,157 +553,6 @@
     lock_guard_no_thread_safety_analysis(Mutex1& m) : std::lock_guard<Mutex1>(m) {}
 };
 
-// Define global capabilities for thread-safety annotation.
-//
-// These can be manually modified, or
-// compile generate_mutex_order.cpp in the tests directory
-// to generate this.
-
-// --- Begin generated section
-
-// Capabilities in priority order
-// (declaration only, value is nullptr)
-inline mutex* AudioFlinger_Mutex;
-inline mutex* EffectHandle_Mutex
-        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_Mutex);
-inline mutex* AudioFlinger_HardwareMutex
-        ACQUIRED_AFTER(android::audio_utils::EffectHandle_Mutex);
-inline mutex* DeviceEffectManager_Mutex
-        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_HardwareMutex);
-inline mutex* PatchCommandThread_Mutex
-        ACQUIRED_AFTER(android::audio_utils::DeviceEffectManager_Mutex);
-inline mutex* ThreadBase_Mutex
-        ACQUIRED_AFTER(android::audio_utils::PatchCommandThread_Mutex);
-inline mutex* AudioFlinger_ClientMutex
-        ACQUIRED_AFTER(android::audio_utils::ThreadBase_Mutex);
-inline mutex* MelReporter_Mutex
-        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_ClientMutex);
-inline mutex* EffectChain_Mutex
-        ACQUIRED_AFTER(android::audio_utils::MelReporter_Mutex);
-inline mutex* EffectBase_Mutex
-        ACQUIRED_AFTER(android::audio_utils::EffectChain_Mutex);
-inline mutex* AudioFlinger_UnregisteredWritersMutex
-        ACQUIRED_AFTER(android::audio_utils::EffectBase_Mutex);
-inline mutex* AsyncCallbackThread_Mutex
-        ACQUIRED_AFTER(android::audio_utils::AudioFlinger_UnregisteredWritersMutex);
-inline mutex* ConfigEvent_Mutex
-        ACQUIRED_AFTER(android::audio_utils::AsyncCallbackThread_Mutex);
-inline mutex* OutputTrack_TrackMetadataMutex
-        ACQUIRED_AFTER(android::audio_utils::ConfigEvent_Mutex);
-inline mutex* PassthruPatchRecord_ReadMutex
-        ACQUIRED_AFTER(android::audio_utils::OutputTrack_TrackMetadataMutex);
-inline mutex* PatchCommandThread_ListenerMutex
-        ACQUIRED_AFTER(android::audio_utils::PassthruPatchRecord_ReadMutex);
-inline mutex* PlaybackThread_AudioTrackCbMutex
-        ACQUIRED_AFTER(android::audio_utils::PatchCommandThread_ListenerMutex);
-
-// Exclusion by capability
-#define EXCLUDES_BELOW_PlaybackThread_AudioTrackCbMutex
-#define EXCLUDES_PlaybackThread_AudioTrackCbMutex \
-    EXCLUDES(android::audio_utils::PlaybackThread_AudioTrackCbMutex) \
-    EXCLUDES_BELOW_PlaybackThread_AudioTrackCbMutex
-
-#define EXCLUDES_BELOW_PatchCommandThread_ListenerMutex \
-    EXCLUDES_PlaybackThread_AudioTrackCbMutex
-#define EXCLUDES_PatchCommandThread_ListenerMutex \
-    EXCLUDES(android::audio_utils::PatchCommandThread_ListenerMutex) \
-    EXCLUDES_BELOW_PatchCommandThread_ListenerMutex
-
-#define EXCLUDES_BELOW_PassthruPatchRecord_ReadMutex \
-    EXCLUDES_PatchCommandThread_ListenerMutex
-#define EXCLUDES_PassthruPatchRecord_ReadMutex \
-    EXCLUDES(android::audio_utils::PassthruPatchRecord_ReadMutex) \
-    EXCLUDES_BELOW_PassthruPatchRecord_ReadMutex
-
-#define EXCLUDES_BELOW_OutputTrack_TrackMetadataMutex \
-    EXCLUDES_PassthruPatchRecord_ReadMutex
-#define EXCLUDES_OutputTrack_TrackMetadataMutex \
-    EXCLUDES(android::audio_utils::OutputTrack_TrackMetadataMutex) \
-    EXCLUDES_BELOW_OutputTrack_TrackMetadataMutex
-
-#define EXCLUDES_BELOW_ConfigEvent_Mutex \
-    EXCLUDES_OutputTrack_TrackMetadataMutex
-#define EXCLUDES_ConfigEvent_Mutex \
-    EXCLUDES(android::audio_utils::ConfigEvent_Mutex) \
-    EXCLUDES_BELOW_ConfigEvent_Mutex
-
-#define EXCLUDES_BELOW_AsyncCallbackThread_Mutex \
-    EXCLUDES_ConfigEvent_Mutex
-#define EXCLUDES_AsyncCallbackThread_Mutex \
-    EXCLUDES(android::audio_utils::AsyncCallbackThread_Mutex) \
-    EXCLUDES_BELOW_AsyncCallbackThread_Mutex
-
-#define EXCLUDES_BELOW_AudioFlinger_UnregisteredWritersMutex \
-    EXCLUDES_AsyncCallbackThread_Mutex
-#define EXCLUDES_AudioFlinger_UnregisteredWritersMutex \
-    EXCLUDES(android::audio_utils::AudioFlinger_UnregisteredWritersMutex) \
-    EXCLUDES_BELOW_AudioFlinger_UnregisteredWritersMutex
-
-#define EXCLUDES_BELOW_EffectBase_Mutex \
-    EXCLUDES_AudioFlinger_UnregisteredWritersMutex
-#define EXCLUDES_EffectBase_Mutex \
-    EXCLUDES(android::audio_utils::EffectBase_Mutex) \
-    EXCLUDES_BELOW_EffectBase_Mutex
-
-#define EXCLUDES_BELOW_EffectChain_Mutex \
-    EXCLUDES_EffectBase_Mutex
-#define EXCLUDES_EffectChain_Mutex \
-    EXCLUDES(android::audio_utils::EffectChain_Mutex) \
-    EXCLUDES_BELOW_EffectChain_Mutex
-
-#define EXCLUDES_BELOW_MelReporter_Mutex \
-    EXCLUDES_EffectChain_Mutex
-#define EXCLUDES_MelReporter_Mutex \
-    EXCLUDES(android::audio_utils::MelReporter_Mutex) \
-    EXCLUDES_BELOW_MelReporter_Mutex
-
-#define EXCLUDES_BELOW_AudioFlinger_ClientMutex \
-    EXCLUDES_MelReporter_Mutex
-#define EXCLUDES_AudioFlinger_ClientMutex \
-    EXCLUDES(android::audio_utils::AudioFlinger_ClientMutex) \
-    EXCLUDES_BELOW_AudioFlinger_ClientMutex
-
-#define EXCLUDES_BELOW_ThreadBase_Mutex \
-    EXCLUDES_AudioFlinger_ClientMutex
-#define EXCLUDES_ThreadBase_Mutex \
-    EXCLUDES(android::audio_utils::ThreadBase_Mutex) \
-    EXCLUDES_BELOW_ThreadBase_Mutex
-
-#define EXCLUDES_BELOW_PatchCommandThread_Mutex \
-    EXCLUDES_ThreadBase_Mutex
-#define EXCLUDES_PatchCommandThread_Mutex \
-    EXCLUDES(android::audio_utils::PatchCommandThread_Mutex) \
-    EXCLUDES_BELOW_PatchCommandThread_Mutex
-
-#define EXCLUDES_BELOW_DeviceEffectManager_Mutex \
-    EXCLUDES_PatchCommandThread_Mutex
-#define EXCLUDES_DeviceEffectManager_Mutex \
-    EXCLUDES(android::audio_utils::DeviceEffectManager_Mutex) \
-    EXCLUDES_BELOW_DeviceEffectManager_Mutex
-
-#define EXCLUDES_BELOW_AudioFlinger_HardwareMutex \
-    EXCLUDES_DeviceEffectManager_Mutex
-#define EXCLUDES_AudioFlinger_HardwareMutex \
-    EXCLUDES(android::audio_utils::AudioFlinger_HardwareMutex) \
-    EXCLUDES_BELOW_AudioFlinger_HardwareMutex
-
-#define EXCLUDES_BELOW_EffectHandle_Mutex \
-    EXCLUDES_AudioFlinger_HardwareMutex
-#define EXCLUDES_EffectHandle_Mutex \
-    EXCLUDES(android::audio_utils::EffectHandle_Mutex) \
-    EXCLUDES_BELOW_EffectHandle_Mutex
-
-#define EXCLUDES_BELOW_AudioFlinger_Mutex \
-    EXCLUDES_EffectHandle_Mutex
-#define EXCLUDES_AudioFlinger_Mutex \
-    EXCLUDES(android::audio_utils::AudioFlinger_Mutex) \
-    EXCLUDES_BELOW_AudioFlinger_Mutex
-
-#define EXCLUDES_AUDIO_ALL \
-    EXCLUDES_AudioFlinger_Mutex
-
-// --- End generated section
-
 } // namespace android::audio_utils
 
 #pragma pop_macro("LOG_TAG")
diff --git a/audio_utils/mutex.cpp b/audio_utils/mutex.cpp
index 98a062e..a3fed47 100644
--- a/audio_utils/mutex.cpp
+++ b/audio_utils/mutex.cpp
@@ -15,14 +15,13 @@
  */
 
 #define LOG_TAG "audio_utils::mutex"
+#include <utils/Log.h>
 
-#include <audio_utils/mutex.h>
 #include <com_android_media_audio_flags.h>
 
 namespace android::audio_utils {
 
-/*static*/
-bool mutex::get_enable_flag() {
+bool mutex_get_enable_flag() {
     static const bool enable = []() {
         const bool flag = com::android::media::audio::flags::mutex_priority_inheritance();
         ALOGD("get_enable_flag: mutex_priority_inheritance: %s", flag ? "true" : "false");
diff --git a/audio_utils/tests/generate_mutex_order.cpp b/audio_utils/tests/generate_mutex_order.cpp
index 29cea79..0f9f45d 100644
--- a/audio_utils/tests/generate_mutex_order.cpp
+++ b/audio_utils/tests/generate_mutex_order.cpp
@@ -41,8 +41,10 @@
   // 4) AudioFlinger -> ThreadBase -> EffectChain -> EffectBase(EffectModule)
   // 5) EffectHandle -> ThreadBase -> EffectChain -> EffectBase(EffectModule)
 
-  "AudioFlinger_Mutex",
   "EffectHandle_Mutex",
+  "EffectBase_PolicyMutex",  // held for AudioSystem::registerEffect, must come
+                             // after EffectHandle_Mutex.
+  "AudioFlinger_Mutex",
   "AudioFlinger_HardwareMutex",
   "DeviceEffectManager_Mutex",
   "PatchCommandThread_Mutex",
@@ -50,6 +52,7 @@
   "AudioFlinger_ClientMutex",
   "MelReporter_Mutex",
   "EffectChain_Mutex",
+  "DeviceEffectProxy_ProxyMutex",  // used for device effects (which have no chain).
   "EffectBase_Mutex",
 
   // These mutexes are in leaf objects
@@ -62,6 +65,10 @@
   "PassthruPatchRecord_ReadMutex",
   "PatchCommandThread_ListenerMutex",
   "PlaybackThread_AudioTrackCbMutex",
+  "MediaLogNotifier_Mutex",
+  "OtherMutex", // DO NOT CHANGE THIS: OtherMutex is used for mutexes without a specified order.
+                // An OtherMutex will always be the lowest order mutex and cannot acquire
+                // another named mutex while being held.
 };
 
 using namespace std;
@@ -70,7 +77,28 @@
 // ordering and exclusion as listed above.
 
 int main() {
-  cout << "// Capabilities in priority order\n"
+  cout << "// Lock order\n";
+  cout << "enum class MutexOrder : uint32_t {\n";
+
+  for (size_t i = 0; i < size(mutexes); ++i) {
+      cout << "    k" << mutexes[i] << " = " << i << ",\n";
+  }
+  cout << "    kSize = " << size(mutexes) << ",\n";
+  cout << "};\n";
+
+  cout << "\n// Lock by name\n";
+  cout << "inline constexpr const char* const gMutexNames[] = {\n";
+  for (size_t i = 0; i < size(mutexes); ++i) {
+      cout << "    \"" << mutexes[i] << "\",\n";
+  }
+  cout << "};\n";
+
+  cout << "\n// Forward declarations\n";
+  cout << "class AudioMutexAttributes;\n";
+  cout << "template <typename T> class mutex_impl;\n";
+  cout << "using mutex = mutex_impl<AudioMutexAttributes>;\n";
+
+  cout << "\n// Capabilities in priority order\n"
        << "// (declaration only, value is nullptr)\n";
   const char *last = nullptr;
   for (auto mutex : mutexes) {