diff options
author | 2016-05-20 12:14:37 -0700 | |
---|---|---|
committer | 2016-06-13 13:29:24 -0700 | |
commit | 41b1261e233e78553ad4e3a11dda80b1c5df07c5 (patch) | |
tree | 49d34d1505f0e666d5a8e75eb957626eb8344d1c | |
parent | 1e2a2a0ee81401072d9fc0f842c7ec1a915c5a07 (diff) |
libui: Adds C++ shim for gralloc1
Adds a C++ shim which wraps a gralloc1 device and provides a somewhat
nicer interface to the rest of the system.
Bug: 28401203
Change-Id: I934ed41999bd4b9aa04d9ad8d40e7f8fba6f30ee
-rw-r--r-- | include/ui/Gralloc1.h | 238 | ||||
-rw-r--r-- | libs/ui/Android.mk | 1 | ||||
-rw-r--r-- | libs/ui/Gralloc1.cpp | 402 |
3 files changed, 641 insertions, 0 deletions
diff --git a/include/ui/Gralloc1.h b/include/ui/Gralloc1.h new file mode 100644 index 0000000000..cf8c173eee --- /dev/null +++ b/include/ui/Gralloc1.h @@ -0,0 +1,238 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UI_GRALLOC1_H +#define ANDROID_UI_GRALLOC1_H + +#define GRALLOC1_LOG_TAG "Gralloc1" + +#include <ui/Gralloc1On0Adapter.h> + +#include <unordered_set> + +namespace std { + template <> + struct hash<gralloc1_capability_t> { + size_t operator()(gralloc1_capability_t capability) const { + return std::hash<int32_t>()(static_cast<int32_t>(capability)); + } + }; +} + +namespace android { + +class Fence; +class GraphicBuffer; + +namespace Gralloc1 { + +class Device; + +class Descriptor { +public: + Descriptor(Device& device, gralloc1_buffer_descriptor_t deviceId) + : mShimDevice(device), + mDeviceId(deviceId), + mWidth(0), + mHeight(0), + mFormat(static_cast<android_pixel_format_t>(0)), + mProducerUsage(GRALLOC1_PRODUCER_USAGE_NONE), + mConsumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {} + + ~Descriptor(); + + gralloc1_buffer_descriptor_t getDeviceId() const { return mDeviceId; } + + gralloc1_error_t setDimensions(uint32_t width, uint32_t height); + gralloc1_error_t setFormat(android_pixel_format_t format); + gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage); + gralloc1_error_t setConsumerUsage(gralloc1_consumer_usage_t usage); + +private: + Device& mShimDevice; + const gralloc1_buffer_descriptor_t mDeviceId; + + uint32_t mWidth; + uint32_t mHeight; + android_pixel_format_t mFormat; + gralloc1_producer_usage_t mProducerUsage; + gralloc1_consumer_usage_t mConsumerUsage; + +}; // Descriptor + +class Device { + friend class Gralloc1::Descriptor; + +public: + Device(gralloc1_device_t* device); + + bool hasCapability(gralloc1_capability_t capability) const; + + std::string dump(); + + std::shared_ptr<Descriptor> createDescriptor(); + + gralloc1_error_t getStride(buffer_handle_t buffer, uint32_t* outStride); + + gralloc1_error_t allocate( + const std::vector<std::shared_ptr<const Descriptor>>& descriptors, + std::vector<buffer_handle_t>* outBuffers); + gralloc1_error_t allocate( + const std::shared_ptr<const Descriptor>& descriptor, + gralloc1_backing_store_t id, buffer_handle_t* outBuffer); + + gralloc1_error_t retain(buffer_handle_t buffer); + gralloc1_error_t retain(const GraphicBuffer* buffer); + + gralloc1_error_t release(buffer_handle_t buffer); + + gralloc1_error_t getNumFlexPlanes(buffer_handle_t buffer, + uint32_t* outNumPlanes); + + gralloc1_error_t lock(buffer_handle_t buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t* accessRegion, void** outData, + const sp<Fence>& acquireFence); + gralloc1_error_t lockFlex(buffer_handle_t buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t* accessRegion, + struct android_flex_layout* outData, const sp<Fence>& acquireFence); + gralloc1_error_t lockYCbCr(buffer_handle_t buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t* accessRegion, struct android_ycbcr* outData, + const sp<Fence>& acquireFence); + + gralloc1_error_t unlock(buffer_handle_t buffer, sp<Fence>* outFence); + +private: + std::unordered_set<gralloc1_capability_t> loadCapabilities(); + + bool loadFunctions(); + + template <typename LockType, typename OutType> + gralloc1_error_t lockHelper(LockType pfn, buffer_handle_t buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t* accessRegion, OutType* outData, + const sp<Fence>& acquireFence) { + int32_t intError = pfn(mDevice, buffer, + static_cast<uint64_t>(producerUsage), + static_cast<uint64_t>(consumerUsage), accessRegion, outData, + acquireFence->dup()); + return static_cast<gralloc1_error_t>(intError); + } + + gralloc1_device_t* const mDevice; + + const std::unordered_set<gralloc1_capability_t> mCapabilities; + + template <typename PFN, gralloc1_function_descriptor_t descriptor> + struct FunctionLoader { + FunctionLoader() : pfn(nullptr) {} + + bool load(gralloc1_device_t* device, bool errorIfNull) { + gralloc1_function_pointer_t rawPointer = + device->getFunction(device, descriptor); + pfn = reinterpret_cast<PFN>(rawPointer); + if (errorIfNull && !rawPointer) { + ALOG(LOG_ERROR, GRALLOC1_LOG_TAG, + "Failed to load function pointer %d", descriptor); + } + return rawPointer != nullptr; + } + + template <typename ...Args> + typename std::result_of<PFN(Args...)>::type operator()(Args... args) { + return pfn(args...); + } + + PFN pfn; + }; + + // Function pointers + struct Functions { + FunctionLoader<GRALLOC1_PFN_DUMP, GRALLOC1_FUNCTION_DUMP> dump; + FunctionLoader<GRALLOC1_PFN_CREATE_DESCRIPTOR, + GRALLOC1_FUNCTION_CREATE_DESCRIPTOR> createDescriptor; + FunctionLoader<GRALLOC1_PFN_DESTROY_DESCRIPTOR, + GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR> destroyDescriptor; + FunctionLoader<GRALLOC1_PFN_SET_CONSUMER_USAGE, + GRALLOC1_FUNCTION_SET_CONSUMER_USAGE> setConsumerUsage; + FunctionLoader<GRALLOC1_PFN_SET_DIMENSIONS, + GRALLOC1_FUNCTION_SET_DIMENSIONS> setDimensions; + FunctionLoader<GRALLOC1_PFN_SET_FORMAT, + GRALLOC1_FUNCTION_SET_FORMAT> setFormat; + FunctionLoader<GRALLOC1_PFN_SET_PRODUCER_USAGE, + GRALLOC1_FUNCTION_SET_PRODUCER_USAGE> setProducerUsage; + FunctionLoader<GRALLOC1_PFN_GET_BACKING_STORE, + GRALLOC1_FUNCTION_GET_BACKING_STORE> getBackingStore; + FunctionLoader<GRALLOC1_PFN_GET_CONSUMER_USAGE, + GRALLOC1_FUNCTION_GET_CONSUMER_USAGE> getConsumerUsage; + FunctionLoader<GRALLOC1_PFN_GET_DIMENSIONS, + GRALLOC1_FUNCTION_GET_DIMENSIONS> getDimensions; + FunctionLoader<GRALLOC1_PFN_GET_FORMAT, + GRALLOC1_FUNCTION_GET_FORMAT> getFormat; + FunctionLoader<GRALLOC1_PFN_GET_PRODUCER_USAGE, + GRALLOC1_FUNCTION_GET_PRODUCER_USAGE> getProducerUsage; + FunctionLoader<GRALLOC1_PFN_GET_STRIDE, + GRALLOC1_FUNCTION_GET_STRIDE> getStride; + FunctionLoader<GRALLOC1_PFN_ALLOCATE, + GRALLOC1_FUNCTION_ALLOCATE> allocate; + FunctionLoader<GRALLOC1_PFN_RETAIN, + GRALLOC1_FUNCTION_RETAIN> retain; + FunctionLoader<GRALLOC1_PFN_RELEASE, + GRALLOC1_FUNCTION_RELEASE> release; + FunctionLoader<GRALLOC1_PFN_GET_NUM_FLEX_PLANES, + GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES> getNumFlexPlanes; + FunctionLoader<GRALLOC1_PFN_LOCK, + GRALLOC1_FUNCTION_LOCK> lock; + FunctionLoader<GRALLOC1_PFN_LOCK_FLEX, + GRALLOC1_FUNCTION_LOCK_FLEX> lockFlex; + FunctionLoader<GRALLOC1_PFN_LOCK_YCBCR, + GRALLOC1_FUNCTION_LOCK_YCBCR> lockYCbCr; + FunctionLoader<GRALLOC1_PFN_UNLOCK, + GRALLOC1_FUNCTION_UNLOCK> unlock; + + // Adapter-only functions + FunctionLoader<GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER, + GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER> retainGraphicBuffer; + FunctionLoader<GRALLOC1_PFN_ALLOCATE_WITH_ID, + GRALLOC1_FUNCTION_ALLOCATE_WITH_ID> allocateWithId; + } mFunctions; + +}; // class android::Gralloc1::Device + +class Loader +{ +public: + Loader(); + ~Loader(); + + std::unique_ptr<Device> getDevice(); + +private: + static std::unique_ptr<Gralloc1On0Adapter> mAdapter; + std::unique_ptr<Device> mDevice; +}; + +} // namespace android::Gralloc1 + +} // namespace android + +#endif diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index 85ad36d5b8..e690ede195 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -37,6 +37,7 @@ LOCAL_CPPFLAGS += -Wno-padded LOCAL_SRC_FILES := \ Fence.cpp \ FrameStats.cpp \ + Gralloc1.cpp \ Gralloc1On0Adapter.cpp \ GraphicBuffer.cpp \ GraphicBufferAllocator.cpp \ diff --git a/libs/ui/Gralloc1.cpp b/libs/ui/Gralloc1.cpp new file mode 100644 index 0000000000..4c73ce4535 --- /dev/null +++ b/libs/ui/Gralloc1.cpp @@ -0,0 +1,402 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 + +#include <ui/Gralloc1.h> + +#include <vector> + +#undef LOG_TAG +#define LOG_TAG GRALLOC1_LOG_TAG + +namespace android { + +namespace Gralloc1 { + +Descriptor::~Descriptor() +{ + int32_t intError = mShimDevice.mFunctions.destroyDescriptor( + mShimDevice.mDevice, mDeviceId); + auto error = static_cast<gralloc1_error_t>(intError); + if (error != GRALLOC1_ERROR_NONE) { + ALOGE("destroyDescriptor failed: %d", intError); + } +} + +gralloc1_error_t Descriptor::setDimensions(uint32_t width, uint32_t height) +{ + int32_t intError = mShimDevice.mFunctions.setDimensions(mShimDevice.mDevice, + mDeviceId, width, height); + auto error = static_cast<gralloc1_error_t>(intError); + if (error != GRALLOC1_ERROR_NONE) { + return error; + } + mWidth = width; + mHeight = height; + return error; +} + +template <typename ApiType> +struct Setter { + typedef int32_t (*Type)(gralloc1_device_t*, gralloc1_buffer_descriptor_t, + ApiType); +}; + +template <typename ApiType, typename ValueType> +static inline gralloc1_error_t setHelper( + typename Setter<ApiType>::Type setter, gralloc1_device_t* device, + gralloc1_buffer_descriptor_t id, ValueType newValue, + ValueType* cacheVariable) +{ + int32_t intError = setter(device, id, static_cast<ApiType>(newValue)); + auto error = static_cast<gralloc1_error_t>(intError); + if (error != GRALLOC1_ERROR_NONE) { + return error; + } + *cacheVariable = newValue; + return error; +} + +gralloc1_error_t Descriptor::setFormat(android_pixel_format_t format) +{ + return setHelper<int32_t>(mShimDevice.mFunctions.setFormat.pfn, + mShimDevice.mDevice, mDeviceId, format, &mFormat); +} + +gralloc1_error_t Descriptor::setProducerUsage(gralloc1_producer_usage_t usage) +{ + return setHelper<uint64_t>(mShimDevice.mFunctions.setProducerUsage.pfn, + mShimDevice.mDevice, mDeviceId, usage, &mProducerUsage); +} + +gralloc1_error_t Descriptor::setConsumerUsage(gralloc1_consumer_usage_t usage) +{ + return setHelper<uint64_t>(mShimDevice.mFunctions.setConsumerUsage.pfn, + mShimDevice.mDevice, mDeviceId, usage, &mConsumerUsage); +} + +Device::Device(gralloc1_device_t* device) + : mDevice(device), + mCapabilities(loadCapabilities()), + mFunctions() +{ + if (!loadFunctions()) { + ALOGE("Failed to load a required function, aborting"); + abort(); + } +} + +bool Device::hasCapability(gralloc1_capability_t capability) const +{ + return mCapabilities.count(capability) > 0; +} + +std::string Device::dump() +{ + uint32_t length = 0; + mFunctions.dump(mDevice, &length, nullptr); + + std::vector<char> output; + output.resize(length); + mFunctions.dump(mDevice, &length, output.data()); + + return std::string(output.cbegin(), output.cend()); +} + +std::shared_ptr<Descriptor> Device::createDescriptor() +{ + gralloc1_buffer_descriptor_t descriptorId; + int32_t intError = mFunctions.createDescriptor(mDevice, &descriptorId); + auto error = static_cast<gralloc1_error_t>(intError); + if (error != GRALLOC1_ERROR_NONE) { + return nullptr; + } + auto descriptor = std::make_shared<Descriptor>(*this, descriptorId); + return descriptor; +} + +gralloc1_error_t Device::getStride(buffer_handle_t buffer, uint32_t* outStride) +{ + int32_t intError = mFunctions.getStride(mDevice, buffer, outStride); + return static_cast<gralloc1_error_t>(intError); +} + +static inline bool allocationSucceded(gralloc1_error_t error) +{ + return error == GRALLOC1_ERROR_NONE || error == GRALLOC1_ERROR_NOT_SHARED; +} + +gralloc1_error_t Device::allocate( + const std::vector<std::shared_ptr<const Descriptor>>& descriptors, + std::vector<buffer_handle_t>* outBuffers) +{ + if (mFunctions.allocate.pfn == nullptr) { + // Allocation is not supported on this device + return GRALLOC1_ERROR_UNSUPPORTED; + } + + std::vector<gralloc1_buffer_descriptor_t> deviceIds; + for (const auto& descriptor : descriptors) { + deviceIds.emplace_back(descriptor->getDeviceId()); + } + + std::vector<buffer_handle_t> buffers(descriptors.size()); + int32_t intError = mFunctions.allocate(mDevice, + static_cast<uint32_t>(descriptors.size()), deviceIds.data(), + buffers.data()); + auto error = static_cast<gralloc1_error_t>(intError); + if (allocationSucceded(error)) { + *outBuffers = std::move(buffers); + } + + return error; +} + +gralloc1_error_t Device::allocate( + const std::shared_ptr<const Descriptor>& descriptor, + gralloc1_backing_store_t id, buffer_handle_t* outBuffer) +{ + gralloc1_error_t error = GRALLOC1_ERROR_NONE; + + if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { + buffer_handle_t buffer = nullptr; + int32_t intError = mFunctions.allocateWithId(mDevice, + descriptor->getDeviceId(), id, &buffer); + error = static_cast<gralloc1_error_t>(intError); + if (allocationSucceded(error)) { + *outBuffer = buffer; + } + } else { + std::vector<std::shared_ptr<const Descriptor>> descriptors; + descriptors.emplace_back(descriptor); + std::vector<buffer_handle_t> buffers; + error = allocate(descriptors, &buffers); + if (allocationSucceded(error)) { + *outBuffer = buffers[0]; + } + } + + return error; +} + +gralloc1_error_t Device::retain(buffer_handle_t buffer) +{ + int32_t intError = mFunctions.retain(mDevice, buffer); + return static_cast<gralloc1_error_t>(intError); +} + +gralloc1_error_t Device::retain(const GraphicBuffer* buffer) +{ + if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { + return mFunctions.retainGraphicBuffer(mDevice, buffer); + } else { + return retain(buffer->getNativeBuffer()->handle); + } +} + +gralloc1_error_t Device::release(buffer_handle_t buffer) +{ + int32_t intError = mFunctions.release(mDevice, buffer); + return static_cast<gralloc1_error_t>(intError); +} + +gralloc1_error_t Device::getNumFlexPlanes(buffer_handle_t buffer, + uint32_t* outNumPlanes) +{ + uint32_t numPlanes = 0; + int32_t intError = mFunctions.getNumFlexPlanes(mDevice, buffer, &numPlanes); + auto error = static_cast<gralloc1_error_t>(intError); + if (error == GRALLOC1_ERROR_NONE) { + *outNumPlanes = numPlanes; + } + return error; +} + +gralloc1_error_t Device::lock(buffer_handle_t buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t* accessRegion, void** outData, + const sp<Fence>& acquireFence) +{ + ALOGV("Calling lock(%p)", buffer); + return lockHelper(mFunctions.lock.pfn, buffer, producerUsage, + consumerUsage, accessRegion, outData, acquireFence); +} + +gralloc1_error_t Device::lockFlex(buffer_handle_t buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t* accessRegion, + struct android_flex_layout* outData, + const sp<Fence>& acquireFence) +{ + ALOGV("Calling lockFlex(%p)", buffer); + return lockHelper(mFunctions.lockFlex.pfn, buffer, producerUsage, + consumerUsage, accessRegion, outData, acquireFence); +} + +gralloc1_error_t Device::lockYCbCr(buffer_handle_t buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t* accessRegion, + struct android_ycbcr* outData, + const sp<Fence>& acquireFence) +{ + ALOGV("Calling lockYCbCr(%p)", buffer); + return lockHelper(mFunctions.lockYCbCr.pfn, buffer, producerUsage, + consumerUsage, accessRegion, outData, acquireFence); +} + +gralloc1_error_t Device::unlock(buffer_handle_t buffer, sp<Fence>* outFence) +{ + int32_t fenceFd = -1; + int32_t intError = mFunctions.unlock(mDevice, buffer, &fenceFd); + auto error = static_cast<gralloc1_error_t>(intError); + if (error == GRALLOC1_ERROR_NONE) { + *outFence = new Fence(fenceFd); + } + return error; +} + +std::unordered_set<gralloc1_capability_t> Device::loadCapabilities() +{ + std::vector<int32_t> intCapabilities; + uint32_t numCapabilities = 0; + mDevice->getCapabilities(mDevice, &numCapabilities, nullptr); + + intCapabilities.resize(numCapabilities); + mDevice->getCapabilities(mDevice, &numCapabilities, intCapabilities.data()); + + std::unordered_set<gralloc1_capability_t> capabilities; + for (const auto intCapability : intCapabilities) { + capabilities.emplace(static_cast<gralloc1_capability_t>(intCapability)); + } + return capabilities; +} + +bool Device::loadFunctions() +{ + // Functions which must always be present + if (!mFunctions.dump.load(mDevice, true)) { + return false; + } + if (!mFunctions.createDescriptor.load(mDevice, true)) { + return false; + } + if (!mFunctions.destroyDescriptor.load(mDevice, true)) { + return false; + } + if (!mFunctions.setConsumerUsage.load(mDevice, true)) { + return false; + } + if (!mFunctions.setDimensions.load(mDevice, true)) { + return false; + } + if (!mFunctions.setFormat.load(mDevice, true)) { + return false; + } + if (!mFunctions.setProducerUsage.load(mDevice, true)) { + return false; + } + if (!mFunctions.getBackingStore.load(mDevice, true)) { + return false; + } + if (!mFunctions.getConsumerUsage.load(mDevice, true)) { + return false; + } + if (!mFunctions.getDimensions.load(mDevice, true)) { + return false; + } + if (!mFunctions.getFormat.load(mDevice, true)) { + return false; + } + if (!mFunctions.getProducerUsage.load(mDevice, true)) { + return false; + } + if (!mFunctions.getStride.load(mDevice, true)) { + return false; + } + if (!mFunctions.retain.load(mDevice, true)) { + return false; + } + if (!mFunctions.release.load(mDevice, true)) { + return false; + } + if (!mFunctions.getNumFlexPlanes.load(mDevice, true)) { + return false; + } + if (!mFunctions.lock.load(mDevice, true)) { + return false; + } + if (!mFunctions.lockFlex.load(mDevice, true)) { + return false; + } + if (!mFunctions.unlock.load(mDevice, true)) { + return false; + } + + if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { + // These should always be present on the adapter + if (!mFunctions.retainGraphicBuffer.load(mDevice, true)) { + return false; + } + if (!mFunctions.lockYCbCr.load(mDevice, true)) { + return false; + } + + // allocateWithId may not be present if we're only able to map in this + // process + mFunctions.allocateWithId.load(mDevice, false); + } else { + // allocate may not be present if we're only able to map in this process + mFunctions.allocate.load(mDevice, false); + } + + return true; +} + +std::unique_ptr<Gralloc1On0Adapter> Loader::mAdapter = nullptr; + +Loader::Loader() + : mDevice(nullptr) +{ + hw_module_t const* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + uint8_t majorVersion = (module->module_api_version >> 8) & 0xFF; + uint8_t minorVersion = module->module_api_version & 0xFF; + gralloc1_device_t* device = nullptr; + if (majorVersion == 1) { + gralloc1_open(module, &device); + } else { + if (!mAdapter) { + mAdapter = std::make_unique<Gralloc1On0Adapter>(module); + } + device = mAdapter->getDevice(); + } + mDevice = std::make_unique<Gralloc1::Device>(device); +} + +Loader::~Loader() {} + +std::unique_ptr<Device> Loader::getDevice() +{ + return std::move(mDevice); +} + +} // namespace android::Gralloc1 + +} // namespace android |