OSDN Git Service

graphics: revise gralloc interfaces
authorChia-I Wu <olv@google.com>
Fri, 31 Mar 2017 19:48:11 +0000 (12:48 -0700)
committerChia-I Wu <olv@google.com>
Mon, 10 Apr 2017 18:15:54 +0000 (11:15 -0700)
Revise IAllocator and IMapper to reduce IPC and to support gralloc0
devices.

Specifically, IAllocator is trimmed down to have essentially only

    allocate(BufferDescriptor descriptor, uint32_t count)
        generates (Error error,
                   uint32_t stride,
                   vec<handle> buffers);

The ability to allocate buffers with shared backing store is
removed.  ProducerUsage and ConsumerUsage are moved to the
graphics.common package and are merged and renamed to BufferUsage.
BufferUsage's bits follow gralloc0.

IMapper gains

    typedef vec<uint32_t> BufferDescriptor;
    createDescriptor(BufferDescriptorInfo descriptorInfo)
          generates (Error error,
                     BufferDescriptor descriptor);

where BufferDescriptor is an implementation-defined blob.  lockFlex
is replaced by lockYCbCr.  All getters are removed.

Reference counting with retain/release is replaced by
importBuffer/freeBuffer.

Most if not all gralloc1 features are not used by the runtime yet.
There is also not too much test written for them.  As such, they
tend to behave differently between implementations and cannot be
used reliably.

Bug: 36481301
Test: builds and boots on Pixel
Change-Id: I1d31105120517ea2c128c7a19297acf3bfd312bb

45 files changed:
automotive/evs/1.0/vts/functional/FrameHandler.cpp
automotive/evs/1.0/vts/functional/FrameHandler.h
camera/device/1.0/Android.bp
camera/device/1.0/ICameraDevicePreviewCallback.hal
camera/device/1.0/default/CameraDevice.cpp
camera/device/3.2/Android.bp
camera/device/3.2/default/CameraDeviceSession.cpp
camera/device/3.2/default/convert.cpp
camera/device/3.2/types.hal
camera/provider/2.4/Android.bp
camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
graphics/Android.bp
graphics/allocator/2.0/Android.bp
graphics/allocator/2.0/IAllocator.hal
graphics/allocator/2.0/IAllocatorClient.hal [deleted file]
graphics/allocator/2.0/default/Android.bp
graphics/allocator/2.0/default/Gralloc.cpp
graphics/allocator/2.0/default/Gralloc0Allocator.cpp [new file with mode: 0644]
graphics/allocator/2.0/default/Gralloc0Allocator.h [new file with mode: 0644]
graphics/allocator/2.0/default/Gralloc1Allocator.cpp [new file with mode: 0644]
graphics/allocator/2.0/default/Gralloc1Allocator.h [new file with mode: 0644]
graphics/allocator/2.0/types.hal [deleted file]
graphics/allocator/2.0/vts/functional/Android.bp [deleted file]
graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp [deleted file]
graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h [deleted file]
graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp [deleted file]
graphics/common/1.0/Android.mk
graphics/common/1.0/types.hal
graphics/composer/2.1/vts/functional/Android.bp
graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
graphics/mapper/2.0/Android.bp
graphics/mapper/2.0/IMapper.hal
graphics/mapper/2.0/default/Android.bp
graphics/mapper/2.0/default/Gralloc0Mapper.cpp [new file with mode: 0644]
graphics/mapper/2.0/default/Gralloc0Mapper.h [new file with mode: 0644]
graphics/mapper/2.0/default/Gralloc1Mapper.cpp [new file with mode: 0644]
graphics/mapper/2.0/default/Gralloc1Mapper.h [new file with mode: 0644]
graphics/mapper/2.0/default/GrallocBufferDescriptor.h [new file with mode: 0644]
graphics/mapper/2.0/default/GrallocMapper.cpp
graphics/mapper/2.0/default/GrallocMapper.h
graphics/mapper/2.0/types.hal
graphics/mapper/2.0/vts/functional/Android.bp
graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp

index 01d9a0e..58c2f26 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <android/log.h>
 #include <cutils/native_handle.h>
-#include <ui/GraphicBufferMapper.h>
 #include <ui/GraphicBuffer.h>
 
 #include <algorithm>    // std::min
@@ -135,11 +134,7 @@ Return<void> FrameHandler::deliverFrame(const BufferDesc& bufferArg) {
     // Local flag we use to keep track of when the stream is stopping
     bool timeToStop = false;
 
-    // TODO:  Why do we get a gralloc crash if we don't clone the buffer here?
-    BufferDesc buffer(bufferArg);
-    ALOGD("Clone the received frame as %p", buffer.memHandle.getNativeHandle());
-
-    if (buffer.memHandle.getNativeHandle() == nullptr) {
+    if (bufferArg.memHandle.getNativeHandle() == nullptr) {
         // Signal that the last frame has been received and the stream is stopped
         timeToStop = true;
     } else {
@@ -157,13 +152,8 @@ Return<void> FrameHandler::deliverFrame(const BufferDesc& bufferArg) {
                 printf("Didn't get target buffer - frame lost\n");
                 ALOGE("Didn't get requested output buffer -- skipping this frame.");
             } else {
-                // In order for the handles passed through HIDL and stored in the BufferDesc to
-                // be lockable, we must register them with GraphicBufferMapper
-                registerBufferHelper(tgtBuffer);
-                registerBufferHelper(buffer);
-
                 // Copy the contents of the of buffer.memHandle into tgtBuffer
-                copyBufferContents(tgtBuffer, buffer);
+                copyBufferContents(tgtBuffer, bufferArg);
 
                 // Send the target buffer back for display
                 Return <EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
@@ -183,10 +173,6 @@ Return<void> FrameHandler::deliverFrame(const BufferDesc& bufferArg) {
                     mFramesDisplayed++;
                     mLock.unlock();
                 }
-
-                // Now tell GraphicBufferMapper we won't be using these handles anymore
-                unregisterBufferHelper(tgtBuffer);
-                unregisterBufferHelper(buffer);
             }
         }
 
@@ -233,24 +219,22 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer,
     const unsigned height    = std::min(tgtBuffer.height,
                                         srcBuffer.height);
 
-    android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
-
+    sp<android::GraphicBuffer> tgt = new android::GraphicBuffer(
+        tgtBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
+        tgtBuffer.width, tgtBuffer.height, tgtBuffer.format, 1, tgtBuffer.usage,
+        tgtBuffer.stride);
+    sp<android::GraphicBuffer> src = new android::GraphicBuffer(
+        srcBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
+        srcBuffer.width, srcBuffer.height, srcBuffer.format, 1, srcBuffer.usage,
+        srcBuffer.stride);
 
     // Lock our source buffer for reading
     unsigned char* srcPixels = nullptr;
-    mapper.registerBuffer(srcBuffer.memHandle);
-    mapper.lock(srcBuffer.memHandle,
-                GRALLOC_USAGE_SW_READ_OFTEN,
-                android::Rect(width, height),
-                (void **) &srcPixels);
+    src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
 
     // Lock our target buffer for writing
     unsigned char* tgtPixels = nullptr;
-    mapper.registerBuffer(tgtBuffer.memHandle);
-    mapper.lock(tgtBuffer.memHandle,
-                GRALLOC_USAGE_SW_WRITE_OFTEN,
-                android::Rect(width, height),
-                (void **) &tgtPixels);
+    tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
 
     if (srcPixels && tgtPixels) {
         for (unsigned row = 0; row < height; row++) {
@@ -267,45 +251,11 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer,
     }
 
     if (srcPixels) {
-        mapper.unlock(srcBuffer.memHandle);
+        src->unlock();
     }
     if (tgtPixels) {
-        mapper.unlock(tgtBuffer.memHandle);
+        tgt->unlock();
     }
-    mapper.unregisterBuffer(srcBuffer.memHandle);
-    mapper.unregisterBuffer(tgtBuffer.memHandle);
 
     return success;
 }
-
-
-void FrameHandler::registerBufferHelper(const BufferDesc& buffer)
-{
-    // In order for the handles passed through HIDL and stored in the BufferDesc to
-    // be lockable, we must register them with GraphicBufferMapper.
-    // If the device upon which we're running supports gralloc1, we could just call
-    // registerBuffer directly with the handle.  But that call  is broken for gralloc0 devices
-    // (which we care about, at least for now).  As a result, we have to synthesize a GraphicBuffer
-    // object around the buffer handle in order to make a call to the overloaded alternate
-    // version of the registerBuffer call that does happen to work on gralloc0 devices.
-#if REGISTER_BUFFER_ALWAYS_WORKS
-    android::GraphicBufferMapper::get().registerBuffer(buffer.memHandle);
-#else
-    android::sp<android::GraphicBuffer> pGfxBuff = new android::GraphicBuffer(
-            buffer.width, buffer.height, buffer.format,
-            1, /* we always use exactly one layer */
-            buffer.usage, buffer.stride,
-            const_cast<native_handle_t*>(buffer.memHandle.getNativeHandle()),
-            false /* GraphicBuffer should not try to free the handle */
-    );
-
-    android::GraphicBufferMapper::get().registerBuffer(pGfxBuff.get());
-#endif
-}
-
-
-void FrameHandler::unregisterBufferHelper(const BufferDesc& buffer)
-{
-    // Now tell GraphicBufferMapper we won't be using these handles anymore
-    android::GraphicBufferMapper::get().unregisterBuffer(buffer.memHandle);
-}
index d5c3f6b..17a3980 100644 (file)
@@ -68,8 +68,6 @@ private:
 
     // Local implementation details
     bool copyBufferContents(const BufferDesc& tgtBuffer, const BufferDesc& srcBuffer);
-    void registerBufferHelper(const BufferDesc& buffer);
-    void unregisterBufferHelper(const BufferDesc& buffer);
 
     // Values initialized as startup
     android::sp <IEvsCamera>    mCamera;
index 44a108c..81e41aa 100644 (file)
@@ -66,7 +66,6 @@ cc_library_shared {
         "libutils",
         "libcutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -76,7 +75,6 @@ cc_library_shared {
         "libhwbinder",
         "libutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
index 4c9b517..5421981 100644 (file)
@@ -17,7 +17,6 @@
 package android.hardware.camera.device@1.0;
 
 import android.hardware.camera.common@1.0::types;
-import android.hardware.graphics.allocator@2.0::types;
 import android.hardware.graphics.common@1.0::types;
 
 /**
@@ -89,7 +88,7 @@ interface ICameraDevicePreviewCallback {
      *
      * @return Status The status code for this operation.
      */
-    setUsage(ProducerUsage usage) generates (Status status);
+    setUsage(BufferUsage usage) generates (Status status);
 
     /**
      * Set the expected buffering mode for the preview output.
index 6495f30..cb20fec 100644 (file)
@@ -30,7 +30,7 @@ namespace device {
 namespace V1_0 {
 namespace implementation {
 
-using ::android::hardware::graphics::allocator::V2_0::ProducerUsage;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
 
 HandleImporter& CameraDevice::sHandleImporter = HandleImporter::getInstance();
@@ -259,7 +259,7 @@ int CameraDevice::sSetUsage(struct preview_stream_ops* w, int usage) {
     }
 
     object->cleanUpCirculatingBuffers();
-    return getStatusT(object->mPreviewCallback->setUsage((ProducerUsage) usage));
+    return getStatusT(object->mPreviewCallback->setUsage((BufferUsage)usage));
 }
 
 int CameraDevice::sSetSwapInterval(struct preview_stream_ops *w, int interval) {
index fd7276f..7807a85 100644 (file)
@@ -66,7 +66,6 @@ cc_library_shared {
         "libutils",
         "libcutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -76,7 +75,6 @@ cc_library_shared {
         "libhwbinder",
         "libutils",
         "android.hardware.camera.common@1.0",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
index 5b3024b..5bb53c7 100644 (file)
@@ -650,7 +650,8 @@ Return<void> CameraDeviceSession::configureStreams(
         mVideoStreamIds.clear();
         for (const auto& stream : requestedConfiguration.streams) {
             if (stream.streamType == StreamType::OUTPUT &&
-                    stream.usage & graphics::allocator::V2_0::ConsumerUsage::VIDEO_ENCODER) {
+                stream.usage &
+                    graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
                 mVideoStreamIds.push_back(stream.id);
             }
         }
index c7cc75a..d878deb 100644 (file)
@@ -28,8 +28,7 @@ namespace implementation {
 
 using ::android::hardware::graphics::common::V1_0::Dataspace;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::camera::device::V3_2::ConsumerUsageFlags;
-using ::android::hardware::camera::device::V3_2::ProducerUsageFlags;
+using ::android::hardware::camera::device::V3_2::BufferUsageFlags;
 
 bool convertFromHidl(const CameraMetadata &src, const camera_metadata_t** dst) {
     if (src.size() == 0) {
@@ -78,11 +77,11 @@ void convertToHidl(const Camera3Stream* src, HalStream* dst) {
     dst->overrideFormat = (PixelFormat) src->format;
     dst->maxBuffers = src->max_buffers;
     if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
-        dst->consumerUsage = (ConsumerUsageFlags) 0;
-        dst->producerUsage = (ProducerUsageFlags) src->usage;
+        dst->consumerUsage = (BufferUsageFlags)0;
+        dst->producerUsage = (BufferUsageFlags)src->usage;
     } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
-        dst->producerUsage = (ProducerUsageFlags) 0;
-        dst->consumerUsage = (ConsumerUsageFlags) src->usage;
+        dst->producerUsage = (BufferUsageFlags)0;
+        dst->consumerUsage = (BufferUsageFlags)src->usage;
     } else {
         //Should not reach here per current HIDL spec, but we might end up adding
         // bi-directional stream to HIDL.
index 5ae7a18..1632570 100644 (file)
 
 package android.hardware.camera.device@3.2;
 
-import android.hardware.graphics.allocator@2.0::types;
 import android.hardware.graphics.common@1.0::types;
 
 typedef vec<uint8_t> CameraMetadata;
-typedef bitfield<ProducerUsage> ProducerUsageFlags;
-typedef bitfield<ConsumerUsage> ConsumerUsageFlags;
+typedef bitfield<BufferUsage> BufferUsageFlags;
 typedef bitfield<Dataspace> DataspaceFlags;
 
 /**
@@ -255,7 +253,7 @@ struct Stream {
      * with ILLEGAL_ARGUMENT if the combined flags cannot be supported due to
      * imcompatible buffer format, dataSpace, or other hardware limitations.
      */
-    ConsumerUsageFlags usage;
+    BufferUsageFlags usage;
 
     /**
      * A field that describes the contents of the buffer. The format and buffer
@@ -373,8 +371,8 @@ struct HalStream {
      * consumerUsage must be set. For other types, producerUsage must be set,
      * and consumerUsage must be 0.
      */
-    ProducerUsageFlags producerUsage;
-    ConsumerUsageFlags consumerUsage;
+    BufferUsageFlags producerUsage;
+    BufferUsageFlags consumerUsage;
 
     /**
      * The maximum number of buffers the HAL device may need to have dequeued at
index 1656325..d295f3e 100644 (file)
@@ -57,7 +57,6 @@ cc_library_shared {
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -69,7 +68,6 @@ cc_library_shared {
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
index 74e6efe..e37f989 100644 (file)
@@ -52,8 +52,8 @@ using ::android::BufferQueue;
 using ::android::BufferItemConsumer;
 using ::android::Surface;
 using ::android::CameraParameters;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::graphics::allocator::V2_0::ProducerUsage;
 using ::android::hardware::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
 using ::android::hardware::camera::common::V1_0::TorchMode;
@@ -233,7 +233,7 @@ struct PreviewWindowCb : public ICameraDevicePreviewCallback {
     Return<Status> setCrop(int32_t left, int32_t top,
             int32_t right, int32_t bottom) override;
 
-    Return<Status> setUsage(ProducerUsage usage) override;
+    Return<Status> setUsage(BufferUsage usage) override;
 
     Return<Status> setSwapInterval(int32_t interval) override;
 
@@ -408,7 +408,7 @@ Return<Status> PreviewWindowCb::setCrop(int32_t left, int32_t top,
     return mapToStatus(rc);
 }
 
-Return<Status> PreviewWindowCb::setUsage(ProducerUsage usage) {
+Return<Status> PreviewWindowCb::setUsage(BufferUsage usage) {
     auto rc = native_window_set_usage(mAnw.get(), static_cast<int>(usage));
     if (rc == ::android::OK) {
         mPreviewUsage =  static_cast<int>(usage);
index f4f7db4..9aea85f 100644 (file)
@@ -2,7 +2,6 @@
 subdirs = [
     "allocator/2.0",
     "allocator/2.0/default",
-    "allocator/2.0/vts/functional",
     "bufferqueue/1.0",
     "common/1.0",
     "composer/2.1",
index 271f2ce..f707468 100644 (file)
@@ -3,9 +3,7 @@
 filegroup {
     name: "android.hardware.graphics.allocator@2.0_hal",
     srcs: [
-        "types.hal",
         "IAllocator.hal",
-        "IAllocatorClient.hal",
     ],
 }
 
@@ -17,9 +15,7 @@ genrule {
         ":android.hardware.graphics.allocator@2.0_hal",
     ],
     out: [
-        "android/hardware/graphics/allocator/2.0/types.cpp",
         "android/hardware/graphics/allocator/2.0/AllocatorAll.cpp",
-        "android/hardware/graphics/allocator/2.0/AllocatorClientAll.cpp",
     ],
 }
 
@@ -31,18 +27,11 @@ genrule {
         ":android.hardware.graphics.allocator@2.0_hal",
     ],
     out: [
-        "android/hardware/graphics/allocator/2.0/types.h",
-        "android/hardware/graphics/allocator/2.0/hwtypes.h",
         "android/hardware/graphics/allocator/2.0/IAllocator.h",
         "android/hardware/graphics/allocator/2.0/IHwAllocator.h",
         "android/hardware/graphics/allocator/2.0/BnHwAllocator.h",
         "android/hardware/graphics/allocator/2.0/BpHwAllocator.h",
         "android/hardware/graphics/allocator/2.0/BsAllocator.h",
-        "android/hardware/graphics/allocator/2.0/IAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/IHwAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/BnHwAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/BpHwAllocatorClient.h",
-        "android/hardware/graphics/allocator/2.0/BsAllocatorClient.h",
     ],
 }
 
@@ -59,6 +48,7 @@ cc_library_shared {
         "libutils",
         "libcutils",
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
         "android.hidl.base@1.0",
     ],
     export_shared_lib_headers: [
@@ -67,6 +57,7 @@ cc_library_shared {
         "libhwbinder",
         "libutils",
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
         "android.hidl.base@1.0",
     ],
 }
index bf0e141..43a3916 100644 (file)
 
 package android.hardware.graphics.allocator@2.0;
 
-import IAllocatorClient;
+import android.hardware.graphics.mapper@2.0;
 
 interface IAllocator {
-    enum Capability : int32_t {
-        /** reserved */
-        INVALID = 0,
-
-        /**
-         * IAllocatorClient::testAllocate must always return UNDEFINED unless
-         * this capability is supported.
-         */
-        TEST_ALLOCATE = 1,
-
-        /**
-         * IAllocatorClient::BufferDescriptorInfo::layerCount must be 1 unless
-         * this capability is supported.
-         */
-        LAYERED_BUFFERS = 2,
-    };
-
-    /**
-     * Provides a list of supported capabilities (as described in the
-     * definition of Capability above). This list must not change after
-     * initialization.
-     *
-     * @return capabilities is a list of supported capabilities.
-     */
-    @entry
-    @exit
-    @callflow(next="*")
-    getCapabilities() generates (vec<Capability> capabilities);
-
     /**
      * Retrieves implementation-defined debug information, which will be
      * displayed during, for example, `dumpsys SurfaceFlinger`.
@@ -60,15 +31,27 @@ interface IAllocator {
     dumpDebugInfo() generates (string debugInfo);
 
     /**
-     * Creates a client of the allocator. All resources created by the client
-     * are owned by the client and are only visible to the client, unless they
-     * are exported by exportHandle.
+     * Allocates buffers with the properties specified by the descriptor.
      *
+     * @param descriptor specifies the properties of the buffers to allocate.
+     * @param count is the number of buffers to allocate.
      * @return error is NONE upon success. Otherwise,
-     *         NO_RESOURCES when no more client can currently be created.
-     * @return client is the newly created client.
+     *         BAD_DESCRIPTOR when the descriptor is invalid.
+     *         NO_RESOURCES when the allocation cannot be fulfilled at this
+     *                      time.
+     *         UNSUPPORTED when any of the property encoded in the descriptor
+     *                     is not supported.
+     * @return stride is the number of pixels between two consecutive rows of
+     *         the buffers, when the concept of consecutive rows is defined.
+     *         Otherwise, it has no meaning.
+     * @return buffers is an array of raw handles to the newly allocated
+     *         buffers.
      */
     @entry
+    @exit
     @callflow(next="*")
-    createClient() generates (Error error, IAllocatorClient client);
+    allocate(BufferDescriptor descriptor, uint32_t count)
+        generates (Error error,
+                   uint32_t stride,
+                   vec<handle> buffers);
 };
diff --git a/graphics/allocator/2.0/IAllocatorClient.hal b/graphics/allocator/2.0/IAllocatorClient.hal
deleted file mode 100644 (file)
index 8ca568f..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.hardware.graphics.allocator@2.0;
-
-import android.hardware.graphics.common@1.0::PixelFormat;
-
-interface IAllocatorClient {
-    struct BufferDescriptorInfo {
-        /**
-         * The width specifies how many columns of pixels must be in the
-         * allocated buffer, but does not necessarily represent the offset in
-         * columns between the same column in adjacent rows. The rows may be
-         * padded.
-         */
-        uint32_t width;
-
-       /**
-        * The height specifies how many rows of pixels must be in the
-        * allocated buffer.
-        */
-        uint32_t height;
-
-       /**
-        * The number of image layers that must be in the allocated buffer.
-        */
-        uint32_t layerCount;
-
-        /** Buffer pixel format. */
-        PixelFormat format;
-
-        /**
-         * Buffer producer usage mask; valid flags can be found in the
-         * definition of ProducerUsage.
-         */
-        uint64_t producerUsageMask;
-
-        /**
-         * Buffer consumer usage mask; valid flags can be found in the
-         * definition of ConsumerUsage.
-         */
-        uint64_t consumerUsageMask;
-    };
-
-    /**
-     * Creates a new, opaque buffer descriptor.
-     *
-     * @param descriptorInfo specifies the attributes of the buffer
-     *        descriptor.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_VALUE when any attribute in descriptorInfo is invalid.
-     *         NO_RESOURCES when no more descriptors can currently be created.
-     * @return descriptor is the newly created buffer descriptor.
-     */
-    @entry
-    @callflow(next="*")
-    createDescriptor(BufferDescriptorInfo descriptorInfo)
-          generates (Error error,
-                     BufferDescriptor descriptor);
-
-    /**
-     * Destroys an existing buffer descriptor.
-     *
-     * @param descriptor is the descriptor to destroy.
-     * @return error is either NONE or BAD_DESCRIPTOR.
-     */
-    @exit
-    @callflow(next="*")
-    destroyDescriptor(BufferDescriptor descriptor) generates (Error error);
-
-    /**
-     * Tests whether a buffer allocation can succeed, ignoring potential
-     * resource contention which might lead to a NO_RESOURCES error.
-     *
-     * @param descriptors is a list of buffer descriptors.
-     * @return error is NONE or NOT_SHARED upon success;
-     *         NONE when buffers can be created and share a backing store.
-     *         NOT_SHARED when buffers can be created but require more than a
-     *                    backing store.
-     *         Otherwise,
-     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
-     *         UNSUPPORTED when any of the descriptors can never be satisfied.
-     *         UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities.
-     */
-    @callflow(next="allocate")
-    testAllocate(vec<BufferDescriptor> descriptors) generates (Error error);
-
-    /**
-     * Attempts to allocate a list of buffers sharing a backing store.
-     *
-     * Each buffer must correspond to one of the descriptors passed into the
-     * function and must hold a reference to its backing store. If the device
-     * is unable to share the backing store between the buffers, it must
-     * attempt to allocate the buffers with different backing stores and
-     * return NOT_SHARED if it is successful.
-     *
-     * @param descriptors is the buffer descriptors to attempt to allocate.
-     * @return error is NONE or NOT_SHARED upon success;
-     *         NONE when buffers can be created and share a backing store.
-     *         NOT_SHARED when buffers can be created but require more than a
-     *                    backing store.
-     *         Otherwise,
-     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
-     *         UNSUPPORTED when any of the descriptors can never be satisfied.
-     *         NO_RESOURCES when any of the buffers cannot be created at this
-     *                      time.
-     * @return buffers is the allocated buffers.
-     */
-    @callflow(next="exportHandle")
-    allocate(vec<BufferDescriptor> descriptors)
-        generates (Error error,
-                   vec<Buffer> buffers);
-
-    /**
-     * Frees a buffer.
-     *
-     * @param buffer is the buffer to be freed.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_BUFFER when the buffer is invalid.
-     */
-    @exit
-    @callflow(next="*")
-    free(Buffer buffer) generates (Error error);
-
-    /**
-     * Exports a buffer for use in other client libraries or for cross-process
-     * sharing.
-     *
-     * The exported handle is a handle to the backing store of the buffer, not
-     * to the buffer itself. It however may not hold any reference to the
-     * backing store and may be considered invalid by client libraries. To use
-     * it and, in most cases, to save it for later use, a client must make a
-     * clone of the handle and have the cloned handle hold a reference to the
-     * backing store. Such a cloned handle will stay valid even after the
-     * original buffer is freed. Refer to native_handle_clone and IMapper for
-     * how a handle is cloned and how a reference is added.
-     *
-     * @param descriptor is the descriptor used to allocate the buffer.
-     * @param buffer is the buffer to be exported.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_DESCRIPTOR when the descriptor is invalid.
-     *         BAD_BUFFER when the buffer is invalid.
-     *         BAD_VALUE when descriptor and buffer do not match.
-     *         NO_RESOURCES when the buffer cannot be exported at this time.
-     * @return bufferHandle is the exported handle.
-     */
-    @callflow(next="free")
-    exportHandle(BufferDescriptor descriptor,
-                 Buffer buffer)
-      generates (Error error,
-                 handle bufferHandle);
-};
index 0baef89..6adfa71 100644 (file)
@@ -3,7 +3,7 @@ cc_library_shared {
     defaults: ["hidl_defaults"],
     proprietary: true,
     relative_install_path: "hw",
-    srcs: ["Gralloc.cpp"],
+    srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"],
     cppflags: ["-Wall", "-Wextra"],
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
@@ -15,6 +15,7 @@ cc_library_shared {
         "liblog",
         "libutils",
     ],
+    static_libs: ["libgrallocmapperincludes"],
 }
 
 cc_binary {
index 0b9e863..273d3f5 100644 (file)
 
 #define LOG_TAG "GrallocPassthrough"
 
-#include <mutex>
-#include <type_traits>
-#include <unordered_set>
-#include <vector>
-
-#include <string.h>
+#include "Gralloc.h"
+#include "Gralloc0Allocator.h"
+#include "Gralloc1Allocator.h"
 
-#include <hardware/gralloc1.h>
 #include <log/log.h>
 
-#include "Gralloc.h"
-
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -35,417 +29,6 @@ namespace allocator {
 namespace V2_0 {
 namespace implementation {
 
-class GrallocHal : public IAllocator {
-public:
-    GrallocHal(const hw_module_t* module);
-    virtual ~GrallocHal();
-
-    // IAllocator interface
-    Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> createClient(createClient_cb hidl_cb) override;
-
-    Error createDescriptor(
-            const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-            BufferDescriptor* outDescriptor);
-    Error destroyDescriptor(BufferDescriptor descriptor);
-
-    Error testAllocate(const hidl_vec<BufferDescriptor>& descriptors);
-    Error allocate(const hidl_vec<BufferDescriptor>& descriptors,
-            hidl_vec<Buffer>* outBuffers);
-    Error free(Buffer buffer);
-
-    Error exportHandle(Buffer buffer, const native_handle_t** outHandle);
-
-private:
-    void initCapabilities();
-
-    template<typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    bool hasCapability(Capability capability) const;
-
-    gralloc1_device_t* mDevice;
-
-    std::unordered_set<Capability> 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_ALLOCATE allocate;
-        GRALLOC1_PFN_RELEASE release;
-    } mDispatch;
-};
-
-class GrallocClient : public IAllocatorClient {
-public:
-    GrallocClient(GrallocHal& hal);
-    virtual ~GrallocClient();
-
-    // IAllocatorClient interface
-    Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
-            createDescriptor_cb hidl_cb) override;
-    Return<Error> destroyDescriptor(BufferDescriptor descriptor) override;
-
-    Return<Error> testAllocate(
-            const hidl_vec<BufferDescriptor>& descriptors) override;
-    Return<void> allocate(const hidl_vec<BufferDescriptor>& descriptors,
-            allocate_cb hidl_cb) override;
-    Return<Error> free(Buffer buffer) override;
-
-    Return<void> exportHandle(BufferDescriptor descriptor,
-            Buffer buffer, exportHandle_cb hidl_cb) override;
-
-private:
-    GrallocHal& mHal;
-
-    std::mutex mMutex;
-    std::unordered_set<BufferDescriptor> mDescriptors;
-    std::unordered_set<Buffer> mBuffers;
-};
-
-GrallocHal::GrallocHal(const hw_module_t* module)
-    : mDevice(nullptr), mDispatch()
-{
-    int status = gralloc1_open(module, &mDevice);
-    if (status) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                strerror(-status));
-    }
-
-    initCapabilities();
-    initDispatch();
-}
-
-GrallocHal::~GrallocHal()
-{
-    gralloc1_close(mDevice);
-}
-
-void GrallocHal::initCapabilities()
-{
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<Capability> caps(count);
-    mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
-              std::underlying_type<Capability>::type*>(caps.data()));
-    caps.resize(count);
-
-    mCapabilities.insert(caps.cbegin(), caps.cend());
-}
-
-template<typename T>
-void GrallocHal::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 GrallocHal::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 (hasCapability(Capability::LAYERED_BUFFERS)) {
-        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_ALLOCATE, &mDispatch.allocate);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-}
-
-bool GrallocHal::hasCapability(Capability capability) const
-{
-    return (mCapabilities.count(capability) > 0);
-}
-
-Return<void> GrallocHal::getCapabilities(getCapabilities_cb hidl_cb)
-{
-    std::vector<Capability> caps(
-            mCapabilities.cbegin(), mCapabilities.cend());
-
-    hidl_vec<Capability> reply;
-    reply.setToExternal(caps.data(), caps.size());
-    hidl_cb(reply);
-
-    return Void();
-}
-
-Return<void> GrallocHal::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> GrallocHal::createClient(createClient_cb hidl_cb)
-{
-    sp<IAllocatorClient> client = new GrallocClient(*this);
-    hidl_cb(Error::NONE, client);
-
-    return Void();
-}
-
-Error GrallocHal::createDescriptor(
-        const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-        BufferDescriptor* outDescriptor)
-{
-    gralloc1_buffer_descriptor_t descriptor;
-    int32_t err = mDispatch.createDescriptor(mDevice, &descriptor);
-    if (err != GRALLOC1_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    err = mDispatch.setDimensions(mDevice, descriptor,
-            descriptorInfo.width, descriptorInfo.height);
-    if (err == GRALLOC1_ERROR_NONE) {
-        err = mDispatch.setFormat(mDevice, descriptor,
-                static_cast<int32_t>(descriptorInfo.format));
-    }
-    if (err == GRALLOC1_ERROR_NONE) {
-        if (hasCapability(Capability::LAYERED_BUFFERS)) {
-            err = mDispatch.setLayerCount(mDevice, descriptor,
-                    descriptorInfo.layerCount);
-        } else if (descriptorInfo.layerCount != 1) {
-            err = GRALLOC1_ERROR_BAD_VALUE;
-        }
-    }
-    if (err == GRALLOC1_ERROR_NONE) {
-        uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
-        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
-            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
-        }
-        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
-            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-        }
-        err = mDispatch.setProducerUsage(mDevice, descriptor,
-                descriptorInfo.producerUsageMask);
-    }
-    if (err == GRALLOC1_ERROR_NONE) {
-        uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask;
-        if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
-            consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
-        }
-        err = mDispatch.setConsumerUsage(mDevice, descriptor,
-                consumerUsageMask);
-    }
-
-    if (err == GRALLOC1_ERROR_NONE) {
-        *outDescriptor = descriptor;
-    } else {
-        mDispatch.destroyDescriptor(mDevice, descriptor);
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::destroyDescriptor(BufferDescriptor descriptor)
-{
-    int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor);
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::testAllocate(const hidl_vec<BufferDescriptor>& descriptors)
-{
-    if (!hasCapability(Capability::TEST_ALLOCATE)) {
-        return Error::UNDEFINED;
-    }
-
-    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
-            descriptors.data(), nullptr);
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::allocate(const hidl_vec<BufferDescriptor>& descriptors,
-        hidl_vec<Buffer>* outBuffers)
-{
-    std::vector<buffer_handle_t> buffers(descriptors.size());
-    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
-            descriptors.data(), buffers.data());
-    if (err == GRALLOC1_ERROR_NONE || err == GRALLOC1_ERROR_NOT_SHARED) {
-        outBuffers->resize(buffers.size());
-        for (size_t i = 0; i < outBuffers->size(); i++) {
-            (*outBuffers)[i] = static_cast<Buffer>(
-                    reinterpret_cast<uintptr_t>(buffers[i]));
-        }
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::free(Buffer buffer)
-{
-    buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(
-            static_cast<uintptr_t>(buffer));
-
-    int32_t err = mDispatch.release(mDevice, handle);
-    return static_cast<Error>(err);
-}
-
-Error GrallocHal::exportHandle(Buffer buffer,
-        const native_handle_t** outHandle)
-{
-    // we rely on the caller to validate buffer here
-    *outHandle = reinterpret_cast<buffer_handle_t>(
-            static_cast<uintptr_t>(buffer));
-    return Error::NONE;
-}
-
-GrallocClient::GrallocClient(GrallocHal& hal)
-    : mHal(hal)
-{
-}
-
-GrallocClient::~GrallocClient()
-{
-    if (!mBuffers.empty()) {
-        ALOGW("client destroyed with valid buffers");
-        for (auto buf : mBuffers) {
-            mHal.free(buf);
-        }
-    }
-
-    if (!mDescriptors.empty()) {
-        ALOGW("client destroyed with valid buffer descriptors");
-        for (auto desc : mDescriptors) {
-            mHal.destroyDescriptor(desc);
-        }
-    }
-}
-
-Return<void> GrallocClient::createDescriptor(
-        const BufferDescriptorInfo& descriptorInfo,
-        createDescriptor_cb hidl_cb)
-{
-    BufferDescriptor descriptor = 0;
-    Error err = mHal.createDescriptor(descriptorInfo, &descriptor);
-
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        auto result = mDescriptors.insert(descriptor);
-        if (!result.second) {
-            ALOGW("duplicated buffer descriptor id returned");
-            mHal.destroyDescriptor(descriptor);
-            err = Error::NO_RESOURCES;
-        }
-    }
-
-    hidl_cb(err, descriptor);
-    return Void();
-}
-
-Return<Error> GrallocClient::destroyDescriptor(BufferDescriptor descriptor)
-{
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (!mDescriptors.erase(descriptor)) {
-            return Error::BAD_DESCRIPTOR;
-        }
-    }
-
-    return mHal.destroyDescriptor(descriptor);
-}
-
-Return<Error> GrallocClient::testAllocate(
-        const hidl_vec<BufferDescriptor>& descriptors)
-{
-    return mHal.testAllocate(descriptors);
-}
-
-Return<void> GrallocClient::allocate(
-        const hidl_vec<BufferDescriptor>& descriptors,
-        allocate_cb hidl_cb) {
-    hidl_vec<Buffer> buffers;
-    Error err = mHal.allocate(descriptors, &buffers);
-
-    if (err == Error::NONE || err == Error::NOT_SHARED) {
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        for (size_t i = 0; i < buffers.size(); i++) {
-            auto result = mBuffers.insert(buffers[i]);
-            if (!result.second) {
-                ALOGW("duplicated buffer id returned");
-
-                for (size_t j = 0; j < buffers.size(); j++) {
-                    if (j < i) {
-                        mBuffers.erase(buffers[i]);
-                    }
-                    mHal.free(buffers[i]);
-                }
-
-                buffers = hidl_vec<Buffer>();
-                err = Error::NO_RESOURCES;
-                break;
-            }
-        }
-    }
-
-    hidl_cb(err, buffers);
-    return Void();
-}
-
-Return<Error> GrallocClient::free(Buffer buffer)
-{
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (!mBuffers.erase(buffer)) {
-            return Error::BAD_BUFFER;
-        }
-    }
-
-    return mHal.free(buffer);
-}
-
-Return<void> GrallocClient::exportHandle(BufferDescriptor /*descriptor*/,
-        Buffer buffer, exportHandle_cb hidl_cb)
-{
-    const native_handle_t* handle = nullptr;
-
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (mBuffers.count(buffer) == 0) {
-            hidl_cb(Error::BAD_BUFFER, handle);
-            return Void();
-        }
-    }
-
-    Error err = mHal.exportHandle(buffer, &handle);
-
-    hidl_cb(err, handle);
-    return Void();
-}
-
 IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
     const hw_module_t* module = nullptr;
     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
@@ -455,12 +38,15 @@ IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
     }
 
     uint8_t major = (module->module_api_version >> 8) & 0xff;
-    if (major != 1) {
-        ALOGE("unknown gralloc module major version %d", major);
-        return nullptr;
+    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;
     }
-
-    return new GrallocHal(module);
 }
 
 } // namespace implementation
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
new file mode 100644 (file)
index 0000000..3b62bb3
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..0e90527
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..c0a5e1e
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * 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);
+
+    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;
+    }
+
+    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);
+
+    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;
+    }
+
+    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
new file mode 100644 (file)
index 0000000..7b5a966
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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/types.hal b/graphics/allocator/2.0/types.hal
deleted file mode 100644 (file)
index d9b184b..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.hardware.graphics.allocator@2.0;
-
-enum Error : int32_t {
-    NONE            = 0, /** no error */
-    BAD_DESCRIPTOR  = 1, /** invalid BufferDescriptor */
-    BAD_BUFFER      = 2, /** invalid Buffer */
-    BAD_VALUE       = 3, /** invalid width, height, etc. */
-    NOT_SHARED      = 4, /** buffers not sharing backing store */
-    NO_RESOURCES    = 5, /** temporary failure due to resource contention */
-    UNDEFINED       = 6, /** an operation has no defined meaning */
-    UNSUPPORTED     = 7, /** permanent failure */
-};
-
-enum ProducerUsage : uint64_t {
-    /** bit 0 is reserved */
-
-    /** buffer is read by CPU occasionally */
-    CPU_READ        = 1ULL << 1,
-    /** buffer is read by CPU frequently */
-    CPU_READ_OFTEN  = 1ULL << 2,
-
-    /** bit 3 is reserved */
-    /** bit 4 is reserved */
-
-    /** buffer is written by CPU occasionally */
-    CPU_WRITE       = 1ULL << 5,
-    /** buffer is written by CPU frequently */
-    CPU_WRITE_OFTEN = 1ULL << 6,
-
-    /** bit 7 is reserved */
-    /** bit 8 is reserved */
-
-    /** buffer is used as a GPU render target */
-    GPU_RENDER_TARGET = 1ULL << 9,
-
-    /** bit 10 is reserved */
-    /** bit 11 is reserved */
-    /** bit 12 is reserved */
-    /** bit 13 is reserved */
-
-    /**
-     * Buffer is allocated with hardware-level protection against copying the
-     * contents (or information derived from the contents) into unprotected
-     * memory.
-     */
-    PROTECTED         = 1ULL << 14,
-
-    /** bit 15 is reserved */
-    /** bit 16 is reserved */
-
-    /** buffer is used as a camera HAL output */
-    CAMERA            = 1ULL << 17,
-
-    /** bit 18 is reserved */
-    /** bit 19 is reserved */
-    /** bit 20 is reserved */
-    /** bit 21 is reserved */
-
-    /** buffer is used as a video decoder output */
-    VIDEO_DECODER     = 1ULL << 22,
-
-    /** buffer is used as a sensor direct report output */
-    SENSOR_DIRECT_DATA = 1ULL << 23,
-
-    /** bits 24-27 are reserved for future versions */
-    /** bits 28-31 are reserved for vendor extensions */
-
-    /** bits 32-47 are reserved for future versions */
-    /** bits 48-63 are reserved for vendor extensions */
-};
-
-enum ConsumerUsage : uint64_t {
-    /** bit 0 is reserved */
-
-    /** buffer is read by CPU occasionally */
-    CPU_READ          = 1ULL << 1,
-    /** buffer is read by CPU frequently */
-    CPU_READ_OFTEN    = 1ULL << 2,
-
-    /** bit 3 is reserved */
-    /** bit 4 is reserved */
-    /** bit 5 is reserved */
-    /** bit 6 is reserved */
-    /** bit 7 is reserved */
-
-    /** buffer is used as a GPU texture */
-    GPU_TEXTURE       = 1ULL << 8,
-
-    /** bit 9 is reserved */
-    /** bit 10 is reserved */
-
-    /** buffer is used by hwcomposer HAL */
-    HWCOMPOSER        = 1ULL << 11,
-    /** buffer is a hwcomposer HAL client target */
-    CLIENT_TARGET     = 1ULL << 12,
-
-    /** bit 13 is reserved */
-    /** bit 14 is reserved */
-
-    /** buffer is used as a hwcomposer HAL cursor */
-    CURSOR            = 1ULL << 15,
-
-    /** buffer is used as a video encoder input */
-    VIDEO_ENCODER     = 1ULL << 16,
-
-    /** bit 17 is reserved */
-
-    /** buffer is used as a camera HAL input */
-    CAMERA            = 1ULL << 18,
-
-    /** bit 19 is reserved */
-
-    /** buffer is used as a renderscript allocation */
-    RENDERSCRIPT      = 1ULL << 20,
-
-    /** bit 21 is reserved */
-    /** bit 22 is reserved */
-
-    /**
-     * buffer is used as as an OpenGL shader storage or uniform
-       buffer object */
-    GPU_DATA_BUFFER    = 1ULL << 23,
-
-    /** bits 24-27 are reserved for future versions */
-    /** bits 28-31 are reserved for vendor extensions */
-
-    /** bits 32-47 are reserved for future versions */
-    /** bits 48-63 are reserved for vendor extensions */
-};
-
-typedef uint64_t BufferDescriptor;
-typedef uint64_t Buffer;
diff --git a/graphics/allocator/2.0/vts/functional/Android.bp b/graphics/allocator/2.0/vts/functional/Android.bp
deleted file mode 100644 (file)
index fb77ab3..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (C) 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.
-//
-
-cc_library_static {
-    name: "libVtsHalGraphicsAllocatorTestUtils",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalGraphicsAllocatorTestUtils.cpp"],
-    shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
-    ],
-    static_libs: [
-        "VtsHalHidlTargetTestBase",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ],
-    export_include_dirs: ["."],
-}
-
-cc_test {
-    name: "VtsHalGraphicsAllocatorV2_0TargetTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalGraphicsAllocatorV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.graphics.allocator@2.0",
-    ],
-    static_libs: [
-        "libVtsHalGraphicsAllocatorTestUtils",
-        "VtsHalHidlTargetTestBase",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ]
-}
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp
deleted file mode 100644 (file)
index 0dc43be..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 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 <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-
-Allocator::Allocator() { init(); }
-
-void Allocator::init() {
-  mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>();
-  ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
-
-  std::vector<IAllocator::Capability> capabilities = getCapabilities();
-  mCapabilities.insert(capabilities.begin(), capabilities.end());
-}
-
-sp<IAllocator> Allocator::getRaw() const { return mAllocator; }
-
-bool Allocator::hasCapability(IAllocator::Capability capability) const {
-  return mCapabilities.count(capability) > 0;
-}
-
-std::vector<IAllocator::Capability> Allocator::getCapabilities() {
-  std::vector<IAllocator::Capability> capabilities;
-  mAllocator->getCapabilities(
-      [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
-
-  return capabilities;
-}
-
-std::string Allocator::dumpDebugInfo() {
-  std::string debugInfo;
-  mAllocator->dumpDebugInfo(
-      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
-  return debugInfo;
-}
-
-std::unique_ptr<AllocatorClient> Allocator::createClient() {
-  std::unique_ptr<AllocatorClient> client;
-  mAllocator->createClient([&](const auto& tmpError, const auto& tmpClient) {
-    ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
-    client = std::make_unique<AllocatorClient>(tmpClient);
-  });
-
-  return client;
-}
-
-AllocatorClient::AllocatorClient(const sp<IAllocatorClient>& client)
-    : mClient(client) {}
-
-AllocatorClient::~AllocatorClient() {
-  for (auto buffer : mBuffers) {
-    EXPECT_EQ(Error::NONE, mClient->free(buffer))
-        << "failed to free buffer " << buffer;
-  }
-  mBuffers.clear();
-
-  for (auto descriptor : mDescriptors) {
-    EXPECT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor))
-        << "failed to destroy descriptor " << descriptor;
-  }
-  mDescriptors.clear();
-}
-
-sp<IAllocatorClient> AllocatorClient::getRaw() const { return mClient; }
-
-BufferDescriptor AllocatorClient::createDescriptor(
-    const IAllocatorClient::BufferDescriptorInfo& info) {
-  BufferDescriptor descriptor = 0;
-  mClient->createDescriptor(
-      info, [&](const auto& tmpError, const auto& tmpDescriptor) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
-        descriptor = tmpDescriptor;
-
-        EXPECT_TRUE(mDescriptors.insert(descriptor).second)
-            << "duplicated descriptor id " << descriptor;
-      });
-
-  return descriptor;
-}
-
-void AllocatorClient::destroyDescriptor(BufferDescriptor descriptor) {
-  ASSERT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor))
-      << "failed to destroy descriptor " << descriptor;
-
-  mDescriptors.erase(descriptor);
-}
-
-Error AllocatorClient::testAllocate(
-    const std::vector<BufferDescriptor>& descriptors) {
-  return mClient->testAllocate(descriptors);
-}
-
-bool AllocatorClient::testAllocate(BufferDescriptor descriptor) {
-  std::vector<BufferDescriptor> descriptors(1, descriptor);
-  Error error = testAllocate(descriptors);
-  return (error == Error::NONE || error == Error::NOT_SHARED);
-}
-
-Error AllocatorClient::allocate(
-    const std::vector<BufferDescriptor>& descriptors,
-    std::vector<Buffer>& buffers) {
-  Error error = Error::NO_RESOURCES;
-  mClient->allocate(descriptors, [&](const auto& tmpError,
-                                     const auto& tmpBuffers) {
-    ASSERT_TRUE(tmpError == Error::NONE || tmpError == Error::NOT_SHARED)
-        << "failed to allocate buffer";
-    ASSERT_EQ(descriptors.size(), tmpBuffers.size()) << "invalid buffer count";
-
-    error = tmpError;
-    buffers = tmpBuffers;
-
-    for (auto buffer : buffers) {
-      EXPECT_TRUE(mBuffers.insert(buffer).second)
-          << "duplicated buffer id " << buffer;
-    }
-  });
-
-  return error;
-}
-
-Buffer AllocatorClient::allocate(BufferDescriptor descriptor) {
-  std::vector<BufferDescriptor> descriptors(1, descriptor);
-  std::vector<Buffer> buffers;
-  allocate(descriptors, buffers);
-  if (::testing::Test::HasFatalFailure()) {
-    return 0;
-  }
-
-  return buffers[0];
-}
-
-void AllocatorClient::free(Buffer buffer) {
-  ASSERT_EQ(Error::NONE, mClient->free(buffer))
-      << "failed to free buffer " << buffer;
-
-  mBuffers.erase(buffer);
-}
-
-native_handle_t* AllocatorClient::exportHandle(BufferDescriptor descriptor,
-                                               Buffer buffer) {
-  native_handle_t* handle;
-  mClient->exportHandle(
-      descriptor, buffer, [&](const auto& tmpError, const auto& tmpHandle) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to export buffer handle";
-        ASSERT_NE(nullptr, tmpHandle.getNativeHandle())
-            << "invalid buffer handle";
-
-        handle = native_handle_clone(tmpHandle.getNativeHandle());
-        ASSERT_NE(nullptr, handle) << "failed to clone handle";
-      });
-
-  return handle;
-}
-
-}  // namespace tests
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h
deleted file mode 100644 (file)
index c9bfe8f..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
-#define VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
-
-#include <memory>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-
-class AllocatorClient;
-
-// A wrapper to IAllocator.
-class Allocator {
- public:
-  Allocator();
-
-  sp<IAllocator> getRaw() const;
-
-  // Returns true when the allocator supports the specified capability.
-  bool hasCapability(IAllocator::Capability capability) const;
-
-  std::vector<IAllocator::Capability> getCapabilities();
-  std::string dumpDebugInfo();
-  std::unique_ptr<AllocatorClient> createClient();
-
- private:
-  void init();
-
-  sp<IAllocator> mAllocator;
-  std::unordered_set<IAllocator::Capability> mCapabilities;
-};
-
-// A wrapper to IAllocatorClient.
-class AllocatorClient {
- public:
-  AllocatorClient(const sp<IAllocatorClient>& client);
-  ~AllocatorClient();
-
-  sp<IAllocatorClient> getRaw() const;
-
-  BufferDescriptor createDescriptor(
-      const IAllocatorClient::BufferDescriptorInfo& info);
-  void destroyDescriptor(BufferDescriptor descriptor);
-
-  Error testAllocate(const std::vector<BufferDescriptor>& descriptors);
-  bool testAllocate(BufferDescriptor descriptor);
-
-  Error allocate(const std::vector<BufferDescriptor>& descriptors,
-                 std::vector<Buffer>& buffers);
-  Buffer allocate(BufferDescriptor descriptor);
-  void free(Buffer buffer);
-
-  // Returns a handle to the buffer.  The ownership of the handle is
-  // transferred to the caller.
-  native_handle_t* exportHandle(BufferDescriptor descriptor, Buffer buffer);
-
- private:
-  sp<IAllocatorClient> mClient;
-
-  // Keep track of all descriptors and buffers.  When a test fails with
-  // ASSERT_*, the destructor will clean up the resources for the test.
-  std::unordered_set<BufferDescriptor> mDescriptors;
-  std::unordered_set<Buffer> mBuffers;
-};
-
-}  // namespace tests
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp
deleted file mode 100644 (file)
index b1c764f..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 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 "graphics_allocator_hidl_hal_test"
-
-#include <android-base/logging.h>
-#include <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-namespace {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-#define CHECK_FEATURE_OR_SKIP(FEATURE_NAME)                 \
-  do {                                                      \
-    if (!mAllocator->hasCapability(FEATURE_NAME)) {         \
-      std::cout << "[  SKIPPED ] Feature " << #FEATURE_NAME \
-                << " not supported" << std::endl;           \
-      return;                                               \
-    }                                                       \
-  } while (0)
-
-class GraphicsAllocatorHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
-  void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
-    ASSERT_NO_FATAL_FAILURE(mClient = mAllocator->createClient());
-
-    mDummyDescriptorInfo.width = 64;
-    mDummyDescriptorInfo.height = 64;
-    mDummyDescriptorInfo.layerCount = 1;
-    mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
-    mDummyDescriptorInfo.producerUsageMask =
-        static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
-    mDummyDescriptorInfo.consumerUsageMask =
-        static_cast<uint64_t>(ConsumerUsage::CPU_READ);
-  }
-
-  void TearDown() override {}
-
-  std::unique_ptr<Allocator> mAllocator;
-  std::unique_ptr<AllocatorClient> mClient;
-  IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
-};
-
-TEST_F(GraphicsAllocatorHidlTest, GetCapabilities) {
-  auto capabilities = mAllocator->getCapabilities();
-  for (auto cap : capabilities) {
-    EXPECT_NE(IAllocator::Capability::INVALID, cap);
-  }
-}
-
-TEST_F(GraphicsAllocatorHidlTest, DumpDebugInfo) {
-  mAllocator->dumpDebugInfo();
-}
-
-TEST_F(GraphicsAllocatorHidlTest, CreateDestroyDescriptor) {
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-  mClient->destroyDescriptor(descriptor);
-}
-
-/**
- * Test testAllocate with a single buffer descriptor.
- */
-TEST_F(GraphicsAllocatorHidlTest, TestAllocateBasic) {
-  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
-
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  ASSERT_TRUE(mClient->testAllocate(descriptor));
-}
-
-/**
- * Test testAllocate with two buffer descriptors.
- */
-TEST_F(GraphicsAllocatorHidlTest, TestAllocateArray) {
-  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
-
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  hidl_vec<BufferDescriptor> descriptors;
-  descriptors.resize(2);
-  descriptors[0] = descriptor;
-  descriptors[1] = descriptor;
-
-  auto error = mClient->testAllocate(descriptors);
-  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
-}
-
-/**
- * Test allocate/free with a single buffer descriptor.
- */
-TEST_F(GraphicsAllocatorHidlTest, AllocateFreeBasic) {
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  Buffer buffer;
-  ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor));
-
-  mClient->free(buffer);
-}
-
-/**
- * Test allocate/free with an array of buffer descriptors.
- */
-TEST_F(GraphicsAllocatorHidlTest, AllocateFreeArray) {
-  BufferDescriptor descriptor1;
-  ASSERT_NO_FATAL_FAILURE(descriptor1 =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  BufferDescriptor descriptor2;
-  ASSERT_NO_FATAL_FAILURE(descriptor2 =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  hidl_vec<BufferDescriptor> descriptors;
-  descriptors.resize(3);
-  descriptors[0] = descriptor1;
-  descriptors[1] = descriptor1;
-  descriptors[2] = descriptor2;
-
-  std::vector<Buffer> buffers;
-  ASSERT_NO_FATAL_FAILURE(mClient->allocate(descriptors, buffers));
-
-  for (auto buf : buffers) {
-    mClient->free(buf);
-  }
-}
-
-TEST_F(GraphicsAllocatorHidlTest, ExportHandle) {
-  BufferDescriptor descriptor;
-  ASSERT_NO_FATAL_FAILURE(descriptor =
-                              mClient->createDescriptor(mDummyDescriptorInfo));
-
-  Buffer buffer;
-  ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor));
-
-  native_handle_t* handle;
-  ASSERT_NO_FATAL_FAILURE(handle = mClient->exportHandle(descriptor, buffer));
-
-  native_handle_close(handle);
-  native_handle_delete(handle);
-}
-
-}  // namespace anonymous
-}  // namespace tests
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-
-  return status;
-}
index c08053d..ae80c6a 100644 (file)
@@ -13,6 +13,25 @@ intermediates := $(call local-generated-sources-dir, COMMON)
 HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
 
 #
+# Build types.hal (BufferUsage)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.BufferUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (ColorMode)
 #
 GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
@@ -139,6 +158,25 @@ intermediates := $(call local-generated-sources-dir, COMMON)
 HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
 
 #
+# Build types.hal (BufferUsage)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.BufferUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+       $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (ColorMode)
 #
 GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
index 979e4c4..6d94d76 100644 (file)
@@ -442,6 +442,90 @@ enum PixelFormat : int32_t {
 };
 
 /**
+ * Buffer usage definitions.
+ */
+enum BufferUsage : uint64_t {
+    /** bit 0-3 is an enum */
+    CPU_READ_MASK   = 0xfULL,
+    /** buffer is never read by CPU */
+    CPU_READ_NEVER  = 0,
+    /** buffer is rarely read by CPU */
+    CPU_READ_RARELY = 2,
+    /** buffer is often read by CPU */
+    CPU_READ_OFTEN  = 3,
+
+    /** bit 4-7 is an enum */
+    CPU_WRITE_MASK   = 0xfULL << 4,
+    /** buffer is never written by CPU */
+    CPU_WRITE_NEVER  = 0 << 4,
+    /** buffer is rarely written by CPU */
+    CPU_WRITE_RARELY = 2 << 4,
+    /** buffer is often written by CPU */
+    CPU_WRITE_OFTEN  = 3 << 4,
+
+    /** buffer is used as a GPU texture */
+    GPU_TEXTURE       = 1ULL << 8,
+
+    /** buffer is used as a GPU render target */
+    GPU_RENDER_TARGET = 1ULL << 9,
+
+    /** bit 10 must be zero */
+
+    /** buffer is used as a composer HAL overlay layer */
+    COMPOSER_OVERLAY  = 1ULL << 11,
+    /** buffer is used as a composer HAL client target */
+    COMPOSER_CLIENT_TARGET = 1ULL << 12,
+
+    /** bit 13 must be zero */
+
+    /**
+     * Buffer is allocated with hardware-level protection against copying the
+     * contents (or information derived from the contents) into unprotected
+     * memory.
+     */
+    PROTECTED         = 1ULL << 14,
+
+    /** buffer is used as a hwcomposer HAL cursor layer */
+    COMPOSER_CURSOR   = 1ULL << 15,
+
+    /** buffer is used as a video encoder input */
+    VIDEO_ENCODER     = 1ULL << 16,
+
+    /** buffer is used as a camera HAL output */
+    CAMERA_OUTPUT     = 1ULL << 17,
+
+    /** buffer is used as a camera HAL input */
+    CAMERA_INPUT      = 1ULL << 18,
+
+    /** bit 19 must be zero */
+
+    /** buffer is used as a renderscript allocation */
+    RENDERSCRIPT      = 1ULL << 20,
+
+    /** bit 21 must be zero */
+
+    /** buffer is used as a video decoder output */
+    VIDEO_DECODER     = 1ULL << 22,
+
+    /** buffer is used as a sensor direct report output */
+    SENSOR_DIRECT_DATA = 1ULL << 23,
+
+    /**
+     * buffer is used as as an OpenGL shader storage or uniform
+     * buffer object
+     */
+    GPU_DATA_BUFFER   = 1ULL << 24,
+
+    /** bits 25-27 must be zero and are reserved for future versions */
+    /** bits 28-31 are reserved for vendor extensions */
+    VENDOR_MASK       = 0xfULL << 28,
+
+    /** bits 32-47 must be zero and are reserved for future versions */
+    /** bits 48-63 are reserved for vendor extensions */
+    VENDOR_MASK_HI    = 0xffffULL << 48,
+};
+
+/**
  * Transformation definitions
  *
  * IMPORTANT NOTE:
index 8e1f925..66323d4 100644 (file)
@@ -52,7 +52,6 @@ cc_test {
     ],
     static_libs: [
         "libhwcomposer-command-buffer",
-        "libVtsHalGraphicsAllocatorTestUtils",
         "libVtsHalGraphicsComposerTestUtils",
         "libVtsHalGraphicsMapperTestUtils",
         "VtsHalHidlTargetTestBase",
index 0da3a33..387222f 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <IComposerCommandBuffer.h>
 #include <android-base/logging.h>
-#include "VtsHalGraphicsAllocatorTestUtils.h"
 #include "VtsHalGraphicsComposerTestUtils.h"
 #include "VtsHalGraphicsMapperTestUtils.h"
 
@@ -40,22 +39,15 @@ namespace V2_1 {
 namespace tests {
 namespace {
 
-using android::hardware::graphics::allocator::V2_0::Buffer;
-using android::hardware::graphics::allocator::V2_0::BufferDescriptor;
-using android::hardware::graphics::allocator::V2_0::ConsumerUsage;
-using android::hardware::graphics::allocator::V2_0::IAllocator;
-using android::hardware::graphics::allocator::V2_0::IAllocatorClient;
-using android::hardware::graphics::allocator::V2_0::ProducerUsage;
-using android::hardware::graphics::allocator::V2_0::tests::Allocator;
-using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient;
+using android::hardware::graphics::common::V1_0::BufferUsage;
 using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::ColorTransform;
 using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::hardware::graphics::common::V1_0::Transform;
 using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::tests::Mapper;
-using GrallocError = android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 // IComposerCallback to be installed with IComposerClient::registerCallback.
 class GraphicsComposerCallback : public IComposerCallback {
@@ -409,9 +401,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
   void SetUp() override {
     ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
-    ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
-    ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient());
-    ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique<Mapper>());
+    ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
     mWriter = std::make_unique<CommandWriterBase>(1024);
     mReader = std::make_unique<CommandReader>();
@@ -422,15 +412,15 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
   }
 
   const native_handle_t* allocate() {
-    IAllocatorClient::BufferDescriptorInfo info{};
-    info.width = 64;
-    info.height = 64;
-    info.layerCount = 1;
-    info.format = PixelFormat::RGBA_8888;
-    info.producerUsageMask = static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
-    info.consumerUsageMask = static_cast<uint64_t>(ConsumerUsage::CPU_READ);
-
-    return mMapper->allocate(mAllocatorClient, info);
+      IMapper::BufferDescriptorInfo info{};
+      info.width = 64;
+      info.height = 64;
+      info.layerCount = 1;
+      info.format = PixelFormat::RGBA_8888;
+      info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
+                                         BufferUsage::CPU_READ_OFTEN);
+
+      return mGralloc->allocate(info);
   }
 
   void execute() {
@@ -507,9 +497,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
   std::unique_ptr<CommandReader> mReader;
 
  private:
-  std::unique_ptr<Allocator> mAllocator;
-  std::unique_ptr<AllocatorClient> mAllocatorClient;
-  std::unique_ptr<Mapper> mMapper;
+  std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
index 98a509b..cc2bd73 100644 (file)
@@ -51,7 +51,6 @@ cc_library_shared {
         "liblog",
         "libutils",
         "libcutils",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
@@ -60,7 +59,6 @@ cc_library_shared {
         "libhidltransport",
         "libhwbinder",
         "libutils",
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
index 573dcd0..246be24 100644 (file)
 
 package android.hardware.graphics.mapper@2.0;
 
-import android.hardware.graphics.common@1.0::PixelFormat;
-import android.hardware.graphics.allocator@2.0;
+import android.hardware.graphics.common@1.0;
 
 interface IMapper {
+    struct BufferDescriptorInfo {
+        /**
+         * The width specifies how many columns of pixels must be in the
+         * allocated buffer, but does not necessarily represent the offset in
+         * columns between the same column in adjacent rows. The rows may be
+         * padded.
+         */
+        uint32_t width;
+
+       /**
+        * The height specifies how many rows of pixels must be in the
+        * allocated buffer.
+        */
+        uint32_t height;
+
+       /**
+        * The number of image layers that must be in the allocated buffer.
+        */
+        uint32_t layerCount;
+
+        /** Buffer pixel format. */
+        PixelFormat format;
+
+        /**
+         * Buffer usage mask; valid flags can be found in the definition of
+         * BufferUsage.
+         */
+        bitfield<BufferUsage> usage;
+    };
+
     struct Rect {
         int32_t left;
         int32_t top;
@@ -28,170 +57,76 @@ interface IMapper {
     };
 
     /**
-     * Adds a reference to the given buffer handle.
+     * Creates a buffer descriptor. The descriptor can be used with IAllocator
+     * to allocate buffers.
      *
-     * A buffer handle received from a remote process or exported by
-     * IAllocator::exportHandle is unknown to the mapper. There is also no
-     * guarantee that the buffer's backing store will stay alive. This
-     * function must be called at least once in both cases to intrdouce the
-     * buffer handle to the mapper and to secure the backing store. It may
-     * also be called more than once to increase the reference count if two
-     * components in the same process want to interact with the buffer
-     * independently.
+     * Since the buffer descriptor fully describes a buffer, any device
+     * dependent or device independent checks must be performed here whenever
+     * possible. Specifically, when layered buffers are not supported, this
+     * function must return UNSUPPORTED if layerCount is great than 1.
      *
-     * @param bufferHandle is the buffer to which a reference must be added.
+     * @param descriptorInfo specifies the attributes of the descriptor.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid
-     *                  NO_RESOURCES when it is not possible to add a
-     *                               reference to this buffer at this time
+     *                  BAD_VALUE when any of the specified attributes is
+     *                            invalid or conflicting.
+     *                  NO_RESOURCES when the creation cannot be fullfilled at
+     *                               this time.
+     *                  UNSUPPORTED when any of the specified attributes is
+     *                              not supported.
+     * @return descriptor is the newly created buffer descriptor.
      */
     @entry
     @callflow(next="*")
-    retain(handle bufferHandle) generates (Error error);
-
-    /**
-     * Removes a reference from the given buffer buffer.
-     *
-     * If no references remain, the buffer handle must be freed with
-     * native_handle_close/native_handle_delete by the mapper. When the last
-     * buffer handle referring to a particular backing store is freed, that
-     * backing store must also be freed.
-     *
-     * @param bufferHandle is the buffer from which a reference must be
-     *        removed.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     */
-    @exit
-    release(handle bufferHandle) generates (Error error);
-
-    /**
-     * Gets the width and height of the buffer in pixels.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get the dimensions.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return width is the width of the buffer in pixels.
-     * @return height is the height of the buffer in pixels.
-     */
-    @callflow(next="*")
-    getDimensions(handle bufferHandle)
-       generates (Error error,
-                  uint32_t width,
-                  uint32_t height);
-
-    /**
-     * Gets the format of the buffer.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get format.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return format is the format of the buffer.
-     */
-    @callflow(next="*")
-    getFormat(handle bufferHandle)
-        generates (Error error,
-                   PixelFormat format);
-
-    /**
-     * Gets the number of layers of the buffer.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get format.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return layerCount is the number of layers of the buffer.
-     */
-    @callflow(next="*")
-    getLayerCount(handle bufferHandle)
-       generates (Error error,
-                  uint32_t layerCount);
-
-    /**
-     * Gets the producer usage flags which were used to allocate this buffer.
-     *
-     * See IAllocator::BufferDescriptorInfo for more information.
-     *
-     * @param bufferHandle is the buffer from which to get the producer usage
-     *        flags.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return usageMask contains the producer usage flags of the buffer.
-     */
-    @callflow(next="*")
-    getProducerUsageMask(handle bufferHandle)
-              generates (Error error,
-                         uint64_t usageMask);
+    createDescriptor(BufferDescriptorInfo descriptorInfo)
+          generates (Error error,
+                     BufferDescriptor descriptor);
 
     /**
-     * Gets the consumer usage flags which were used to allocate this buffer.
+     * Imports a raw buffer handle to create an imported buffer handle for use
+     * with the rest of the mapper or with other in-process libraries.
      *
-     * See IAllocator::BufferDescriptorInfo for more information.
+     * A buffer handle is considered raw when it is cloned or when it is
+     * received from another HAL or another process. A raw buffer handle must
+     * not be used to access the underlying graphics buffer. It must be
+     * imported to create an imported handle first.
      *
-     * @param bufferHandle is the buffer from which to get the consumer usage
-     *        flags.
-     * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return usageMask contains the consumer usage flags of the buffer.
-     */
-    @callflow(next="*")
-    getConsumerUsageMask(handle bufferHandle)
-              generates (Error error,
-                         uint64_t usageMask);
-
-    /**
-     * Gets a value that uniquely identifies the backing store of the given
-     * buffer.
-     *
-     * Buffers which share a backing store should return the same value from
-     * this function. If the buffer is present in more than one process, the
-     * backing store value for that buffer is not required to be the same in
-     * every process.
+     * This function must at least validate the raw handle before creating the
+     * imported handle. It must also support importing the same raw handle
+     * multiple times to create multiple imported handles. The imported handle
+     * must be considered valid everywhere in the process, including in
+     * another instance of the mapper.
      *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer from which to get the backing store
-     *        identifier.
+     * @param rawHandle is the raw buffer handle to import.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return store is the backing store identifier for this buffer.
+     *                  BAD_BUFFER when the raw handle is invalid.
+     *                  NO_RESOURCES when the raw handle cannot be imported at
+     *                               this time.
+     * @return buffer is the imported buffer handle and has the type
+     *         buffer_handle_t.
      */
+    @entry
     @callflow(next="*")
-    getBackingStore(handle bufferHandle)
-         generates (Error error,
-                    BackingStore store);
+    importBuffer(handle rawHandle) generates (Error error, pointer buffer);
 
     /**
-     * Gets the stride of the buffer in pixels.
+     * Frees a buffer handle. Buffer handles returned by importBuffer must be
+     * freed with this function when no longer needed.
      *
-     * The stride is the offset in pixel-sized elements between the same
-     * column in two adjacent rows of pixels. This may not be equal to the
-     * width of the buffer.
+     * This function must free up all resources allocated by importBuffer for
+     * the imported handle. For example, if the imported handle was created
+     * with native_handle_create, this function must call native_handle_close
+     * and native_handle_delete.
      *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer from which to get the stride.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     *                  UNDEFINED when the notion of a stride is not
-     *                            meaningful for the buffer format.
-     * @return store is the stride in pixels.
+     *                  BAD_BUFFER when the buffer is invalid.
      */
+    @exit
     @callflow(next="*")
-    getStride(handle bufferHandle)
-        generates (Error error,
-                   uint32_t stride);
+    freeBuffer(pointer buffer) generates (Error error);
 
     /**
      * Locks the given buffer for the specified CPU usage.
      *
-     * Exactly one of producerUsageMask and consumerUsageMask must be 0. The
-     * usage which is not 0 must be one of the *Usage::CPU* values, as
-     * applicable. Locking a buffer for a non-CPU usage is not supported.
-     *
      * Locking the same buffer simultaneously from multiple threads is
      * permitted, but if any of the threads attempt to lock the buffer for
      * writing, the behavior is undefined, except that it must not cause
@@ -209,39 +144,27 @@ interface IMapper {
      * address will represent the top-left corner of the entire buffer, even
      * if accessRegion does not begin at the top-left corner.
      *
-     * acquireFence is a file descriptor referring to a acquire sync fence
-     * object, which will be signaled when it is safe for the device to access
-     * the contents of the buffer (prior to locking). If it is already safe to
-     * access the buffer contents, -1 may be passed instead.
-     *
-     * @param bufferHandle is the buffer to lock.
-     * @param producerUsageMask contains the producer usage flags to request;
-     *        either this or consumerUsagemask must be 0, and the other must
-     *        be a CPU usage.
-     * @param consumerUsageMask contains the consumer usage flags to request;
-     *        either this or producerUsageMask must be 0, and the other must
-     *        be a CPU usage.
+     * @param buffer is the buffer to lock.
+     * @param cpuUsage specifies one or more CPU usage flags to request.
      * @param accessRegion is the portion of the buffer that the client
      *        intends to access.
-     * @param acquireFence is a sync fence file descriptor as described above.
+     * @param acquireFence, when non-empty, is a handle containing a file
+     *        descriptor referring to a sync fence object, which will be
+     *        signaled when it is safe for the mapper to lock the buffer. If
+     *        it is already safe to lock, acquireFence is empty.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     *                  BAD_VALUE when neither or both of producerUsageMask
-     *                            and consumerUsageMask were 0, or the usage
-     *                            which was not 0 was not a CPU usage.
+     *                  BAD_BUFFER when the buffer is invalid or is
+     *                             incompatible with this function.
+     *                  BAD_VALUE when cpuUsage is 0, contains non-CPU usage
+     *                            flags, or is incompatible with the buffer.
      *                  NO_RESOURCES when the buffer cannot be locked at this
      *                               time, but locking may succeed at a future
      *                               time.
-     *                  UNSUPPORTED when the buffer cannot be locked with the
-     *                              given usage, and any future attempts at
-     *                              locking will also fail.
-     * @return data will be filled with a CPU-accessible pointer to the buffer
-     *         data.
+     * @return data is a CPU-accessible pointer to the buffer data.
      */
     @callflow(next="unlock")
-    lock(handle bufferHandle,
-         uint64_t producerUsageMask,
-         uint64_t consumerUsageMask,
+    lock(pointer buffer,
+         bitfield<BufferUsage> cpuUsage,
          Rect accessRegion,
          handle acquireFence)
         generates (Error error,
@@ -249,7 +172,7 @@ interface IMapper {
 
     /**
      * This is largely the same as lock(), except that instead of returning a
-     * pointer directly to the buffer data, it returns an FlexLayout struct
+     * pointer directly to the buffer data, it returns an YCbCrLayout struct
      * describing how to access the data planes.
      *
      * This function must work on buffers with PixelFormat::YCbCr_*_888 if
@@ -257,67 +180,46 @@ interface IMapper {
      * multimedia codecs when they are configured with a
      * flexible-YUV-compatible color format.
      *
-     * This function may also be called on buffers of other formats, including
-     * non-YUV formats, but if the buffer format is not compatible with a
-     * flexible representation, it may return UNSUPPORTED.
-     *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer to lock.
-     * @param producerUsageMask contains the producer usage flags to request;
-     *        either this or consumerUsagemask must be 0, and the other must
-     *        be a CPU usage.
-     * @param consumerUsageMask contains the consumer usage flags to request;
-     *        either this or producerUsageMask must be 0, and the other must
-     *        be a CPU usage.
+     * @param buffer is the buffer to lock.
+     * @param cpuUsage specifies one or more CPU usage flags to request.
      * @param accessRegion is the portion of the buffer that the client
      *        intends to access.
-     * @param acquireFence is a sync fence file descriptor as described in
-     *        lock().
+     * @param acquireFence, when non-empty, is a handle containing a file
+     *        descriptor referring to a sync fence object, which will be
+     *        signaled when it is safe for the mapper to lock the buffer. If
+     *        it is already safe to lock, acquireFence is empty.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     *                  BAD_VALUE when neither or both of producerUsageMask
-     *                            and consumerUsageMask were 0, or the usage
-     *                            which was not 0 was not a CPU usage.
+     *                  BAD_BUFFER when the buffer is invalid or is
+     *                             incompatible with this function.
+     *                  BAD_VALUE when cpuUsage is 0, contains non-CPU usage
+     *                            flags, or is incompatible with the buffer.
      *                  NO_RESOURCES when the buffer cannot be locked at this
      *                               time, but locking may succeed at a future
      *                               time.
-     *                  UNSUPPORTED when the buffer cannot be locked with the
-     *                              given usage, and any future attempts at
-     *                              locking will also fail.
-     * @return flexLayout will be filled with the description of the planes in
-     *         the buffer.
+     * @return layout is the data layout of the buffer.
      */
     @callflow(next="unlock")
-    lockFlex(handle bufferHandle,
-             uint64_t producerUsageMask,
-             uint64_t consumerUsageMask,
-             Rect accessRegion,
-             handle acquireFence)
+    lockYCbCr(pointer buffer,
+              bitfield<BufferUsage> cpuUsage,
+              Rect accessRegion,
+              handle acquireFence)
         generates (Error error,
-                   FlexLayout layout);
+                   YCbCrLayout layout);
 
     /**
-     * This function indicates to the device that the client will be done with
-     * the buffer when releaseFence signals.
-     *
-     * releaseFence will be filled with a file descriptor referring to a
-     * release sync fence object, which will be signaled when it is safe to
-     * access the contents of the buffer (after the buffer has been unlocked).
-     * If it is already safe to access the buffer contents, then -1 may be
-     * returned instead.
-     *
-     * This function is used to unlock both buffers locked by lock() and those
-     * locked by lockFlex().
+     * Unlocks a buffer to indicate all CPU accesses to the buffer have
+     * completed.
      *
-     * @param device is the mapper device.
-     * @param bufferHandle is the buffer to unlock.
+     * @param buffer is the buffer to unlock.
      * @return error is NONE upon success. Otherwise,
-     *                  BAD_BUFFER when the buffer handle is invalid.
-     * @return releaseFence is a sync fence file descriptor as described
-     *         above.
+     *                  BAD_BUFFER when the buffer is invalid or not locked.
+     * @return releaseFence, when non-empty, is a handle containing a file
+     *         descriptor referring to a sync fence object. The sync fence
+     *         object will be signaled when the mapper has completed any
+     *         pending work.
      */
     @callflow(next="*")
-    unlock(handle bufferHandle)
+    unlock(pointer buffer)
         generates (Error error,
                    handle releaseFence);
 };
index 1dc5aea..090c61f 100644 (file)
@@ -18,10 +18,9 @@ cc_library_shared {
     defaults: ["hidl_defaults"],
     proprietary: true,
     relative_install_path: "hw",
-    srcs: ["GrallocMapper.cpp"],
+    srcs: ["GrallocMapper.cpp", "Gralloc0Mapper.cpp", "Gralloc1Mapper.cpp"],
     cppflags: ["-Wall", "-Wextra"],
     shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "libbase",
         "libcutils",
@@ -29,6 +28,12 @@ cc_library_shared {
         "libhidlbase",
         "libhidltransport",
         "liblog",
+        "libsync",
         "libutils",
     ],
 }
+
+cc_library_static {
+    name: "libgrallocmapperincludes",
+    export_include_dirs: ["."],
+}
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
new file mode 100644 (file)
index 0000000..28f5016
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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 "Gralloc0Mapper"
+
+#include "Gralloc0Mapper.h"
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
+    : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
+      mMinor(module->module_api_version & 0xff) {
+    mCapabilities.highUsageBits = false;
+    mCapabilities.layeredBuffers = false;
+    mCapabilities.unregisterImplyDelete = false;
+}
+
+Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) {
+    int result = mModule->registerBuffer(mModule, bufferHandle);
+    return result ? Error::BAD_BUFFER : Error::NONE;
+}
+
+void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
+    mModule->unregisterBuffer(mModule, bufferHandle);
+}
+
+Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 void** outData) {
+    int result;
+    void* data = nullptr;
+    if (mMinor >= 3 && mModule->lockAsync) {
+        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+        // gralloc's responsibility to close it, even on locking errors.
+        if (fenceFd >= 0) {
+            fenceFd = dup(fenceFd);
+            if (fenceFd < 0) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        result = mModule->lockAsync(mModule, bufferHandle, cpuUsage,
+                                    accessRegion.left, accessRegion.top,
+                                    accessRegion.width, accessRegion.height,
+                                    &data, fenceFd);
+    } else {
+        waitFenceFd(fenceFd, "Gralloc0Mapper::lock");
+
+        result = mModule->lock(mModule, bufferHandle, cpuUsage,
+                               accessRegion.left, accessRegion.top,
+                               accessRegion.width, accessRegion.height, &data);
+    }
+
+    if (result) {
+        return Error::BAD_VALUE;
+    } else {
+        *outData = data;
+        return Error::NONE;
+    }
+}
+
+Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 YCbCrLayout* outLayout) {
+    int result;
+    android_ycbcr ycbcr = {};
+    if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
+        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+        // gralloc's responsibility to close it, even on locking errors.
+        if (fenceFd >= 0) {
+            fenceFd = dup(fenceFd);
+            if (fenceFd < 0) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage,
+                                          accessRegion.left, accessRegion.top,
+                                          accessRegion.width,
+                                          accessRegion.height, &ycbcr, fenceFd);
+    } else {
+        waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr");
+
+        if (mModule->lock_ycbcr) {
+            result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage,
+                                         accessRegion.left, accessRegion.top,
+                                         accessRegion.width,
+                                         accessRegion.height, &ycbcr);
+        } else {
+            result = -EINVAL;
+        }
+    }
+
+    if (result) {
+        return Error::BAD_VALUE;
+    } else {
+        outLayout->y = ycbcr.y;
+        outLayout->cb = ycbcr.cb;
+        outLayout->cr = ycbcr.cr;
+        outLayout->yStride = ycbcr.ystride;
+        outLayout->cStride = ycbcr.cstride;
+        outLayout->chromaStep = ycbcr.chroma_step;
+        return Error::NONE;
+    }
+}
+
+Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle,
+                                   int* outFenceFd) {
+    int result;
+    int fenceFd = -1;
+    if (mMinor >= 3 && mModule->unlockAsync) {
+        result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
+    } else {
+        result = mModule->unlock(mModule, bufferHandle);
+    }
+
+    if (result) {
+        // we always own the fenceFd even when unlock failed
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
+
+        return Error::BAD_VALUE;
+    } else {
+        *outFenceFd = fenceFd;
+        return Error::NONE;
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.h b/graphics/mapper/2.0/default/Gralloc0Mapper.h
new file mode 100644 (file)
index 0000000..e792a69
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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_MAPPER_V2_0_GRALLOC0MAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
+
+#include "GrallocMapper.h"
+
+#include <hardware/gralloc.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+class Gralloc0Mapper : public GrallocMapper {
+   public:
+    Gralloc0Mapper(const hw_module_t* module);
+
+   private:
+    Error registerBuffer(buffer_handle_t bufferHandle) override;
+    void unregisterBuffer(buffer_handle_t bufferHandle) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     void** outData) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     YCbCrLayout* outLayout) override;
+    Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
+
+    const gralloc_module_t* mModule;
+    uint8_t mMinor;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
new file mode 100644 (file)
index 0000000..c1e5adc
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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 "Gralloc1Mapper"
+
+#include "Gralloc1Mapper.h"
+
+#include <vector>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+
+Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module)
+    : mDevice(nullptr), mDispatch() {
+    int result = gralloc1_open(module, &mDevice);
+    if (result) {
+        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+                         strerror(-result));
+    }
+
+    initCapabilities();
+    initDispatch();
+}
+
+Gralloc1Mapper::~Gralloc1Mapper() {
+    gralloc1_close(mDevice);
+}
+
+void Gralloc1Mapper::initCapabilities() {
+    mCapabilities.highUsageBits = true;
+    mCapabilities.layeredBuffers = false;
+    mCapabilities.unregisterImplyDelete = false;
+
+    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) {
+        switch (capability) {
+            case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
+                mCapabilities.layeredBuffers = true;
+                break;
+            case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
+                mCapabilities.unregisterImplyDelete = true;
+                break;
+        }
+    }
+}
+
+template <typename T>
+void Gralloc1Mapper::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 Gralloc1Mapper::initDispatch() {
+    initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
+    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
+    initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
+                 &mDispatch.getNumFlexPlanes);
+    initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
+    initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
+    initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
+}
+
+Error Gralloc1Mapper::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;
+    }
+}
+
+bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex,
+                                   YCbCrLayout* outLayout) {
+    // must be YCbCr
+    if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
+        return false;
+    }
+
+    for (int i = 0; i < 3; i++) {
+        const auto& plane = flex.planes[i];
+        // must have 8-bit depth
+        if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+            return false;
+        }
+
+        if (plane.component == FLEX_COMPONENT_Y) {
+            // Y must not be interleaved
+            if (plane.h_increment != 1) {
+                return false;
+            }
+        } else {
+            // Cb and Cr can be interleaved
+            if (plane.h_increment != 1 && plane.h_increment != 2) {
+                return false;
+            }
+        }
+
+        if (!plane.v_increment) {
+            return false;
+        }
+    }
+
+    if (flex.planes[0].component != FLEX_COMPONENT_Y ||
+        flex.planes[1].component != FLEX_COMPONENT_Cb ||
+        flex.planes[2].component != FLEX_COMPONENT_Cr) {
+        return false;
+    }
+
+    const auto& y = flex.planes[0];
+    const auto& cb = flex.planes[1];
+    const auto& cr = flex.planes[2];
+
+    if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
+        return false;
+    }
+
+    outLayout->y = y.top_left;
+    outLayout->cb = cb.top_left;
+    outLayout->cr = cr.top_left;
+    outLayout->yStride = y.v_increment;
+    outLayout->cStride = cb.v_increment;
+    outLayout->chromaStep = cb.h_increment;
+
+    return true;
+}
+
+gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) {
+    return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+}
+
+Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) {
+    return toError(mDispatch.retain(mDevice, bufferHandle));
+}
+
+void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
+    mDispatch.release(mDevice, bufferHandle);
+}
+
+Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 void** outData) {
+    // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+    // gralloc's responsibility to close it, even on locking errors.
+    if (fenceFd >= 0) {
+        fenceFd = dup(fenceFd);
+        if (fenceFd < 0) {
+            return Error::NO_RESOURCES;
+        }
+    }
+
+    const uint64_t consumerUsage =
+        cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+    const auto accessRect = asGralloc1Rect(accessRegion);
+    void* data = nullptr;
+    int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage,
+                                   consumerUsage, &accessRect, &data, fenceFd);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outData = data;
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
+                                 uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion, int fenceFd,
+                                 YCbCrLayout* outLayout) {
+    // prepare flex layout
+    android_flex_layout flex = {};
+    int32_t error =
+        mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
+    if (error != GRALLOC1_ERROR_NONE) {
+        return toError(error);
+    }
+    std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
+    flex.planes = flexPlanes.data();
+
+    // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
+    // gralloc's responsibility to close it, even on locking errors.
+    if (fenceFd >= 0) {
+        fenceFd = dup(fenceFd);
+        if (fenceFd < 0) {
+            return Error::NO_RESOURCES;
+        }
+    }
+
+    const uint64_t consumerUsage =
+        cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+    const auto accessRect = asGralloc1Rect(accessRegion);
+    error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage,
+                               &accessRect, &flex, fenceFd);
+    if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
+        ALOGD("unable to convert android_flex_layout to YCbCrLayout");
+
+        // undo the lock
+        fenceFd = -1;
+        mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
+
+        error = GRALLOC1_ERROR_BAD_HANDLE;
+    }
+
+    return toError(error);
+}
+
+Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle,
+                                   int* outFenceFd) {
+    int fenceFd = -1;
+    int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        *outFenceFd = fenceFd;
+    } else if (fenceFd >= 0) {
+        // we always own the fenceFd even when unlock failed
+        close(fenceFd);
+    }
+
+    return toError(error);
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.h b/graphics/mapper/2.0/default/Gralloc1Mapper.h
new file mode 100644 (file)
index 0000000..452afdf
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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_MAPPER_V2_0_GRALLOC1MAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
+
+#include "GrallocMapper.h"
+
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+class Gralloc1Mapper : public GrallocMapper {
+   public:
+    Gralloc1Mapper(const hw_module_t* module);
+    ~Gralloc1Mapper();
+
+   private:
+    void initCapabilities();
+
+    template <typename T>
+    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
+    void initDispatch();
+
+    static Error toError(int32_t error);
+    static bool toYCbCrLayout(const android_flex_layout& flex,
+                              YCbCrLayout* outLayout);
+    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
+
+    Error registerBuffer(buffer_handle_t bufferHandle) override;
+    void unregisterBuffer(buffer_handle_t bufferHandle) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     void** outData) override;
+    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                     const IMapper::Rect& accessRegion, int fenceFd,
+                     YCbCrLayout* outLayout) override;
+    Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
+
+    gralloc1_device_t* mDevice;
+
+    struct {
+        GRALLOC1_PFN_RETAIN retain;
+        GRALLOC1_PFN_RELEASE release;
+        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+        GRALLOC1_PFN_LOCK lock;
+        GRALLOC1_PFN_LOCK_FLEX lockFlex;
+        GRALLOC1_PFN_UNLOCK unlock;
+    } mDispatch;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
diff --git a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
new file mode 100644 (file)
index 0000000..9b5ab04
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+/**
+ * BufferDescriptor is created by IMapper and consumed by IAllocator. It is
+ * versioned so that IMapper and IAllocator can be updated independently.
+ */
+constexpr uint32_t grallocBufferDescriptorSize = 7;
+constexpr uint32_t grallocBufferDescriptorMagicVersion = ((0x9487 << 16) | 0);
+
+inline BufferDescriptor grallocEncodeBufferDescriptor(
+    const IMapper::BufferDescriptorInfo& descriptorInfo) {
+    BufferDescriptor descriptor;
+    descriptor.resize(grallocBufferDescriptorSize);
+    descriptor[0] = grallocBufferDescriptorMagicVersion;
+    descriptor[1] = descriptorInfo.width;
+    descriptor[2] = descriptorInfo.height;
+    descriptor[3] = descriptorInfo.layerCount;
+    descriptor[4] = static_cast<uint32_t>(descriptorInfo.format);
+    descriptor[5] = static_cast<uint32_t>(descriptorInfo.usage);
+    descriptor[6] = static_cast<uint32_t>(descriptorInfo.usage >> 32);
+
+    return descriptor;
+}
+
+inline bool grallocDecodeBufferDescriptor(
+    const BufferDescriptor& descriptor,
+    IMapper::BufferDescriptorInfo* outDescriptorInfo) {
+    if (descriptor.size() != grallocBufferDescriptorSize ||
+        descriptor[0] != grallocBufferDescriptorMagicVersion) {
+        return false;
+    }
+
+    *outDescriptorInfo = IMapper::BufferDescriptorInfo{
+        descriptor[1],
+        descriptor[2],
+        descriptor[3],
+        static_cast<PixelFormat>(descriptor[4]),
+        (static_cast<uint64_t>(descriptor[6]) << 32) | descriptor[5],
+    };
+
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
index 526aca2..339317a 100644 (file)
 
 #include "GrallocMapper.h"
 
-#include <mutex>
-#include <vector>
-#include <unordered_map>
+#include "Gralloc0Mapper.h"
+#include "Gralloc1Mapper.h"
+#include "GrallocBufferDescriptor.h"
 
-#include <string.h>
+#include <inttypes.h>
 
-#include <hardware/gralloc1.h>
 #include <log/log.h>
+#include <sync/sync.h>
 
 namespace android {
 namespace hardware {
@@ -33,374 +33,251 @@ namespace mapper {
 namespace V2_0 {
 namespace implementation {
 
-namespace {
-
-using android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::common::V1_0::BufferUsage;
 using android::hardware::graphics::common::V1_0::PixelFormat;
 
-class GrallocMapperHal : public IMapper {
-public:
-    GrallocMapperHal(const hw_module_t* module);
-    ~GrallocMapperHal();
-
-    // IMapper interface
-    Return<Error> retain(const hidl_handle& bufferHandle) override;
-    Return<Error> release(const hidl_handle& bufferHandle) override;
-    Return<void> getDimensions(const hidl_handle& bufferHandle,
-            getDimensions_cb hidl_cb) override;
-    Return<void> getFormat(const hidl_handle& bufferHandle,
-            getFormat_cb hidl_cb) override;
-    Return<void> getLayerCount(const hidl_handle& bufferHandle,
-            getLayerCount_cb hidl_cb) override;
-    Return<void> getProducerUsageMask(const hidl_handle& bufferHandle,
-            getProducerUsageMask_cb hidl_cb) override;
-    Return<void> getConsumerUsageMask(const hidl_handle& bufferHandle,
-            getConsumerUsageMask_cb hidl_cb) override;
-    Return<void> getBackingStore(const hidl_handle& bufferHandle,
-            getBackingStore_cb hidl_cb) override;
-    Return<void> getStride(const hidl_handle& bufferHandle,
-            getStride_cb hidl_cb) override;
-    Return<void> lock(const hidl_handle& bufferHandle,
-            uint64_t producerUsageMask, uint64_t consumerUsageMask,
-            const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-            lock_cb hidl_cb) override;
-    Return<void> lockFlex(const hidl_handle& bufferHandle,
-            uint64_t producerUsageMask, uint64_t consumerUsageMask,
-            const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-            lockFlex_cb hidl_cb) override;
-    Return<void> unlock(const hidl_handle& bufferHandle,
-            unlock_cb hidl_cb) override;
-
-private:
-    void initCapabilities();
-
-    template<typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
-    static bool dupFence(const hidl_handle& fenceHandle, int* outFd);
-
-    gralloc1_device_t* mDevice;
-
-    struct {
-        bool layeredBuffers;
-    } mCapabilities;
-
-    struct {
-        GRALLOC1_PFN_RETAIN retain;
-        GRALLOC1_PFN_RELEASE release;
-        GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
-        GRALLOC1_PFN_GET_FORMAT getFormat;
-        GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount;
-        GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
-        GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
-        GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
-        GRALLOC1_PFN_GET_STRIDE getStride;
-        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
-        GRALLOC1_PFN_LOCK lock;
-        GRALLOC1_PFN_LOCK_FLEX lockFlex;
-        GRALLOC1_PFN_UNLOCK unlock;
-    } mDispatch;
-
-    std::mutex mMutex;
-    std::unordered_map<buffer_handle_t, size_t> mBufferReferenceCounts;
-};
-
-GrallocMapperHal::GrallocMapperHal(const hw_module_t* module)
-    : mDevice(nullptr), mCapabilities(), mDispatch()
-{
-    int status = gralloc1_open(module, &mDevice);
-    if (status) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                strerror(-status));
+std::mutex GrallocMapper::mMutex;
+std::unordered_set<buffer_handle_t> GrallocMapper::mRegisteredHandles;
+
+bool GrallocMapper::validateDescriptorInfo(
+    const BufferDescriptorInfo& descriptorInfo) const {
+    const uint64_t validUsageBits =
+        BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+        BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
+        BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
+        BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR |
+        BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT |
+        BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+        BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+        BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
+        (mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI
+                                     : static_cast<BufferUsage>(0));
+
+    if (!descriptorInfo.width || !descriptorInfo.height ||
+        !descriptorInfo.layerCount) {
+        return false;
     }
 
-    initCapabilities();
-    initDispatch();
-}
-
-GrallocMapperHal::~GrallocMapperHal()
-{
-    gralloc1_close(mDevice);
-}
-
-void GrallocMapperHal::initCapabilities()
-{
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> caps(count);
-    mDevice->getCapabilities(mDevice, &count, caps.data());
-    caps.resize(count);
+    if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
+        return false;
+    }
 
-    for (auto cap : caps) {
-        switch (cap) {
-        case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
-            mCapabilities.layeredBuffers = true;
-            break;
-        default:
-            break;
-        }
+    if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+        return false;
     }
-}
 
-template<typename T>
-void GrallocMapperHal::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);
+    if (descriptorInfo.usage & ~validUsageBits) {
+        // could not fail as gralloc may use the reserved bits...
+        ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+              descriptorInfo.usage & ~validUsageBits);
     }
 
-    *outPfn = reinterpret_cast<T>(pfn);
+    return true;
 }
 
-void GrallocMapperHal::initDispatch()
-{
-    initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-    initDispatch(GRALLOC1_FUNCTION_GET_DIMENSIONS, &mDispatch.getDimensions);
-    initDispatch(GRALLOC1_FUNCTION_GET_FORMAT, &mDispatch.getFormat);
-    if (mCapabilities.layeredBuffers) {
-        initDispatch(GRALLOC1_FUNCTION_GET_LAYER_COUNT,
-                &mDispatch.getLayerCount);
+Return<void> GrallocMapper::createDescriptor(
+    const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) {
+    if (validateDescriptorInfo(descriptorInfo)) {
+        hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo));
+    } else {
+        hidl_cb(Error::BAD_VALUE, BufferDescriptor());
     }
-    initDispatch(GRALLOC1_FUNCTION_GET_PRODUCER_USAGE,
-            &mDispatch.getProducerUsage);
-    initDispatch(GRALLOC1_FUNCTION_GET_CONSUMER_USAGE,
-            &mDispatch.getConsumerUsage);
-    initDispatch(GRALLOC1_FUNCTION_GET_BACKING_STORE,
-            &mDispatch.getBackingStore);
-    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
-    initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
-            &mDispatch.getNumFlexPlanes);
-    initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
-    initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
-    initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
+
+    return Void();
 }
 
-gralloc1_rect_t GrallocMapperHal::asGralloc1Rect(const IMapper::Rect& rect)
-{
-    return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+bool GrallocMapper::addRegisteredHandle(buffer_handle_t bufferHandle) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mRegisteredHandles.insert(bufferHandle).second;
 }
 
-bool GrallocMapperHal::dupFence(const hidl_handle& fenceHandle, int* outFd)
-{
-    auto handle = fenceHandle.getNativeHandle();
-    if (!handle || handle->numFds == 0) {
-        *outFd = -1;
-        return true;
-    }
+native_handle_t* GrallocMapper::popRegisteredHandle(void* buffer) {
+    auto bufferHandle = static_cast<native_handle_t*>(buffer);
 
-    if (handle->numFds > 1) {
-        ALOGE("invalid fence handle with %d fds", handle->numFds);
-        return false;
-    }
-
-    *outFd = dup(handle->data[0]);
-    return (*outFd >= 0);
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mRegisteredHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
 }
 
-Return<Error> GrallocMapperHal::retain(const hidl_handle& bufferHandle)
-{
-    int32_t err = mDispatch.retain(mDevice, bufferHandle);
-    if (err == GRALLOC1_ERROR_NONE) {
-        auto nativeHandle = bufferHandle.getNativeHandle();
-        std::lock_guard<std::mutex> lock(mMutex);
+buffer_handle_t GrallocMapper::getRegisteredHandle(const void* buffer) {
+    auto bufferHandle = static_cast<buffer_handle_t>(buffer);
 
-        ++mBufferReferenceCounts[nativeHandle];
-    }
-    return static_cast<Error>(err);
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mRegisteredHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
 }
 
-Return<Error> GrallocMapperHal::release(const hidl_handle& bufferHandle)
-{
-    int32_t err = mDispatch.release(mDevice, bufferHandle);
-    if (err == GRALLOC1_ERROR_NONE) {
-        auto nativeHandle = bufferHandle.getNativeHandle();
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        auto iter = mBufferReferenceCounts.find(bufferHandle);
-        if (iter == mBufferReferenceCounts.end()) {
-            // this should never happen
-            err = GRALLOC1_ERROR_BAD_HANDLE;
-        } else if (--iter->second == 0) {
-            native_handle_close(nativeHandle);
-            native_handle_delete(const_cast<native_handle_t*>(nativeHandle));
-
-            mBufferReferenceCounts.erase(iter);
-        }
+Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle,
+                                         importBuffer_cb hidl_cb) {
+    // importing an already imported handle rather than a raw handle
+    if (getRegisteredHandle(rawHandle.getNativeHandle())) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
     }
 
-    return static_cast<Error>(err);
-}
+    if (!rawHandle.getNativeHandle()) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
+    }
 
-Return<void> GrallocMapperHal::getDimensions(const hidl_handle& bufferHandle,
-        getDimensions_cb hidl_cb)
-{
-    uint32_t width = 0;
-    uint32_t height = 0;
-    int32_t err = mDispatch.getDimensions(mDevice, bufferHandle,
-            &width, &height);
+    native_handle_t* bufferHandle =
+        native_handle_clone(rawHandle.getNativeHandle());
+    if (!bufferHandle) {
+        hidl_cb(Error::NO_RESOURCES, nullptr);
+        return Void();
+    }
 
-    hidl_cb(static_cast<Error>(err), width, height);
-    return Void();
-}
+    Error error = registerBuffer(bufferHandle);
+    if (error != Error::NONE) {
+        native_handle_close(bufferHandle);
+        native_handle_delete(bufferHandle);
 
-Return<void> GrallocMapperHal::getFormat(const hidl_handle& bufferHandle,
-        getFormat_cb hidl_cb)
-{
-    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    int32_t err = mDispatch.getFormat(mDevice, bufferHandle, &format);
+        hidl_cb(error, nullptr);
+        return Void();
+    }
 
-    hidl_cb(static_cast<Error>(err), static_cast<PixelFormat>(format));
-    return Void();
-}
+    // The newly cloned handle is already registered?  This can only happen
+    // when a handle previously registered was native_handle_delete'd instead
+    // of freeBuffer'd.
+    if (!addRegisteredHandle(bufferHandle)) {
+        ALOGE("handle %p has already been imported; potential fd leaking",
+              bufferHandle);
+        unregisterBuffer(bufferHandle);
+        if (!mCapabilities.unregisterImplyDelete) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+        }
 
-Return<void> GrallocMapperHal::getLayerCount(const hidl_handle& bufferHandle,
-        getLayerCount_cb hidl_cb)
-{
-    int32_t err = GRALLOC1_ERROR_NONE;
-    uint32_t count = 1;
-    if (mCapabilities.layeredBuffers) {
-        err = mDispatch.getLayerCount(mDevice, bufferHandle, &count);
+        hidl_cb(Error::NO_RESOURCES, nullptr);
+        return Void();
     }
 
-    hidl_cb(static_cast<Error>(err), count);
+    hidl_cb(Error::NONE, bufferHandle);
     return Void();
 }
 
-Return<void> GrallocMapperHal::getProducerUsageMask(
-        const hidl_handle& bufferHandle, getProducerUsageMask_cb hidl_cb)
-{
-    uint64_t mask = 0x0;
-    int32_t err = mDispatch.getProducerUsage(mDevice, bufferHandle, &mask);
+Return<Error> GrallocMapper::freeBuffer(void* buffer) {
+    native_handle_t* bufferHandle = popRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        return Error::BAD_BUFFER;
+    }
 
-    hidl_cb(static_cast<Error>(err), mask);
-    return Void();
+    unregisterBuffer(bufferHandle);
+    if (!mCapabilities.unregisterImplyDelete) {
+        native_handle_close(bufferHandle);
+        native_handle_delete(bufferHandle);
+    }
+
+    return Error::NONE;
 }
 
-Return<void> GrallocMapperHal::getConsumerUsageMask(
-        const hidl_handle& bufferHandle, getConsumerUsageMask_cb hidl_cb)
-{
-    uint64_t mask = 0x0;
-    int32_t err = mDispatch.getConsumerUsage(mDevice, bufferHandle, &mask);
+void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
+    if (fenceFd < 0) {
+        return;
+    }
 
-    hidl_cb(static_cast<Error>(err), mask);
-    return Void();
+    const int warningTimeout = 3500;
+    const int error = sync_wait(fenceFd, warningTimeout);
+    if (error < 0 && errno == ETIME) {
+        ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd,
+              warningTimeout);
+        sync_wait(fenceFd, -1);
+    }
 }
 
-Return<void> GrallocMapperHal::getBackingStore(
-        const hidl_handle& bufferHandle, getBackingStore_cb hidl_cb)
-{
-    uint64_t store = 0;
-    int32_t err = mDispatch.getBackingStore(mDevice, bufferHandle, &store);
+bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle,
+                               int* outFenceFd) {
+    auto handle = fenceHandle.getNativeHandle();
+    if (handle && handle->numFds > 1) {
+        ALOGE("invalid fence handle with %d fds", handle->numFds);
+        return false;
+    }
 
-    hidl_cb(static_cast<Error>(err), store);
-    return Void();
+    *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+    return true;
 }
 
-Return<void> GrallocMapperHal::getStride(const hidl_handle& bufferHandle,
-        getStride_cb hidl_cb)
-{
-    uint32_t stride = 0;
-    int32_t err = mDispatch.getStride(mDevice, bufferHandle, &stride);
+hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) {
+    native_handle_t* handle = nullptr;
+    if (fenceFd >= 0) {
+        handle = native_handle_init(handleStorage, 1, 0);
+        handle->data[0] = fenceFd;
+    }
 
-    hidl_cb(static_cast<Error>(err), stride);
-    return Void();
+    return hidl_handle(handle);
 }
 
-Return<void> GrallocMapperHal::lock(const hidl_handle& bufferHandle,
-        uint64_t producerUsageMask, uint64_t consumerUsageMask,
-        const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-        lock_cb hidl_cb)
-{
-    gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
+Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage,
+                                 const IMapper::Rect& accessRegion,
+                                 const hidl_handle& acquireFence,
+                                 lock_cb hidl_cb) {
+    buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
+    }
 
-    int fence = -1;
-    if (!dupFence(acquireFence, &fence)) {
-        hidl_cb(Error::NO_RESOURCES, nullptr);
+    int fenceFd;
+    if (!getFenceFd(acquireFence, &fenceFd)) {
+        hidl_cb(Error::BAD_VALUE, nullptr);
         return Void();
     }
 
     void* data = nullptr;
-    int32_t err = mDispatch.lock(mDevice, bufferHandle, producerUsageMask,
-            consumerUsageMask, &rect, &data, fence);
-    if (err != GRALLOC1_ERROR_NONE) {
-        close(fence);
-    }
+    Error error =
+        lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
 
-    hidl_cb(static_cast<Error>(err), data);
+    hidl_cb(error, data);
     return Void();
 }
 
-Return<void> GrallocMapperHal::lockFlex(const hidl_handle& bufferHandle,
-        uint64_t producerUsageMask, uint64_t consumerUsageMask,
-        const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
-        lockFlex_cb hidl_cb)
-{
-    FlexLayout layout_reply{};
-
-    uint32_t planeCount = 0;
-    int32_t err = mDispatch.getNumFlexPlanes(mDevice, bufferHandle,
-            &planeCount);
-    if (err != GRALLOC1_ERROR_NONE) {
-        hidl_cb(static_cast<Error>(err), layout_reply);
+Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
+                                      const IMapper::Rect& accessRegion,
+                                      const hidl_handle& acquireFence,
+                                      lockYCbCr_cb hidl_cb) {
+    YCbCrLayout layout = {};
+
+    buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        hidl_cb(Error::BAD_BUFFER, layout);
         return Void();
     }
 
-    gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
-
-    int fence = -1;
-    if (!dupFence(acquireFence, &fence)) {
-        hidl_cb(Error::NO_RESOURCES, layout_reply);
+    int fenceFd;
+    if (!getFenceFd(acquireFence, &fenceFd)) {
+        hidl_cb(Error::BAD_VALUE, layout);
         return Void();
     }
 
-    std::vector<android_flex_plane_t> planes(planeCount);
-    android_flex_layout_t layout{};
-    layout.num_planes = planes.size();
-    layout.planes = planes.data();
-
-    err = mDispatch.lockFlex(mDevice, bufferHandle, producerUsageMask,
-            consumerUsageMask, &rect, &layout, fence);
-    if (err == GRALLOC1_ERROR_NONE) {
-        layout_reply.format = static_cast<FlexFormat>(layout.format);
-
-        planes.resize(layout.num_planes);
-        layout_reply.planes.setToExternal(
-                reinterpret_cast<FlexPlane*>(planes.data()), planes.size());
-    } else {
-        close(fence);
-    }
+    Error error =
+        lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
 
-    hidl_cb(static_cast<Error>(err), layout_reply);
+    hidl_cb(error, layout);
     return Void();
 }
 
-Return<void> GrallocMapperHal::unlock(const hidl_handle& bufferHandle,
-        unlock_cb hidl_cb)
-{
-    int32_t fence = -1;
-    int32_t err = mDispatch.unlock(mDevice, bufferHandle, &fence);
+Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) {
+    buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+    if (!bufferHandle) {
+        hidl_cb(Error::BAD_BUFFER, nullptr);
+        return Void();
+    }
+
+    int fenceFd;
+    Error error = unlockBuffer(bufferHandle, &fenceFd);
+    if (error == Error::NONE) {
+        NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
 
-    NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
-    hidl_handle fenceHandle;
-    if (err == GRALLOC1_ERROR_NONE && fence >= 0) {
-        auto nativeHandle = native_handle_init(fenceStorage, 1, 0);
-        nativeHandle->data[0] = fence;
+        hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
 
-        fenceHandle = nativeHandle;
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
+    } else {
+        hidl_cb(error, nullptr);
     }
 
-    hidl_cb(static_cast<Error>(err), fenceHandle);
     return Void();
 }
 
-} // anonymous namespace
-
 IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
     const hw_module_t* module = nullptr;
     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
@@ -410,12 +287,15 @@ IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
     }
 
     uint8_t major = (module->module_api_version >> 8) & 0xff;
-    if (major != 1) {
-        ALOGE("unknown gralloc module major version %d", major);
-        return nullptr;
+    switch (major) {
+        case 1:
+            return new Gralloc1Mapper(module);
+        case 0:
+            return new Gralloc0Mapper(module);
+        default:
+            ALOGE("unknown gralloc module major version %d", major);
+            return nullptr;
     }
-
-    return new GrallocMapperHal(module);
 }
 
 } // namespace implementation
index a2f89d1..c9c6d8a 100644 (file)
 #define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
 
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+
+#include <mutex>
+#include <unordered_set>
 
 namespace android {
 namespace hardware {
@@ -26,6 +30,68 @@ namespace mapper {
 namespace V2_0 {
 namespace implementation {
 
+class GrallocMapper : public IMapper {
+   public:
+    // IMapper interface
+    Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
+                                  createDescriptor_cb hidl_cb) override;
+    Return<void> importBuffer(const hidl_handle& rawHandle,
+                              importBuffer_cb hidl_cb) override;
+    Return<Error> freeBuffer(void* buffer) override;
+    Return<void> lock(void* buffer, uint64_t cpuUsage,
+                      const IMapper::Rect& accessRegion,
+                      const hidl_handle& acquireFence,
+                      lock_cb hidl_cb) override;
+    Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage,
+                           const IMapper::Rect& accessRegion,
+                           const hidl_handle& acquireFence,
+                           lockYCbCr_cb hidl_cb) override;
+    Return<void> unlock(void* buffer, unlock_cb hidl_cb) override;
+
+   protected:
+    static void waitFenceFd(int fenceFd, const char* logname);
+
+    struct {
+        bool highUsageBits;
+        bool layeredBuffers;
+        bool unregisterImplyDelete;
+    } mCapabilities = {};
+
+   private:
+    virtual bool validateDescriptorInfo(
+        const BufferDescriptorInfo& descriptorInfo) const;
+
+    // Register a buffer.  The handle is already cloned by the caller.
+    virtual Error registerBuffer(buffer_handle_t bufferHandle) = 0;
+
+    // Unregister a buffer.  The handle is closed and deleted by the
+    // callee if and only if mCapabilities.unregisterImplyDelete is set.
+    virtual void unregisterBuffer(buffer_handle_t bufferHandle) = 0;
+
+    // Lock a buffer.  The fence is owned by the caller.
+    virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                             const IMapper::Rect& accessRegion, int fenceFd,
+                             void** outData) = 0;
+    virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+                             const IMapper::Rect& accessRegion, int fenceFd,
+                             YCbCrLayout* outLayout) = 0;
+
+    // Unlock a buffer.  The returned fence is owned by the caller.
+    virtual Error unlockBuffer(buffer_handle_t bufferHandle,
+                               int* outFenceFd) = 0;
+
+    static bool addRegisteredHandle(buffer_handle_t bufferHandle);
+    static buffer_handle_t getRegisteredHandle(const void* buffer);
+    static native_handle_t* popRegisteredHandle(void* buffer);
+
+    static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd);
+    static hidl_handle getFenceHandle(int fenceFd, char* handleStorage);
+
+    // these are static and shared by all mappers
+    static std::mutex mMutex;
+    static std::unordered_set<buffer_handle_t> mRegisteredHandles;
+};
+
 extern "C" IMapper* HIDL_FETCH_IMapper(const char* name);
 
 } // namespace implementation
