Add interface to query the mmap support.

Currently, the mmap support is defined in system property. But the
vendor may set the values wrongly which may cause some CTS tests fail.
These values are best known by the HAL. In that case, add interface to
query MMAP support.

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: Ida9060b93fa3315031fc451bdea2004ba95207e7
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..e0740de 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -17,20 +17,26 @@
 #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>
+#include <binder/IInterface.h>
 #include <hidl/HidlTransportSupport.h>
 #include <mediautils/LimitProcessMemory.h>
 #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 +152,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 0a26051..921e2d2 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -331,6 +331,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/AudioMode.aidl",
         "aidl/android/media/AudioOffloadInfo.aidl",
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 057befd..be0dff8 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2353,6 +2353,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 ee64894..566f77c 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -17,6 +17,9 @@
 
 #define LOG_TAG "IAudioFlinger"
 //#define LOG_NDEBUG 0
+
+#include <algorithm>
+
 #include <utils/Log.h>
 
 #include <stdint.h>
@@ -777,6 +780,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
@@ -1249,4 +1258,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 7b02a9d..de859b8 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.AudioMode;
 import android.media.AudioPatch;
 import android.media.AudioPort;
@@ -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 50ab42a..0da8186 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -19,6 +19,8 @@
 
 #include <sys/types.h>
 
+#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>
@@ -613,6 +615,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 a74661a..03ad9b0 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,
         };
 
         /**
@@ -641,6 +652,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..ed39231 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -23,6 +23,8 @@
         "EffectHalHidl.cpp",
         "EffectsFactoryHalHidl.cpp",
         "StreamHalHidl.cpp",
+
+        "PropertyUtils.cpp",
     ],
 
     cflags: [
@@ -50,6 +52,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..e4ab46f 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>
@@ -32,6 +33,7 @@
 #include "DeviceHalHidl.h"
 #include "EffectHalHidl.h"
 #include "ParameterUtils.h"
+#include "PropertyUtils.h"
 #include "StreamHalHidl.h"
 
 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
@@ -457,6 +459,14 @@
 }
 #endif
 
+status_t DeviceHalHidl::getMmapPolicyInfos(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *policyInfos) {
+    // TODO: this is just for test, faking a data by querying the system property.
+    // When AIDL HAL is ready, this should query AIDL HAL when possible.
+    return utils::getMmapPolicyInfosFromSystemProperty(policyType, policyInfos);
+}
+
 status_t DeviceHalHidl::dump(int fd, const Vector<String16>& args) {
     if (mDevice == 0) return NO_INIT;
     native_handle_t* hidlHandle = native_handle_create(1, 0);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 2694ab3..b93390b 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -119,6 +119,10 @@
     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,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos) override;
+
     status_t dump(int fd, const Vector<String16>& args) override;
 
   private:
diff --git a/media/libaudiohal/impl/DeviceHalLocal.cpp b/media/libaudiohal/impl/DeviceHalLocal.cpp
index e0304af..bc37886 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.cpp
+++ b/media/libaudiohal/impl/DeviceHalLocal.cpp
@@ -20,6 +20,7 @@
 #include <utils/Log.h>
 
 #include "DeviceHalLocal.h"
+#include "PropertyUtils.h"
 #include "StreamHalLocal.h"
 
 namespace android {
@@ -233,6 +234,12 @@
     return INVALID_OPERATION;
 }
 
+status_t DeviceHalLocal::getMmapPolicyInfos(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *policyInfos) {
+    return utils::getMmapPolicyInfosFromSystemProperty(policyType, policyInfos);
+}
+
 status_t DeviceHalLocal::dump(int fd, const Vector<String16>& /* args */) {
     return mDev->dump(mDev, fd);
 }
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 2fde936..869b1b7 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -112,6 +112,10 @@
     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,
+            std::vector<media::AudioMMapPolicyInfo> *policyInfos) override;
+
     status_t dump(int fd, const Vector<String16>& args) override;
 
     void closeOutputStream(struct audio_stream_out *stream_out);
diff --git a/media/libaudiohal/impl/PropertyUtils.cpp b/media/libaudiohal/impl/PropertyUtils.cpp
new file mode 100644
index 0000000..55eec2b
--- /dev/null
+++ b/media/libaudiohal/impl/PropertyUtils.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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 <android/media/AudioMMapPolicy.h>
+#include <cutils/properties.h>
+
+#include "PropertyUtils.h"
+
+namespace android {
+namespace CPP_VERSION {
+namespace utils {
+
+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 "";
+    }
+}
+
+#define MMAP_POLICY_UNSPECIFIED 0
+#define MMAP_POLICY_NEVER 1
+#define MMAP_POLICY_AUTO 2
+#define MMAP_POLICY_ALWAYS 3
+
+int getDefaultPolicyFromType(media::AudioMMapPolicyType policyType) {
+    switch (policyType) {
+        case media::AudioMMapPolicyType::EXCLUSIVE:
+            return MMAP_POLICY_UNSPECIFIED;
+        case media::AudioMMapPolicyType::DEFAULT:
+        default:
+            return MMAP_POLICY_NEVER;
+    }
+}
+
+media::AudioMMapPolicy legacy2aidlAudioMMapPolicy(int legacy) {
+    switch (legacy) {
+        case MMAP_POLICY_NEVER:
+            return media::AudioMMapPolicy::NEVER;
+        case MMAP_POLICY_AUTO:
+            return media::AudioMMapPolicy::AUTO;
+        case MMAP_POLICY_ALWAYS:
+            return media::AudioMMapPolicy::ALWAYS;
+        case MMAP_POLICY_UNSPECIFIED:
+        default:
+            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 = utils::legacy2aidlAudioMMapPolicy(
+            property_get_int32(propertyStr.c_str(), utils::getDefaultPolicyFromType(policyType)));
+    policyInfos->push_back(policyInfo);
+    return NO_ERROR;
+}
+
+} // namespace utils
+} // namespace CPP_VERSION
+} // namespace android
\ No newline at end of file
diff --git a/media/libaudiohal/impl/PropertyUtils.h b/media/libaudiohal/impl/PropertyUtils.h
new file mode 100644
index 0000000..b9d0057
--- /dev/null
+++ b/media/libaudiohal/impl/PropertyUtils.h
@@ -0,0 +1,32 @@
+/*
+ * 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 {
+namespace CPP_VERSION {
+namespace utils {
+
+status_t getMmapPolicyInfosFromSystemProperty(
+        media::AudioMMapPolicyType policyType,
+        std::vector<media::AudioMMapPolicyInfo> *policyInfos);
+
+} // namespace utils
+} // namespace CPP_VERSION
+} // namespace android
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: