Merge "change media analytics references to media metrics"
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index bd274d8..84a6d6b 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -107,8 +107,11 @@
 
     if (useMic) {
         // talk into the appropriate microphone for the duration
+        audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+        attr.source = AUDIO_SOURCE_MIC;
+
         source = new AudioSource(
-                AUDIO_SOURCE_MIC,
+                &attr,
                 String16(),
                 sampleRate,
                 channels);
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index e0b3939..071bb74 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -50,13 +50,8 @@
     ],
 
     shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.bufferqueue@2.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
+        "android.hardware.graphics.common@1.2",
         "android.hardware.media.bufferpool@2.0",
         "libbase",
         "libcutils",
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 78ac355..3ac3d89 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -18,19 +18,21 @@
 #define LOG_TAG "C2AllocatorGralloc"
 #include <utils/Log.h>
 
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <mutex>
+
+#include <android/hardware/graphics/common/1.2/types.h>
 #include <cutils/native_handle.h>
 #include <hardware/gralloc.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
 
 #include <C2AllocatorGralloc.h>
 #include <C2Buffer.h>
 #include <C2PlatformSupport.h>
 
+using ::android::hardware::hidl_handle;
+using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
+
 namespace android {
 
 namespace /* unnamed */ {
@@ -63,82 +65,9 @@
             (expected & PASSTHROUGH_USAGE_MASK));
 }
 
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using PixelFormat2 = ::android::hardware::graphics::common::V1_0::PixelFormat;
-using PixelFormat3 = ::android::hardware::graphics::common::V1_2::PixelFormat;
-using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
-
-using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
-using BufferDescriptor2 = ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
-using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
-
-using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
-using BufferDescriptor3 = ::android::hardware::graphics::mapper::V3_0::BufferDescriptor;
-using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
-using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
-
-using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
-using BufferDescriptor4 = ::android::hardware::graphics::mapper::V4_0::BufferDescriptor;
-using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
-using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
-
 namespace /* unnamed */ {
 
-struct BufferDescriptorInfo2 {
-    IMapper2::BufferDescriptorInfo mapperInfo;
-    uint32_t stride;
-};
-
-struct BufferDescriptorInfo3 {
-    IMapper3::BufferDescriptorInfo mapperInfo;
-    uint32_t stride;
-};
-
-struct BufferDescriptorInfo4 {
-    IMapper4::BufferDescriptorInfo mapperInfo;
-    uint32_t stride;
-};
-
 /* ===================================== GRALLOC ALLOCATION ==================================== */
-c2_status_t maperr2error(Error2 maperr) {
-    switch (maperr) {
-        case Error2::NONE:           return C2_OK;
-        case Error2::BAD_DESCRIPTOR: return C2_BAD_VALUE;
-        case Error2::BAD_BUFFER:     return C2_BAD_VALUE;
-        case Error2::BAD_VALUE:      return C2_BAD_VALUE;
-        case Error2::NO_RESOURCES:   return C2_NO_MEMORY;
-        case Error2::UNSUPPORTED:    return C2_CANNOT_DO;
-    }
-    return C2_CORRUPTED;
-}
-
-c2_status_t maperr2error(Error3 maperr) {
-    switch (maperr) {
-        case Error3::NONE:           return C2_OK;
-        case Error3::BAD_DESCRIPTOR: return C2_BAD_VALUE;
-        case Error3::BAD_BUFFER:     return C2_BAD_VALUE;
-        case Error3::BAD_VALUE:      return C2_BAD_VALUE;
-        case Error3::NO_RESOURCES:   return C2_NO_MEMORY;
-        case Error3::UNSUPPORTED:    return C2_CANNOT_DO;
-    }
-    return C2_CORRUPTED;
-}
-
-c2_status_t maperr2error(Error4 maperr) {
-    switch (maperr) {
-        case Error4::NONE:           return C2_OK;
-        case Error4::BAD_DESCRIPTOR: return C2_BAD_VALUE;
-        case Error4::BAD_BUFFER:     return C2_BAD_VALUE;
-        case Error4::BAD_VALUE:      return C2_BAD_VALUE;
-        case Error4::NO_RESOURCES:   return C2_NO_MEMORY;
-        case Error4::UNSUPPORTED:    return C2_CANNOT_DO;
-    }
-    return C2_CORRUPTED;
-}
-
 bool native_handle_is_invalid(const native_handle_t *const handle) {
     // perform basic validation of a native handle
     if (handle == nullptr) {
@@ -334,21 +263,11 @@
 
     // internal methods
     // |handle| will be moved.
+
     C2AllocationGralloc(
-              const BufferDescriptorInfo2 &info,
-              const sp<IMapper2> &mapper,
-              hidl_handle &hidlHandle,
-              const C2HandleGralloc *const handle,
-              C2Allocator::id_t allocatorId);
-    C2AllocationGralloc(
-              const BufferDescriptorInfo3 &info,
-              const sp<IMapper3> &mapper,
-              hidl_handle &hidlHandle,
-              const C2HandleGralloc *const handle,
-              C2Allocator::id_t allocatorId);
-    C2AllocationGralloc(
-              const BufferDescriptorInfo4 &info,
-              const sp<IMapper4> &mapper,
+              uint32_t width, uint32_t height,
+              uint32_t format, uint32_t layerCount,
+              uint64_t grallocUsage, uint32_t stride,
               hidl_handle &hidlHandle,
               const C2HandleGralloc *const handle,
               C2Allocator::id_t allocatorId);
@@ -356,12 +275,12 @@
     c2_status_t status() const;
 
 private:
-    const BufferDescriptorInfo2 mInfo2{};
-    const sp<IMapper2> mMapper2{nullptr};
-    const BufferDescriptorInfo3 mInfo3{};
-    const sp<IMapper3> mMapper3{nullptr};
-    const BufferDescriptorInfo4 mInfo4{};
-    const sp<IMapper4> mMapper4{nullptr};
+    const uint32_t mWidth;
+    const uint32_t mHeight;
+    const uint32_t mFormat;
+    const uint32_t mLayerCount;
+    const uint64_t mGrallocUsage;
+    const uint32_t mStride;
     const hidl_handle mHidlHandle;
     const C2HandleGralloc *mHandle;
     buffer_handle_t mBuffer;
@@ -372,48 +291,19 @@
 };
 
 C2AllocationGralloc::C2AllocationGralloc(
-          const BufferDescriptorInfo2 &info,
-          const sp<IMapper2> &mapper,
+          uint32_t width, uint32_t height,
+          uint32_t format, uint32_t layerCount,
+          uint64_t grallocUsage, uint32_t stride,
           hidl_handle &hidlHandle,
           const C2HandleGralloc *const handle,
           C2Allocator::id_t allocatorId)
-    : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
-      mInfo2(info),
-      mMapper2(mapper),
-      mHidlHandle(std::move(hidlHandle)),
-      mHandle(handle),
-      mBuffer(nullptr),
-      mLockedHandle(nullptr),
-      mLocked(false),
-      mAllocatorId(allocatorId) {
-}
-
-C2AllocationGralloc::C2AllocationGralloc(
-          const BufferDescriptorInfo3 &info,
-          const sp<IMapper3> &mapper,
-          hidl_handle &hidlHandle,
-          const C2HandleGralloc *const handle,
-          C2Allocator::id_t allocatorId)
-    : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
-      mInfo3(info),
-      mMapper3(mapper),
-      mHidlHandle(std::move(hidlHandle)),
-      mHandle(handle),
-      mBuffer(nullptr),
-      mLockedHandle(nullptr),
-      mLocked(false),
-      mAllocatorId(allocatorId) {
-}
-
-C2AllocationGralloc::C2AllocationGralloc(
-          const BufferDescriptorInfo4 &info,
-          const sp<IMapper4> &mapper,
-          hidl_handle &hidlHandle,
-          const C2HandleGralloc *const handle,
-          C2Allocator::id_t allocatorId)
-    : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
-      mInfo4(info),
-      mMapper4(mapper),
+    : C2GraphicAllocation(width, height),
+      mWidth(width),
+      mHeight(height),
+      mFormat(format),
+      mLayerCount(layerCount),
+      mGrallocUsage(grallocUsage),
+      mStride(stride),
       mHidlHandle(std::move(hidlHandle)),
       mHandle(handle),
       mBuffer(nullptr),
@@ -429,23 +319,10 @@
         unmap(addr, C2Rect(), nullptr);
     }
     if (mBuffer) {
-        if (mMapper2) {
-            if (!mMapper2->freeBuffer(const_cast<native_handle_t *>(
-                    mBuffer)).isOk()) {
-                ALOGE("failed transaction: freeBuffer");
-            }
-        } else if (mMapper3) {
-            if (!mMapper3->freeBuffer(const_cast<native_handle_t *>(
-                    mBuffer)).isOk()) {
-                ALOGE("failed transaction: freeBuffer");
-            }
-        } else {
-            if (!mMapper4->freeBuffer(const_cast<native_handle_t *>(
-                    mBuffer)).isOk()) {
-                ALOGE("failed transaction: freeBuffer");
-            }
+        status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
+        if (err) {
+            ALOGE("failed transaction: freeBuffer");
         }
-
     }
     if (mHandle) {
         native_handle_delete(
@@ -466,7 +343,7 @@
           (long long)usage.expected, (long long)grallocUsage);
 
     // TODO
-    (void) fence;
+    (void)fence;
 
     std::lock_guard<std::mutex> lock(mMappedLock);
     if (mBuffer && mLocked) {
@@ -478,45 +355,13 @@
         return C2_BAD_VALUE;
     }
 
-    c2_status_t err = C2_OK;
     if (!mBuffer) {
-        if (mMapper2) {
-            if (!mMapper2->importBuffer(
-                    mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
-                        err = maperr2error(maperr);
-                        if (err == C2_OK) {
-                            mBuffer = static_cast<buffer_handle_t>(buffer);
-                        }
-                    }).isOk()) {
-                ALOGE("failed transaction: importBuffer");
-                return C2_CORRUPTED;
-            }
-        } else if (mMapper3) {
-            if (!mMapper3->importBuffer(
-                    mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
-                        err = maperr2error(maperr);
-                        if (err == C2_OK) {
-                            mBuffer = static_cast<buffer_handle_t>(buffer);
-                        }
-                    }).isOk()) {
-                ALOGE("failed transaction: importBuffer (@3.0)");
-                return C2_CORRUPTED;
-            }
-        } else {
-            if (!mMapper4->importBuffer(
-                    mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
-                        err = maperr2error(maperr);
-                        if (err == C2_OK) {
-                            mBuffer = static_cast<buffer_handle_t>(buffer);
-                        }
-                    }).isOk()) {
-                ALOGE("failed transaction: importBuffer (@4.0)");
-                return C2_CORRUPTED;
-            }
-        }
-        if (err != C2_OK) {
-            ALOGD("importBuffer failed: %d", err);
-            return err;
+        status_t err = GraphicBufferMapper::get().importBuffer(
+                            mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
+                            mFormat, mGrallocUsage, mStride, &mBuffer);
+        if (err) {
+            ALOGE("failed transaction: importBuffer");
+            return C2_CORRUPTED;
         }
         if (mBuffer == nullptr) {
             ALOGD("importBuffer returned null buffer");
@@ -528,96 +373,26 @@
         if (mHandle) {
             mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
         }
-        if (mMapper2) {
-            mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
-                    mBuffer, mInfo2.mapperInfo.width, mInfo2.mapperInfo.height,
-                    (uint32_t)mInfo2.mapperInfo.format, mInfo2.mapperInfo.usage,
-                    mInfo2.stride, generation, igbp_id, igbp_slot);
-        } else if (mMapper3) {
-            mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
-                    mBuffer, mInfo3.mapperInfo.width, mInfo3.mapperInfo.height,
-                    (uint32_t)mInfo3.mapperInfo.format, mInfo3.mapperInfo.usage,
-                    mInfo3.stride, generation, igbp_id, igbp_slot);
-        } else {
-            mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
-                    mBuffer, mInfo4.mapperInfo.width, mInfo4.mapperInfo.height,
-                    (uint32_t)mInfo4.mapperInfo.format, mInfo4.mapperInfo.usage,
-                    mInfo4.stride, generation, igbp_id, igbp_slot);
-        }
-    }
 
-    PixelFormat4 format;
-    if (mMapper2) {
-        format = PixelFormat4(mInfo2.mapperInfo.format);
-    } else if (mMapper3) {
-        format = PixelFormat4(mInfo3.mapperInfo.format);
-    } else {
-        format = PixelFormat4(mInfo4.mapperInfo.format);
+        mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
+                mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
+                mStride, generation, igbp_id, igbp_slot);
     }
-    switch (format) {
-        case PixelFormat4::RGBA_1010102: {
+    switch (mFormat) {
+        case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
             // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
             // Surface. In all other cases it is RGBA. We don't know which case it is here, so
             // default to YUV for now.
             void *pointer = nullptr;
-            if (mMapper2) {
-                if (!mMapper2->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_1010102)");
-                    return C2_CORRUPTED;
-                }
-            } else if (mMapper3) {
-                if (!mMapper3->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
-                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                            (void)bytesPerPixel;
-                            (void)bytesPerStride;
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_1010102) (@3.0)");
-                    return C2_CORRUPTED;
-                }
-            } else {
-                if (!mMapper4->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_1010102) (@4.0)");
-                    return C2_CORRUPTED;
-                }
-            }
-            if (err != C2_OK) {
-                ALOGD("lock failed: %d", err);
-                return err;
+            // TODO: fence
+            status_t err = GraphicBufferMapper::get().lock(
+                                const_cast<native_handle_t *>(mBuffer), grallocUsage,
+                                { (int32_t)rect.left, (int32_t)rect.top,
+                                  (int32_t)rect.width, (int32_t)rect.height },
+                                &pointer);
+            if (err) {
+                ALOGE("failed transaction: lock(RGBA_1010102)");
+                return C2_CORRUPTED;
             }
             // treat as 32-bit values
             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
@@ -627,18 +402,10 @@
             layout->type = C2PlanarLayout::TYPE_YUVA;
             layout->numPlanes = 4;
             layout->rootPlanes = 1;
-            int32_t stride;
-            if (mMapper2) {
-                stride = int32_t(mInfo2.stride);
-            } else if (mMapper3) {
-                stride = int32_t(mInfo3.stride);
-            } else {
-                stride = int32_t(mInfo4.stride);
-            }
             layout->planes[C2PlanarLayout::PLANE_Y] = {
                 C2PlaneInfo::CHANNEL_Y,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -651,7 +418,7 @@
             layout->planes[C2PlanarLayout::PLANE_U] = {
                 C2PlaneInfo::CHANNEL_CB,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -664,7 +431,7 @@
             layout->planes[C2PlanarLayout::PLANE_V] = {
                 C2PlaneInfo::CHANNEL_CR,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -677,7 +444,7 @@
             layout->planes[C2PlanarLayout::PLANE_A] = {
                 C2PlaneInfo::CHANNEL_A,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -690,69 +457,20 @@
             break;
         }
 
-        case PixelFormat4::RGBA_8888:
+        case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
             // TODO: alpha channel
             // fall-through
-        case PixelFormat4::RGBX_8888: {
+        case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
             void *pointer = nullptr;
-            if (mMapper2) {
-                if (!mMapper2->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_8888)");
-                    return C2_CORRUPTED;
-                }
-            } else if (mMapper3) {
-                if (!mMapper3->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
-                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                            (void)bytesPerPixel;
-                            (void)bytesPerStride;
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_8888) (@3.0)");
-                    return C2_CORRUPTED;
-                }
-            } else {
-                if (!mMapper4->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_8888) (@4.0)");
-                    return C2_CORRUPTED;
-                }
-            }
-            if (err != C2_OK) {
-                ALOGD("lock failed: %d", err);
-                return err;
+            // TODO: fence
+            status_t err = GraphicBufferMapper::get().lock(
+                                const_cast<native_handle_t*>(mBuffer), grallocUsage,
+                                { (int32_t)rect.left, (int32_t)rect.top,
+                                  (int32_t)rect.width, (int32_t)rect.height },
+                                &pointer);
+            if (err) {
+                ALOGE("failed transaction: lock(RGBA_8888)");
+                return C2_CORRUPTED;
             }
             addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
             addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
@@ -760,18 +478,10 @@
             layout->type = C2PlanarLayout::TYPE_RGB;
             layout->numPlanes = 3;
             layout->rootPlanes = 1;
-            int32_t stride;
-            if (mMapper2) {
-                stride = int32_t(mInfo2.stride);
-            } else if (mMapper3) {
-                stride = int32_t(mInfo3.stride);
-            } else {
-                stride = int32_t(mInfo4.stride);
-            }
             layout->planes[C2PlanarLayout::PLANE_R] = {
                 C2PlaneInfo::CHANNEL_R,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -784,7 +494,7 @@
             layout->planes[C2PlanarLayout::PLANE_G] = {
                 C2PlaneInfo::CHANNEL_G,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -797,7 +507,7 @@
             layout->planes[C2PlanarLayout::PLANE_B] = {
                 C2PlaneInfo::CHANNEL_B,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -810,142 +520,23 @@
             break;
         }
 
-        case PixelFormat4::BLOB: {
-            void* pointer = nullptr;
-            if (mMapper2) {
-                if (!mMapper2->lock(const_cast<native_handle_t*>(mBuffer), grallocUsage,
-                                    {(int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width,
-                                     (int32_t)rect.height},
-                                    // TODO: fence
-                                    hidl_handle(),
-                                    [&err, &pointer](const auto& maperr, const auto& mapPointer) {
-                                        err = maperr2error(maperr);
-                                        if (err == C2_OK) {
-                                            pointer = mapPointer;
-                                        }
-                                    }).isOk()) {
-                    ALOGE("failed transaction: lock(BLOB)");
-                    return C2_CORRUPTED;
-                }
-            } else if (mMapper3) {
-                if (!mMapper3->lock(
-                        const_cast<native_handle_t*>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
-                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                            (void)bytesPerPixel;
-                            (void)bytesPerStride;
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(BLOB) (@3.0)");
-                    return C2_CORRUPTED;
-                }
-            } else {
-                if (!mMapper4->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(BLOB) (@4.0)");
-                    return C2_CORRUPTED;
-                }
-            }
-            if (err != C2_OK) {
-                ALOGD("lock failed: %d", err);
-                return err;
-            }
-
-            *addr = static_cast<uint8_t*>(pointer);
-            break;
-        }
-
-        case PixelFormat4::YCBCR_420_888:
+        case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
             // fall-through
-        case PixelFormat4::YV12:
+        case static_cast<uint32_t>(PixelFormat4::YV12):
             // fall-through
         default: {
-            struct YCbCrLayout {
-                void* y;
-                void* cb;
-                void* cr;
-                uint32_t yStride;
-                uint32_t cStride;
-                uint32_t chromaStep;
-            };
-            YCbCrLayout ycbcrLayout;
-            if (mMapper2) {
-                if (!mMapper2->lockYCbCr(
-                        const_cast<native_handle_t *>(mBuffer), grallocUsage,
+            android_ycbcr ycbcrLayout;
+
+            status_t err = GraphicBufferMapper::get().lockYCbCr(
+                        const_cast<native_handle_t*>(mBuffer), grallocUsage,
                         { (int32_t)rect.left, (int32_t)rect.top,
                           (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                ycbcrLayout = YCbCrLayout{
-                                        mapLayout.y,
-                                        mapLayout.cb,
-                                        mapLayout.cr,
-                                        mapLayout.yStride,
-                                        mapLayout.cStride,
-                                        mapLayout.chromaStep};
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lockYCbCr");
-                    return C2_CORRUPTED;
-                }
-            } else if (mMapper3) {
-                if (!mMapper3->lockYCbCr(
-                        const_cast<native_handle_t *>(mBuffer), grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                ycbcrLayout = YCbCrLayout{
-                                        mapLayout.y,
-                                        mapLayout.cb,
-                                        mapLayout.cr,
-                                        mapLayout.yStride,
-                                        mapLayout.cStride,
-                                        mapLayout.chromaStep};
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lockYCbCr (@3.0)");
-                    return C2_CORRUPTED;
-                }
-            } else {
-                // No device currently supports IMapper 4.0 so it is safe to just return an error
-                // code here.
-                //
-                // This will be supported by a combination of lock and BufferMetadata getters.
-                // We are going to refactor all the IAllocator/IMapper versioning code into a
-                // shared library. We will then add the IMapper 4.0 lockYCbCr support then.
-                ALOGE("failed transaction: lockYCbCr (@4.0)");
+                        &ycbcrLayout);
+            if (err) {
+                ALOGE("failed transaction: lockYCbCr");
                 return C2_CORRUPTED;
             }
-            if (err != C2_OK) {
-                ALOGD("lockYCbCr failed: %d", err);
-                return err;
-            }
+
             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
             addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
@@ -955,7 +546,7 @@
             layout->planes[C2PlanarLayout::PLANE_Y] = {
                 C2PlaneInfo::CHANNEL_Y,         // channel
                 1,                              // colInc
-                (int32_t)ycbcrLayout.yStride,   // rowInc
+                (int32_t)ycbcrLayout.ystride,   // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -967,8 +558,8 @@
             };
             layout->planes[C2PlanarLayout::PLANE_U] = {
                 C2PlaneInfo::CHANNEL_CB,          // channel
-                (int32_t)ycbcrLayout.chromaStep,  // colInc
-                (int32_t)ycbcrLayout.cStride,     // rowInc
+                (int32_t)ycbcrLayout.chroma_step, // colInc
+                (int32_t)ycbcrLayout.cstride,     // rowInc
                 2,                                // mColSampling
                 2,                                // mRowSampling
                 8,                                // allocatedDepth
@@ -980,8 +571,8 @@
             };
             layout->planes[C2PlanarLayout::PLANE_V] = {
                 C2PlaneInfo::CHANNEL_CR,          // channel
-                (int32_t)ycbcrLayout.chromaStep,  // colInc
-                (int32_t)ycbcrLayout.cStride,     // rowInc
+                (int32_t)ycbcrLayout.chroma_step, // colInc
+                (int32_t)ycbcrLayout.cstride,     // rowInc
                 2,                                // mColSampling
                 2,                                // mRowSampling
                 8,                                // allocatedDepth
@@ -993,11 +584,11 @@
             };
             // handle interleaved formats
             intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
-            if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
+            if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
                 layout->rootPlanes = 2;
                 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
                 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
-            } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
+            } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
                 layout->rootPlanes = 2;
                 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
                 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
@@ -1015,59 +606,18 @@
     // TODO: check addr and size, use fence
     (void)addr;
     (void)rect;
+    (void)fence;
 
     std::lock_guard<std::mutex> lock(mMappedLock);
-    c2_status_t err = C2_OK;
-    if (mMapper2) {
-        if (!mMapper2->unlock(
-                const_cast<native_handle_t *>(mBuffer),
-                [&err, &fence](const auto &maperr, const auto &releaseFence) {
-                    // TODO
-                    (void) fence;
-                    (void) releaseFence;
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        // TODO: fence
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: unlock");
-            return C2_CORRUPTED;
-        }
-    } else if (mMapper3) {
-        if (!mMapper3->unlock(
-                const_cast<native_handle_t *>(mBuffer),
-                [&err, &fence](const auto &maperr, const auto &releaseFence) {
-                    // TODO
-                    (void) fence;
-                    (void) releaseFence;
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        // TODO: fence
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: unlock (@3.0)");
-            return C2_CORRUPTED;
-        }
-    } else {
-        if (!mMapper4->unlock(
-                const_cast<native_handle_t *>(mBuffer),
-                [&err, &fence](const auto &maperr, const auto &releaseFence) {
-                    // TODO
-                    (void) fence;
-                    (void) releaseFence;
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        // TODO: fence
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: unlock (@4.0)");
-            return C2_CORRUPTED;
-        }
+    // TODO: fence
+    status_t err = GraphicBufferMapper::get().unlock(mBuffer);
+    if (err) {
+        ALOGE("failed transaction: unlock");
+        return C2_CORRUPTED;
     }
-    if (err == C2_OK) {
-        mLocked = false;
-    }
-    return err;
+
+    mLocked = false;
+    return C2_OK;
 }
 
 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
@@ -1104,12 +654,6 @@
 private:
     std::shared_ptr<C2Allocator::Traits> mTraits;
     c2_status_t mInit;
-    sp<IAllocator2> mAllocator2;
-    sp<IMapper2> mMapper2;
-    sp<IAllocator3> mAllocator3;
-    sp<IMapper3> mMapper3;
-    sp<IAllocator4> mAllocator4;
-    sp<IMapper4> mMapper4;
     const bool mBufferQueue;
 };
 
@@ -1127,27 +671,6 @@
     C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
     Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
     mTraits = std::make_shared<C2Allocator::Traits>(traits);
-
-    // gralloc allocator is a singleton, so all objects share a global service
-    mAllocator4 = IAllocator4::getService();
-    mMapper4 = IMapper4::getService();
-    if (!mAllocator4 || !mMapper4) {
-        mAllocator4 = nullptr;
-        mMapper4 = nullptr;
-        mAllocator3 = IAllocator3::getService();
-        mMapper3 = IMapper3::getService();
-        if (!mAllocator3 || !mMapper3) {
-            mAllocator3 = nullptr;
-            mMapper3 = nullptr;
-            mAllocator2 = IAllocator2::getService();
-            mMapper2 = IMapper2::getService();
-            if (!mAllocator2 || !mMapper2) {
-                mAllocator2 = nullptr;
-                mMapper2 = nullptr;
-                mInit = C2_CORRUPTED;
-            }
-        }
-    }
 }
 
 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
@@ -1157,257 +680,59 @@
     ALOGV("allocating buffer with usage %#llx => %#llx",
           (long long)usage.expected, (long long)grallocUsage);
 
-    c2_status_t err = C2_OK;
-    hidl_handle buffer{};
+    buffer_handle_t buffer;
 
-    if (mMapper2) {
-        BufferDescriptorInfo2 info = {
-            {
-                width,
-                height,
-                1u,  // layerCount
-                PixelFormat2(format),
-                grallocUsage,
-            },
-            0u,  // stride placeholder
-        };
-        BufferDescriptor2 desc;
-        if (!mMapper2->createDescriptor(
-                info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        desc = descriptor;
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: createDescriptor");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
+    uint32_t stride = 0;
 
-        // IAllocator shares IMapper error codes.
-        if (!mAllocator2->allocate(
-                desc,
-                1u,
-                [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
-                    err = maperr2error(maperr);
-                    if (err != C2_OK) {
-                        return;
-                    }
-                    if (buffers.size() != 1u) {
-                        err = C2_CORRUPTED;
-                        return;
-                    }
-                    info.stride = stride;
-                    buffer = buffers[0];
-                }).isOk()) {
-            ALOGE("failed transaction: allocate");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper2, buffer,
-                C2HandleGralloc::WrapAndMoveNativeHandle(
-                        buffer.getNativeHandle(),
-                        width, height,
-                        format, grallocUsage, info.stride,
-                        0, 0, mBufferQueue ? ~0 : 0),
-                mTraits->id));
-        return C2_OK;
-    } else if (mMapper3) {
-        BufferDescriptorInfo3 info = {
-            {
-                width,
-                height,
-                1u,  // layerCount
-                PixelFormat4(format),
-                grallocUsage,
-            },
-            0u,  // stride placeholder
-        };
-        BufferDescriptor3 desc;
-        if (!mMapper3->createDescriptor(
-                info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        desc = descriptor;
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: createDescriptor");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-
-        // IAllocator shares IMapper error codes.
-        if (!mAllocator3->allocate(
-                desc,
-                1u,
-                [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
-                    err = maperr2error(maperr);
-                    if (err != C2_OK) {
-                        return;
-                    }
-                    if (buffers.size() != 1u) {
-                        err = C2_CORRUPTED;
-                        return;
-                    }
-                    info.stride = stride;
-                    buffer = buffers[0];
-                }).isOk()) {
-            ALOGE("failed transaction: allocate");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper3, buffer,
-                C2HandleGralloc::WrapAndMoveNativeHandle(
-                        buffer.getNativeHandle(),
-                        width, height,
-                        format, grallocUsage, info.stride,
-                        0, 0, mBufferQueue ? ~0 : 0),
-                mTraits->id));
-        return C2_OK;
-    } else {
-        BufferDescriptorInfo4 info = {
-            {
-                "C2GrallocAllocation",
-                width,
-                height,
-                1u,  // layerCount
-                PixelFormat4(format),
-                grallocUsage,
-            },
-            0u,  // stride placeholder
-        };
-        BufferDescriptor4 desc;
-        if (!mMapper4->createDescriptor(
-                info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        desc = descriptor;
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: createDescriptor");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-
-        // IAllocator shares IMapper error codes.
-        if (!mAllocator4->allocate(
-                desc,
-                1u,
-                [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
-                    err = maperr2error(maperr);
-                    if (err != C2_OK) {
-                        return;
-                    }
-                    if (buffers.size() != 1u) {
-                        err = C2_CORRUPTED;
-                        return;
-                    }
-                    info.stride = stride;
-                    buffer = buffers[0];
-                }).isOk()) {
-            ALOGE("failed transaction: allocate");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper4, buffer,
-                C2HandleGralloc::WrapAndMoveNativeHandle(
-                        buffer.getNativeHandle(),
-                        width, height,
-                        format, grallocUsage, info.stride,
-                        0, 0, mBufferQueue ? ~0 : 0),
-                mTraits->id));
-        return C2_OK;
+    status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
+            1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
+    if (err) {
+        ALOGE("failed transaction: allocate");
+        return C2_CORRUPTED;
     }
+
+    hidl_handle hidlHandle;
+    hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
+
+    allocation->reset(new C2AllocationGralloc(
+            width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
+            C2HandleGralloc::WrapAndMoveNativeHandle(
+                    hidlHandle, width, height,
+                    format, grallocUsage, stride,
+                    0, 0, mBufferQueue ? ~0 : 0),
+            mTraits->id));
+    return C2_OK;
 }
 
 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
-    if (mMapper2) {
-        BufferDescriptorInfo2 info;
-        info.mapperInfo.layerCount = 1u;
-        uint32_t generation;
-        uint64_t igbp_id;
-        uint32_t igbp_slot;
-        const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
-                handle,
-                &info.mapperInfo.width, &info.mapperInfo.height,
-                (uint32_t *)&info.mapperInfo.format,
-                (uint64_t *)&info.mapperInfo.usage,
-                &info.stride,
-                &generation, &igbp_id, &igbp_slot);
-        if (grallocHandle == nullptr) {
-            return C2_BAD_VALUE;
-        }
 
-        hidl_handle hidlHandle;
-        hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
+    uint32_t generation;
+    uint64_t igbp_id;
+    uint32_t igbp_slot;
 
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper2, hidlHandle, grallocHandle, mTraits->id));
-        return C2_OK;
-    } else if (mMapper3) {
-        BufferDescriptorInfo3 info;
-        info.mapperInfo.layerCount = 1u;
-        uint32_t generation;
-        uint64_t igbp_id;
-        uint32_t igbp_slot;
-        const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
-                handle,
-                &info.mapperInfo.width, &info.mapperInfo.height,
-                (uint32_t *)&info.mapperInfo.format,
-                (uint64_t *)&info.mapperInfo.usage,
-                &info.stride,
-                &generation, &igbp_id, &igbp_slot);
-        if (grallocHandle == nullptr) {
-            return C2_BAD_VALUE;
-        }
+    uint32_t width;
+    uint32_t height;
+    uint32_t format;
+    uint32_t layerCount = 1;
+    uint64_t grallocUsage;
+    uint32_t stride;
 
-        hidl_handle hidlHandle;
-        hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
-
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper3, hidlHandle, grallocHandle, mTraits->id));
-        return C2_OK;
-    } else {
-        BufferDescriptorInfo4 info;
-        info.mapperInfo.layerCount = 1u;
-        uint32_t generation;
-        uint64_t igbp_id;
-        uint32_t igbp_slot;
-        const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
-                handle,
-                &info.mapperInfo.width, &info.mapperInfo.height,
-                (uint32_t *)&info.mapperInfo.format,
-                (uint64_t *)&info.mapperInfo.usage,
-                &info.stride,
-                &generation, &igbp_id, &igbp_slot);
-        if (grallocHandle == nullptr) {
-            return C2_BAD_VALUE;
-        }
-
-        hidl_handle hidlHandle;
-        hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
-
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper4, hidlHandle, grallocHandle, mTraits->id));
-        return C2_OK;
+    const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
+            handle, &width, &height, &format, &grallocUsage, &stride,
+            &generation, &igbp_id, &igbp_slot);
+    if (grallocHandle == nullptr) {
+        return C2_BAD_VALUE;
     }
+
+    hidl_handle hidlHandle;
+    hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
+
+    allocation->reset(new C2AllocationGralloc(
+            width, height, format, layerCount,
+            grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
+    return C2_OK;
 }
 
 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
diff --git a/media/libaaudio/examples/utils/AAudioArgsParser.h b/media/libaaudio/examples/utils/AAudioArgsParser.h
index 9115778..4bba436 100644
--- a/media/libaaudio/examples/utils/AAudioArgsParser.h
+++ b/media/libaaudio/examples/utils/AAudioArgsParser.h
@@ -38,12 +38,15 @@
                                 aaudio_input_preset_t inputPreset) = nullptr;
 static void (*s_setAllowedCapturePolicy)(AAudioStreamBuilder* builder,
                                           aaudio_allowed_capture_policy_t usage) = nullptr;
+static void (*s_setPrivacySensitive)(AAudioStreamBuilder* builder,
+                                          bool privacySensitive) = nullptr;
 
 static bool s_loadAttempted = false;
 static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr;
 static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr;
 static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr;
 static aaudio_allowed_capture_policy_t (*s_getAllowedCapturePolicy)(AAudioStream *stream) = nullptr;
+static bool (*s_isPrivacySensitive)(AAudioStream *stream) = nullptr;
 
 // Link to test functions in shared library.
 static void loadFutureFunctions() {
@@ -68,6 +71,10 @@
                 dlsym(handle, "AAudioStreamBuilder_setAllowedCapturePolicy");
         if (s_setAllowedCapturePolicy == nullptr) goto error;
 
+        s_setPrivacySensitive = (void (*)(AAudioStreamBuilder *, bool))
+                dlsym(handle, "AAudioStreamBuilder_setPrivacySensitive");
+        if (s_setPrivacySensitive == nullptr) goto error;
+
         s_getUsage = (aaudio_usage_t (*)(AAudioStream *))
                 dlsym(handle, "AAudioStream_getUsage");
         if (s_getUsage == nullptr) goto error;
@@ -83,6 +90,10 @@
         s_getAllowedCapturePolicy = (aaudio_input_preset_t (*)(AAudioStream *))
                 dlsym(handle, "AAudioStream_getAllowedCapturePolicy");
         if (s_getAllowedCapturePolicy == nullptr) goto error;
+
+        s_isPrivacySensitive = (bool (*)(AAudioStream *))
+                dlsym(handle, "AAudioStream_isPrivacySensitive");
+        if (s_isPrivacySensitive == nullptr) goto error;
     }
     return;
 
@@ -91,9 +102,11 @@
     s_setUsage = nullptr;
     s_setContentType = nullptr;
     s_setInputPreset = nullptr;
+    s_setPrivacySensitive = nullptr;
     s_getUsage = nullptr;
     s_getContentType = nullptr;
     s_getInputPreset = nullptr;
+    s_isPrivacySensitive = nullptr;
     dlclose(handle);
     return;
 }
@@ -211,6 +224,14 @@
         mFramesPerCallback = size;
     }
 
+    int32_t isPrivacySensitive() const {
+        return mPrivacySensitive;
+    }
+
+    void setPrivacySensitive(int32_t privacySensitive) {
+        mPrivacySensitive = privacySensitive;
+    }
+
     /**
      * Apply these parameters to a stream builder.
      * @param builder
@@ -234,12 +255,12 @@
         }
         if (s_setContentType != nullptr) {
             s_setContentType(builder, mContentType);
-        } else if (mUsage != AAUDIO_UNSPECIFIED){
+        } else if (mContentType != AAUDIO_UNSPECIFIED){
             printf("WARNING: setContentType not supported");
         }
         if (s_setInputPreset != nullptr) {
             s_setInputPreset(builder, mInputPreset);
-        } else if (mUsage != AAUDIO_UNSPECIFIED){
+        } else if (mInputPreset != AAUDIO_UNSPECIFIED){
             printf("WARNING: setInputPreset not supported");
         }
 
@@ -249,6 +270,15 @@
         } else if (mAllowedCapturePolicy != AAUDIO_UNSPECIFIED){
             printf("WARNING: setAllowedCapturePolicy not supported");
         }
+
+        if (mPrivacySensitive != PRIVACY_SENSITIVE_DEFAULT) {
+            if (s_setPrivacySensitive != nullptr) {
+                s_setPrivacySensitive(builder,
+                    mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED);
+            } else {
+                printf("WARNING: setPrivacySensitive not supported");
+            }
+        }
     }
 
     static constexpr int32_t   kDefaultNumberOfBursts = 2;
@@ -270,6 +300,13 @@
 
     int32_t                    mNumberOfBursts  = kDefaultNumberOfBursts;
     int32_t                    mFramesPerCallback = AAUDIO_UNSPECIFIED;
+
+    enum {
+        PRIVACY_SENSITIVE_DEFAULT = -1,
+        PRIVACY_SENSITIVE_DISABLED = 0,
+        PRIVACY_SENSITIVE_ENABLED = 1,
+    };
+    int32_t                    mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
 };
 
 class AAudioArgsParser : public AAudioParameters {
@@ -341,6 +378,9 @@
                 case 'z':
                     setFramesPerCallback(atoi(&arg[2]));
                     break;
+                case 'S':
+                    setPrivacySensitive(atoi(&arg[2]));
+                    break;
                 default:
                     unrecognized = true;
                     break;
@@ -399,6 +439,9 @@
         printf("      -x to use EXCLUSIVE mode\n");
         printf("      -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n");
         printf("      -z{callbackSize} or block size, in frames, default = 0\n");
+        printf("      -S{0|1} set privacy Sensitive enabled or disabled\n");
+        printf("          0 = disabled\n");
+        printf("          1 = enabled\n");
     }
 
     static aaudio_performance_mode_t parseAllowedCapturePolicy(char c) {
@@ -506,10 +549,15 @@
                    getContentType(), s_getContentType(stream));
         }
 
-        if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT
-            && s_getInputPreset != nullptr) {
+        if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT) {
+            if (s_getInputPreset != nullptr) {
                 printf("  InputPreset:  requested = %d, actual = %d\n",
                        getInputPreset(), s_getInputPreset(stream));
+            }
+            if (s_isPrivacySensitive != nullptr) {
+                printf("  Privacy Sensitive:  requested = %d, actual = %d\n",
+                       isPrivacySensitive(), s_isPrivacySensitive(stream));
+            }
         }
 
         printf("  Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index a4322a1..5bebd61 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -759,6 +759,28 @@
 AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
         aaudio_session_id_t sessionId) __INTRODUCED_IN(28);
 
+
+/** Indicates whether this input stream must be marked as privacy sensitive or not.
+ *
+ * When true, this input stream is privacy sensitive and any concurrent capture
+ * is not permitted.
+ *
+ * This is off (false) by default except when the input preset is {@link #AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION}
+ * or {@link #AAUDIO_INPUT_PRESET_CAMCORDER}.
+ *
+ * Always takes precedence over default from input preset when set explicitly.
+ *
+ * Only relevant if the stream direction is {@link #AAUDIO_DIRECTION_INPUT}.
+ *
+ * Added in API level 30.
+ *
+ * @param builder reference provided by AAudio_createStreamBuilder()
+ * @param privacySensitive true if capture from this stream must be marked as privacy sensitive,
+ * false otherwise.
+ */
+AAUDIO_API void AAudioStreamBuilder_setPrivacySensitive(AAudioStreamBuilder* builder,
+        bool privacySensitive) __INTRODUCED_IN(30);
+
 /**
  * Return one of these values from the data callback function.
  */
@@ -1444,6 +1466,20 @@
 AAUDIO_API aaudio_allowed_capture_policy_t AAudioStream_getAllowedCapturePolicy(
         AAudioStream* stream) __INTRODUCED_IN(29);
 
+
+/**
+ * Return whether this input stream is marked as privacy sensitive or not.
+ *
+ * See {@link #AAudioStreamBuilder_setPrivacySensitive()}.
+ *
+ * Added in API level 30.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return true if privacy sensitive, false otherwise
+ */
+AAUDIO_API bool AAudioStream_isPrivacySensitive(AAudioStream* stream)
+        __INTRODUCED_IN(30);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
index a987fab..b785f88 100644
--- a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
@@ -66,6 +66,8 @@
     if (status != NO_ERROR) goto error;
     status = parcel->writeInt32(getSessionId());
     if (status != NO_ERROR) goto error;
+    status = parcel->writeInt32(isPrivacySensitive() ? 1 : 0);
+    if (status != NO_ERROR) goto error;
     return NO_ERROR;
 error:
     ALOGE("%s(): write failed = %d", __func__, status);
@@ -111,7 +113,9 @@
     status = parcel->readInt32(&value);
     if (status != NO_ERROR) goto error;
     setSessionId(value);
-
+    status = parcel->readInt32(&value);
+    if (status != NO_ERROR) goto error;
+    setPrivacySensitive(value == 1);
     return NO_ERROR;
 error:
     ALOGE("%s(): read failed = %d", __func__, status);
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 7481daa..bfad254 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -116,6 +116,7 @@
     request.getConfiguration().setUsage(getUsage());
     request.getConfiguration().setContentType(getContentType());
     request.getConfiguration().setInputPreset(getInputPreset());
+    request.getConfiguration().setPrivacySensitive(isPrivacySensitive());
 
     request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
 
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 8040e6a..184e9cb 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -149,6 +149,12 @@
     streamBuilder->setInputPreset(inputPreset);
 }
 
+AAUDIO_API void AAudioStreamBuilder_setPrivacySensitive(AAudioStreamBuilder* builder,
+                                                   bool privacySensitive) {
+    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+    streamBuilder->setPrivacySensitiveRequest(privacySensitive);
+}
+
 AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
                                                               int32_t frames)
 {
@@ -507,3 +513,9 @@
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
     return audioStream->isMMap();
 }
+
+AAUDIO_API bool AAudioStream_isPrivacySensitive(AAudioStream* stream)
+{
+    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+    return audioStream->isPrivacySensitive();
+}
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index c9711da..58058f5 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -47,6 +47,7 @@
     mContentType          = other.mContentType;
     mInputPreset          = other.mInputPreset;
     mAllowedCapturePolicy = other.mAllowedCapturePolicy;
+    mIsPrivacySensitive   = other.mIsPrivacySensitive;
 }
 
 static aaudio_result_t isFormatValid(audio_format_t format) {
@@ -195,4 +196,5 @@
     ALOGD("mContentType          = %6d", mContentType);
     ALOGD("mInputPreset          = %6d", mInputPreset);
     ALOGD("mAllowedCapturePolicy = %6d", mAllowedCapturePolicy);
+    ALOGD("mIsPrivacySensitive   = %s", mIsPrivacySensitive ? "true" : "false");
 }
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.h b/media/libaaudio/src/core/AAudioStreamParameters.h
index 2e21a8d..3e65b37 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.h
+++ b/media/libaaudio/src/core/AAudioStreamParameters.h
@@ -128,6 +128,14 @@
         mSessionId = sessionId;
     }
 
+    bool isPrivacySensitive() const {
+        return mIsPrivacySensitive;
+    }
+
+    void setPrivacySensitive(bool privacySensitive) {
+        mIsPrivacySensitive = privacySensitive;
+    }
+
     /**
      * @return bytes per frame of getFormat()
      */
@@ -158,6 +166,7 @@
     int32_t                         mBufferCapacity       = AAUDIO_UNSPECIFIED;
     aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_UNSPECIFIED;
     aaudio_session_id_t             mSessionId            = AAUDIO_SESSION_ID_NONE;
+    bool                            mIsPrivacySensitive   = false;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 5303631..d928222 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -91,6 +91,7 @@
     if (mAllowedCapturePolicy == AAUDIO_UNSPECIFIED) {
         mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
     }
+    mIsPrivacySensitive = builder.isPrivacySensitive();
 
     // callbacks
     mFramesPerDataCallback = builder.getFramesPerDataCallback();
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 044c979..b4ffcf2 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -234,6 +234,10 @@
         return mSessionId;
     }
 
+    bool isPrivacySensitive() const {
+        return mIsPrivacySensitive;
+    }
+
     /**
      * This is only valid after setSamplesPerFrame() and setFormat() have been called.
      */
@@ -543,6 +547,13 @@
         mAllowedCapturePolicy = policy;
     }
 
+    /**
+     * This should not be called after the open() call.
+     */
+    void setPrivacySensitive(bool privacySensitive) {
+        mIsPrivacySensitive = privacySensitive;
+    }
+
 private:
 
     aaudio_result_t safeStop();
@@ -565,6 +576,7 @@
     aaudio_content_type_t       mContentType     = AAUDIO_UNSPECIFIED;
     aaudio_input_preset_t       mInputPreset     = AAUDIO_UNSPECIFIED;
     aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
+    bool                        mIsPrivacySensitive = false;
 
     int32_t                     mSessionId = AAUDIO_UNSPECIFIED;
 
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 44f45b3..af28a59 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -158,6 +158,19 @@
         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
     }
 
+    setPrivacySensitive(false);
+    if (mPrivacySensitiveReq == PRIVACY_SENSITIVE_DEFAULT) {
+        // When not explicitly requested, set privacy sensitive mode according to input preset:
+        // communication and camcorder captures are considered privacy sensitive by default.
+        aaudio_input_preset_t preset = getInputPreset();
+        if (preset == AAUDIO_INPUT_PRESET_CAMCORDER
+                || preset == AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION) {
+            setPrivacySensitive(true);
+        }
+    } else if (mPrivacySensitiveReq == PRIVACY_SENSITIVE_ENABLED) {
+        setPrivacySensitive(true);
+    }
+
     result = builder_createStream(getDirection(), sharingMode, allowMMap, &audioStream);
     if (result == AAUDIO_OK) {
         // Open the stream using the parameters from the builder.
@@ -257,4 +270,5 @@
           mFramesPerDataCallback);
     ALOGI("usage  = %6d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
           getUsage(), getContentType(), getInputPreset(), getAllowedCapturePolicy());
+    ALOGI("privacy sensitive = %s", isPrivacySensitive() ? "true" : "false");
 }
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index 8149af2..d5fb80d 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -98,6 +98,12 @@
         return this;
     }
 
+    AudioStreamBuilder* setPrivacySensitiveRequest(bool privacySensitive) {
+        mPrivacySensitiveReq =
+            privacySensitive ? PRIVACY_SENSITIVE_ENABLED : PRIVACY_SENSITIVE_DISABLED;
+        return this;
+    }
+
     aaudio_result_t build(AudioStream **streamPtr);
 
     virtual aaudio_result_t validate() const override;
@@ -114,6 +120,14 @@
 
     AAudioStream_errorCallback mErrorCallbackProc = nullptr;
     void                      *mErrorCallbackUserData = nullptr;
+
+    enum {
+        PRIVACY_SENSITIVE_DEFAULT = -1,
+        PRIVACY_SENSITIVE_DISABLED = 0,
+        PRIVACY_SENSITIVE_ENABLED = 1,
+    };
+    typedef int32_t privacy_sensitive_t;
+    privacy_sensitive_t        mPrivacySensitiveReq = PRIVACY_SENSITIVE_DEFAULT;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 71efc30..54af580 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -142,11 +142,13 @@
     const audio_source_t source =
             AAudioConvert_inputPresetToAudioSource(builder.getInputPreset());
 
+    const audio_flags_mask_t attrFlags =
+            AAudioConvert_privacySensitiveToAudioFlagsMask(builder.isPrivacySensitive());
     const audio_attributes_t attributes = {
             .content_type = contentType,
             .usage = AUDIO_USAGE_UNKNOWN, // only used for output
             .source = source,
-            .flags = AUDIO_FLAG_NONE, // Different than the AUDIO_INPUT_FLAGS
+            .flags = attrFlags, // Different than the AUDIO_INPUT_FLAGS
             .tags = ""
     };
 
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index c2f7fd0..ef89697 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -234,6 +234,11 @@
     }
 }
 
+audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
+        bool privacySensitive) {
+    return privacySensitive ? AUDIO_FLAG_CAPTURE_PRIVATE : AUDIO_FLAG_NONE;
+}
+
 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
                                     int32_t bytesPerFrame,
                                     int32_t *sizeInBytes) {
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index 5dcddf3..d2e4805 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -92,6 +92,9 @@
 audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
         aaudio_allowed_capture_policy_t policy);
 
+audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
+        bool privacySensitive);
+
 // Note that this code may be replaced by Settings or by some other system configuration tool.
 
 /**
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 0f2d48e..c22db59 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -262,8 +262,12 @@
     }
 
     if (pAttributes == NULL) {
-        memset(&mAttributes, 0, sizeof(audio_attributes_t));
+        mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
         mAttributes.source = inputSource;
+        if (inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION
+                || inputSource == AUDIO_SOURCE_CAMCORDER) {
+            mAttributes.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+        }
     } else {
         // stream type shouldn't be looked at, this track has audio attributes
         memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a354ce1..ac86f72 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -67,7 +67,9 @@
     GET_ACTIVE_MICROPHONES,
     GET_PORT_ID,
     SET_PREFERRED_MICROPHONE_DIRECTION,
-    SET_PREFERRED_MICROPHONE_FIELD_DIMENSION
+    SET_PREFERRED_MICROPHONE_FIELD_DIMENSION,
+    SET_PRIVACY_SENSITIVE,
+    GET_PRIVACY_SENSITIVE
 };
 
 class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -151,6 +153,36 @@
         return reply.readInt32();
     }
 
+    status_t setPrivacySensitive(bool privacySensitive)
+    {
+        ALOGV("%s(%s)", __func__, privacySensitive ? "true" : "false");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(privacySensitive ? 1 : 0);
+        status_t status = remote()->transact(SET_PRIVACY_SENSITIVE, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return reply.readInt32();
+    }
+
+    status_t isPrivacySensitive(bool *privacySensitive) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        *privacySensitive = false;
+        status_t status = remote()->transact(GET_PRIVACY_SENSITIVE, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (status == NO_ERROR) {
+            *privacySensitive = reply.readInt32() == 1;
+        }
+        ALOGV("%s status %d enabled: %s", __func__, status, *privacySensitive ? "true" : "false");
+        return status;
+    }
+
     status_t setOutputFormat(int of)
     {
         ALOGV("setOutputFormat(%d)", of);
@@ -537,6 +569,24 @@
             reply->writeInt32(setAudioSource(as));
             return NO_ERROR;
         } break;
+        case SET_PRIVACY_SENSITIVE: {
+            ALOGV("SET_PRIVACY_SENSITIVE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            bool privacySensitive = data.readInt32() == 1;
+            reply->writeInt32(setPrivacySensitive(privacySensitive));
+            return NO_ERROR;
+        } break;
+        case GET_PRIVACY_SENSITIVE: {
+            ALOGV("GET_PRIVACY_SENSITIVE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            bool privacySensitive = false;
+            status_t status = isPrivacySensitive(&privacySensitive);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(privacySensitive ? 1 : 0);
+            }
+            return NO_ERROR;
+        } break;
         case SET_OUTPUT_FORMAT: {
             ALOGV("SET_OUTPUT_FORMAT");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index f9c557c..651bd5e 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -44,6 +44,8 @@
     virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface) = 0;
     virtual status_t setVideoSource(int vs) = 0;
     virtual status_t setAudioSource(int as) = 0;
+    virtual status_t setPrivacySensitive(bool privacySensitive) = 0;
+    virtual status_t isPrivacySensitive(bool *privacySensitive) const = 0;
     virtual status_t setOutputFormat(int of) = 0;
     virtual status_t setVideoEncoder(int ve) = 0;
     virtual status_t setAudioEncoder(int ae) = 0;
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index a2dff31..8493f64 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -39,6 +39,8 @@
 
     virtual status_t init() = 0;
     virtual status_t setAudioSource(audio_source_t as) = 0;
+    virtual status_t setPrivacySensitive(bool privacySensitive) = 0 ;
+    virtual status_t isPrivacySensitive(bool *privacySensitive) const = 0;
     virtual status_t setVideoSource(video_source vs) = 0;
     virtual status_t setOutputFormat(output_format of) = 0;
     virtual status_t setAudioEncoder(audio_encoder ae) = 0;
@@ -79,6 +81,7 @@
 
 
 protected:
+
     String16 mOpPackageName;
 
 private:
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index 2dd4b7f..6e2d94d 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -236,6 +236,8 @@
     status_t    setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
     status_t    setVideoSource(int vs);
     status_t    setAudioSource(int as);
+    status_t    setPrivacySensitive(bool privacySensitive);
+    status_t    isPrivacySensitive(bool *privacySensitive) const;
     status_t    setOutputFormat(int of);
     status_t    setVideoEncoder(int ve);
     status_t    setAudioEncoder(int ae);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 4570af9..70655d5 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -178,6 +178,47 @@
     return ret;
 }
 
+status_t MediaRecorder::setPrivacySensitive(bool privacySensitive)
+{
+    ALOGV("%s(%s)", __func__, privacySensitive ? "true" : "false");
+    if (mMediaRecorder == NULL) {
+        ALOGE("%s: media recorder is not initialized yet", __func__);
+        return INVALID_OPERATION;
+    }
+
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED) || !mIsAudioSourceSet) {
+        ALOGE("%s called in an invalid state(%d) or audio source not (%d)",
+            __func__, mCurrentState, mIsAudioSourceSet);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setPrivacySensitive(privacySensitive);
+    if (OK != ret) {
+        ALOGV("%s failed: %d", __func__, ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return ret;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::isPrivacySensitive(bool *privacySensitive) const
+{
+    if (mMediaRecorder == NULL) {
+        ALOGE("%s: media recorder is not initialized yet", __func__);
+        return INVALID_OPERATION;
+    }
+
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED) || !mIsAudioSourceSet) {
+        ALOGE("%s called in an invalid state(%d) or audio source not (%d)",
+            __func__, mCurrentState, mIsAudioSourceSet);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->isPrivacySensitive(privacySensitive);
+    ALOGV("%s status: %d eanbled %s", __func__, ret, *privacySensitive ? "enabled" : "disabled");
+    return ret;
+}
+
 status_t MediaRecorder::setOutputFormat(int of)
 {
     ALOGV("setOutputFormat(%d)", of);
diff --git a/media/libmediahelper/TypeConverter.cpp b/media/libmediahelper/TypeConverter.cpp
index 817aadf..6ea6172 100644
--- a/media/libmediahelper/TypeConverter.cpp
+++ b/media/libmediahelper/TypeConverter.cpp
@@ -395,6 +395,7 @@
     MAKE_STRING_FROM_ENUM(AUDIO_FLAG_DEEP_BUFFER),
     MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_MEDIA_PROJECTION),
     MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_SYSTEM_CAPTURE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_CAPTURE_PRIVATE),
     TERMINATOR
 };
 
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index c61ed1b..9b1974b 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -138,6 +138,29 @@
     return mRecorder->setAudioSource((audio_source_t)as);
 }
 
+status_t MediaRecorderClient::setPrivacySensitive(bool privacySensitive)
+{
+    ALOGV("%s(%s)", __func__, privacySensitive ? "true" : "false");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)  {
+        ALOGE("%s: recorder is not initialized", __func__);
+        return NO_INIT;
+    }
+    return mRecorder->setPrivacySensitive(privacySensitive);
+}
+
+status_t MediaRecorderClient::isPrivacySensitive(bool *privacySensitive) const
+{
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)  {
+        ALOGE("%s: recorder is not initialized", __func__);
+        return NO_INIT;
+    }
+    status_t status = mRecorder->isPrivacySensitive(privacySensitive);
+    ALOGV("%s: status: %d enabled: %s", __func__, status, *privacySensitive ? "true" : "false");
+    return status;
+}
+
 status_t MediaRecorderClient::setOutputFormat(int of)
 {
     ALOGV("setOutputFormat(%d)", of);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 9e0f877..12257e5 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -51,6 +51,8 @@
     virtual     status_t   setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
     virtual     status_t   setVideoSource(int vs);
     virtual     status_t   setAudioSource(int as);
+                status_t   setPrivacySensitive(bool privacySensitive) override;
+                status_t   isPrivacySensitive(bool *privacySensitive) const override;
     virtual     status_t   setOutputFormat(int of);
     virtual     status_t   setVideoEncoder(int ve);
     virtual     status_t   setAudioEncoder(int ae);
@@ -98,7 +100,7 @@
     sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedNotifier;
 
     pid_t                  mPid;
-    Mutex                  mLock;
+    mutable Mutex          mLock;
     MediaRecorderBase      *mRecorder;
     sp<MediaPlayerService> mMediaPlayerService;
 };
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 954ccc9..d36c6e3 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -115,6 +115,7 @@
       mWriter(NULL),
       mOutputFd(-1),
       mAudioSource((audio_source_t)AUDIO_SOURCE_CNT), // initialize with invalid value
+      mPrivacySensitive(PRIVACY_SENSITIVE_DEFAULT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
       mStarted(false),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
@@ -238,7 +239,31 @@
     } else {
         mAudioSource = as;
     }
+    // Reset privacy sensitive in case this is the second time audio source is set
+    mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
+    return OK;
+}
 
+status_t StagefrightRecorder::setPrivacySensitive(bool privacySensitive) {
+    // privacy sensitive cannot be set before audio source is set
+    if (mAudioSource == AUDIO_SOURCE_CNT) {
+        return INVALID_OPERATION;
+    }
+    mPrivacySensitive = privacySensitive ? PRIVACY_SENSITIVE_ENABLED : PRIVACY_SENSITIVE_DISABLED;
+    return OK;
+}
+
+status_t StagefrightRecorder::isPrivacySensitive(bool *privacySensitive) const {
+    *privacySensitive = false;
+    if (mAudioSource == AUDIO_SOURCE_CNT) {
+        return INVALID_OPERATION;
+    }
+    if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
+         *privacySensitive = mAudioSource == AUDIO_SOURCE_VOICE_COMMUNICATION
+                || mAudioSource == AUDIO_SOURCE_CAMCORDER;
+    } else {
+        *privacySensitive = mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED;
+    }
     return OK;
 }
 
@@ -1082,9 +1107,35 @@
         }
     }
 
+    audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+    attr.source = mAudioSource;
+    // attr.flags AUDIO_FLAG_CAPTURE_PRIVATE is cleared by default
+    if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
+        if (attr.source == AUDIO_SOURCE_VOICE_COMMUNICATION
+                || attr.source == AUDIO_SOURCE_CAMCORDER) {
+            attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+            mPrivacySensitive = PRIVACY_SENSITIVE_ENABLED;
+        } else {
+            mPrivacySensitive = PRIVACY_SENSITIVE_DISABLED;
+        }
+    } else {
+        if (mAudioSource == AUDIO_SOURCE_REMOTE_SUBMIX
+                || mAudioSource == AUDIO_SOURCE_FM_TUNER
+                || mAudioSource == AUDIO_SOURCE_VOICE_DOWNLINK
+                || mAudioSource == AUDIO_SOURCE_VOICE_UPLINK
+                || mAudioSource == AUDIO_SOURCE_VOICE_CALL
+                || mAudioSource == AUDIO_SOURCE_ECHO_REFERENCE) {
+            ALOGE("Cannot request private capture with source: %d", mAudioSource);
+            return NULL;
+        }
+        if (mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED) {
+            attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+        }
+    }
+
     sp<AudioSource> audioSource =
         new AudioSource(
-                mAudioSource,
+                &attr,
                 mOpPackageName,
                 sourceSampleRate,
                 mAudioChannels,
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 8bf083a..9e0f4b7 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -46,6 +46,8 @@
     virtual ~StagefrightRecorder();
     virtual status_t init();
     virtual status_t setAudioSource(audio_source_t as);
+            status_t setPrivacySensitive(bool privacySensitive) override;
+            status_t isPrivacySensitive(bool *privacySensitive) const override;
     virtual status_t setVideoSource(video_source vs);
     virtual status_t setOutputFormat(output_format of);
     virtual status_t setAudioEncoder(audio_encoder ae);
@@ -82,6 +84,13 @@
             status_t getPortId(audio_port_handle_t *portId) const override;
 
 private:
+
+    enum privacy_sensitive_t {
+        PRIVACY_SENSITIVE_DEFAULT = -1,
+        PRIVACY_SENSITIVE_DISABLED = 0,
+        PRIVACY_SENSITIVE_ENABLED = 1,
+    };
+
     mutable Mutex mLock;
     sp<hardware::ICamera> mCamera;
     sp<ICameraRecordingProxy> mCameraProxy;
@@ -101,6 +110,7 @@
     void updateMetrics();
 
     audio_source_t mAudioSource;
+    privacy_sensitive_t mPrivacySensitive;
     video_source mVideoSource;
     output_format mOutputFormat;
     audio_encoder mAudioEncoder;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index d78d729..00c5b40 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -50,7 +50,7 @@
 }
 
 AudioSource::AudioSource(
-        audio_source_t inputSource, const String16 &opPackageName,
+        const audio_attributes_t *attr, const String16 &opPackageName,
         uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate,
         uid_t uid, pid_t pid, audio_port_handle_t selectedDeviceId,
         audio_microphone_direction_t selectedMicDirection,
@@ -92,7 +92,7 @@
         }
 
         mRecord = new AudioRecord(
-                    inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
+                    AUDIO_SOURCE_DEFAULT, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
                     audio_channel_in_mask_from_count(channelCount),
                     opPackageName,
                     (size_t) (bufCount * frameCount),
@@ -104,7 +104,7 @@
                     AUDIO_INPUT_FLAG_NONE,
                     uid,
                     pid,
-                    NULL /*pAttributes*/,
+                    attr,
                     selectedDeviceId,
                     selectedMicDirection,
                     selectedMicFieldDimension);
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index af04dad..ad4ab47 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -37,7 +37,7 @@
     // Note that the "channels" parameter _is_ the number of channels,
     // _not_ a bitmask of audio_channels_t constants.
     AudioSource(
-            audio_source_t inputSource,
+            const audio_attributes_t *attr,
             const String16 &opPackageName,
             uint32_t sampleRate,
             uint32_t channels,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index c8d7d0c..c83512f 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -489,7 +489,7 @@
             latestActive = current;
             latestStartNs = current->startTimeNs;
         }
-        if (isPrivacySensitiveSource(current->attributes.source)) {
+        if ((current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0) {
             if (current->startTimeNs > latestSensitiveStartNs) {
                 latestSensitiveActive = current;
                 latestSensitiveStartNs = current->startTimeNs;
@@ -602,19 +602,6 @@
 }
 
 /* static */
-bool AudioPolicyService::isPrivacySensitiveSource(audio_source_t source)
-{
-    switch (source) {
-        case AUDIO_SOURCE_CAMCORDER:
-        case AUDIO_SOURCE_VOICE_COMMUNICATION:
-            return true;
-        default:
-            break;
-    }
-    return false;
-}
-
-/* static */
 bool AudioPolicyService::isVirtualSource(audio_source_t source)
 {
     switch (source) {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 2bd02c8..850226e 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -338,7 +338,6 @@
 
     void silenceAllRecordings_l();
 
-    static bool isPrivacySensitiveSource(audio_source_t source);
     static bool isVirtualSource(audio_source_t source);
 
     // If recording we need to make sure the UID is allowed to do that. If the UID is idle
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 553754e..2753f1f 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -62,6 +62,7 @@
     result << "    InputPreset:          " << getInputPreset() << "\n";
     result << "    Reference Count:      " << mOpenCount << "\n";
     result << "    Session Id:           " << getSessionId() << "\n";
+    result << "    Privacy Sensitive:    " << isPrivacySensitive() << "\n";
     result << "    Connected:            " << mConnected.load() << "\n";
     result << "    Registered Streams:" << "\n";
     result << AAudioServiceStreamShared::dumpHeader() << "\n";
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index b05baa4..5bdb8eb 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -90,9 +90,14 @@
     const audio_source_t source = (direction == AAUDIO_DIRECTION_INPUT)
             ? AAudioConvert_inputPresetToAudioSource(getInputPreset())
             : AUDIO_SOURCE_DEFAULT;
-    const audio_flags_mask_t flags = AUDIO_FLAG_LOW_LATENCY |
-            AAudioConvert_allowCapturePolicyToAudioFlagsMask(getAllowedCapturePolicy());
-
+    audio_flags_mask_t flags;
+    if (direction == AAUDIO_DIRECTION_OUTPUT) {
+        flags = AUDIO_FLAG_LOW_LATENCY
+            | AAudioConvert_allowCapturePolicyToAudioFlagsMask(getAllowedCapturePolicy());
+    } else {
+        flags = AUDIO_FLAG_LOW_LATENCY
+            | AAudioConvert_privacySensitiveToAudioFlagsMask(isPrivacySensitive());
+    }
     const audio_attributes_t attributes = {
             .content_type = contentType,
             .usage = usage,