Merge "graphics: rev IAllocator/IMapper to 4.0"
This commit is contained in:
commit
b5f60c41d0
13 changed files with 1459 additions and 2 deletions
|
@ -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>
|
||||
|
|
20
graphics/allocator/4.0/Android.bp
Normal file
20
graphics/allocator/4.0/Android.bp
Normal 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,
|
||||
}
|
55
graphics/allocator/4.0/IAllocator.hal
Normal file
55
graphics/allocator/4.0/IAllocator.hal
Normal 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);
|
||||
};
|
||||
|
21
graphics/mapper/4.0/Android.bp
Normal file
21
graphics/mapper/4.0/Android.bp
Normal 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,
|
||||
}
|
304
graphics/mapper/4.0/IMapper.hal
Normal file
304
graphics/mapper/4.0/IMapper.hal
Normal 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);
|
||||
|
||||
};
|
||||
|
84
graphics/mapper/4.0/types.hal
Normal file
84
graphics/mapper/4.0/types.hal
Normal 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;
|
||||
};
|
3
graphics/mapper/4.0/utils/OWNERS
Normal file
3
graphics/mapper/4.0/utils/OWNERS
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Graphics team
|
||||
marissaw@google.com
|
||||
stoza@google.com
|
34
graphics/mapper/4.0/utils/vts/Android.bp
Normal file
34
graphics/mapper/4.0/utils/vts/Android.bp
Normal 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"],
|
||||
}
|
304
graphics/mapper/4.0/utils/vts/MapperVts.cpp
Normal file
304
graphics/mapper/4.0/utils/vts/MapperVts.cpp
Normal 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
|
105
graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
Normal file
105
graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
Normal 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
|
3
graphics/mapper/4.0/vts/OWNERS
Normal file
3
graphics/mapper/4.0/vts/OWNERS
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Graphics team
|
||||
marissaw@google.com
|
||||
stoza@google.com
|
30
graphics/mapper/4.0/vts/functional/Android.bp
Normal file
30
graphics/mapper/4.0/vts/functional/Android.bp
Normal 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"],
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue