Add interface to query the mmap support.

Currently, the mmap support is defined in system property. But the
system property only indicates if the mmap is supported or not. It
doesn't indicate on which device mmap is supported. In that case, adding
an interface to query the mmap support can help make things clear.

Test: atest AAudioTests
Test: Run OboeTester TEST OUTPUT
Test: Verify that MMAP is showed as enabled if supported
Test: Try toggling MMAP on and off when opening streams
Bug: 193275465
Change-Id: Iac289c1a02e6e2ab4076ab6f2b5045efecad97ac
diff --git a/media/audioserver/Android.bp b/media/audioserver/Android.bp
index be25ffb..e4fc4de 100644
--- a/media/audioserver/Android.bp
+++ b/media/audioserver/Android.bp
@@ -26,6 +26,7 @@
 
     shared_libs: [
         "libaaudioservice",
+        "libaudioclient",
         "libaudioflinger",
         "libaudiopolicyservice",
         "libaudioprocessing",
@@ -41,7 +42,6 @@
         "libpowermanager",
         "libutils",
         "libvibrator",
-
     ],
 
     // TODO check if we still need all of these include directories
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 8ee1efb..fd66573 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -17,11 +17,17 @@
 #define LOG_TAG "audioserver"
 //#define LOG_NDEBUG 0
 
+#include <algorithm>
+
 #include <fcntl.h>
 #include <sys/prctl.h>
 #include <sys/wait.h>
 #include <cutils/properties.h>
 
+#include <android/media/AudioMMapPolicy.h>
+#include <android/media/AudioMMapPolicyInfo.h>
+#include <android/media/AudioMMapPolicyType.h>
+#include <android/media/IAudioFlingerService.h>
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
@@ -30,7 +36,6 @@
 #include <utils/Log.h>
 
 // from include_dirs
-#include "aaudio/AAudioTesting.h" // aaudio_policy_t, AAUDIO_PROP_MMAP_POLICY, AAUDIO_POLICY_*
 #include "AudioFlinger.h"
 #include "AudioPolicyService.h"
 #include "AAudioService.h"
@@ -146,10 +151,24 @@
         // AAudioService should only be used in OC-MR1 and later.
         // And only enable the AAudioService if the system MMAP policy explicitly allows it.
         // This prevents a client from misusing AAudioService when it is not supported.
-        aaudio_policy_t mmapPolicy = property_get_int32(AAUDIO_PROP_MMAP_POLICY,
-                                                        AAUDIO_POLICY_NEVER);
-        if (mmapPolicy == AAUDIO_POLICY_AUTO || mmapPolicy == AAUDIO_POLICY_ALWAYS) {
+        // If we cannot get audio flinger here, there must be some serious problems. In that case,
+        // attempting to call audio flinger on a null pointer could make the process crash
+        // and attract attentions.
+        sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+        std::vector<media::AudioMMapPolicyInfo> policyInfos;
+        status_t status = af->getMmapPolicyInfos(
+                media::AudioMMapPolicyType::DEFAULT, &policyInfos);
+        // Initialize aaudio service when querying mmap policy succeeds and
+        // any of the policy supports MMAP.
+        if (status == NO_ERROR &&
+            std::any_of(policyInfos.begin(), policyInfos.end(), [](const auto& info) {
+                    return info.mmapPolicy == media::AudioMMapPolicy::AUTO ||
+                           info.mmapPolicy == media::AudioMMapPolicy::ALWAYS;
+            })) {
             AAudioService::instantiate();
+        } else {
+            ALOGD("Do not init aaudio service, status %d, policy info size %zu",
+                  status, policyInfos.size());
         }
 
         ProcessState::self()->startThreadPool();
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index a8fd0d9..2a6b235 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -20,9 +20,14 @@
 
 #include <new>
 #include <stdint.h>
+#include <vector>
 
 #include <aaudio/AAudio.h>
 #include <aaudio/AAudioTesting.h>
+#include <android/media/AudioMMapPolicy.h>
+#include <android/media/AudioMMapPolicyInfo.h>
+#include <android/media/AudioMMapPolicyType.h>
+#include <media/AudioSystem.h>
 
 #include "binding/AAudioBinderClient.h"
 #include "client/AudioStreamInternalCapture.h"
@@ -86,6 +91,37 @@
     return result;
 }
 
