Merge "graphics: revise gralloc interfaces" into oc-dev
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
index 01d9a0e..58c2f26 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
@@ -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 @@
// 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 @@
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 @@
mFramesDisplayed++;
mLock.unlock();
}
-
- // Now tell GraphicBufferMapper we won't be using these handles anymore
- unregisterBufferHelper(tgtBuffer);
- unregisterBufferHelper(buffer);
}
}
@@ -233,24 +219,22 @@
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 @@
}
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);
-}
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.h b/automotive/evs/1.0/vts/functional/FrameHandler.h
index d5c3f6b..17a3980 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.h
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.h
@@ -68,8 +68,6 @@
// 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;
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index 44a108c..81e41aa 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -66,7 +66,6 @@
"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 @@
"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",
],
diff --git a/camera/device/1.0/ICameraDevicePreviewCallback.hal b/camera/device/1.0/ICameraDevicePreviewCallback.hal
index 4c9b517..5421981 100644
--- a/camera/device/1.0/ICameraDevicePreviewCallback.hal
+++ b/camera/device/1.0/ICameraDevicePreviewCallback.hal
@@ -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 @@
*
* @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.
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 6495f30..cb20fec 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -30,7 +30,7 @@
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 @@
}
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) {
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
index fd7276f..7807a85 100644
--- a/camera/device/3.2/Android.bp
+++ b/camera/device/3.2/Android.bp
@@ -66,7 +66,6 @@
"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 @@
"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",
],
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 5b3024b..5bb53c7 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -650,7 +650,8 @@
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);
}
}
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
index c7cc75a..d878deb 100644
--- a/camera/device/3.2/default/convert.cpp
+++ b/camera/device/3.2/default/convert.cpp
@@ -28,8 +28,7 @@
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 @@
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.
diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal
index 5ae7a18..1632570 100644
--- a/camera/device/3.2/types.hal
+++ b/camera/device/3.2/types.hal
@@ -16,12 +16,10 @@
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 @@
* 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 @@
* 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
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 1656325..d295f3e 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -57,7 +57,6 @@
"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 @@
"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",
],
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 74e6efe..e37f989 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -52,8 +52,8 @@
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 @@
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 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);
diff --git a/graphics/Android.bp b/graphics/Android.bp
index f4f7db4..9aea85f 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -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",
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
index 271f2ce..f707468 100644
--- a/graphics/allocator/2.0/Android.bp
+++ b/graphics/allocator/2.0/Android.bp
@@ -3,9 +3,7 @@
filegroup {
name: "android.hardware.graphics.allocator@2.0_hal",
srcs: [
- "types.hal",
"IAllocator.hal",
- "IAllocatorClient.hal",
],
}
@@ -17,9 +15,7 @@
":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 @@
":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 @@
"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 @@
"libhwbinder",
"libutils",
"android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.mapper@2.0",
"android.hidl.base@1.0",
],
}
diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal
index bf0e141..43a3916 100644
--- a/graphics/allocator/2.0/IAllocator.hal
+++ b/graphics/allocator/2.0/IAllocator.hal
@@ -16,38 +16,9 @@
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 @@
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
index 8ca568f..0000000
--- a/graphics/allocator/2.0/IAllocatorClient.hal
+++ /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);
-};
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 0baef89..6adfa71 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -3,7 +3,7 @@
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 @@
"liblog",
"libutils",
],
+ static_libs: ["libgrallocmapperincludes"],
}
cc_binary {
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
index 0b9e863..273d3f5 100644
--- a/graphics/allocator/2.0/default/Gralloc.cpp
+++ b/graphics/allocator/2.0/default/Gralloc.cpp
@@ -16,17 +16,11 @@
#define LOG_TAG "GrallocPassthrough"
-#include <mutex>
-#include <type_traits>
-#include <unordered_set>
-#include <vector>
-
-#include <string.h>
-
-#include <hardware/gralloc1.h>
-#include <log/log.h>
-
#include "Gralloc.h"
+#include "Gralloc0Allocator.h"
+#include "Gralloc1Allocator.h"
+
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -35,417 +29,6 @@
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 @@
}
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
index 0000000..3b62bb3
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
@@ -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
index 0000000..0e90527
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc0Allocator.h
@@ -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
index 0000000..c0a5e1e
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
@@ -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
index 0000000..7b5a966
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1Allocator.h
@@ -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
index d9b184b..0000000
--- a/graphics/allocator/2.0/types.hal
+++ /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
index fb77ab3..0000000
--- a/graphics/allocator/2.0/vts/functional/Android.bp
+++ /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
index 0dc43be..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp
+++ /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
index c9bfe8f..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h
+++ /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
index b1c764f..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp
+++ /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;
-}
diff --git a/graphics/common/1.0/Android.mk b/graphics/common/1.0/Android.mk
index c08053d..ae80c6a 100644
--- a/graphics/common/1.0/Android.mk
+++ b/graphics/common/1.0/Android.mk
@@ -13,6 +13,25 @@
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 @@
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
diff --git a/graphics/common/1.0/types.hal b/graphics/common/1.0/types.hal
index 8aa0779..3bd1ec1 100644
--- a/graphics/common/1.0/types.hal
+++ b/graphics/common/1.0/types.hal
@@ -450,6 +450,90 @@
};
/**
+ * 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:
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 8e1f925..66323d4 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -52,7 +52,6 @@
],
static_libs: [
"libhwcomposer-command-buffer",
- "libVtsHalGraphicsAllocatorTestUtils",
"libVtsHalGraphicsComposerTestUtils",
"libVtsHalGraphicsMapperTestUtils",
"VtsHalHidlTargetTestBase",
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 0da3a33..387222f 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -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 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 @@
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 @@
}
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);
+ 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 mMapper->allocate(mAllocatorClient, info);
+ return mGralloc->allocate(info);
}
void execute() {
@@ -507,9 +497,7 @@
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;
};
/**
diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp
index 98a509b..cc2bd73 100644
--- a/graphics/mapper/2.0/Android.bp
+++ b/graphics/mapper/2.0/Android.bp
@@ -51,7 +51,6 @@
"liblog",
"libutils",
"libcutils",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
@@ -60,7 +59,6 @@
"libhidltransport",
"libhwbinder",
"libutils",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal
index 573dcd0..246be24 100644
--- a/graphics/mapper/2.0/IMapper.hal
+++ b/graphics/mapper/2.0/IMapper.hal
@@ -16,10 +16,39 @@
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 @@
};
/**
- * 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);
+ createDescriptor(BufferDescriptorInfo descriptorInfo)
+ generates (Error error,
+ BufferDescriptor descriptor);
/**
- * Removes a reference from the given buffer 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.
*
- * 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.
+ * 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 a reference must be
- * removed.
+ * 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 rawHandle is the raw buffer handle to import.
* @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
+ * 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="*")
+ importBuffer(handle rawHandle) generates (Error error, pointer buffer);
+
+ /**
+ * Frees a buffer handle. Buffer handles returned by importBuffer must be
+ * freed with this function when no longer needed.
+ *
+ * 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.
+ *
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer 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);
-
- /**
- * Gets the consumer 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 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.
- *
- * @param device is the mapper device.
- * @param bufferHandle is the buffer from which to get the backing store
- * identifier.
- * @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.
- */
- @callflow(next="*")
- getBackingStore(handle bufferHandle)
- generates (Error error,
- BackingStore store);
-
- /**
- * Gets the stride of the buffer in pixels.
- *
- * 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.
- *
- * @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.
- */
- @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 @@
* 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 @@
/**
* 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 @@
* 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.
+ * Unlocks a buffer to indicate all CPU accesses to the buffer have
+ * completed.
*
- * 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().
- *
- * @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);
};
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 1dc5aea..090c61f 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -18,10 +18,9 @@
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 @@
"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
index 0000000..28f5016
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
@@ -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
index 0000000..e792a69
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc0Mapper.h
@@ -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
index 0000000..c1e5adc
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
@@ -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
index 0000000..452afdf
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc1Mapper.h
@@ -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
index 0000000..9b5ab04
--- /dev/null
+++ b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
@@ -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
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
index 526aca2..339317a 100644
--- a/graphics/mapper/2.0/default/GrallocMapper.cpp
+++ b/graphics/mapper/2.0/default/GrallocMapper.cpp
@@ -17,14 +17,14 @@
#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 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();
+std::mutex GrallocMapper::mMutex;
+std::unordered_set<buffer_handle_t> GrallocMapper::mRegisteredHandles;
- // 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;
+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));
-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));
- }
-
- 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);
-
- for (auto cap : caps) {
- switch (cap) {
- case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
- mCapabilities.layeredBuffers = true;
- break;
- default:
- break;
- }
- }
-}
-
-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);
- }
-
- *outPfn = reinterpret_cast<T>(pfn);
-}
-
-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);
- }
- 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);
-}
-
-gralloc1_rect_t GrallocMapperHal::asGralloc1Rect(const IMapper::Rect& rect)
-{
- return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
-}
-
-bool GrallocMapperHal::dupFence(const hidl_handle& fenceHandle, int* outFd)
-{
- auto handle = fenceHandle.getNativeHandle();
- if (!handle || handle->numFds == 0) {
- *outFd = -1;
- return true;
- }
-
- if (handle->numFds > 1) {
- ALOGE("invalid fence handle with %d fds", handle->numFds);
+ if (!descriptorInfo.width || !descriptorInfo.height ||
+ !descriptorInfo.layerCount) {
return false;
}
- *outFd = dup(handle->data[0]);
- return (*outFd >= 0);
-}
-
-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);
-
- ++mBufferReferenceCounts[nativeHandle];
- }
- return static_cast<Error>(err);
-}
-
-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);
- }
+ if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
+ return false;
}
- return static_cast<Error>(err);
-}
-
-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);
-
- hidl_cb(static_cast<Error>(err), width, height);
- return Void();
-}
-
-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(static_cast<Error>(err), static_cast<PixelFormat>(format));
- return Void();
-}
-
-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);
+ if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+ return false;
}
- hidl_cb(static_cast<Error>(err), count);
+ 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);
+ }
+
+ return true;
+}
+
+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());
+ }
+
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);
-
- hidl_cb(static_cast<Error>(err), mask);
- return Void();
+bool GrallocMapper::addRegisteredHandle(buffer_handle_t bufferHandle) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.insert(bufferHandle).second;
}
-Return<void> GrallocMapperHal::getConsumerUsageMask(
- const hidl_handle& bufferHandle, getConsumerUsageMask_cb hidl_cb)
-{
- uint64_t mask = 0x0;
- int32_t err = mDispatch.getConsumerUsage(mDevice, bufferHandle, &mask);
+native_handle_t* GrallocMapper::popRegisteredHandle(void* buffer) {
+ auto bufferHandle = static_cast<native_handle_t*>(buffer);
- hidl_cb(static_cast<Error>(err), mask);
- return Void();
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
}
-Return<void> GrallocMapperHal::getBackingStore(
- const hidl_handle& bufferHandle, getBackingStore_cb hidl_cb)
-{
- uint64_t store = 0;
- int32_t err = mDispatch.getBackingStore(mDevice, bufferHandle, &store);
+buffer_handle_t GrallocMapper::getRegisteredHandle(const void* buffer) {
+ auto bufferHandle = static_cast<buffer_handle_t>(buffer);
- hidl_cb(static_cast<Error>(err), store);
- return Void();
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
}
-Return<void> GrallocMapperHal::getStride(const hidl_handle& bufferHandle,
- getStride_cb hidl_cb)
-{
- uint32_t stride = 0;
- int32_t err = mDispatch.getStride(mDevice, bufferHandle, &stride);
+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();
+ }
- hidl_cb(static_cast<Error>(err), stride);
- return Void();
-}
+ if (!rawHandle.getNativeHandle()) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
-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);
-
- int fence = -1;
- if (!dupFence(acquireFence, &fence)) {
+ native_handle_t* bufferHandle =
+ native_handle_clone(rawHandle.getNativeHandle());
+ if (!bufferHandle) {
hidl_cb(Error::NO_RESOURCES, nullptr);
return Void();
}
+ Error error = registerBuffer(bufferHandle);
+ if (error != Error::NONE) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+
+ hidl_cb(error, nullptr);
+ 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);
+ }
+
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ hidl_cb(Error::NONE, bufferHandle);
+ return Void();
+}
+
+Return<Error> GrallocMapper::freeBuffer(void* buffer) {
+ native_handle_t* bufferHandle = popRegisteredHandle(buffer);
+ if (!bufferHandle) {
+ return Error::BAD_BUFFER;
+ }
+
+ unregisterBuffer(bufferHandle);
+ if (!mCapabilities.unregisterImplyDelete) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ }
+
+ return Error::NONE;
+}
+
+void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
+ if (fenceFd < 0) {
+ return;
+ }
+
+ 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);
+ }
+}
+
+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;
+ }
+
+ *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+ return true;
+}
+
+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;
+ }
+
+ return hidl_handle(handle);
+}
+
+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 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{};
+Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lockYCbCr_cb hidl_cb) {
+ YCbCrLayout layout = {};
- 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);
+ 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();
+ Error error =
+ lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
- err = mDispatch.lockFlex(mDevice, bufferHandle, producerUsageMask,
- consumerUsageMask, &rect, &layout, fence);
- if (err == GRALLOC1_ERROR_NONE) {
- layout_reply.format = static_cast<FlexFormat>(layout.format);
+ hidl_cb(error, layout);
+ return Void();
+}
- planes.resize(layout.num_planes);
- layout_reply.planes.setToExternal(
- reinterpret_cast<FlexPlane*>(planes.data()), planes.size());
+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);
+
+ hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
} else {
- close(fence);
+ hidl_cb(error, nullptr);
}
- hidl_cb(static_cast<Error>(err), layout_reply);
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);
-
- 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;
-
- fenceHandle = nativeHandle;
- }
-
- 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 @@
}
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
diff --git a/graphics/mapper/2.0/default/GrallocMapper.h b/graphics/mapper/2.0/default/GrallocMapper.h
index a2f89d1..c9c6d8a 100644
--- a/graphics/mapper/2.0/default/GrallocMapper.h
+++ b/graphics/mapper/2.0/default/GrallocMapper.h
@@ -18,6 +18,10 @@
#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 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
diff --git a/graphics/mapper/2.0/types.hal b/graphics/mapper/2.0/types.hal
index 2946e85..e9b2f3a 100644
--- a/graphics/mapper/2.0/types.hal
+++ b/graphics/mapper/2.0/types.hal
@@ -16,101 +16,50 @@
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 */
+};
+
/**
- * 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.
- *
- * 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
- *
- * 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.
- *
- * 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.
- *
- * Each plane can be subsampled either vertically or horizontally by
- * a power-of-two factor.
- *
- * 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.
+ * 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;
-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 */
+/**
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with PixelFormat::YCBCR_*_888.
+ *
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. PixelFormat::YCBCR_420_888 has subsampling 4:2:0.
+ *
+ * Buffers must have a 8 bit depth.
+ *
+ * y, cb, and cr point to the first byte of their respective planes.
+ *
+ * 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.
+ *
+ * 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.
+ */
+struct YCbCrLayout {
+ pointer y;
+ pointer cb;
+ pointer cr;
+ uint32_t yStride;
+ uint32_t cStride;
+ uint32_t chromaStep;
};
-
-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 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;
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index e26f087..1c0e4c5 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -24,7 +24,6 @@
],
static_libs: [
"VtsHalHidlTargetTestBase",
- "libVtsHalGraphicsAllocatorTestUtils",
],
cflags: [
"-Wall",
@@ -54,7 +53,6 @@
"android.hardware.graphics.common@1.0",
],
static_libs: [
- "libVtsHalGraphicsAllocatorTestUtils",
"libVtsHalGraphicsMapperTestUtils",
"VtsHalHidlTargetTestBase",
],
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
index f6a26ac..c534889 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
@@ -25,228 +25,233 @@
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;
-
-Mapper::Mapper() { init(); }
-
-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";
+Gralloc::Gralloc() {
+ init();
}
-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--;
+void Gralloc::init() {
+ mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>();
+ ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
+
+ 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";
+}
+
+Gralloc::~Gralloc() {
+ for (auto bufferHandle : mClonedBuffers) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ native_handle_close(buffer);
+ native_handle_delete(buffer);
}
- }
- mHandles.clear();
+ 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;
+ }
+ mImportedBuffers.clear();
}
-sp<IMapper> Mapper::getRaw() const { return mMapper; }
-
-void Mapper::retain(const native_handle_t* handle) {
- Error error = mMapper->retain(handle);
- ASSERT_EQ(Error::NONE, error) << "failed to retain handle " << handle;
-
- mHandles[handle]++;
+sp<IAllocator> Gralloc::getAllocator() const {
+ return mAllocator;
}
-void Mapper::release(const native_handle_t* handle) {
- Error error = mMapper->release(handle);
- ASSERT_EQ(Error::NONE, error) << "failed to release handle " << handle;
+std::string Gralloc::dumpDebugInfo() {
+ std::string debugInfo;
+ mAllocator->dumpDebugInfo(
+ [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
- if (--mHandles[handle] == 0) {
- mHandles.erase(handle);
- }
+ return debugInfo;
}
-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;
- });
+const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
+ const native_handle_t* bufferHandle =
+ native_handle_clone(rawHandle.getNativeHandle());
+ EXPECT_NE(nullptr, bufferHandle);
- return dimensions;
+ if (bufferHandle) {
+ mClonedBuffers.insert(bufferHandle);
+ }
+
+ 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";
- return format;
+ 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 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;
+ }
+
+ return buffers[0];
}
-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 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);
+ });
- return backingStore;
+ if (bufferHandle) {
+ mImportedBuffers.insert(bufferHandle);
+ }
+
+ 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* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int acquireFence) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
- 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;
- });
+ 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;
+ }
- if (acquireFence >= 0) {
- close(acquireFence);
- }
-
- return data;
-}
-
-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);
- }
-
- return layout;
-}
-
-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;
- }
+ if (acquireFence >= 0) {
+ close(acquireFence);
}
- });
- return releaseFence;
+ return data;
}
-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;
- }
+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);
- Buffer buffer = allocatorClient->allocate(descriptor);
- if (::testing::Test::HasFatalFailure()) {
- allocatorClient->destroyDescriptor(descriptor);
- return nullptr;
- }
+ 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;
+ }
- const native_handle_t* handle =
- allocatorClient->exportHandle(descriptor, buffer);
- if (handle) {
- retain(handle);
- }
+ 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;
+ });
- allocatorClient->free(buffer);
- allocatorClient->destroyDescriptor(descriptor);
+ if (acquireFence >= 0) {
+ close(acquireFence);
+ }
- return handle;
+ return layout;
+}
+
+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
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
index c186b00..757f20b 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
@@ -17,14 +17,12 @@
#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 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;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
-// A wrapper to IMapper.
-class Mapper {
- public:
- Mapper();
- ~Mapper();
+// A wrapper to IAllocator and IMapper.
+class Gralloc {
+ public:
+ Gralloc();
+ ~Gralloc();
- sp<IMapper> getRaw() const;
+ // IAllocator methods
- void retain(const native_handle_t* handle);
- void release(const native_handle_t* handle);
+ sp<IAllocator> getAllocator() const;
- struct Dimensions {
- uint32_t width;
- uint32_t height;
- };
- Dimensions getDimensions(const native_handle_t* handle);
+ std::string dumpDebugInfo();
- 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);
+ // 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);
- // 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);
+ // IMapper methods
- // 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);
+ sp<IMapper> getMapper() const;
- private:
- void init();
+ BufferDescriptor createDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo);
- sp<IMapper> mMapper;
+ const native_handle_t* importBuffer(const hidl_handle& rawHandle);
+ void freeBuffer(const native_handle_t* bufferHandle);
- // 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;
+ // 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
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index 92d74d5..f066a1e 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -14,10 +14,10 @@
* 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 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>());
+ ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
- 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);
+ 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));
- IAllocatorClient::BufferDescriptorInfo info = {};
+ 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));
- Mapper::Dimensions dimensions;
- ASSERT_NO_FATAL_FAILURE(dimensions = mMapper->getDimensions(buffer));
- info.width = dimensions.width;
- info.height = dimensions.height;
+ if (count >= 1) {
+ EXPECT_LE(mDummyDescriptorInfo.width, stride)
+ << "invalid buffer stride";
+ }
- 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));
+ for (auto bufferHandle : bufferHandles) {
+ mGralloc->freeBuffer(bufferHandle);
+ }
+ }
+}
- 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 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);
+ });
+}
- ASSERT_NO_FATAL_FAILURE(mMapper->getBackingStore(buffer));
+/**
+ * Test IAllocator::allocate does not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+ auto info = mDummyDescriptorInfo;
+ info.width = 1024;
+ info.height = 1024;
- uint32_t stride;
- ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
- EXPECT_LE(info.width, stride);
+ for (int i = 0; i < 2048; i++) {
+ auto bufferHandle = mGralloc->allocate(info, false);
+ mGralloc->freeBuffer(bufferHandle);
+ }
+}
+
+/**
+ * Test IMapper::createDescriptor with valid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+ ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
+}
+
+/**
+ * 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";
+ });
+}
+
+/**
+ * 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));
+}
+
+/**
+ * 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::importBuffer and IMapper::freeBuffer cross mapper instances.
+ */
+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));
+}
+
+/**
+ * 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);
+ }
+}
+
+/**
+ * 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);
+}
+
+/**
+ * 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);
}
/**
* Test IMapper::lock and IMapper::unlock.
*/
-TEST_F(GraphicsMapperHidlTest, LockBasic) {
- const auto& info = mDummyDescriptorInfo;
+TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+ const auto& info = mDummyDescriptorInfo;
- const native_handle_t* buffer;
- ASSERT_NO_FATAL_FAILURE(
- buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle =
+ mGralloc->allocate(info, true, &stride));
- uint32_t stride;
- ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
+ // 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)));
- // 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)));
+ // RGBA_8888
+ size_t strideInBytes = stride * 4;
+ size_t writeInBytes = info.width * 4;
- 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;
+ 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;
+TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+ auto info = mDummyDescriptorInfo;
+ info.format = PixelFormat::YV12;
- const native_handle_t* buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = mMapper->allocate(mAllocatorClient, info));
+ 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;
- 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());
+ // 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));
- 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);
+ 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);
- 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;
- }
+ 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));
+ ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
- // lock buffer for reading
- ASSERT_NO_FATAL_FAILURE(
- layout =
- mMapper->lockFlex(buffer, 0, info.consumerUsageMask, region, fence));
+ // lock again for reading
+ ASSERT_NO_FATAL_FAILURE(
+ layout = mGralloc->lockYCbCr(bufferHandle, info.usage, 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);
+ 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, 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]);
- }
+ 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);
+ }
}
-} // namespace anonymous
+/**
+ * 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
} // namespace tests
} // namespace V2_0
} // namespace mapper