Merge "graphics: rev IAllocator/IMapper to 4.0"

This commit is contained in:
TreeHugger Robot 2019-08-07 21:22:39 +00:00 committed by Android (Google) Code Review
commit b5f60c41d0
13 changed files with 1459 additions and 2 deletions

View file

@ -195,8 +195,8 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.graphics.allocator</name>
<version>2.0</version>
<version>3.0</version>
<version>4.0</version>
<interface>
<name>IAllocator</name>
<instance>default</instance>
@ -212,8 +212,8 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.graphics.mapper</name>
<version>2.1</version>
<version>3.0</version>
<version>4.0</version>
<interface>
<name>IMapper</name>
<instance>default</instance>

View file

@ -0,0 +1,20 @@
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "android.hardware.graphics.allocator@4.0",
root: "android.hardware",
vndk: {
enabled: true,
},
srcs: [
"IAllocator.hal",
],
interfaces: [
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@4.0",
"android.hidl.base@1.0",
],
gen_java: false,
}

View file

@ -0,0 +1,55 @@
/*
* Copyright 2019 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@4.0;
import android.hardware.graphics.mapper@4.0;
interface IAllocator {
/**
* Retrieves implementation-defined debug information, which will be
* displayed during, for example, `dumpsys SurfaceFlinger`.
*
* @return debugInfo is a string of debug information.
*/
dumpDebugInfo() generates (string debugInfo);
/**
* Allocates buffers with the properties specified by the descriptor.
*
* Allocations should be optimized for usage bits provided in the
* descriptor.
*
* @param descriptor Properties of the buffers to allocate. This must be
* obtained from IMapper::createDescriptor().
* @param count The number of buffers to allocate.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_DESCRIPTOR` if the descriptor is invalid.
* - `NO_RESOURCES` if the allocation cannot be fulfilled at this time.
* - `UNSUPPORTED` if any of the properties encoded in the descriptor
* are not supported.
* @return stride The number of pixels between two consecutive rows of
* an allocated buffer, when the concept of consecutive rows is defined.
* Otherwise, it has no meaning.
* @return buffers Array of raw handles to the allocated buffers.
*/
allocate(BufferDescriptor descriptor, uint32_t count)
generates (Error error,
uint32_t stride,
vec<handle> buffers);
};

View file

@ -0,0 +1,21 @@
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "android.hardware.graphics.mapper@4.0",
root: "android.hardware",
vndk: {
enabled: true,
support_system_process: true,
},
srcs: [
"types.hal",
"IMapper.hal",
],
interfaces: [
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
"android.hidl.base@1.0",
],
gen_java: false,
}

View file