+namespace {
+
+aaudio_policy_t aidl2legacy_aaudio_policy(android::media::AudioMMapPolicy aidl) {
+    switch (aidl) {
+        case android::media::AudioMMapPolicy::NEVER:
+            return AAUDIO_POLICY_NEVER;
+        case android::media::AudioMMapPolicy::AUTO:
+            return AAUDIO_POLICY_AUTO;
+        case android::media::AudioMMapPolicy::ALWAYS:
+            return AAUDIO_POLICY_ALWAYS;
+        case android::media::AudioMMapPolicy::UNSPECIFIED:
+        default:
+            return AAUDIO_UNSPECIFIED;
+    }
+}
+
+// The aaudio policy will be ALWAYS, NEVER, UNSPECIFIED only when all policy info are
+// ALWAYS, NEVER or UNSPECIFIED. Otherwise, the aaudio policy will be AUTO.
+aaudio_policy_t getAAudioPolicy(
+        const std::vector<android::media::AudioMMapPolicyInfo>& policyInfos) {
+    if (policyInfos.empty()) return AAUDIO_POLICY_AUTO;
+    for (size_t i = 1; i < policyInfos.size(); ++i) {
+        if (policyInfos.at(i).mmapPolicy != policyInfos.at(0).mmapPolicy) {
+            return AAUDIO_POLICY_AUTO;
+        }
+    }
+    return aidl2legacy_aaudio_policy(policyInfos.at(0).mmapPolicy);
+}
+
+} // namespace
+
 // Try to open using MMAP path if that is allowed.
 // Fall back to Legacy path if MMAP not available.
 // Exact behavior is controlled by MMapPolicy.
@@ -104,25 +140,32 @@
         return result;
     }
 
+    std::vector<android::media::AudioMMapPolicyInfo> policyInfos;
     // The API setting is the highest priority.
     aaudio_policy_t mmapPolicy = AudioGlobal_getMMapPolicy();
     // If not specified then get from a system property.
-    if (mmapPolicy == AAUDIO_UNSPECIFIED) {
-        mmapPolicy = AAudioProperty_getMMapPolicy();
+    if (mmapPolicy == AAUDIO_UNSPECIFIED && android::AudioSystem::getMmapPolicyInfo(
+                android::media::AudioMMapPolicyType::DEFAULT, &policyInfos) == NO_ERROR) {
+        mmapPolicy = getAAudioPolicy(policyInfos);
     }
     // If still not specified then use the default.
     if (mmapPolicy == AAUDIO_UNSPECIFIED) {
         mmapPolicy = AAUDIO_MMAP_POLICY_DEFAULT;
     }
 
-    int32_t mapExclusivePolicy = AAudioProperty_getMMapExclusivePolicy();
-    if (mapExclusivePolicy == AAUDIO_UNSPECIFIED) {
-        mapExclusivePolicy = AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT;
+    policyInfos.clear();
+    aaudio_policy_t mmapExclusivePolicy = AAUDIO_UNSPECIFIED;
+    if (android::AudioSystem::getMmapPolicyInfo(
+            android::media::AudioMMapPolicyType::EXCLUSIVE, &policyInfos) == NO_ERROR) {
+        mmapExclusivePolicy = getAAudioPolicy(policyInfos);
+    }
+    if (mmapExclusivePolicy == AAUDIO_UNSPECIFIED) {
+        mmapExclusivePolicy = AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT;
     }
 
     aaudio_sharing_mode_t sharingMode = getSharingMode();
     if ((sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE)
-        && (mapExclusivePolicy == AAUDIO_POLICY_NEVER)) {
+        && (mmapExclusivePolicy == AAUDIO_POLICY_NEVER)) {
         ALOGD("%s() EXCLUSIVE sharing mode not supported. Use SHARED.", __func__);
         sharingMode = AAUDIO_SHARING_MODE_SHARED;
         setSharingMode(sharingMode);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 322f360..8ea3f32 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -325,6 +325,9 @@
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
         "aidl/android/media/AudioIoFlags.aidl",
+        "aidl/android/media/AudioMMapPolicy.aidl",
+        "aidl/android/media/AudioMMapPolicyInfo.aidl",
+        "aidl/android/media/AudioMMapPolicyType.aidl",
         "aidl/android/media/AudioMixLatencyClass.aidl",
         "aidl/android/media/AudioOutputFlags.aidl",
         "aidl/android/media/AudioPatch.aidl",
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 46ad296..97cb9af 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2359,6 +2359,16 @@
     return af->setVibratorInfos(vibratorInfos);
 }
 
+status_t AudioSystem::getMmapPolicyInfo(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *policyInfos) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == nullptr) {
+        return PERMISSION_DENIED;
+    }
+    return af->getMmapPolicyInfos(policyType, policyInfos);
+}
+
 // ---------------------------------------------------------------------------
 
 int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index b67f1f7..fdec918 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -17,6 +17,7 @@
 
 #define LOG_TAG "IAudioFlinger"
 //#define LOG_NDEBUG 0