index 2946e85..e9b2f3a 100644 (file)
 
 package android.hardware.graphics.mapper@2.0;
 
+enum Error : int32_t {
+    NONE            = 0, /** no error */
+    BAD_DESCRIPTOR  = 1, /** invalid BufferDescriptor */
+    BAD_BUFFER      = 2, /** invalid buffer handle */
+    BAD_VALUE       = 3, /** invalid width, height, etc. */
+    /* 4 is reserved */
+    NO_RESOURCES    = 5, /** temporary failure due to resource contention */
+    /* 6 is reserved */
+    UNSUPPORTED     = 7, /** permanent failure */
+};
+
+/**
+ * A buffer descriptor is an implementation-defined opaque data returned by
+ * createDescriptor. It describes the properties of a buffer and is consumed
+ * by the allocator.
+ */
+typedef vec<uint32_t> BufferDescriptor;
+
 /**
- * Structures for describing flexible YUVA/RGBA formats for consumption by
- * applications. Such flexible formats contain a plane for each component (e.g.
- * red, green, blue), where each plane is laid out in a grid-like pattern
- * occupying unique byte addresses and with consistent byte offsets between
- * neighboring pixels.
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with PixelFormat::YCBCR_*_888.
  *
- * The FlexLayout structure is used with any pixel format that can be
- * represented by it, such as:
- *  - PixelFormat::YCBCR_*_888
- *  - PixelFormat::FLEX_RGB*_888
- *  - PixelFormat::RGB[AX]_888[8],BGRA_8888,RGB_888
- *  - PixelFormat::YV12,Y8,Y16,YCBCR_422_SP/I,YCRCB_420_SP
- *  - even implementation defined formats that can be represented by
- *    the structures
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. PixelFormat::YCBCR_420_888 has subsampling 4:2:0.
  *
- * Vertical increment (aka. row increment or stride) describes the distance in
- * bytes from the first pixel of one row to the first pixel of the next row
- * (below) for the component plane. This can be negative.
+ * Buffers must have a 8 bit depth.
  *
- * Horizontal increment (aka. column or pixel increment) describes the distance
- * in bytes from one pixel to the next pixel (to the right) on the same row for
- * the component plane. This can be negative.
+ * y, cb, and cr point to the first byte of their respective planes.
  *
- * Each plane can be subsampled either vertically or horizontally by
- * a power-of-two factor.
+ * Stride describes the distance in bytes from the first value of one row of
+ * the image to the first value of the next row. It includes the width of the
+ * image plus padding.
+ * yStride is the stride of the luma plane.
+ * cStride is the stride of the chroma planes.
  *
- * The bit-depth of each component can be arbitrary, as long as the pixels are
- * laid out on whole bytes, in native byte-order, using the most significant
- * bits of each unit.
+ * chromaStep is the distance in bytes from one chroma pixel value to the
+ * next. This is 2 bytes for semiplanar (because chroma values are interleaved
+ * and each chroma value is one byte) and 1 for planar.
  */
-
-enum FlexComponent : int32_t {
-    Y  = 1 << 0, /** luma */
-    CB = 1 << 1, /** chroma blue */
-    CR = 1 << 2, /** chroma red */
-
-    R  = 1 << 10, /** red */
-    G  = 1 << 11, /** green */
-    B  = 1 << 12, /** blue */
-
-    A  = 1 << 30, /** alpha */
-};
-
-enum FlexFormat : int32_t {
-    /** not a flexible format */
-    INVALID = 0x0,
-
-    Y       = FlexComponent:Y,
-    YCBCR   = Y | FlexComponent:CB | FlexComponent:CR,
-    YCBCRA  = YCBCR | FlexComponent:A,
-
-    RGB     = FlexComponent:R | FlexComponent:G | FlexComponent:B,
-    RGBA    = RGB | FlexComponent:A,
+struct YCbCrLayout {
+    pointer y;
+    pointer cb;
+    pointer cr;
+    uint32_t yStride;
+    uint32_t cStride;
+    uint32_t chromaStep;
 };
-
-struct FlexPlane {
-    /** Pointer to the first byte of the top-left pixel of the plane. */
-    pointer topLeft;
-
-    FlexComponent component;
-
-    /**
-     * Bits allocated for the component in each pixel. Must be a positive
-     * multiple of 8.
-     */
-    int32_t bitsPerComponent;
-
-    /**
-     * Number of the most significant bits used in the format for this
-     * component. Must be between 1 and bitsPerComponent, inclusive.
-     */
-    int32_t bitsUsed;
-
-    /** Horizontal increment. */
-    int32_t hIncrement;
-    /** Vertical increment. */
-    int32_t vIncrement;
-    /** Horizontal subsampling. Must be a positive power of 2. */
-    int32_t hSubsampling;
-    /** Vertical subsampling. Must be a positive power of 2. */
-    int32_t vSubsampling;
-};
-
-struct FlexLayout {
-    /** The kind of flexible format. */
-    FlexFormat format;
-
-    /**
-     * A plane for each component; ordered in increasing component value
-     * order. E.g. FlexFormat::RGBA maps 0 -> R, 1 -> G, etc.  Can have size 0
-     * for FlexFormat::INVALID.
-     */
-    vec<FlexPlane> planes;
-};
-
-/** Backing store ID of a buffer. See IMapper::getBackingStore. */
-typedef uint64_t BackingStore;
index e26f087..1c0e4c5 100644 (file)
@@ -24,7 +24,6 @@ cc_library_static {
     ],
     static_libs: [
         "VtsHalHidlTargetTestBase",
-        "libVtsHalGraphicsAllocatorTestUtils",
     ],
     cflags: [
         "-Wall",
@@ -54,7 +53,6 @@ cc_test {
         "android.hardware.graphics.common@1.0",
     ],
     static_libs: [
-        "libVtsHalGraphicsAllocatorTestUtils",
         "libVtsHalGraphicsMapperTestUtils",
         "VtsHalHidlTargetTestBase",
     ],
index f6a26ac..c534889 100644 (file)
@@ -25,228 +25,233 @@ namespace mapper {
 namespace V2_0 {
 namespace tests {
 
-using android::hardware::graphics::allocator::V2_0::Buffer;
-using android::hardware::graphics::allocator::V2_0::BufferDescriptor;
-using android::hardware::graphics::allocator::V2_0::Error;
+Gralloc::Gralloc() {
+    init();
+}
 
-Mapper::Mapper() { init(); }
+void Gralloc::init() {
+    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>();
+    ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
 
-void Mapper::init() {
-  mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>();
-  ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
-  ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
+    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>();
+    ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
+    ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
 }
 
-Mapper::~Mapper() {
-  for (auto it : mHandles) {
-    while (it.second) {
-      EXPECT_EQ(Error::NONE, mMapper->release(it.first))
-          << "failed to release handle " << it.first;
-      it.second--;
+Gralloc::~Gralloc() {
+    for (auto bufferHandle : mClonedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
+    mClonedBuffers.clear();
+
+    for (auto bufferHandle : mImportedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer))
+            << "failed to free buffer " << buffer;
     }
-  }
-  mHandles.clear();
+    mImportedBuffers.clear();
 }
 
-sp<IMapper> Mapper::getRaw() const { return mMapper; }
+sp<IAllocator> Gralloc::getAllocator() const {
+    return mAllocator;
+}
 
-void Mapper::retain(const native_handle_t* handle) {
-  Error error = mMapper->retain(handle);
-  ASSERT_EQ(Error::NONE, error) << "failed to retain handle " << handle;
+std::string Gralloc::dumpDebugInfo() {
+    std::string debugInfo;
+    mAllocator->dumpDebugInfo(
+        [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
 
-  mHandles[handle]++;
+    return debugInfo;
 }
 
-void Mapper::release(const native_handle_t* handle) {
-  Error error = mMapper->release(handle);
-  ASSERT_EQ(Error::NONE, error) << "failed to release handle " << handle;
+const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle =
+        native_handle_clone(rawHandle.getNativeHandle());
+    EXPECT_NE(nullptr, bufferHandle);
 
-  if (--mHandles[handle] == 0) {
-    mHandles.erase(handle);
-  }
-}
+    if (bufferHandle) {
+        mClonedBuffers.insert(bufferHandle);
+    }
 
-Mapper::Dimensions Mapper::getDimensions(const native_handle_t* handle) {
-  Dimensions dimensions = {};
-  mMapper->getDimensions(handle, [&](const auto& tmpError, const auto& tmpWidth,
-                                     const auto& tmpHeight) {
-    ASSERT_EQ(Error::NONE, tmpError)
-        << "failed to get dimensions for handle " << handle;
-    dimensions.width = tmpWidth;
-    dimensions.height = tmpHeight;
-  });
-
-  return dimensions;
+    return bufferHandle;
 }
 
-PixelFormat Mapper::getFormat(const native_handle_t* handle) {
-  PixelFormat format = static_cast<PixelFormat>(0);
-  mMapper->getFormat(handle, [&](const auto& tmpError, const auto& tmpFormat) {
-    ASSERT_EQ(Error::NONE, tmpError)
-        << "failed to get format for handle " << handle;
-    format = tmpFormat;
-  });
+std::vector<const native_handle_t*> Gralloc::allocate(
+    const BufferDescriptor& descriptor, uint32_t count, bool import,
+    uint32_t* outStride) {
+    std::vector<const native_handle_t*> bufferHandles;
+    bufferHandles.reserve(count);
+    mAllocator->allocate(
+        descriptor, count, [&](const auto& tmpError, const auto& tmpStride,
+                               const auto& tmpBuffers) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
+            ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
+
+            for (uint32_t i = 0; i < count; i++) {
+                if (import) {
+                    ASSERT_NO_FATAL_FAILURE(
+                        bufferHandles.push_back(importBuffer(tmpBuffers[i])));
+                } else {
+                    ASSERT_NO_FATAL_FAILURE(
+                        bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
+                }
+            }
+
+            if (outStride) {
+                *outStride = tmpStride;
+            }
+        });
+
+    if (::testing::Test::HasFatalFailure()) {
+        bufferHandles.clear();
+    }
 
-  return format;
+    return bufferHandles;
 }
 
-uint32_t Mapper::getLayerCount(const native_handle_t* handle) {
-  uint32_t count = 0;
-  mMapper->getLayerCount(
-      handle, [&](const auto& tmpError, const auto& tmpCount) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get layer count for handle " << handle;
-        count = tmpCount;
-      });
+const native_handle_t* Gralloc::allocate(
+    const IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
+    uint32_t* outStride) {
+    BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
 
-  return count;
-}
+    auto buffers = allocate(descriptor, 1, import, outStride);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
 
-uint64_t Mapper::getProducerUsageMask(const native_handle_t* handle) {
-  uint64_t usageMask = 0;
-  mMapper->getProducerUsageMask(
-      handle, [&](const auto& tmpError, const auto& tmpUsageMask) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get producer usage mask for handle " << handle;
-        usageMask = tmpUsageMask;
-      });
+    return buffers[0];
+}
 
-  return usageMask;
+sp<IMapper> Gralloc::getMapper() const {
+    return mMapper;
 }
 
-uint64_t Mapper::getConsumerUsageMask(const native_handle_t* handle) {
-  uint64_t usageMask = 0;
-  mMapper->getConsumerUsageMask(
-      handle, [&](const auto& tmpError, const auto& tmpUsageMask) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get consumer usage mask for handle " << handle;
-        usageMask = tmpUsageMask;
-      });
+BufferDescriptor Gralloc::createDescriptor(
+    const IMapper::BufferDescriptorInfo& descriptorInfo) {
+    BufferDescriptor descriptor;
+    mMapper->createDescriptor(
+        descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+            descriptor = tmpDescriptor;
+        });
 
-  return usageMask;
+    return descriptor;
 }
 
-BackingStore Mapper::getBackingStore(const native_handle_t* handle) {
-  BackingStore backingStore = 0;
-  mMapper->getBackingStore(
-      handle, [&](const auto& tmpError, const auto& tmpBackingStore) {
-        ASSERT_EQ(Error::NONE, tmpError)
-            << "failed to get backing store for handle " << handle;
-        backingStore = tmpBackingStore;
-      });
+const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = nullptr;
+    mMapper->importBuffer(
+        rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p"
+                                             << rawHandle.getNativeHandle();
+            bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+        });
+
+    if (bufferHandle) {
+        mImportedBuffers.insert(bufferHandle);
+    }
 
-  return backingStore;
+    return bufferHandle;
 }
 
-uint32_t Mapper::getStride(const native_handle_t* handle) {
-  uint32_t stride = 0;
-  mMapper->getStride(handle, [&](const auto& tmpError, const auto& tmpStride) {
-    ASSERT_EQ(Error::NONE, tmpError)
-        << "failed to get stride for handle " << handle;
-    stride = tmpStride;
-  });
+void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
-  return stride;
+    if (mImportedBuffers.erase(bufferHandle)) {
+        Error error = mMapper->freeBuffer(buffer);
+        ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
+    } else {
+        mClonedBuffers.erase(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
 }
 
-void* Mapper::lock(const native_handle_t* handle, uint64_t producerUsageMask,
-                   uint64_t consumerUsageMask,
-                   const IMapper::Rect& accessRegion, int acquireFence) {
-  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1);
-  native_handle_t* acquireFenceHandle = nullptr;
-  if (acquireFence >= 0) {
-    acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1);
-    acquireFenceHandle->data[0] = acquireFence;
-  }
-
-  void* data = nullptr;
-  mMapper->lock(
-      handle, producerUsageMask, consumerUsageMask, accessRegion,
-      acquireFenceHandle, [&](const auto& tmpError, const auto& tmpData) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to lock handle " << handle;
-        data = tmpData;
-      });
-
-  if (acquireFence >= 0) {
-    close(acquireFence);
-  }
-
-  return data;
-}
+void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const IMapper::Rect& accessRegion, int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
 
-FlexLayout Mapper::lockFlex(const native_handle_t* handle,
-                            uint64_t producerUsageMask,
-                            uint64_t consumerUsageMask,
-                            const IMapper::Rect& accessRegion,
-                            int acquireFence) {
-  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1);
-  native_handle_t* acquireFenceHandle = nullptr;
-  if (acquireFence >= 0) {
-    acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1);
-    acquireFenceHandle->data[0] = acquireFence;
-  }
-
-  FlexLayout layout = {};
-  mMapper->lockFlex(handle, producerUsageMask, consumerUsageMask, accessRegion,
-                    acquireFenceHandle,
-                    [&](const auto& tmpError, const auto& tmpLayout) {
+    void* data = nullptr;
+    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                  [&](const auto& tmpError, const auto& tmpData) {
                       ASSERT_EQ(Error::NONE, tmpError)
-                          << "failed to lockFlex handle " << handle;
-                      layout = tmpLayout;
-                    });
+                          << "failed to lock buffer " << buffer;
+                      data = tmpData;
+                  });
 
-  if (acquireFence >= 0) {
-    close(acquireFence);
-  }
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
 
-  return layout;
+    return data;
 }
 
-int Mapper::unlock(const native_handle_t* handle) {
-  int releaseFence = -1;
-  mMapper->unlock(handle, [&](const auto& tmpError,
-                              const auto& tmpReleaseFence) {
-    ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock handle " << handle;
-
-    auto handle = tmpReleaseFence.getNativeHandle();
-    if (handle) {
-      ASSERT_EQ(0, handle->numInts) << "invalid fence handle " << handle;
-      if (handle->numFds == 1) {
-        releaseFence = dup(handle->data[0]);
-        ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
-      } else {
-        ASSERT_EQ(0, handle->numFds) << " invalid fence handle " << handle;
-      }
+YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle,
+                               uint64_t cpuUsage,
+                               const IMapper::Rect& accessRegion,
+                               int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    YCbCrLayout layout = {};
+    mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                       [&](const auto& tmpError, const auto& tmpLayout) {
+                           ASSERT_EQ(Error::NONE, tmpError)
+                               << "failed to lockYCbCr buffer " << buffer;
+                           layout = tmpLayout;
+                       });
+
+    if (acquireFence >= 0) {
+        close(acquireFence);
     }
-  });
 
-  return releaseFence;
+    return layout;
 }
 
-const native_handle_t* Mapper::allocate(
-    std::unique_ptr<AllocatorClient>& allocatorClient,
-    const IAllocatorClient::BufferDescriptorInfo& info) {
-  BufferDescriptor descriptor = allocatorClient->createDescriptor(info);
-  if (::testing::Test::HasFatalFailure()) {
-    return nullptr;
-  }
-
-  Buffer buffer = allocatorClient->allocate(descriptor);
-  if (::testing::Test::HasFatalFailure()) {
-    allocatorClient->destroyDescriptor(descriptor);
-    return nullptr;
-  }
-
-  const native_handle_t* handle =
-      allocatorClient->exportHandle(descriptor, buffer);
-  if (handle) {
-    retain(handle);
-  }
-
-  allocatorClient->free(buffer);
-  allocatorClient->destroyDescriptor(descriptor);
-
-  return handle;
+int Gralloc::unlock(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    mMapper->unlock(
+        buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer "
+                                             << buffer;
+
+            auto fenceHandle = tmpReleaseFence.getNativeHandle();
+            if (fenceHandle) {
+                ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle "
+                                                   << fenceHandle;
+                if (fenceHandle->numFds == 1) {
+                    releaseFence = dup(fenceHandle->data[0]);
+                    ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
+                } else {
+                    ASSERT_EQ(0, fenceHandle->numFds)
+                        << " invalid fence handle " << fenceHandle;
+                }
+            }
+        });
+
+    return releaseFence;
 }
 
 }  // namespace tests
index c186b00..757f20b 100644 (file)
 #ifndef VTS_HAL_GRAPHICS_MAPPER_UTILS
 #define VTS_HAL_GRAPHICS_MAPPER_UTILS
 
-#include <memory>
-#include <unordered_map>
+#include <unordered_set>
 
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <utils/StrongPointer.h>
 
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -32,59 +30,62 @@ namespace mapper {
 namespace V2_0 {
 namespace tests {
 
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::allocator::V2_0::IAllocatorClient;
-using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient;
-
-// A wrapper to IMapper.
-class Mapper {
- public:
-  Mapper();
-  ~Mapper();
-
-  sp<IMapper> getRaw() const;
-
-  void retain(const native_handle_t* handle);
-  void release(const native_handle_t* handle);
-
-  struct Dimensions {
-    uint32_t width;
-    uint32_t height;
-  };
-  Dimensions getDimensions(const native_handle_t* handle);
-
-  PixelFormat getFormat(const native_handle_t* handle);
-  uint32_t getLayerCount(const native_handle_t* handle);
-  uint64_t getProducerUsageMask(const native_handle_t* handle);
-  uint64_t getConsumerUsageMask(const native_handle_t* handle);
-  BackingStore getBackingStore(const native_handle_t* handle);
-  uint32_t getStride(const native_handle_t* handle);
-
-  // We use fd instead of hidl_handle in these functions to pass fences
-  // in and out of the mapper.  The ownership of the fd is always transferred
-  // with each of these functions.
-  void* lock(const native_handle_t* handle, uint64_t producerUsageMask,
-             uint64_t consumerUsageMask, const IMapper::Rect& accessRegion,
-             int acquireFence);
-  FlexLayout lockFlex(const native_handle_t* handle, uint64_t producerUsageMask,
-                      uint64_t consumerUsageMask,
-                      const IMapper::Rect& accessRegion, int acquireFence);
-  int unlock(const native_handle_t* handle);
-
-  // Requests AllocatorClient to allocate a buffer, export the handle, and
-  // register the handle with mapper.
-  const native_handle_t* allocate(
-      std::unique_ptr<AllocatorClient>& allocatorClient,
-      const IAllocatorClient::BufferDescriptorInfo& info);
-
- private:
-  void init();
-
-  sp<IMapper> mMapper;
-
-  // Keep track of all registered (retained) handles.  When a test fails with
-  // ASSERT_*, the destructor will release the handles for the test.
-  std::unordered_map<const native_handle_t*, uint64_t> mHandles;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+
+// A wrapper to IAllocator and IMapper.
+class Gralloc {
+   public:
+    Gralloc();
+    ~Gralloc();
+
+    // IAllocator methods
+
+    sp<IAllocator> getAllocator() const;
+
+    std::string dumpDebugInfo();
+
+    // When import is false, this simply calls IAllocator::allocate. When import
+    // is true, the returned buffers are also imported into the mapper.
+    //
+    // Either case, the returned buffers must be freed with freeBuffer.
+    std::vector<const native_handle_t*> allocate(
+        const BufferDescriptor& descriptor, uint32_t count, bool import = true,
+        uint32_t* outStride = nullptr);
+    const native_handle_t* allocate(
+        const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
+        uint32_t* outStride = nullptr);
+
+    // IMapper methods
+
+    sp<IMapper> getMapper() const;
+
+    BufferDescriptor createDescriptor(
+        const IMapper::BufferDescriptorInfo& descriptorInfo);
+
+    const native_handle_t* importBuffer(const hidl_handle& rawHandle);
+    void freeBuffer(const native_handle_t* bufferHandle);
+
+    // We use fd instead of hidl_handle in these functions to pass fences
+    // in and out of the mapper.  The ownership of the fd is always transferred
+    // with each of these functions.
+    void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const IMapper::Rect& accessRegion, int acquireFence);
+    YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle,
+                          uint64_t cpuUsage, const IMapper::Rect& accessRegion,
+                          int acquireFence);
+    int unlock(const native_handle_t* bufferHandle);
+
+   private:
+    void init();
+    const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
+
+    sp<IAllocator> mAllocator;
+    sp<IMapper> mMapper;
+
+    // Keep track of all cloned and imported handles.  When a test fails with
+    // ASSERT_*, the destructor will free the handles for the test.
+    std::unordered_set<const native_handle_t*> mClonedBuffers;
+    std::unordered_set<const native_handle_t*> mImportedBuffers;
 };
 
 }  // namespace tests
index 92d74d5..f066a1e 100644 (file)
  * limitations under the License.
  */
 
-#define LOG_TAG "graphics_mapper_hidl_hal_test"
+#define LOG_TAG "VtsHalGraphicsMapperV2_0TargetTest"
 
-#include <android-base/logging.h>
 #include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
 #include <sync/sync.h>
 #include "VtsHalGraphicsMapperTestUtils.h"
 
@@ -29,202 +29,384 @@ namespace V2_0 {
 namespace tests {
 namespace {
 
-using namespace android::hardware::graphics::allocator::V2_0;
-using namespace android::hardware::graphics::allocator::V2_0::tests;
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::common::V1_0::PixelFormat;
 
 class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  protected:
   void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
-    ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient());
-    ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique<Mapper>());
-
-    mDummyDescriptorInfo.width = 64;
-    mDummyDescriptorInfo.height = 64;
-    mDummyDescriptorInfo.layerCount = 1;
-    mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
-    mDummyDescriptorInfo.producerUsageMask =
-        static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
-    mDummyDescriptorInfo.consumerUsageMask =
-        static_cast<uint64_t>(ConsumerUsage::CPU_READ);
+      ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+
+      mDummyDescriptorInfo.width = 64;
+      mDummyDescriptorInfo.height = 64;
+      mDummyDescriptorInfo.layerCount = 1;
+      mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+      mDummyDescriptorInfo.usage = static_cast<uint64_t>(
+          BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
   }
 
   void TearDown() override {}
 
-  std::unique_ptr<Allocator> mAllocator;
-  std::unique_ptr<AllocatorClient> mAllocatorClient;
-  std::unique_ptr<Mapper> mMapper;
-  IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
+  std::unique_ptr<Gralloc> mGralloc;
+  IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
 };
 
 /**
- * Test IMapper::retain and IMapper::release.
+ * Test IAllocator::dumpDebugInfo by calling it.
  */
-TEST_F(GraphicsMapperHidlTest, RetainRelease) {
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(
-      buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
-
-  const int maxRefs = 10;
-  for (int i = 0; i < maxRefs; i++) {
-    ASSERT_NO_FATAL_FAILURE(mMapper->retain(buffer));
-  }
-  for (int i = 0; i < maxRefs; i++) {
-    ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer));
-  }
-
-  ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer));
+TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
+    mGralloc->dumpDebugInfo();
 }
 
 /**
- * Test IMapper::get* getters.
+ * Test IAllocator::allocate with valid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, Getters) {
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(
-      buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
+    BufferDescriptor descriptor;
+    ASSERT_NO_FATAL_FAILURE(
+        descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
+
+    for (uint32_t count = 0; count < 5; count++) {
+        std::vector<const native_handle_t*> bufferHandles;
+        uint32_t stride;
+        ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(
+                                    descriptor, count, false, &stride));
+
+        if (count >= 1) {
+            EXPECT_LE(mDummyDescriptorInfo.width, stride)
+                << "invalid buffer stride";
+        }
+
+        for (auto bufferHandle : bufferHandles) {
+            mGralloc->freeBuffer(bufferHandle);
+        }
+    }
+}
 
-  IAllocatorClient::BufferDescriptorInfo info = {};
+/**
+ * Test IAllocator::allocate with invalid buffer descriptors.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
+    // this assumes any valid descriptor is non-empty
+    BufferDescriptor descriptor;
+    mGralloc->getAllocator()->allocate(
+        descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) {
+            EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
+        });
+}
 
-  Mapper::Dimensions dimensions;
-  ASSERT_NO_FATAL_FAILURE(dimensions = mMapper->getDimensions(buffer));
-  info.width = dimensions.width;
-  info.height = dimensions.height;
+/**
+ * Test IAllocator::allocate does not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 1024;
+    info.height = 1024;
+
+    for (int i = 0; i < 2048; i++) {
+        auto bufferHandle = mGralloc->allocate(info, false);
+        mGralloc->freeBuffer(bufferHandle);
+    }
+}
 
-  ASSERT_NO_FATAL_FAILURE(info.format = mMapper->getFormat(buffer));
-  ASSERT_NO_FATAL_FAILURE(info.producerUsageMask =
-                              mMapper->getProducerUsageMask(buffer));
-  ASSERT_NO_FATAL_FAILURE(info.consumerUsageMask =
-                              mMapper->getConsumerUsageMask(buffer));
+/**
+ * Test IMapper::createDescriptor with valid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+    ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
+}
 
-  EXPECT_EQ(mDummyDescriptorInfo.width, info.width);
-  EXPECT_EQ(mDummyDescriptorInfo.height, info.height);
-  EXPECT_EQ(mDummyDescriptorInfo.format, info.format);
-  EXPECT_EQ(mDummyDescriptorInfo.producerUsageMask, info.producerUsageMask);
-  EXPECT_EQ(mDummyDescriptorInfo.consumerUsageMask, info.consumerUsageMask);
+/**
+ * Test IMapper::createDescriptor with invalid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 0;
+    mGralloc->getMapper()->createDescriptor(
+        info, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_VALUE, tmpError)
+                << "createDescriptor did not fail with BAD_VALUE";
+        });
+}
 
-  ASSERT_NO_FATAL_FAILURE(mMapper->getBackingStore(buffer));
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
+    const native_handle_t* bufferHandle;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle =
+                                mGralloc->allocate(mDummyDescriptorInfo, true));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
+}
 
-  uint32_t stride;
-  ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
-  EXPECT_LE(info.width, stride);
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
+    const native_handle_t* clonedBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(
+        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+    // A cloned handle is a raw handle. Check that we can import it multiple
+    // times.
+    const native_handle_t* importedBufferHandles[2];
+    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] =
+                                mGralloc->importBuffer(clonedBufferHandle));
+    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] =
+                                mGralloc->importBuffer(clonedBufferHandle));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle));
 }
 
 /**
- * Test IMapper::lock and IMapper::unlock.
+ * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
  */
-TEST_F(GraphicsMapperHidlTest, LockBasic) {
-  const auto& info = mDummyDescriptorInfo;
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
+    const native_handle_t* rawHandle;
+    ASSERT_NO_FATAL_FAILURE(
+        rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+    native_handle_t* importedHandle = nullptr;
+    mGralloc->getMapper()->importBuffer(
+        rawHandle, [&](const auto& tmpError, const auto& buffer) {
+            ASSERT_EQ(Error::NONE, tmpError);
+            importedHandle = static_cast<native_handle_t*>(buffer);
+        });
+
+    // free the imported handle with another mapper
+    std::unique_ptr<Gralloc> anotherGralloc;
+    ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>());
+    Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
+    ASSERT_EQ(Error::NONE, error);
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle));
+}
 
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(
-      buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 1024;
+    info.height = 1024;
+
+    for (int i = 0; i < 2048; i++) {
+        auto bufferHandle = mGralloc->allocate(info, true);
+        mGralloc->freeBuffer(bufferHandle);
+    }
+}
 