@ -0,0 +1,304 @@
/*
* Copyright 2019 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.mapper@4.0;
import android.hardware.graphics.common@1.2::BufferUsage;
import android.hardware.graphics.common@1.2::PixelFormat;
import android.hardware.graphics.common@1.2::Rect;
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;
int32_t width;
int32_t height;
};
/**
* Creates a buffer descriptor. The descriptor can be used with IAllocator
* to allocate buffers.
*
* 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 `description.layers` is great than
* 1.
*
* @param description Attributes of the descriptor.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_VALUE` if any of the specified attributes are invalid or
* inconsistent.
* - `NO_RESOURCES` if the creation cannot be fullfilled due to
* unavailability of resources.
* - `UNSUPPORTED` when any of the specified attributes are not
* supported.
* @return descriptor Newly created buffer descriptor.
*/
createDescriptor(BufferDescriptorInfo description)
generates (Error error,
BufferDescriptor descriptor);
/**
* 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.
*
* A buffer handle is considered raw when it is cloned (e.g., with
* `native_handle_clone()`) from another buffer handle locally, or when it
* is received from another HAL server/client or another process. A raw
* buffer handle must not be used to access the underlying graphic
* buffer. It must be imported to create an imported handle first.
*
* 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.
*
* Because of passthrough HALs, a raw buffer handle received from a HAL
* may actually have been imported in the process. importBuffer() must treat
* such a handle as if it is raw and must not return `BAD_BUFFER`. The
* returned handle is independent from the input handle as usual, and
* freeBuffer() must be called on it when it is no longer needed.
*
* @param rawHandle Raw buffer handle to import.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_BUFFER` if the raw handle is invalid.
* - `NO_RESOURCES` if the raw handle cannot be imported due to
* unavailability of resources.
* @return buffer Imported buffer handle that has the type
* `buffer_handle_t` which is a handle type.
*/
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()`.
*
* @param buffer Imported buffer handle.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_BUFFER` if the buffer is invalid.
*/
freeBuffer(pointer buffer) generates (Error error);
/**
* Validates that the buffer can be safely accessed by a caller who assumes
* the specified @p description and @p stride. This must at least validate
* that the buffer size is large enough. Validating the buffer against
* individual buffer attributes is optional.
*
* @param buffer Buffer to validate against.
* @param description Attributes of the buffer.
* @param stride Stride returned by IAllocator::allocate().
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_BUFFER` if the buffer is invalid.
* - `BAD_VALUE` if the buffer cannot be safely accessed.
*/
validateBufferSize(pointer buffer,
BufferDescriptorInfo description,
uint32_t stride)
generates (Error error);
/**
* Calculates the transport size of a buffer. An imported buffer handle is a
* raw buffer handle with the process-local runtime data appended. This
* function, for example, allows a caller to omit the process-local runtime
* data at the tail when serializing the imported buffer handle.
*
* Note that a client might or might not omit the process-local runtime data
* when sending an imported buffer handle. The mapper must support both
* cases on the receiving end.
*
* @param buffer Buffer to get the transport size from.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_BUFFER` if the buffer is invalid.
* @return numFds The number of file descriptors needed for transport.
* @return numInts The number of integers needed for transport.
*/
getTransportSize(pointer buffer)
generates (Error error,
uint32_t numFds,
uint32_t numInts);
/**
* Locks the given buffer for the specified CPU usage.
*
* 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
* process termination or block the client indefinitely. Leaving the
* buffer content in an indeterminate state or returning an error are both
* acceptable.
*
* 1D buffers (width = size in bytes, height = 1, pixel_format = BLOB) must
* "lock in place". The buffers must be directly accessible via mapping.
*
* The client must not modify the content of the buffer outside of
* @p accessRegion, and the device need not guarantee that content outside
* of @p accessRegion is valid for reading. The result of reading or writing
* outside of @p accessRegion is undefined, except that it must not cause
* process termination.
*
* On success, @p data must be filled with a pointer to the locked buffer
* memory. This address will represent the top-left corner of the entire
* buffer, even if @p accessRegion does not begin at the top-left corner.
*
* On success, bytesPerPixel must contain the number of bytes per pixel in
* the buffer. If the bytesPerPixel is unknown or variable, a value of -1
* should be returned. bytesPerStride must contain the bytes per stride of
* the buffer. If the bytesPerStride is unknown or variable, a value of -1
* should be returned.
*
* @param buffer Buffer to lock.
* @param cpuUsage CPU usage flags to request. See +ndk
* libnativewindow#AHardwareBuffer_UsageFlags for possible values.
* @param accessRegion Portion of the buffer that the client intends to
* access.
* @param acquireFence 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. @p acquireFence may be an empty fence if
* it is already safe to lock.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_BUFFER` if the buffer is invalid or is incompatible with this
* function.
* - `BAD_VALUE` if @p cpuUsage is 0, contains non-CPU usage flags, or
* is incompatible with the buffer.
* - `NO_RESOURCES` if the buffer cannot be locked at this time. Note
* that locking may succeed at a later time.
* @return data CPU-accessible pointer to the buffer data.
* @return bytesPerPixel the number of bytes per pixel in the buffer
* @return bytesPerStride the number of bytes per stride of the buffer
*/
lock(pointer buffer,
uint64_t cpuUsage,
Rect accessRegion,
handle acquireFence)
generates (Error error,
pointer data,
int32_t bytesPerPixel,
int32_t bytesPerStride);
/**
* Locks a YCbCr buffer for the specified CPU usage.
*
* This is largely the same as lock(), except that instead of returning a
* pointer directly to the buffer data, it returns a `YCbCrLayout` struct
* describing how to access the data planes.
*
* This function must work on buffers with
* `AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_*` if supported by the device, as well
* as with any other formats requested by multimedia codecs when they are
* configured with a flexible-YUV-compatible color format.
*
* @param buffer Buffer to lock.
* @param cpuUsage CPU usage flags to request. See +ndk
* libnativewindow#AHardwareBuffer_UsageFlags for possible values.
* @param accessRegion Portion of the buffer that the client intends to
* access.
* @param acquireFence 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. @p acquireFence may be empty if it is
* already safe to lock.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_BUFFER` if the buffer is invalid or is incompatible with this
* function.
* - `BAD_VALUE` if @p cpuUsage is 0, contains non-CPU usage flags, or
* is incompatible with the buffer.
* - `NO_RESOURCES` if the buffer cannot be locked at this time. Note
* that locking may succeed at a later time.
* @return layout Data layout of the locked buffer.
*/
lockYCbCr(pointer buffer,
uint64_t cpuUsage,
Rect accessRegion,
handle acquireFence)
generates (Error error,
YCbCrLayout layout);
/**
* Unlocks a buffer to indicate all CPU accesses to the buffer have
* completed.
*
* @param buffer Buffer to unlock.
* @return error Error status of the call, which may be
* - `NONE` upon success.
* - `BAD_BUFFER` if the buffer is invalid or not locked.
* @return releaseFence 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. @p releaseFence may be an
* empty fence.
*/
unlock(pointer buffer) generates (Error error, handle releaseFence);
/**
* Test whether the given BufferDescriptorInfo is allocatable.
*
* If this function returns true, it means that a buffer with the given
* description can be allocated on this implementation, unless resource
* exhaustion occurs. If this function returns false, it means that the
* allocation of the given description will never succeed.
*
* @param description the description of the buffer
* @return supported whether the description is supported
*/
isSupported(BufferDescriptorInfo description)
generates (Error error,
bool supported);
};

View file

@ -0,0 +1,84 @@
/*
* Copyright 2019 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.mapper@4.0;
/**
* Error values that may be returned by a method of IAllocator or IMapper.
*/
enum Error : int32_t {
/**
* No error.
*/
NONE = 0,
/**
* Invalid BufferDescriptor.
*/
BAD_DESCRIPTOR = 1,
/**
* Invalid buffer handle.
*/
BAD_BUFFER = 2,
/**
* Invalid HardwareBufferDescription.
*/
BAD_VALUE = 3,
/**
* Resource unavailable.
*/
NO_RESOURCES = 5,
/**
* Permanent failure.
*/
UNSUPPORTED = 7,
};
/**
* 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;
/**
* 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;
};

View file

@ -0,0 +1,3 @@
# Graphics team
marissaw@google.com
stoza@google.com

View file

@ -0,0 +1,34 @@
//
// Copyright (C) 2019 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: "android.hardware.graphics.mapper@4.0-vts",
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["MapperVts.cpp"],
cflags: [
"-O0",
"-g",
],
static_libs: [
"android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.mapper@4.0",
],
export_static_lib_headers: [
"android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.mapper@4.0",
],
export_include_dirs: ["include"],
}

View file

@ -0,0 +1,304 @@
/*
* Copyright 2019 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 <mapper-vts/4.0/MapperVts.h>
#include <VtsHalHidlTargetTestBase.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V4_0 {
namespace vts {
Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
bool errOnFailure) {
if (errOnFailure) {
init(allocatorServiceName, mapperServiceName);
} else {
initNoErr(allocatorServiceName, mapperServiceName);
}
}
void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
}
void Gralloc::initNoErr(const std::string& allocatorServiceName,
const std::string& mapperServiceName) {
mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
if (mMapper.get()) {
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);
}
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<IAllocator> Gralloc::getAllocator() const {
return mAllocator;
}
std::string Gralloc::dumpDebugInfo() {
std::string debugInfo;
mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
return debugInfo;
}
const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
EXPECT_NE(nullptr, bufferHandle);
if (bufferHandle) {
mClonedBuffers.insert(bufferHandle);
}
return bufferHandle;
}
std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
uint32_t count, bool import,
uint32_t* outStride) {
std::vector<const native_handle_t*> bufferHandles;
bufferHandles.reserve(count);
mAllocator->allocate(descriptor, count,
[&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
for (uint32_t i = 0; i < count; i++) {
if (import) {
ASSERT_NO_FATAL_FAILURE(
bufferHandles.push_back(importBuffer(tmpBuffers[i])));
} else {
ASSERT_NO_FATAL_FAILURE(
bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
}
}
if (outStride) {
*outStride = tmpStride;
}
});
if (::testing::Test::HasFatalFailure()) {
bufferHandles.clear();
}
return bufferHandles;
}
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;
}
auto buffers = allocate(descriptor, 1, import, outStride);
if (::testing::Test::HasFatalFailure()) {
return nullptr;
}
return buffers[0];
}
sp<IMapper> Gralloc::getMapper() const {
return mMapper;
}
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 descriptor;
}
const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
const native_handle_t* bufferHandle = nullptr;
mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
ASSERT_EQ(Error::NONE, tmpError)
<< "failed to import buffer %p" << rawHandle.getNativeHandle();
bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
});
if (bufferHandle) {
mImportedBuffers.insert(bufferHandle);
}
return bufferHandle;
}
void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
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* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
int32_t* outBytesPerStride) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
hidl_handle acquireFenceHandle;
if (acquireFence >= 0) {
auto h = native_handle_init(acquireFenceStorage, 1, 0);
h->data[0] = acquireFence;
acquireFenceHandle = h;
}
*outBytesPerPixel = -1;
*outBytesPerStride = -1;
void* data = nullptr;
mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
[&](const auto& tmpError, const auto& tmpData, int32_t tmpBytesPerPixel,
int32_t tmpBytesPerStride) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
data = tmpData;
*outBytesPerPixel = tmpBytesPerPixel;
*outBytesPerStride = tmpBytesPerStride;
});
if (acquireFence >= 0) {
close(acquireFence);
}
return data;
}
YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
hidl_handle acquireFenceHandle;
if (acquireFence >= 0) {
auto h = native_handle_init(acquireFenceStorage, 1, 0);
h->data[0] = acquireFence;
acquireFenceHandle = h;
}
YCbCrLayout layout = {};
mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
[&](const auto& tmpError, const auto& tmpLayout) {
ASSERT_EQ(Error::NONE, tmpError)
<< "failed to lockYCbCr buffer " << buffer;
layout = tmpLayout;
});
if (acquireFence >= 0) {
close(acquireFence);
}
return 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;
}
bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle,
const IMapper::BufferDescriptorInfo& descriptorInfo,
uint32_t stride) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
return error == Error::NONE;
}
void Gralloc::getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
uint32_t* outNumInts) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
*outNumFds = 0;
*outNumInts = 0;
mMapper->getTransportSize(buffer, [&](const auto& tmpError, const auto& tmpNumFds,
const auto& tmpNumInts) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
*outNumFds = tmpNumFds;
*outNumInts = tmpNumInts;
});
}
bool Gralloc::isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) {
bool supported = false;
mMapper->isSupported(descriptorInfo, [&](const auto& tmpError, const auto& tmpSupported) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to check is supported";
supported = tmpSupported;
});
return supported;
}
} // namespace vts
} // namespace V4_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,105 @@
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <unordered_set>
#include <vector>
#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
#include <android/hardware/graphics/mapper/4.0/IMapper.h>
#include <utils/StrongPointer.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V4_0 {
namespace vts {
using android::hardware::graphics::allocator::V4_0::IAllocator;
// A wrapper to IAllocator and IMapper.
class Gralloc {
public:
Gralloc(const std::string& allocatorServiceName = "default",
const std::string& mapperServiceName = "default", bool errOnFailure = true);
~Gralloc();
// IAllocator methods
sp<IAllocator> getAllocator() const;
std::string dumpDebugInfo();
// When import is false, this simply calls IAllocator::allocate. When import
// is true, the returned buffers are also imported into the mapper.
//
// Either case, the returned buffers must be freed with freeBuffer.
std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor, uint32_t count,
bool import = true, uint32_t* outStride = nullptr);
const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
bool import = true, uint32_t* outStride = nullptr);
// IMapper methods
sp<IMapper> getMapper() const;
BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
const native_handle_t* importBuffer(const hidl_handle& rawHandle);
void freeBuffer(const native_handle_t* bufferHandle);
// We use fd instead of hidl_handle in these functions to pass fences
// in and out of the mapper. The ownership of the fd is always transferred
// with each of these functions.
void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
int32_t* outBytesPerStride);
YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence);
int unlock(const native_handle_t* bufferHandle);
bool validateBufferSize(const native_handle_t* bufferHandle,
const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
uint32_t* outNumInts);
bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo);
private:
void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
// initialize without checking for failure to get service
void initNoErr(const std::string& allocatorServiceName, const std::string& mapperServiceName);
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 vts
} // namespace V4_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,3 @@
# Graphics team
marissaw@google.com
stoza@google.com

View file

@ -0,0 +1,30 @@
//
// Copyright 2019 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_test {
name: "VtsHalGraphicsMapperV4_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalGraphicsMapperV4_0TargetTest.cpp"],
static_libs: [
"android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@4.0",
"android.hardware.graphics.mapper@4.0-vts",
],
test_suites: ["general-tests"],
}

View file

@ -0,0 +1,494 @@
/*
* Copyright 2019 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 "VtsHalGraphicsMapperV4_0TargetTest"
#include <chrono>
#include <thread>
#include <vector>
#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <mapper-vts/4.0/MapperVts.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V4_0 {
namespace vts {
namespace {
using android::hardware::graphics::common::V1_2::BufferUsage;
using android::hardware::graphics::common::V1_2::PixelFormat;
// Test environment for graphics.mapper.
class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
public:
// get the test environment singleton
static GraphicsMapperHidlEnvironment* Instance() {
static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
return instance;
}
virtual void registerTestServices() override {
registerTestService<IAllocator>();
registerTestService<IMapper>();
}
};
class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
protected:
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(
mGralloc = std::make_unique<Gralloc>(
GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
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<Gralloc> mGralloc;
IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
};
/**
* Test IAllocator::dumpDebugInfo by calling it.
*/
TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
mGralloc->dumpDebugInfo();
}
/**
* Test IAllocator::allocate with valid buffer descriptors.
*/
TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
BufferDescriptor descriptor;
ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
for (uint32_t count = 0; count < 5; count++) {
std::vector<const native_handle_t*> bufferHandles;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandles =
mGralloc->allocate(descriptor, count, false, &stride));
if (count >= 1) {
EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
}
for (auto bufferHandle : bufferHandles) {
mGralloc->freeBuffer(bufferHandle);
}
}
}
/**
* 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);
});
}
/**
* Test IAllocator::allocate does not leak.
*/
TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
auto info = mDummyDescriptorInfo;
info.width = 1024;
info.height = 1024;
for (int i = 0; i < 2048; i++) {
auto bufferHandle = mGralloc->allocate(info, false);
mGralloc->freeBuffer(bufferHandle);
}
}
/**
* Test that IAllocator::allocate is thread-safe.
*/
TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
BufferDescriptor descriptor;
ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
std::atomic<bool> timeUp(false);
std::atomic<uint64_t> allocationCount(0);
auto threadLoop = [&]() {
while (!timeUp) {
mGralloc->getAllocator()->allocate(
descriptor, 1,
[&](const auto&, const auto&, const auto&) { allocationCount++; });
}
};
std::vector<std::thread> threads;
for (int i = 0; i < 8; i++) {
threads.push_back(std::thread(threadLoop));
}
std::this_thread::sleep_for(std::chrono::seconds(3));
timeUp = true;
LOG(VERBOSE) << "Made " << allocationCount << " threaded allocations";
for (auto& thread : threads) {
thread.join();
}
}
/**
* 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>(
GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
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);
}
/**
* 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, LockUnlockBasic) {
const auto& info = mDummyDescriptorInfo;
const native_handle_t* bufferHandle;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
// lock buffer for writing
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
int fence = -1;
uint8_t* data;
int32_t bytesPerPixel = -1;
int32_t bytesPerStride = -1;
ASSERT_NO_FATAL_FAILURE(
data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence,
&bytesPerPixel, &bytesPerStride)));
// Valid return values are -1 for unsupported or the number bytes for supported which is >=0
EXPECT_GT(bytesPerPixel, -1);
EXPECT_GT(bytesPerStride, -1);
// RGBA_8888
size_t strideInBytes = stride * 4;
size_t writeInBytes = info.width * 4;
for (uint32_t y = 0; y < info.height; y++) {
memset(data, y, writeInBytes);
data += strideInBytes;
}
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
bytesPerPixel = -1;
bytesPerStride = -1;
// lock again for reading
ASSERT_NO_FATAL_FAILURE(
data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence,
&bytesPerPixel, &bytesPerStride)));
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;
}
EXPECT_GT(bytesPerPixel, -1);
EXPECT_GT(bytesPerStride, -1);
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
if (fence >= 0) {
close(fence);
}
}
/**
* Test IMapper::lockYCbCr. This locks a YV12 buffer, and makes sure we can
* write to and read from it.
*/
TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YV12;
const native_handle_t* bufferHandle;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
// lock buffer for writing
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
int fence = -1;
YCbCrLayout layout;
ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
auto yData = static_cast<uint8_t*>(layout.y);
auto cbData = static_cast<uint8_t*>(layout.cb);
auto crData = static_cast<uint8_t*>(layout.cr);
for (uint32_t y = 0; y < info.height; y++) {
for (uint32_t x = 0; x < info.width; x++) {
auto val = static_cast<uint8_t>(info.height * y + x);
yData[layout.yStride * y + x] = val;
if (y % 2 == 0 && x % 2 == 0) {
cbData[layout.cStride * y / 2 + x / 2] = val;
crData[layout.cStride * y / 2 + x / 2] = val;
}
}
}
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
// lock again for reading
ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
yData = static_cast<uint8_t*>(layout.y);
cbData = static_cast<uint8_t*>(layout.cb);
crData = static_cast<uint8_t*>(layout.cr);
for (uint32_t y = 0; y < info.height; y++) {
for (uint32_t x = 0; x < info.width; x++) {
auto val = static_cast<uint8_t>(info.height * y + x);
EXPECT_EQ(val, yData[layout.yStride * y + x]);
if (y % 2 == 0 && x % 2 == 0) {
EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
}
}
}
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
if (fence >= 0) {
close(fence);
}
}
/**
* Test IMapper::unlock with invalid buffers.
*/
TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
native_handle_t* invalidHandle = nullptr;
mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with nullptr did not fail with BAD_BUFFER";
});
invalidHandle = native_handle_create(0, 0);
mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with invalid handle did not fail with BAD_BUFFER";
});
native_handle_delete(invalidHandle);
ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
mGralloc->allocate(mDummyDescriptorInfo, false)));
mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with un-imported handle did not fail with BAD_BUFFER";
});
mGralloc->freeBuffer(invalidHandle);
// disabled as it fails on many existing drivers
#if 0
ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
mGralloc->allocate(mDummyDescriptorInfo, true)));
mGralloc->getMapper()->unlock(
invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with unlocked handle did not fail with BAD_BUFFER";
});
mGralloc->freeBuffer(invalidHandle);
#endif
}
/**
* Test IMapper::isSupported with required format RGBA_8888
*/
TEST_F(GraphicsMapperHidlTest, IsSupportedRGBA8888) {
const auto& info = mDummyDescriptorInfo;
bool supported = false;
ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
ASSERT_TRUE(supported);
}
/**
* Test IMapper::isSupported with required format YV12
*/
TEST_F(GraphicsMapperHidlTest, IsSupportedYV12) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YV12;
bool supported = false;
ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
ASSERT_TRUE(supported);
}
/**
* Test IMapper::isSupported with optional format Y16
*/
TEST_F(GraphicsMapperHidlTest, IsSupportedY16) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::Y16;
bool supported = false;
ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
}
} // namespace
} // namespace vts
} // namespace V4_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android
int main(int argc, char** argv) {
using android::hardware::graphics::mapper::V4_0::vts::GraphicsMapperHidlEnvironment;
::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
int status = RUN_ALL_TESTS();
LOG(INFO) << "Test result = " << status;
return status;
}