+
 #include <utils/Log.h>
 
 #include <stdint.h>
@@ -780,6 +781,12 @@
     return statusTFromBinderStatus(mDelegate->updateSecondaryOutputs(trackSecondaryOutputInfos));
 }
 
+status_t AudioFlingerClientAdapter::getMmapPolicyInfos(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *policyInfos) {
+    return statusTFromBinderStatus(mDelegate->getMmapPolicyInfos(policyType, policyInfos));
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // AudioFlingerServerAdapter
@@ -1252,4 +1259,10 @@
     return Status::fromStatusT(mDelegate->updateSecondaryOutputs(trackSecondaryOutputs));
 }
 
+Status AudioFlingerServerAdapter::getMmapPolicyInfos(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *_aidl_return) {
+    return Status::fromStatusT(mDelegate->getMmapPolicyInfos(policyType, _aidl_return));
+}
+
 } // namespace android
diff --git a/media/libaudioclient/aidl/android/media/AudioMMapPolicy.aidl b/media/libaudioclient/aidl/android/media/AudioMMapPolicy.aidl
new file mode 100644
index 0000000..e3fa951
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMMapPolicy.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+/**
+ * Audio MMAP policy describe how the aaudio MMAP feature is used.
+ * {@hide}
+ */
+@Backing(type="int")
+enum AudioMMapPolicy {
+    /**
+     * The policy is unspecified.
+     */
+    UNSPECIFIED = 0,
+    /**
+     * The MMAP feature is disabled and never used.
+     */
+    NEVER       = 1,
+    /**
+     * If MMAP feature works then uses it. Otherwise, fall back to something else.
+     */
+    AUTO        = 2,
+    /**
+     * The MMAP feature must be used. If not available then fail.
+     */
+    ALWAYS      = 3,
+}
\ No newline at end of file
diff --git a/media/libaudioclient/aidl/android/media/AudioMMapPolicyInfo.aidl b/media/libaudioclient/aidl/android/media/AudioMMapPolicyInfo.aidl
new file mode 100644
index 0000000..ad7bd45
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMMapPolicyInfo.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+import android.media.AudioDevice;
+import android.media.AudioMMapPolicy;
+
+/**
+ * Audio MMAP policy info describes how an aaudio MMAP feature can be
+ * used on a particular device.
+ * {@hide}
+ */
+parcelable AudioMMapPolicyInfo {
+    AudioDevice device;
+    AudioMMapPolicy mmapPolicy = AudioMMapPolicy.UNSPECIFIED;
+}
\ No newline at end of file
diff --git a/media/libaudioclient/aidl/android/media/AudioMMapPolicyType.aidl b/media/libaudioclient/aidl/android/media/AudioMMapPolicyType.aidl
new file mode 100644
index 0000000..d6acd2c
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMMapPolicyType.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+/**
+ * The aaudio MMAP policy type.
+ * {@hide}
+ */
+@Backing(type="int")
+enum AudioMMapPolicyType {
+    /**
+     * Default aaudio mmap policy. It is used to query whether the
+     * aaudio MMAP could be used or not.
+     */
+    DEFAULT    = 1,
+    /**
+     * Exclusive aaudio mmap policy. It is used to query whether the
+     * aaudio MMAP could be used in exclusive mode or not.
+     */
+    EXCLUSIVE  = 2,
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 0f84af6..7a46f48 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.media.AudioMMapPolicyInfo;
+import android.media.AudioMMapPolicyType;
 import android.media.AudioPatch;
 import android.media.AudioPort;
 import android.media.AudioPortConfig;
@@ -217,4 +219,6 @@
     // This usually happens when there is a dynamic policy registered.
     void updateSecondaryOutputs(
             in TrackSecondaryOutputInfo[] trackSecondaryOutputInfos);
+
+    AudioMMapPolicyInfo[] getMmapPolicyInfos(AudioMMapPolicyType policyType);
 }
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 3c610af..c546dfb 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -22,6 +22,8 @@
 #include <set>
 #include <vector>
 
