Merge "audio_hw: close mmap file descriptor to fix leak"
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 94c9c50..6377696 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -4183,6 +4183,13 @@
             if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
                 do_stop = out->playback_started;
                 out->playback_started = false;
+
+                if (out->mmap_shared_memory_fd >= 0) {
+                    ALOGV("%s: closing mmap_shared_memory_fd = %d",
+                          __func__, out->mmap_shared_memory_fd);
+                    close(out->mmap_shared_memory_fd);
+                    out->mmap_shared_memory_fd = -1;
+                }
             }
         } else {
             ALOGD("copl(%p):standby", out);
@@ -6110,6 +6117,9 @@
         // Fall back to non exclusive mode
         info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
     } else {
+        out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
+        ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
+
         if (mmap_size < buffer_size) {
             step = "mmap";
             goto exit;
@@ -6256,6 +6266,12 @@
         } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
             do_stop = in->capture_started;
             in->capture_started = false;
+            if (in->mmap_shared_memory_fd >= 0) {
+                ALOGV("%s: closing mmap_shared_memory_fd = %d",
+                      __func__, in->mmap_shared_memory_fd);
+                close(in->mmap_shared_memory_fd);
+                in->mmap_shared_memory_fd = -1;
+            }
         } else {
             if (audio_extn_cin_attached_usecase(in->usecase))
                 audio_extn_cin_close_input_stream(in);
@@ -6984,6 +7000,9 @@
         // Fall back to non exclusive mode
         info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
     } else {
+        in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
+        ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
+
         if (mmap_size < buffer_size) {
             step = "mmap";
             goto exit;
@@ -7208,6 +7227,7 @@
     out->set_dual_mono = false;
     out->prev_card_status_offline = false;
     out->pspd_coeff_sent = false;
+    out->mmap_shared_memory_fd = -1; // not open
 
     if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
         (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
@@ -8725,6 +8745,7 @@
     in->zoom = 0;
     list_init(&in->aec_list);
     list_init(&in->ns_list);
+    in->mmap_shared_memory_fd = -1; // not open
 
     ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
     if (source == AUDIO_SOURCE_VOICE_UPLINK ||
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 9b7bf5b..ebdaa97 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -368,6 +368,7 @@
     bool muted;
     uint64_t written; /* total frames written, not cleared when entering standby */
     int64_t mmap_time_offset_nanos; /* fudge factor to correct inaccuracies in DSP */
+    int     mmap_shared_memory_fd; /* file descriptor associated with MMAP NOIRQ shared memory */
     audio_io_handle_t handle;
     struct stream_app_type_cfg app_type_cfg;
 
@@ -456,6 +457,7 @@
     struct listnode aec_list;
     struct listnode ns_list;
     int64_t mmap_time_offset_nanos; /* fudge factor to correct inaccuracies in DSP */
+    int     mmap_shared_memory_fd; /* file descriptor associated with MMAP NOIRQ shared memory */
     audio_io_handle_t capture_handle;
     audio_input_flags_t flags;
     char profile[MAX_STREAM_PROFILE_STR_LEN];