Last active
May 15, 2021 14:08
-
-
Save Luiz-Monad/979f9182b7874fc671f20d733b96157b to your computer and use it in GitHub Desktop.
android hack to get buffers from gralloc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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