+#include <android/media/AudioMMapPolicyInfo.h>
+#include <android/media/AudioMMapPolicyType.h>
 #include <android/media/AudioVibratorInfo.h>
 #include <android/media/BnAudioFlingerClient.h>
 #include <android/media/BnAudioPolicyServiceClient.h>
@@ -614,6 +616,10 @@
 
     static status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
 
+    static status_t getMmapPolicyInfo(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos);
+
 private:
 
     class AudioFlingerClient: public IBinder::DeathRecipient, public media::BnAudioFlingerClient
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 25ded38..774e907 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -37,6 +37,8 @@
 #include <string>
 #include <vector>
 
+#include <android/media/AudioMMapPolicyInfo.h>
+#include <android/media/AudioMMapPolicyType.h>
 #include <android/media/AudioVibratorInfo.h>
 #include <android/media/BnAudioFlingerService.h>
 #include <android/media/BpAudioFlingerService.h>
@@ -348,6 +350,10 @@
 
     virtual status_t updateSecondaryOutputs(
             const TrackSecondaryOutputsMap& trackSecondaryOutputs) = 0;
+
+    virtual status_t getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos) = 0;
 };
 
 /**
@@ -445,6 +451,10 @@
     status_t updateSecondaryOutputs(
             const TrackSecondaryOutputsMap& trackSecondaryOutputs) override;
 
+    status_t getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos) override;
+
 private:
     const sp<media::IAudioFlingerService> mDelegate;
 };
@@ -529,6 +539,7 @@
             SET_AUDIO_HAL_PIDS = media::BnAudioFlingerService::TRANSACTION_setAudioHalPids,
             SET_VIBRATOR_INFOS = media::BnAudioFlingerService::TRANSACTION_setVibratorInfos,
             UPDATE_SECONDARY_OUTPUTS = media::BnAudioFlingerService::TRANSACTION_updateSecondaryOutputs,
+            GET_MMAP_POLICY_INFOS = media::BnAudioFlingerService::TRANSACTION_getMmapPolicyInfos,
         };
 
         /**
@@ -643,6 +654,9 @@
     Status setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
     Status updateSecondaryOutputs(
             const std::vector<media::TrackSecondaryOutputInfo>& trackSecondaryOutputInfos) override;
+    Status getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *_aidl_return) override;
 
 private:
     const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index bd24c84..5fe74f9 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -30,6 +30,7 @@
     ],
 
     shared_libs: [
+        "audioclient-types-aidl-cpp",
         "libdl",
         "libhidlbase",
         "liblog",
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index a2c6e8a..d6576f5 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -50,6 +50,7 @@
         "libmedia_helper",
         "libmediautils",
         "libutils",
+        "audioclient-types-aidl-cpp",
     ],
     header_libs: [
         "android.hardware.audio.common.util@all-versions",
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index aa94eea..47acb19 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -20,6 +20,7 @@
 //#define LOG_NDEBUG 0
 
 #include <cutils/native_handle.h>
+#include <cutils/properties.h>
 #include <hwbinder/IPCThreadState.h>
 #include <media/AudioContainers.h>
 #include <utils/Log.h>
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 2694ab3..7b4dd88 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -119,6 +119,13 @@
     status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
     status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
 
+    status_t getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType __unused,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos __unused) override {
+        // TODO: Implement the HAL query when moving to AIDL HAL.
+        return INVALID_OPERATION;
+    }
+
     status_t dump(int fd, const Vector<String16>& args) override;
 
   private:
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 2fde936..d4bb7a0 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -112,6 +112,13 @@
     status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
     status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
 
+    status_t getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType __unused,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos __unused) override {
+        // This function will only be available on AIDL HAL.
+        return INVALID_OPERATION;
+    }
+
     status_t dump(int fd, const Vector<String16>& args) override;
 
     void closeOutputStream(struct audio_stream_out *stream_out);
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index 6f84efe..b46259b 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -46,6 +46,8 @@
 
     status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
 
+    float getHalVersion() const override { return MAJOR_VERSION + (float)MINOR_VERSION / 10; }
+
   private:
     friend class ServiceNotificationListener;
     void addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify);
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
index 568a1fb..5baefa4b 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
@@ -40,6 +40,10 @@
 
             status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
 
+            float getHalVersion() const override {
+                return MAJOR_VERSION + (float)MINOR_VERSION / 10;
+            }
+
   private:
     sp<DevicesFactoryHalInterface> mLocalFactory;
     sp<DevicesFactoryHalInterface> mHidlFactory;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalLocal.h b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
index 32bf362..d2b9104 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalLocal.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
@@ -41,6 +41,10 @@
                 return INVALID_OPERATION;
             }
 
+            float getHalVersion() const override {
+                return MAJOR_VERSION + (float)MINOR_VERSION / 10;
+            }
+
   private:
     friend class DevicesFactoryHalHybrid;
 
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 69cbcec..b93c8d2 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
 #define ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
 
+#include <android/media/AudioMMapPolicyInfo.h>
+#include <android/media/AudioMMapPolicyType.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/MicrophoneInfo.h>
 #include <system/audio.h>
@@ -120,6 +122,10 @@
     virtual status_t removeDeviceEffect(
             audio_port_handle_t device, sp<EffectHalInterface> effect) = 0;
 
+    virtual status_t getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos)  = 0;
+
     virtual status_t dump(int fd, const Vector<String16>& args) = 0;
 
   protected:
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index 5091558..17010e6 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -43,6 +43,8 @@
     // The callback can be only set once.
     virtual status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) = 0;
 
+    virtual float getHalVersion() const = 0;
+
     static sp<DevicesFactoryHalInterface> create();
 
   protected:
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index ea85d04..f401fff 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -41,6 +41,7 @@
         "FastThreadState.cpp",
         "NBAIO_Tee.cpp",
         "PatchPanel.cpp",
+        "PropertyUtils.cpp",
         "SpdifStreamOut.cpp",
         "StateQueue.cpp",
         "Threads.cpp",
@@ -92,6 +93,7 @@
     ],
 
     header_libs: [
+        "libaaudio_headers",
         "libaudioclient_headers",
         "libaudiohal_headers",
         "libmedia_headers",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1bfacd5..c8d753b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -57,6 +57,7 @@
 
 #include "AudioFlinger.h"
 #include "NBAIO_Tee.h"
+#include "PropertyUtils.h"
 
 #include <media/AudioResamplerPublic.h>
 
@@ -335,6 +336,36 @@
     return NO_ERROR;
 }
 
+#define MAX_MMAP_PROPERTY_DEVICE_HAL_VERSION 7.0
+
+status_t AudioFlinger::getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos) {
+    if (const auto it = mPolicyInfos.find(policyType); it != mPolicyInfos.end()) {
+        *policyInfos = it->second;
+        return NO_ERROR;
+    }
+    if (mDevicesFactoryHal->getHalVersion() > MAX_MMAP_PROPERTY_DEVICE_HAL_VERSION) {
+        AutoMutex lock(mHardwareLock);
+        for (size_t i = 0; i < mAudioHwDevs.size(); ++i) {
+            AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
+            std::vector<media::AudioMMapPolicyInfo> infos;
+            status_t status = dev->getMmapPolicyInfos(policyType, &infos);
+            if (status != NO_ERROR) {
+                ALOGE("Failed to query mmap policy info of %d, error %d",
+                      mAudioHwDevs.keyAt(i), status);
+                continue;
+            }
+            policyInfos->insert(policyInfos->end(), infos.begin(), infos.end());
+        }
+        mPolicyInfos[policyType] = *policyInfos;
+    } else {
+        getMmapPolicyInfosFromSystemProperty(policyType, policyInfos);
+        mPolicyInfos[policyType] = *policyInfos;
+    }
+    return NO_ERROR;
+}
+
 // getDefaultVibratorInfo_l must be called with AudioFlinger lock held.
 std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() {
     if (mAudioVibratorInfos.empty()) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index d6bf0ae..b5d587b 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -282,6 +282,10 @@
     virtual status_t updateSecondaryOutputs(
             const TrackSecondaryOutputsMap& trackSecondaryOutputs);
 
+    virtual status_t getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos);
+
     status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
         const std::function<status_t()>& delegate) override;
 
@@ -1004,6 +1008,8 @@
 
     // Keep in sync with java definition in media/java/android/media/AudioRecord.java
     static constexpr int32_t kMaxSharedAudioHistoryMs = 5000;
+
+    std::map<media::AudioMMapPolicyType, std::vector<media::AudioMMapPolicyInfo>> mPolicyInfos;
 };
 
 #undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audioflinger/AudioHwDevice.cpp b/services/audioflinger/AudioHwDevice.cpp
index 16b25f6..b996c6c9 100644
--- a/services/audioflinger/AudioHwDevice.cpp
+++ b/services/audioflinger/AudioHwDevice.cpp
@@ -103,4 +103,12 @@
 }
 
 
+
+status_t AudioHwDevice::getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos) const {
+    return mHwDevice->getMmapPolicyInfos(policyType, policyInfos);
+}
+
+
 }; // namespace android
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index fc2c693..b72072f 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -85,6 +85,10 @@
 
     status_t getAudioPort(struct audio_port_v7 *port) const;
 
+    status_t getMmapPolicyInfos(
+            media::AudioMMapPolicyType policyType,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos) const;
+
 private:
     const audio_module_handle_t mHandle;
     const char * const          mModuleName;
diff --git a/services/audioflinger/PropertyUtils.cpp b/services/audioflinger/PropertyUtils.cpp
new file mode 100644
index 0000000..b8abb8e
--- /dev/null
+++ b/services/audioflinger/PropertyUtils.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+#include <android/media/AudioMMapPolicy.h>
+#include <cutils/properties.h>
+
+#include "PropertyUtils.h"
+
+namespace android {
+
+std::string getMmapPolicyProperty(media::AudioMMapPolicyType policyType) {
+    switch (policyType) {
+        case media::AudioMMapPolicyType::DEFAULT:
+            return "aaudio.mmap_policy";
+        case media::AudioMMapPolicyType::EXCLUSIVE:
+            return "aaudio.mmap_exclusive_policy";
+        default:
+            return "";
+    }
+}
+
+int getDefaultPolicyFromType(media::AudioMMapPolicyType policyType) {
+    switch (policyType) {
+        case media::AudioMMapPolicyType::EXCLUSIVE:
+            return AAUDIO_UNSPECIFIED;
+        case media::AudioMMapPolicyType::DEFAULT:
+        default:
+            return AAUDIO_POLICY_NEVER;
+    }
+}
+
+media::AudioMMapPolicy legacy2aidl_aaudio_policy_t_AudioMMapPolicy(aaudio_policy_t legacy) {
+    switch (legacy) {
+        case AAUDIO_POLICY_NEVER:
+            return media::AudioMMapPolicy::NEVER;
+        case AAUDIO_POLICY_AUTO:
+            return media::AudioMMapPolicy::AUTO;
+        case AAUDIO_POLICY_ALWAYS:
+            return media::AudioMMapPolicy::ALWAYS;
+        case AAUDIO_UNSPECIFIED:
+            return media::AudioMMapPolicy::UNSPECIFIED;
+        default:
+            ALOGE("%s unknown aaudio policy: %d", __func__, legacy);
+            return media::AudioMMapPolicy::UNSPECIFIED;
+    }
+}
+
+status_t getMmapPolicyInfosFromSystemProperty(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *policyInfos) {
+    media::AudioMMapPolicyInfo policyInfo;
+    const std::string propertyStr = getMmapPolicyProperty(policyType);
+    if (propertyStr.empty()) {
+        return BAD_VALUE;
+    }
+    policyInfo.mmapPolicy = legacy2aidl_aaudio_policy_t_AudioMMapPolicy(
+            property_get_int32(propertyStr.c_str(), getDefaultPolicyFromType(policyType)));
+    policyInfos->push_back(policyInfo);
+    return NO_ERROR;
+}
+
+} // namespace android
diff --git a/services/audioflinger/PropertyUtils.h b/services/audioflinger/PropertyUtils.h
new file mode 100644
index 0000000..38cbf92
--- /dev/null
+++ b/services/audioflinger/PropertyUtils.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/media/AudioMMapPolicyType.h>
+#include <android/media/AudioMMapPolicyInfo.h>
+
+namespace android {
+
+status_t getMmapPolicyInfosFromSystemProperty(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *policyInfos);
+
+} // namespace android