-  uint32_t stride;
-  ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
+/**
+ * Test IMapper::importBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    mGralloc->getMapper()->importBuffer(
+        invalidHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "importBuffer with nullptr did not fail with BAD_BUFFER";
+        });
+
+    invalidHandle = native_handle_create(0, 0);
+    mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError,
+                                                           const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "importBuffer with invalid handle did not fail with BAD_BUFFER";
+    });
+    native_handle_delete(invalidHandle);
+
+    const native_handle_t* importedHandle;
+    ASSERT_NO_FATAL_FAILURE(importedHandle =
+                                mGralloc->allocate(mDummyDescriptorInfo, true));
+    mGralloc->getMapper()->importBuffer(
+        importedHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "importBuffer with an "
+                   "already imported handle did "
+                   "not fail with BAD_BUFFER";
+        });
+    mGralloc->freeBuffer(importedHandle);
+}
 
-  // lock buffer for writing
-  const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
-                             static_cast<int32_t>(info.height)};
-  int fence = -1;
-  uint32_t* data;
-  ASSERT_NO_FATAL_FAILURE(
-      data = static_cast<uint32_t*>(
-          mMapper->lock(buffer, info.producerUsageMask, 0, region, fence)));
+/**
+ * Test IMapper::freeBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with nullptr did not fail with BAD_BUFFER";
+
+    invalidHandle = native_handle_create(0, 0);
+    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
+    native_handle_delete(invalidHandle);
+
+    const native_handle_t* clonedBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(
+        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
+
+    mGralloc->freeBuffer(clonedBufferHandle);
+}
 
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      data[stride * y + x] = info.height * y + x;
+/**
+ * Test IMapper::lock and IMapper::unlock.
+ */
+TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+    const auto& info = mDummyDescriptorInfo;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle =
+                                mGralloc->allocate(info, true, &stride));
+
+    // lock buffer for writing
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    int fence = -1;
+    uint8_t* data;
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
+                                bufferHandle, info.usage, region, fence)));
+
+    // RGBA_8888
+    size_t strideInBytes = stride * 4;
+    size_t writeInBytes = info.width * 4;
+
+    for (uint32_t y = 0; y < info.height; y++) {
+        memset(data, y, writeInBytes);
+        data += strideInBytes;
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
 
-  // lock buffer for reading
-  ASSERT_NO_FATAL_FAILURE(
-      data = static_cast<uint32_t*>(
-          mMapper->lock(buffer, 0, info.consumerUsageMask, region, fence)));
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      EXPECT_EQ(info.height * y + x, data[stride * y + x]);
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
+                                bufferHandle, info.usage, region, fence)));
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (size_t i = 0; i < writeInBytes; i++) {
+            EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
+        }
+        data += strideInBytes;
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
-  if (fence >= 0) {
-    close(fence);
-  }
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
 }
 
 /**
- * Test IMapper::lockFlex.  This locks a YV12 buffer, and makes sure we can
+ * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
  * write to and read from it.
  */
-TEST_F(GraphicsMapperHidlTest, LockFlexBasic) {
-  auto info = mDummyDescriptorInfo;
-  info.format = PixelFormat::YV12;
-
-  const native_handle_t* buffer;
-  ASSERT_NO_FATAL_FAILURE(buffer = mMapper->allocate(mAllocatorClient, info));
-
-  // lock buffer for writing
-  const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
-                             static_cast<int32_t>(info.height)};
-  int fence = -1;
-  FlexLayout layout;
-  ASSERT_NO_FATAL_FAILURE(
-      layout =
-          mMapper->lockFlex(buffer, info.producerUsageMask, 0, region, fence));
-  ASSERT_EQ(FlexFormat::YCBCR, layout.format);
-  ASSERT_EQ(3u, layout.planes.size());
-
-  const auto y_stride = layout.planes[0].vIncrement;
-  const auto c_stride = layout.planes[1].vIncrement;
-  auto y_data = static_cast<uint8_t*>(layout.planes[0].topLeft);
-  auto cb_data = static_cast<uint8_t*>(layout.planes[1].topLeft);
-  auto cr_data = static_cast<uint8_t*>(layout.planes[2].topLeft);
-
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      auto val = static_cast<uint8_t>(info.height * y + x);
-
-      y_data[y_stride * y + x] = val;
-      if (y % 2 == 0 && x % 2 == 0) {
-        cb_data[c_stride * y / 2 + x / 2] = val;
-        cr_data[c_stride * y / 2 + x / 2] = val;
-      }
+TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YV12;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle =
+                                mGralloc->allocate(info, true, &stride));
+
+    // lock buffer for writing
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    int fence = -1;
+    YCbCrLayout layout;
+    ASSERT_NO_FATAL_FAILURE(
+        layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+
+    auto yData = static_cast<uint8_t*>(layout.y);
+    auto cbData = static_cast<uint8_t*>(layout.cb);
+    auto crData = static_cast<uint8_t*>(layout.cr);
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (uint32_t x = 0; x < info.width; x++) {
+            auto val = static_cast<uint8_t>(info.height * y + x);
+
+            yData[layout.yStride * y + x] = val;
+            if (y % 2 == 0 && x % 2 == 0) {
+                cbData[layout.cStride * y / 2 + x / 2] = val;
+                crData[layout.cStride * y / 2 + x / 2] = val;
+            }
+        }
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
-
-  // lock buffer for reading
-  ASSERT_NO_FATAL_FAILURE(
-      layout =
-          mMapper->lockFlex(buffer, 0, info.consumerUsageMask, region, fence));
-
-  y_data = static_cast<uint8_t*>(layout.planes[0].topLeft);
-  cb_data = static_cast<uint8_t*>(layout.planes[1].topLeft);
-  cr_data = static_cast<uint8_t*>(layout.planes[2].topLeft);
-  for (uint32_t y = 0; y < info.height; y++) {
-    for (uint32_t x = 0; x < info.width; x++) {
-      auto val = static_cast<uint8_t>(info.height * y + x);
-
-      EXPECT_EQ(val, y_data[y_stride * y + x]);
-      if (y % 2 == 0 && x % 2 == 0) {
-        EXPECT_EQ(val, cb_data[c_stride * y / 2 + x / 2]);
-        EXPECT_EQ(val, cr_data[c_stride * y / 2 + x / 2]);
-      }
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(
+        layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+
+    yData = static_cast<uint8_t*>(layout.y);
+    cbData = static_cast<uint8_t*>(layout.cb);
+    crData = static_cast<uint8_t*>(layout.cr);
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (uint32_t x = 0; x < info.width; x++) {
+            auto val = static_cast<uint8_t>(info.height * y + x);
+
+            EXPECT_EQ(val, yData[layout.yStride * y + x]);
+            if (y % 2 == 0 && x % 2 == 0) {
+                EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
+                EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
+            }
+        }
     }
-  }
 
-  ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
-  if (fence >= 0) {
-    close(fence);
-  }
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
+}
+
+/**
+ * Test IMapper::unlock with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    mGralloc->getMapper()->unlock(
+        invalidHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "unlock with nullptr did not fail with BAD_BUFFER";
+        });
+
+    invalidHandle = native_handle_create(0, 0);
+    mGralloc->getMapper()->unlock(
+        invalidHandle, [&](const auto& tmpError, const auto&) {
+            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "unlock with invalid handle did not fail with BAD_BUFFER";
+        });
+    native_handle_delete(invalidHandle);
+
+    ASSERT_NO_FATAL_FAILURE(invalidHandle =
+                                const_cast<native_handle_t*>(mGralloc->allocate(
+                                    mDummyDescriptorInfo, false)));
+    mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError,
+                                                     const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with un-imported handle did not fail with BAD_BUFFER";
+    });
+    mGralloc->freeBuffer(invalidHandle);
+
+// disabled as it fails on many existing drivers
+#if 0
+  ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
+                              mGralloc->allocate(mDummyDescriptorInfo, true)));
+  mGralloc->getMapper()->unlock(
+      invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with unlocked handle did not fail with BAD_BUFFER";
+      });
+  mGralloc->freeBuffer(invalidHandle);
+#endif
 }
 
-}  // namespace anonymous
+}  // namespace
 }  // namespace tests
 }  // namespace V2_0
 }  // namespace mapper