Skip to content

Instantly share code, notes, and snippets.

@Luiz-Monad
Last active May 15, 2021 14:08
Show Gist options
  • Save Luiz-Monad/979f9182b7874fc671f20d733b96157b to your computer and use it in GitHub Desktop.
Save Luiz-Monad/979f9182b7874fc671f20d733b96157b to your computer and use it in GitHub Desktop.
android hack to get buffers from gralloc
@@ -1,175 +0,0 @@
#include "GraphicBuffer.h"
#include <string>
#include <cstdlib>
#include <iostream>
#include <iostream>
#include <dlfcn.h>
const int GRAPHICBUFFER_SIZE = 1024;
using std::string;
DynamicLibrary::DynamicLibrary(const char *fileName)
{
libHandle = dlopen(fileName, RTLD_LAZY);
if (!libHandle) throw OpenLibFailedException();
}
DynamicLibrary::~DynamicLibrary()
{
if (libHandle) dlclose(libHandle);
}
void *DynamicLibrary::getFunctionPtr(const char *name) const
{
auto ret = (void *)dlsym(libHandle, name);
if (ret == nullptr) {
std::cerr << "Failed to get function " << name << std::endl;
}
return ret;
}
template<typename Func>
void setFuncPtr(Func *&funcPtr, const DynamicLibrary &lib, const string &symname) {
funcPtr = reinterpret_cast<Func *>(lib.getFunctionPtr(symname.c_str()));
}
#if defined(__aarch64__)
# define CPU_ARM_64
#elif defined(__arm__) || defined(__ARM__) || defined(__ARM_NEON__) || defined(ARM_BUILD)
# define CPU_ARM
#elif defined(_M_X64) || defined(__x86_64__) || defined(__amd64__)
# define CPU_X86_64
#elif defined(__i386__) || defined(_M_X86) || defined(_M_IX86) || defined(X86_BUILD)
# define CPU_X86
#else
# warning "target CPU does not support ABI"
#endif
template<typename RT, typename T1, typename T2, typename T3, typename T4>
RT *callConstructor4(void (*fptr)(), void *memory, T1 param1, T2 param2, T3 param3, T4 param4) {
#if defined(CPU_ARM)
// C1 constructors return pointer
typedef RT* (*ABIFptr)(void*, T1, T2, T3, T4);
(void)((ABIFptr)fptr)(memory, param1, param2, param3, param4);
return reinterpret_cast<RT*>(memory);
#elif defined(CPU_ARM_64)
// C1 constructors return void
typedef void (*ABIFptr)(void*, T1, T2, T3, T4);
((ABIFptr)fptr)(memory, param1, param2, param3, param4);
return reinterpret_cast<RT*>(memory);
#elif defined(CPU_X86) || defined(CPU_X86_64)
// ctor returns void
typedef void (*ABIFptr)(void *, T1, T2, T3, T4);
((ABIFptr) fptr)(memory, param1, param2, param3, param4);
return reinterpret_cast<RT *>(memory);
#else
return nullptr;
#endif
}
template<typename T>
void callDestructor(void (*fptr)(), T *obj) {
#if defined(CPU_ARM)
// D1 destructor returns ptr
typedef void* (*ABIFptr)(T* obj);
(void)((ABIFptr)fptr)(obj);
#elif defined(CPU_ARM_64)
// D1 destructor returns void
typedef void (*ABIFptr)(T* obj);
((ABIFptr)fptr)(obj);
#elif defined(CPU_X86) || defined(CPU_X86_64)
// dtor returns void
typedef void (*ABIFptr)(T *obj);
((ABIFptr) fptr)(obj);
#endif
}
template<typename T1, typename T2>
T1 *pointerToOffset(T2 *ptr, size_t bytes) {
return reinterpret_cast<T1 *>((uint8_t *) ptr + bytes);
}
static android::android_native_base_t *getAndroidNativeBase(android::GraphicBuffer *gb) {
return pointerToOffset<android::android_native_base_t>(gb, 2 * sizeof(void *));
}
GraphicBuffer::GraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) :
library("libui.so") {
setFuncPtr(functions.constructor, library, "_ZN7android13GraphicBufferC1Ejjij");
setFuncPtr(functions.destructor, library, "_ZN7android13GraphicBufferD1Ev");
setFuncPtr(functions.getNativeBuffer, library,
"_ZNK7android13GraphicBuffer15getNativeBufferEv");
setFuncPtr(functions.lock, library, "_ZN7android13GraphicBuffer4lockEjPPv");
setFuncPtr(functions.unlock, library, "_ZN7android13GraphicBuffer6unlockEv");
setFuncPtr(functions.initCheck, library, "_ZNK7android13GraphicBuffer9initCheckEv");
// allocate memory for GraphicBuffer object
void *const memory = malloc(GRAPHICBUFFER_SIZE);
if (memory == nullptr) {
std::cerr << "Could not alloc for GraphicBuffer" << std::endl;
return;
}
try {
android::GraphicBuffer *const gb =
callConstructor4<android::GraphicBuffer, uint32_t, uint32_t, PixelFormat, uint32_t>(
functions.constructor,
memory,
width,
height,
format,
usage
);
android::android_native_base_t *const base = getAndroidNativeBase(gb);
status_t ctorStatus = functions.initCheck(gb);
if (ctorStatus) {
// ctor failed
callDestructor<android::GraphicBuffer>(functions.destructor, gb);
std::cerr << "GraphicBuffer ctor failed, initCheck returned " << ctorStatus <<
std::endl;
}
// check object layout
if (base->magic != 0x5f626672u) // "_bfr"
std::cerr << "GraphicBuffer layout unexpected" << std::endl;
// check object version
const uint32_t expectedVersion = sizeof(void *) == 4 ? 96 : 168;
if (base->version != expectedVersion)
std::cerr << "GraphicBuffer version unexpected" << std::endl;
base->incRef(base);
impl = gb;
} catch (...) {
free(memory);
throw;
}
}
GraphicBuffer::~GraphicBuffer() {
if (impl) {
android::android_native_base_t *const base = getAndroidNativeBase(impl);
base->decRef(base);
//no need to call it, decRef will do
//callDestructor<android::GraphicBuffer>(functions.destructor, impl);
}
}
status_t GraphicBuffer::lock(uint32_t usage, void **vaddr) {
return functions.lock(impl, usage, vaddr);
}
status_t GraphicBuffer::unlock() {
return functions.unlock(impl);
}
ANativeWindowBuffer *GraphicBuffer::getNativeBuffer() const {
return functions.getNativeBuffer(impl);
}
uint32_t GraphicBuffer::getStride() const {
return ((android::android_native_buffer_t *) getNativeBuffer())->stride;
}
#pragma once
#include <exception>
#include <cstdint>
#include <cerrno>
class DynamicLibrary
{
public:
DynamicLibrary(const char *fileName);
~DynamicLibrary();
void *getFunctionPtr(const char *name) const;
DynamicLibrary(const DynamicLibrary &) = delete;
DynamicLibrary & operator = (const DynamicLibrary &other) = delete;
private:
void *libHandle;
};
class OpenLibFailedException: public std::exception
{
virtual const char* what() const throw()
{
return "Failed to open Library";
}
};
struct ANativeWindowBuffer;
namespace android
{
class GraphicBuffer;
// include/system/window.h
struct android_native_base_t
{
uint32_t magic;
uint32_t version;
void* reserved[4];
void (*incRef)(struct android_native_base_t* base);
void (*decRef)(struct android_native_base_t* base);
};
// include/ui/android_native_buffer.h
struct android_native_buffer_t
{
struct android_native_base_t common;
int32_t width;
int32_t height;
int32_t stride;
int32_t format;
int32_t usage;
// ...
};
}
// utils/Errors.h
enum status_t
{
OK = 0,
UNKNOWN_ERROR = (-2147483647-1),
NO_MEMORY = -ENOMEM,
INVALID_OPERATION = -ENOSYS,
BAD_VALUE = -EINVAL,
BAD_TYPE = (UNKNOWN_ERROR + 1),
NAME_NOT_FOUND = -ENOENT,
PERMISSION_DENIED = -EPERM,
NO_INIT = -ENODEV,
ALREADY_EXISTS = -EEXIST,
DEAD_OBJECT = -EPIPE,
FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),
BAD_INDEX = -E2BIG,
NOT_ENOUGH_DATA = (UNKNOWN_ERROR + 3),
WOULD_BLOCK = (UNKNOWN_ERROR + 4),
TIMED_OUT = (UNKNOWN_ERROR + 5),
UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7),
};
// ui/PixelFormat.h, system/graphics.h
enum PixelFormat
{
PIXEL_FORMAT_UNKNOWN = 0,
PIXEL_FORMAT_NONE = 0,
PIXEL_FORMAT_CUSTOM = -4,
PIXEL_FORMAT_TRANSLUCENT = -3,
PIXEL_FORMAT_TRANSPARENT = -2,
PIXEL_FORMAT_OPAQUE = -1,
PIXEL_FORMAT_RGBA_8888 = 1,
PIXEL_FORMAT_RGBX_8888 = 2,
PIXEL_FORMAT_RGB_888 = 3,
PIXEL_FORMAT_RGB_565 = 4,
PIXEL_FORMAT_BGRA_8888 = 5,
PIXEL_FORMAT_RGBA_5551 = 6,
PIXEL_FORMAT_RGBA_4444 = 7,
};
// ui/GraphicBuffer.h
struct GraphicBufferFunctions
{
typedef void (*genericFunc) ();
typedef status_t (*initCheckFunc) (android::GraphicBuffer* buffer);
typedef status_t (*lockFunc) (android::GraphicBuffer* buffer, uint32_t usage, void** vaddr);
typedef status_t (*unlockFunc) (android::GraphicBuffer* buffer);
typedef ANativeWindowBuffer* (*getNativeBufferFunc) (const android::GraphicBuffer* buffer);
genericFunc constructor;
genericFunc destructor;
lockFunc lock;
unlockFunc unlock;
getNativeBufferFunc getNativeBuffer;
initCheckFunc initCheck;
};
class GraphicBuffer
{
public:
// ui/GraphicBuffer.h, hardware/gralloc.h
enum {
USAGE_SW_READ_NEVER = 0x00000000,
USAGE_SW_READ_RARELY = 0x00000002,
USAGE_SW_READ_OFTEN = 0x00000003,
USAGE_SW_READ_MASK = 0x0000000f,
USAGE_SW_WRITE_NEVER = 0x00000000,
USAGE_SW_WRITE_RARELY = 0x00000020,
USAGE_SW_WRITE_OFTEN = 0x00000030,
USAGE_SW_WRITE_MASK = 0x000000f0,
USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK | USAGE_SW_WRITE_MASK,
USAGE_PROTECTED = 0x00004000,
USAGE_HW_TEXTURE = 0x00000100,
USAGE_HW_RENDER = 0x00000200,
USAGE_HW_2D = 0x00000400,
USAGE_HW_COMPOSER = 0x00000800,
USAGE_HW_VIDEO_ENCODER = 0x00010000,
USAGE_HW_MASK = 0x00071F00,
};
GraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t usage);
~GraphicBuffer();
status_t lock(uint32_t usage, void** vaddr);
status_t unlock();
ANativeWindowBuffer *getNativeBuffer() const;
uint32_t getStride() const;
private:
DynamicLibrary library;
GraphicBufferFunctions functions;
android::GraphicBuffer *impl = nullptr;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment