Merge "add powerhal 1.2 to compatibility_matrix"
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index 3027555..a32f410 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -53,6 +53,15 @@
 
     ANDROID_LENS_END_3_3,
 
+    /** android.request.availableSessionKeys [static, int32[], ndk_public]
+     *
+     * <p>A subset of the available request keys that the camera device
+     * can pass as part of the capture session initialization.</p>
+     */
+    ANDROID_REQUEST_AVAILABLE_SESSION_KEYS = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_REQUEST_END,
+
+    ANDROID_REQUEST_END_3_3,
+
     /** android.info.version [static, byte, public]
      *
      * <p>A short string for manufacturer version information about the camera device, such as
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 9968f41..ed2ecbb 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -1,10 +1,15 @@
 cc_library_shared {
     name: "android.hardware.graphics.allocator@2.0-impl",
     defaults: ["hidl_defaults"],
-    proprietary: true,
+    vendor: true,
     relative_install_path: "hw",
-    srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"],
-    cppflags: ["-Wall", "-Wextra"],
+    srcs: ["passthrough.cpp"],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0-passthrough",
+    ],
+    header_libs: [
+        "android.hardware.graphics.allocator@2.0-hal",
+    ],
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "libbase",
@@ -15,9 +20,6 @@
         "liblog",
         "libutils",
     ],
-    header_libs: [
-        "libgrallocmapperincludes",
-    ],
 }
 
 cc_binary {
@@ -36,13 +38,3 @@
         "libutils",
     ],
 }
-
-cc_library_static {
-    name: "libgralloc1-adapter",
-    defaults: ["hidl_defaults"],
-    srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"],
-    include_dirs: ["system/core/libsync/include"],
-    cflags: ["-Wall", "-Wextra"],
-    export_include_dirs: ["."],
-    whole_static_libs: ["libgrallocusage"],
-}
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
deleted file mode 100644
index 273d3f5..0000000
--- a/graphics/allocator/2.0/default/Gralloc.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#define LOG_TAG "GrallocPassthrough"
-
-#include "Gralloc.h"
-#include "Gralloc0Allocator.h"
-#include "Gralloc1Allocator.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
-    const hw_module_t* module = nullptr;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err) {
-        ALOGE("failed to get gralloc module");
-        return nullptr;
-    }
-
-    uint8_t major = (module->module_api_version >> 8) & 0xff;
-    switch (major) {
-        case 1:
-            return new Gralloc1Allocator(module);
-        case 0:
-            return new Gralloc0Allocator(module);
-        default:
-            ALOGE("unknown gralloc module major version %d", major);
-            return nullptr;
-    }
-}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc.h b/graphics/allocator/2.0/default/Gralloc.h
deleted file mode 100644
index c79eeaa..0000000
--- a/graphics/allocator/2.0/default/Gralloc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* name);
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
deleted file mode 100644
index 3b62bb3..0000000
--- a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#define LOG_TAG "Gralloc0Allocator"
-
-#include "Gralloc0Allocator.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <vector>
-
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::implementation::
-    grallocDecodeBufferDescriptor;
-
-Gralloc0Allocator::Gralloc0Allocator(const hw_module_t* module) {
-    int result = gralloc_open(module, &mDevice);
-    if (result) {
-        LOG_ALWAYS_FATAL("failed to open gralloc0 device: %s",
-                         strerror(-result));
-    }
-}
-
-Gralloc0Allocator::~Gralloc0Allocator() {
-    gralloc_close(mDevice);
-}
-
-Return<void> Gralloc0Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
-    char buf[4096] = {};
-    if (mDevice->dump) {
-        mDevice->dump(mDevice, buf, sizeof(buf));
-        buf[sizeof(buf) - 1] = '\0';
-    }
-
-    hidl_cb(hidl_string(buf));
-
-    return Void();
-}
-
-Return<void> Gralloc0Allocator::allocate(const BufferDescriptor& descriptor,
-                                         uint32_t count, allocate_cb hidl_cb) {
-    IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    Error error = Error::NONE;
-    uint32_t stride = 0;
-    std::vector<hidl_handle> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        buffer_handle_t tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOne(descriptorInfo, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            mDevice->free(mDevice, tmpBuffer);
-            stride = 0;
-            error = Error::UNSUPPORTED;
-            break;
-        }
-
-        buffers.emplace_back(hidl_handle(tmpBuffer));
-    }
-
-    // return the buffers
-    hidl_vec<hidl_handle> hidl_buffers;
-    if (error == Error::NONE) {
-        hidl_buffers.setToExternal(buffers.data(), buffers.size());
-    }
-    hidl_cb(error, stride, hidl_buffers);
-
-    // free the buffers
-    for (const auto& buffer : buffers) {
-        mDevice->free(mDevice, buffer.getNativeHandle());
-    }
-
-    return Void();
-}
-
-Error Gralloc0Allocator::allocateOne(const IMapper::BufferDescriptorInfo& info,
-                                     buffer_handle_t* outBuffer,
-                                     uint32_t* outStride) {
-    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
-        return Error::BAD_VALUE;
-    }
-
-    buffer_handle_t buffer = nullptr;
-    int stride = 0;
-    int result = mDevice->alloc(mDevice, info.width, info.height,
-                                static_cast<int>(info.format), info.usage,
-                                &buffer, &stride);
-    if (result) {
-        switch (result) {
-            case -EINVAL:
-                return Error::BAD_VALUE;
-            default:
-                return Error::NO_RESOURCES;
-        }
-    }
-
-    *outBuffer = buffer;
-    *outStride = stride;
-
-    return Error::NONE;
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.h b/graphics/allocator/2.0/default/Gralloc0Allocator.h
deleted file mode 100644
index 0e90527..0000000
--- a/graphics/allocator/2.0/default/Gralloc0Allocator.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <hardware/gralloc.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
-class Gralloc0Allocator : public IAllocator {
-   public:
-    Gralloc0Allocator(const hw_module_t* module);
-    virtual ~Gralloc0Allocator();
-
-    // IAllocator interface
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                          allocate_cb hidl_cb) override;
-
-   private:
-    Error allocateOne(const IMapper::BufferDescriptorInfo& info,
-                      buffer_handle_t* outBuffer, uint32_t* outStride);
-
-    alloc_device_t* mDevice;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
deleted file mode 100644
index 6cbb791..0000000
--- a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#define LOG_TAG "Gralloc1Allocator"
-
-#include "Gralloc1Allocator.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <vector>
-
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::mapper::V2_0::implementation::
-    grallocDecodeBufferDescriptor;
-
-Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module)
-    : mDevice(nullptr), mCapabilities(), mDispatch() {
-    int result = gralloc1_open(module, &mDevice);
-    if (result) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                         strerror(-result));
-    }
-
-    initCapabilities();
-    initDispatch();
-}
-
-Gralloc1Allocator::~Gralloc1Allocator() {
-    gralloc1_close(mDevice);
-}
-
-void Gralloc1Allocator::initCapabilities() {
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> capabilities(count);
-    mDevice->getCapabilities(mDevice, &count, capabilities.data());
-    capabilities.resize(count);
-
-    for (auto capability : capabilities) {
-        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
-            mCapabilities.layeredBuffers = true;
-            break;
-        }
-    }
-}
-
-template <typename T>
-void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc,
-                                     T* outPfn) {
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void Gralloc1Allocator::initDispatch() {
-    initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
-    initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
-                 &mDispatch.createDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
-                 &mDispatch.destroyDescriptor);
-    initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
-    initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
-    if (mCapabilities.layeredBuffers) {
-        initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
-                     &mDispatch.setLayerCount);
-    }
-    initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
-                 &mDispatch.setConsumerUsage);
-    initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
-                 &mDispatch.setProducerUsage);
-    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
-    initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-}
-
-Return<void> Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
-    uint32_t len = 0;
-    mDispatch.dump(mDevice, &len, nullptr);
-
-    std::vector<char> buf(len + 1);
-    mDispatch.dump(mDevice, &len, buf.data());
-    buf.resize(len + 1);
-    buf[len] = '\0';
-
-    hidl_string reply;
-    reply.setToExternal(buf.data(), len);
-    hidl_cb(reply);
-
-    return Void();
-}
-
-Return<void> Gralloc1Allocator::allocate(const BufferDescriptor& descriptor,
-                                         uint32_t count, allocate_cb hidl_cb) {
-    IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    gralloc1_buffer_descriptor_t desc;
-    Error error = createDescriptor(descriptorInfo, &desc);
-    if (error != Error::NONE) {
-        hidl_cb(error, 0, hidl_vec<hidl_handle>());
-        return Void();
-    }
-
-    uint32_t stride = 0;
-    std::vector<hidl_handle> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        buffer_handle_t tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOne(desc, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            mDispatch.release(mDevice, tmpBuffer);
-            stride = 0;
-            error = Error::UNSUPPORTED;
-            break;
-        }
-
-        buffers.emplace_back(hidl_handle(tmpBuffer));
-    }
-
-    mDispatch.destroyDescriptor(mDevice, desc);
-
-    // return the buffers
-    hidl_vec<hidl_handle> hidl_buffers;
-    if (error == Error::NONE) {
-        hidl_buffers.setToExternal(buffers.data(), buffers.size());
-    }
-    hidl_cb(error, stride, hidl_buffers);
-
-    // free the buffers
-    for (const auto& buffer : buffers) {
-        mDispatch.release(mDevice, buffer.getNativeHandle());
-    }
-
-    return Void();
-}
-
-Error Gralloc1Allocator::toError(int32_t error) {
-    switch (error) {
-        case GRALLOC1_ERROR_NONE:
-            return Error::NONE;
-        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
-            return Error::BAD_DESCRIPTOR;
-        case GRALLOC1_ERROR_BAD_HANDLE:
-            return Error::BAD_BUFFER;
-        case GRALLOC1_ERROR_BAD_VALUE:
-            return Error::BAD_VALUE;
-        case GRALLOC1_ERROR_NOT_SHARED:
-            return Error::NONE;  // this is fine
-        case GRALLOC1_ERROR_NO_RESOURCES:
-            return Error::NO_RESOURCES;
-        case GRALLOC1_ERROR_UNDEFINED:
-        case GRALLOC1_ERROR_UNSUPPORTED:
-        default:
-            return Error::UNSUPPORTED;
-    }
-}
-
-uint64_t Gralloc1Allocator::toProducerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t producerUsage =
-        usage &
-        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                               BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_WRITE_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::GPU_DATA_BUFFER is always filtered out
-
-    return producerUsage;
-}
-
-uint64_t Gralloc1Allocator::toConsumerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t consumerUsage =
-        usage &
-        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                               BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
-
-    if (usage & BufferUsage::GPU_DATA_BUFFER) {
-        consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
-    }
-
-    return consumerUsage;
-}
-
-Error Gralloc1Allocator::createDescriptor(
-    const IMapper::BufferDescriptorInfo& info,
-    gralloc1_buffer_descriptor_t* outDescriptor) {
-    gralloc1_buffer_descriptor_t descriptor;
-
-    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setDimensions(mDevice, descriptor, info.width,
-                                        info.height);
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setFormat(mDevice, descriptor,
-                                    static_cast<int32_t>(info.format));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        if (mCapabilities.layeredBuffers) {
-            error =
-                mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
-        } else if (info.layerCount > 1) {
-            error = GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setProducerUsage(mDevice, descriptor,
-                                           toProducerUsage(info.usage));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setConsumerUsage(mDevice, descriptor,
-                                           toConsumerUsage(info.usage));
-    }
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outDescriptor = descriptor;
-    } else {
-        mDispatch.destroyDescriptor(mDevice, descriptor);
-    }
-
-    return toError(error);
-}
-
-Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor,
-                                     buffer_handle_t* outBuffer,
-                                     uint32_t* outStride) {
-    buffer_handle_t buffer = nullptr;
-    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
-        return toError(error);
-    }
-
-    uint32_t stride = 0;
-    error = mDispatch.getStride(mDevice, buffer, &stride);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
-        mDispatch.release(mDevice, buffer);
-        return toError(error);
-    }
-
-    *outBuffer = buffer;
-    *outStride = stride;
-
-    return Error::NONE;
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.h b/graphics/allocator/2.0/default/Gralloc1Allocator.h
deleted file mode 100644
index 7b5a966..0000000
--- a/graphics/allocator/2.0/default/Gralloc1Allocator.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
-#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <hardware/gralloc1.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
-class Gralloc1Allocator : public IAllocator {
-   public:
-    Gralloc1Allocator(const hw_module_t* module);
-    virtual ~Gralloc1Allocator();
-
-    // IAllocator interface
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                          allocate_cb hidl_cb) override;
-
-   private:
-    void initCapabilities();
-
-    template <typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    static Error toError(int32_t error);
-    static uint64_t toProducerUsage(uint64_t usage);
-    static uint64_t toConsumerUsage(uint64_t usage);
-
-    Error createDescriptor(const IMapper::BufferDescriptorInfo& info,
-                           gralloc1_buffer_descriptor_t* outDescriptor);
-    Error allocateOne(gralloc1_buffer_descriptor_t descriptor,
-                      buffer_handle_t* outBuffer, uint32_t* outStride);
-
-    gralloc1_device_t* mDevice;
-
-    struct {
-        bool layeredBuffers;
-    } mCapabilities;
-
-    struct {
-        GRALLOC1_PFN_DUMP dump;
-        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
-        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
-        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
-        GRALLOC1_PFN_SET_FORMAT setFormat;
-        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
-        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
-        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
-        GRALLOC1_PFN_GET_STRIDE getStride;
-        GRALLOC1_PFN_ALLOCATE allocate;
-        GRALLOC1_PFN_RELEASE release;
-    } mDispatch;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/passthrough.cpp b/graphics/allocator/2.0/default/passthrough.cpp
new file mode 100644
index 0000000..132cab3
--- /dev/null
+++ b/graphics/allocator/2.0/default/passthrough.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 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 <allocator-passthrough/2.0/GrallocLoader.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::graphics::allocator::V2_0::passthrough::GrallocLoader;
+
+extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
+    return GrallocLoader::load();
+}
diff --git a/graphics/allocator/2.0/default/service.cpp b/graphics/allocator/2.0/default/service.cpp
index 99f462c..bc0539a 100644
--- a/graphics/allocator/2.0/default/service.cpp
+++ b/graphics/allocator/2.0/default/service.cpp
@@ -20,8 +20,8 @@
 
 #include <hidl/LegacySupport.h>
 
-using android::hardware::graphics::allocator::V2_0::IAllocator;
 using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
 
 int main() {
     return defaultPassthroughServiceImplementation<IAllocator>(4);
diff --git a/graphics/allocator/2.0/utils/OWNERS b/graphics/allocator/2.0/utils/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/allocator/2.0/utils/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp b/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp
new file mode 100644
index 0000000..9cb53e3
--- /dev/null
+++ b/graphics/allocator/2.0/utils/gralloc1-adapter/Android.bp
@@ -0,0 +1,10 @@
+cc_library_static {
+    name: "libgralloc1-adapter",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"],
+    include_dirs: ["system/core/libsync/include"],
+    export_include_dirs: ["."],
+    whole_static_libs: ["libgrallocusage"],
+    shared_libs: ["libhardware", "liblog"],
+}
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
similarity index 99%
rename from graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
rename to graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
index 041ce77..b7ed58c 100644
--- a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
+++ b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.cpp
@@ -29,6 +29,7 @@
 #include <sync/sync.h>
 
 #include <inttypes.h>
+#include <unistd.h>
 
 template <typename PFN, typename T>
 static gralloc1_function_pointer_t asFP(T function)
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.h b/graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.h
similarity index 100%
rename from graphics/allocator/2.0/default/Gralloc1On0Adapter.h
rename to graphics/allocator/2.0/utils/gralloc1-adapter/Gralloc1On0Adapter.h
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.cpp b/graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.cpp
similarity index 100%
rename from graphics/allocator/2.0/default/gralloc1-adapter.cpp
rename to graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.cpp
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.h b/graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.h
similarity index 100%
rename from graphics/allocator/2.0/default/gralloc1-adapter.h
rename to graphics/allocator/2.0/utils/gralloc1-adapter/gralloc1-adapter.h
diff --git a/graphics/allocator/2.0/utils/hal/Android.bp b/graphics/allocator/2.0/utils/hal/Android.bp
new file mode 100644
index 0000000..ac642ce
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/Android.bp
@@ -0,0 +1,14 @@
+cc_library_headers {
+    name: "android.hardware.graphics.allocator@2.0-hal",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
new file mode 100644
index 0000000..2f3022e
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "Allocator.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace hal {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+namespace detail {
+
+// AllocatorImpl implements IAllocator on top of AllocatorHal
+template <typename IALLOCATOR, typename ALLOCATOR_HAL>
+class AllocatorImpl : public IALLOCATOR {
+   public:
+    bool init(std::unique_ptr<ALLOCATOR_HAL> hal) {
+        mHal = std::move(hal);
+        return true;
+    }
+
+    // IAllocator 2.0 interface
+    Return<void> dumpDebugInfo(IAllocator::dumpDebugInfo_cb hidl_cb) override {
+        hidl_cb(mHal->dumpDebugInfo());
+        return Void();
+    }
+
+    Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
+                          IAllocator::allocate_cb hidl_cb) override {
+        uint32_t stride;
+        std::vector<const native_handle_t*> buffers;
+        Error error = mHal->allocateBuffers(descriptor, count, &stride, &buffers);
+        if (error != Error::NONE) {
+            hidl_cb(error, 0, hidl_vec<hidl_handle>());
+            return Void();
+        }
+
+        hidl_vec<hidl_handle> hidlBuffers(buffers.cbegin(), buffers.cend());
+        hidl_cb(Error::NONE, stride, hidlBuffers);
+
+        // free the local handles
+        mHal->freeBuffers(buffers);
+
+        return Void();
+    }
+
+   protected:
+    std::unique_ptr<ALLOCATOR_HAL> mHal;
+};
+
+}  // namespace detail
+
+using Allocator = detail::AllocatorImpl<IAllocator, AllocatorHal>;
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h
new file mode 100644
index 0000000..dec377a
--- /dev/null
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/AllocatorHal.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 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 <string>
+#include <vector>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace hal {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class AllocatorHal {
+   public:
+    virtual ~AllocatorHal() = default;
+
+    // dump the debug information
+    virtual std::string dumpDebugInfo() = 0;
+
+    // allocate buffers
+    virtual Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                  uint32_t* outStride,
+                                  std::vector<const native_handle_t*>* outBuffers) = 0;
+
+    // free buffers
+    virtual void freeBuffers(const std::vector<const native_handle_t*>& buffers) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Android.bp b/graphics/allocator/2.0/utils/passthrough/Android.bp
new file mode 100644
index 0000000..b956565
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Android.bp
@@ -0,0 +1,29 @@
+cc_library_static {
+    name: "android.hardware.graphics.allocator@2.0-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    srcs: [
+        "Gralloc0Hal.cpp",
+        "Gralloc1Hal.cpp",
+        "GrallocLoader.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    header_libs: [
+        "android.hardware.graphics.allocator@2.0-hal",
+        "libgrallocmapperincludes",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.allocator@2.0-hal",
+    ],
+    export_include_dirs: ["include"],
+    cflags: ["-DLOG_TAG=\"AllocatorHal\""],
+}
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
new file mode 100644
index 0000000..8edb7dc
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2016 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 <allocator-passthrough/2.0/Gralloc0Hal.h>
+
+#include <string.h>
+
+#include <GrallocBufferDescriptor.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
+
+Gralloc0Hal::~Gralloc0Hal() {
+    if (mDevice) {
+        gralloc_close(mDevice);
+    }
+}
+
+bool Gralloc0Hal::initWithModule(const hw_module_t* module) {
+    int result = gralloc_open(module, &mDevice);
+    if (result) {
+        ALOGE("failed to open gralloc0 device: %s", strerror(-result));
+        mDevice = nullptr;
+        return false;
+    }
+
+    return true;
+}
+
+std::string Gralloc0Hal::dumpDebugInfo() {
+    char buf[4096] = {};
+    if (mDevice->dump) {
+        mDevice->dump(mDevice, buf, sizeof(buf));
+        buf[sizeof(buf) - 1] = '\0';
+    }
+
+    return buf;
+}
+
+Error Gralloc0Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                   uint32_t* outStride,
+                                   std::vector<const native_handle_t*>* outBuffers) {
+    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        return Error::BAD_DESCRIPTOR;
+    }
+
+    Error error = Error::NONE;
+    uint32_t stride = 0;
+    std::vector<const native_handle_t*> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        const native_handle_t* tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        buffers.push_back(tmpBuffer);
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            error = Error::UNSUPPORTED;
+            break;
+        }
+    }
+
+    if (error != Error::NONE) {
+        freeBuffers(buffers);
+        return error;
+    }
+
+    *outStride = stride;
+    *outBuffers = std::move(buffers);
+
+    return Error::NONE;
+}
+
+void Gralloc0Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
+    for (auto buffer : buffers) {
+        int result = mDevice->free(mDevice, buffer);
+        if (result != 0) {
+            ALOGE("failed to free buffer %p: %d", buffer, result);
+        }
+    }
+}
+
+Error Gralloc0Hal::allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                                     const native_handle_t** outBuffer, uint32_t* outStride) {
+    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+        return Error::BAD_VALUE;
+    }
+
+    const native_handle_t* buffer = nullptr;
+    int stride = 0;
+    int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
+                                info.usage, &buffer, &stride);
+    switch (result) {
+        case 0:
+            *outBuffer = buffer;
+            *outStride = stride;
+            return Error::NONE;
+        case -EINVAL:
+            return Error::BAD_VALUE;
+        default:
+            return Error::NO_RESOURCES;
+    }
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
new file mode 100644
index 0000000..e343ecd
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2016 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 <allocator-passthrough/2.0/Gralloc1Hal.h>
+
+#include <string.h>
+
+#include <GrallocBufferDescriptor.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
+
+Gralloc1Hal::~Gralloc1Hal() {
+    if (mDevice) {
+        gralloc1_close(mDevice);
+    }
+}
+
+bool Gralloc1Hal::initWithModule(const hw_module_t* module) {
+    int result = gralloc1_open(module, &mDevice);
+    if (result) {
+        ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+        mDevice = nullptr;
+        return false;
+    }
+
+    initCapabilities();
+    if (!initDispatch()) {
+        gralloc1_close(mDevice);
+        mDevice = nullptr;
+        return false;
+    }
+
+    return true;
+}
+
+void Gralloc1Hal::initCapabilities() {
+    uint32_t count = 0;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<int32_t> capabilities(count);
+    mDevice->getCapabilities(mDevice, &count, capabilities.data());
+    capabilities.resize(count);
+
+    for (auto capability : capabilities) {
+        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+            mCapabilities.layeredBuffers = true;
+            break;
+        }
+    }
+}
+
+gralloc1_function_pointer_t Gralloc1Hal::getDispatchFunction(
+    gralloc1_function_descriptor_t desc) const {
+    auto pfn = mDevice->getFunction(mDevice, desc);
+    if (!pfn) {
+        ALOGE("failed to get gralloc1 function %d", desc);
+        return nullptr;
+    }
+    return pfn;
+}
+
+bool Gralloc1Hal::initDispatch() {
+    if (!initDispatchFunction(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
+        !initDispatchFunction(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
+        return false;
+    }
+
+    if (mCapabilities.layeredBuffers) {
+        if (!initDispatchFunction(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+std::string Gralloc1Hal::dumpDebugInfo() {
+    uint32_t len = 0;
+    mDispatch.dump(mDevice, &len, nullptr);
+
+    std::vector<char> buf(len + 1);
+    mDispatch.dump(mDevice, &len, buf.data());
+    buf.resize(len + 1);
+    buf[len] = '\0';
+
+    return buf.data();
+}
+
+Error Gralloc1Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
+                                   uint32_t* outStride,
+                                   std::vector<const native_handle_t*>* outBuffers) {
+    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+        return Error::BAD_DESCRIPTOR;
+    }
+
+    gralloc1_buffer_descriptor_t desc;
+    Error error = createDescriptor(descriptorInfo, &desc);
+    if (error != Error::NONE) {
+        return error;
+    }
+
+    uint32_t stride = 0;
+    std::vector<const native_handle_t*> buffers;
+    buffers.reserve(count);
+
+    // allocate the buffers
+    for (uint32_t i = 0; i < count; i++) {
+        const native_handle_t* tmpBuffer;
+        uint32_t tmpStride;
+        error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
+        if (error != Error::NONE) {
+            break;
+        }
+
+        buffers.push_back(tmpBuffer);
+
+        if (stride == 0) {
+            stride = tmpStride;
+        } else if (stride != tmpStride) {
+            // non-uniform strides
+            error = Error::UNSUPPORTED;
+            break;
+        }
+    }
+
+    mDispatch.destroyDescriptor(mDevice, desc);
+
+    if (error != Error::NONE) {
+        freeBuffers(buffers);
+        return error;
+    }
+
+    *outStride = stride;
+    *outBuffers = std::move(buffers);
+
+    return Error::NONE;
+}
+
+void Gralloc1Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
+    for (auto buffer : buffers) {
+        int32_t error = mDispatch.release(mDevice, buffer);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("failed to free buffer %p: %d", buffer, error);
+        }
+    }
+}
+
+Error Gralloc1Hal::toError(int32_t error) {
+    switch (error) {
+        case GRALLOC1_ERROR_NONE:
+            return Error::NONE;
+        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+            return Error::BAD_DESCRIPTOR;
+        case GRALLOC1_ERROR_BAD_HANDLE:
+            return Error::BAD_BUFFER;
+        case GRALLOC1_ERROR_BAD_VALUE:
+            return Error::BAD_VALUE;
+        case GRALLOC1_ERROR_NOT_SHARED:
+            return Error::NONE;  // this is fine
+        case GRALLOC1_ERROR_NO_RESOURCES:
+            return Error::NO_RESOURCES;
+        case GRALLOC1_ERROR_UNDEFINED:
+        case GRALLOC1_ERROR_UNSUPPORTED:
+        default:
+            return Error::UNSUPPORTED;
+    }
+}
+
+uint64_t Gralloc1Hal::toProducerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t producerUsage =
+        usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+                                       BufferUsage::GPU_DATA_BUFFER);
+
+    switch (usage & BufferUsage::CPU_WRITE_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    // BufferUsage::GPU_DATA_BUFFER is always filtered out
+
+    return producerUsage;
+}
+
+uint64_t Gralloc1Hal::toConsumerUsage(uint64_t usage) {
+    // this is potentially broken as we have no idea which private flags
+    // should be filtered out
+    uint64_t consumerUsage =
+        usage &
+        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+                               BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
+
+    switch (usage & BufferUsage::CPU_READ_MASK) {
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+            break;
+        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+            break;
+        default:
+            break;
+    }
+
+    // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
+
+    if (usage & BufferUsage::GPU_DATA_BUFFER) {
+        consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
+    }
+
+    return consumerUsage;
+}
+
+Error Gralloc1Hal::createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                                    gralloc1_buffer_descriptor_t* outDescriptor) {
+    gralloc1_buffer_descriptor_t descriptor;
+
+    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        if (mCapabilities.layeredBuffers) {
+            error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+        } else if (info.layerCount > 1) {
+            error = GRALLOC1_ERROR_UNSUPPORTED;
+        }
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
+    }
+    if (error == GRALLOC1_ERROR_NONE) {
+        error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
+    }
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outDescriptor = descriptor;
+    } else {
+        mDispatch.destroyDescriptor(mDevice, descriptor);
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Hal::allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
+                                     const native_handle_t** outBuffer, uint32_t* outStride) {
+    const native_handle_t* buffer = nullptr;
+    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+        return toError(error);
+    }
+
+    uint32_t stride = 0;
+    error = mDispatch.getStride(mDevice, buffer, &stride);
+    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+        mDispatch.release(mDevice, buffer);
+        return toError(error);
+    }
+
+    *outBuffer = buffer;
+    *outStride = stride;
+
+    return Error::NONE;
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
new file mode 100644
index 0000000..dae7a78
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 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 <allocator-passthrough/2.0/GrallocLoader.h>
+
+#include <allocator-hal/2.0/Allocator.h>
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <allocator-passthrough/2.0/Gralloc0Hal.h>
+#include <allocator-passthrough/2.0/Gralloc1Hal.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+const hw_module_t* GrallocLoader::loadModule() {
+    const hw_module_t* module;
+    int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    if (error) {
+        ALOGE("failed to get gralloc module");
+        return nullptr;
+    }
+
+    return module;
+}
+
+int GrallocLoader::getModuleMajorApiVersion(const hw_module_t* module) {
+    return (module->module_api_version >> 8) & 0xff;
+}
+
+std::unique_ptr<hal::AllocatorHal> GrallocLoader::createHal(const hw_module_t* module) {
+    int major = getModuleMajorApiVersion(module);
+    switch (major) {
+        case 1: {
+            auto hal = std::make_unique<Gralloc1Hal>();
+            return hal->initWithModule(module) ? std::move(hal) : nullptr;
+        }
+        case 0: {
+            auto hal = std::make_unique<Gralloc0Hal>();
+            return hal->initWithModule(module) ? std::move(hal) : nullptr;
+        }
+        default:
+            ALOGE("unknown gralloc module major version %d", major);
+            return nullptr;
+    }
+}
+
+IAllocator* GrallocLoader::createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
+    auto allocator = std::make_unique<hal::Allocator>();
+    return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
new file mode 100644
index 0000000..8f433b0
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 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 <allocator-hal/2.0/AllocatorHal.h>
+
+struct alloc_device_t;
+struct hw_module_t;
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class Gralloc0Hal : public virtual hal::AllocatorHal {
+   public:
+    ~Gralloc0Hal();
+    bool initWithModule(const hw_module_t* module);
+
+    std::string dumpDebugInfo() override;
+
+    Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
+                          std::vector<const native_handle_t*>* outBuffers) override;
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+
+   protected:
+    Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                            const native_handle_t** outBuffer, uint32_t* outStride);
+
+    alloc_device_t* mDevice = nullptr;
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
new file mode 100644
index 0000000..3126e91
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2016 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 <allocator-hal/2.0/AllocatorHal.h>
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+using mapper::V2_0::BufferDescriptor;
+using mapper::V2_0::Error;
+
+class Gralloc1Hal : public virtual hal::AllocatorHal {
+   public:
+    ~Gralloc1Hal();
+    bool initWithModule(const hw_module_t* module);
+
+    std::string dumpDebugInfo() override;
+
+    Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
+                          std::vector<const native_handle_t*>* outBuffers) override;
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+
+   protected:
+    template <typename T>
+    bool initDispatchFunction(gralloc1_function_descriptor_t desc, T* outPfn) {
+        auto pfn = getDispatchFunction(desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            return false;
+        }
+    }
+    gralloc1_function_pointer_t getDispatchFunction(gralloc1_function_descriptor_t desc) const;
+
+    virtual void initCapabilities();
+    virtual bool initDispatch();
+
+    static Error toError(int32_t error);
+    static uint64_t toProducerUsage(uint64_t usage);
+    static uint64_t toConsumerUsage(uint64_t usage);
+
+    Error createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
+                           gralloc1_buffer_descriptor_t* outDescriptor);
+
+    Error allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
+                            const native_handle_t** outBuffer, uint32_t* outStride);
+
+    gralloc1_device_t* mDevice = nullptr;
+
+    struct {
+        bool layeredBuffers;
+    } mCapabilities = {};
+
+    struct {
+        GRALLOC1_PFN_DUMP dump;
+        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
+        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
+        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
+        GRALLOC1_PFN_SET_FORMAT setFormat;
+        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
+        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
+        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
+        GRALLOC1_PFN_GET_STRIDE getStride;
+        GRALLOC1_PFN_ALLOCATE allocate;
+        GRALLOC1_PFN_RELEASE release;
+    } mDispatch = {};
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
new file mode 100644
index 0000000..a0b9503
--- /dev/null
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017 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 <memory>
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+
+struct hw_module_t;
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace passthrough {
+
+class GrallocLoader {
+   public:
+    static IAllocator* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+        auto hal = createHal(module);
+        if (!hal) {
+            return nullptr;
+        }
+        return createAllocator(std::move(hal));
+    }
+
+    // load the gralloc module
+    static const hw_module_t* loadModule();
+
+    // return the major api version of the module
+    static int getModuleMajorApiVersion(const hw_module_t* module);
+
+    // create an AllocatorHal instance
+    static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module);
+
+    // create an IAllocator instance
+    static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal);
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
index 0c890bd..fcc51fd 100644
--- a/keymaster/4.0/types.hal
+++ b/keymaster/4.0/types.hal
@@ -136,6 +136,51 @@
                                                 * if device is still on-body (requires secure
                                                 * on-body sensor. */
 
+    /**
+     * TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
+     * unusable except when the user has provided proof of physical presence.  Proof of physical
+     * presence must be a signal that cannot be triggered by an attacker who doesn't have one of:
+     *
+     *    a) Physical control of the device or
+     *
+     *    b) Control of the secure environment that holds the key.
+     *
+     * For instance, proof of user identity may be considered proof of presence if it meets the
+     * requirements.  However, proof of identity established in one security domain (e.g. TEE) does
+     * not constitute proof of presence in another security domain (e.g. StrongBox), and no
+     * mechanism analogous to the authentication token is defined for communicating proof of
+     * presence across security domains.
+     *
+     * Some examples:
+     *
+     *     A hardware button hardwired to a pin on a StrongBox device in such a way that nothing
+     *     other than a button press can trigger the signal constitutes proof of physical presence
+     *     for StrongBox keys.
+     *
+     *     Fingerprint authentication provides proof of presence (and identity) for TEE keys if the
+     *     TEE has exclusive control of the fingerprint scanner and performs fingerprint matching.
+     *
+     *     Password authentication does not provide proof of presence to either TEE or StrongBox,
+     *     even if TEE or StrongBox does the password matching, because password input is handled by
+     *     the non-secure world, which means an attacker who has compromised Android can spoof
+     *     password authentication.
+     *
+     * Note that no mechanism is defined for delivering proof of presence to Keymaster,
+     * except perhaps as implied by an auth token.  This means that Keymaster must be able to check
+     * proof of presence some other way.  Further, the proof of presence must be performed between
+     * begin() and the first call to update() or finish().  If the first update() or the finish()
+     * call is made without proof of presence, the keymaster method must return
+     * ErrorCode::PROOF_OF_PRESENCE_REQUIRED and abort the operation.  The caller must delay the
+     * update() or finish() call until proof of presence has been provided, which means the caller
+     * must also have some mechanism for verifying that the proof has been provided.
+     *
+     * Only one operation requiring TUP may be in flight at a time.  If begin() has already been
+     * called on one key with TRUSTED_USER_PRESENCE_REQUIRED, and another begin() comes in for that
+     * key or another with TRUSTED_USER_PRESENCE_REQUIRED, Keymaster must return
+     * ErrorCode::CONCURRENT_PROOF_OF_PRESENCE_REQUESTED.
+     */
+    TRUSTED_USER_PRESENCE_REQUIRED = TagType:BOOL | 507,
+
     /* Application access control */
     APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
 
@@ -381,6 +426,8 @@
     CANNOT_ATTEST_IDS = -66,
     ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
     HARDWARE_TYPE_UNAVAILABLE = -68,
+    PROOF_OF_PRESENCE_REQUIRED = -69,
+    CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index c8858de..060d904 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -75,6 +75,7 @@
         case Tag::ALLOW_WHILE_ON_BODY:
         case Tag::ROLLBACK_RESISTANCE:
         case Tag::RESET_SINCE_ID_ROTATION:
+        case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
             return true;
 
         /* Integer tags */