aaudio: enable exclusive MMAP mode support

Allow exclusive MMAP mode only if the HAL indicates
that the FD returned for shared memory buffer can be shared
with any application.

NOTE: the way the HAL indicates this is temporary until the audio
HAL is modified in next HIDL release.

Bug: 37167970
Test: check playback and capture in mmap exclusive and shared mode
Change-Id: I09c1461b2f99532ded2ef9d36d483b82096fda68
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
index 892792d..f1593fe 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
@@ -48,8 +48,8 @@
     //aaudio_performance_mode_t requestedPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
     const aaudio_performance_mode_t requestedPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
     //aaudio_performance_mode_t requestedPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
-    const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_SHARED;
-    //const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+    //const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_SHARED;
+    const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
     aaudio_sharing_mode_t actualSharingMode;
 
     AAudioStream *aaudioStream = nullptr;
@@ -70,7 +70,7 @@
 
     printf("%s - Monitor input level using AAudio\n", argv[0]);
 
-//    AAudio_setMMapPolicy(AAUDIO_POLICY_ALWAYS);
+    AAudio_setMMapPolicy(AAUDIO_POLICY_ALWAYS);
 
     recorder.setPerformanceMode(requestedPerformanceMode);
     recorder.setSharingMode(requestedSharingMode);
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index d4cb407..b9269e6 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -27,15 +27,15 @@
 #define SAMPLE_RATE           48000
 #define NUM_SECONDS           4
 
-#define MMAP_POLICY              AAUDIO_UNSPECIFIED
+//#define MMAP_POLICY              AAUDIO_UNSPECIFIED
 //#define MMAP_POLICY              AAUDIO_POLICY_NEVER
 //#define MMAP_POLICY              AAUDIO_POLICY_AUTO
-//#define MMAP_POLICY              AAUDIO_POLICY_ALWAYS
+#define MMAP_POLICY              AAUDIO_POLICY_ALWAYS
 
 #define REQUESTED_FORMAT         AAUDIO_FORMAT_PCM_I16
 
-#define REQUESTED_SHARING_MODE   AAUDIO_SHARING_MODE_SHARED
-//#define REQUESTED_SHARING_MODE   AAUDIO_SHARING_MODE_EXCLUSIVE
+//#define REQUESTED_SHARING_MODE   AAUDIO_SHARING_MODE_SHARED
+#define REQUESTED_SHARING_MODE   AAUDIO_SHARING_MODE_EXCLUSIVE
 
 
 int main(int argc, char **argv)
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index e40f4f9..8b30aa6 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -115,6 +115,7 @@
         setSampleRate(configuration.getSampleRate());
         setSamplesPerFrame(configuration.getSamplesPerFrame());
         setDeviceId(configuration.getDeviceId());
+        setSharingMode(configuration.getSharingMode());
 
         // Save device format so we can do format conversion and volume scaling together.
         mDeviceFormat = configuration.getAudioFormat();
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index cfcfb11..8f89051 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -107,7 +107,7 @@
     }
 
     if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
-        serviceStream = new AAudioServiceStreamMMAP();
+        serviceStream = new AAudioServiceStreamMMAP(mCachedUserId);
         result = serviceStream->open(request, configurationOutput);
         if (result != AAUDIO_OK) {
             // fall back to using a shared stream
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index 40093eb..da7cdf7 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -41,11 +41,12 @@
  * Service Stream that uses an MMAP buffer.
  */
 
-AAudioServiceStreamMMAP::AAudioServiceStreamMMAP()
+AAudioServiceStreamMMAP::AAudioServiceStreamMMAP(uid_t serviceUid)
         : AAudioServiceStreamBase()
         , mMmapStreamCallback(new MyMmapStreamCallback(*this))
         , mPreviousFrameCounter(0)
-        , mMmapStream(nullptr) {
+        , mMmapStream(nullptr)
+        , mCachedUserId(serviceUid) {
 }
 
 AAudioServiceStreamMMAP::~AAudioServiceStreamMMAP() {
@@ -153,10 +154,29 @@
               status);
         return AAUDIO_ERROR_UNAVAILABLE;
     } else {
-        ALOGD("createMmapBuffer status %d shared_address = %p buffer_size %d burst_size %d",
+        ALOGD("createMmapBuffer status %d shared_address = %p buffer_size %d burst_size %d"
+                "Sharable FD: %s",
               status, mMmapBufferinfo.shared_memory_address,
-              mMmapBufferinfo.buffer_size_frames,
-              mMmapBufferinfo.burst_size_frames);
+              abs(mMmapBufferinfo.buffer_size_frames),
+              mMmapBufferinfo.burst_size_frames,
+              mMmapBufferinfo.buffer_size_frames < 0 ? "Yes" : "No");
+    }
+
+    mCapacityInFrames = mMmapBufferinfo.buffer_size_frames;
+    // FIXME: the audio HAL indicates if the shared memory fd can be shared outside of audioserver
+    // by returning a negative buffer size
+    if (mCapacityInFrames < 0) {
+        // Exclusive mode is possible from any client
+        mCapacityInFrames = -mCapacityInFrames;
+    } else {
+        // exclusive mode is only possible if the final fd destination is inside audioserver
+        if ((mMmapClient.clientUid != mCachedUserId) &&
+                configurationInput.getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
+            // Fallback is handled by caller but indicate what is possible in case
+            // this is used in the future
+            configurationOutput.setSharingMode(AAUDIO_SHARING_MODE_SHARED);
+            return AAUDIO_ERROR_UNAVAILABLE;
+        }
     }
 
     // Get information about the stream and pass it back to the caller.
@@ -166,7 +186,6 @@
 
     mAudioDataFileDescriptor = mMmapBufferinfo.shared_memory_fd;
     mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
-    mCapacityInFrames = mMmapBufferinfo.buffer_size_frames;
     mAudioFormat = AAudioConvert_androidToAAudioDataFormat(config.format);
     mSampleRate = config.sample_rate;
 
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index fe75a10..337252d 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -43,7 +43,7 @@
     , public android::MmapStreamCallback {
 
 public:
-    AAudioServiceStreamMMAP();
+    AAudioServiceStreamMMAP(uid_t serviceUid);
     virtual ~AAudioServiceStreamMMAP();
 
 
@@ -134,6 +134,7 @@
     struct audio_mmap_buffer_info             mMmapBufferinfo;
     android::MmapStreamInterface::Client      mMmapClient;
     audio_port_handle_t                       mPortHandle = -1; // TODO review best default
+    uid_t                                     mCachedUserId = -1;
 };
 
 } // namespace aaudio