这一篇文章我们一起来瞧瞧2D(Graphic) buffer分配器C2AllocatorGralloc是如何工作的。
1、GraphicBuffer
在Android系统中,GraphicBufferAllocator和GraphicBufferMapper是与图形缓冲区(Graphic Buffers)管理相关的重要组件,C2AllocatorGralloc依赖这两个组件进行buffer分配,这一小节我们先看看这两个组件是如何协同工作的。由于笔者不太了解graphic相关的内容,因此在这只能根据自己的理解做一点简单的介绍,顺带看看它们的层级结构与调用流程,如有错误欢迎指出。
GraphicBufferAllocator主要负责图形缓冲区的内存分配,GraphicBufferMapper主要负责将分配好的图形缓冲区映射到虚拟地址空间,使CPU可以直接访问这些缓冲区。
接下来会涉及到GraphicBufferAllocator、GraphicBufferMapper、GrallocMapper(Gralloc5Mapper)、和GrallocAllocator(Gralloc5Allocator)这六个类,相关代码实现位于frameworks/native/libs/ui目录下。
2、GraphicBufferMapper
先来看GraphicBufferMapper的构造函数:
GraphicBufferMapper::GraphicBufferMapper() {
mMapper = std::make_unique<const Gralloc5Mapper>();
if (mMapper->isLoaded()) {
mMapperVersion = Version::GRALLOC_5;
return;
}
mMapper = std::make_unique<const Gralloc4Mapper>();
if (mMapper->isLoaded()) {
mMapperVersion = Version::GRALLOC_4;
return;
}
// ...
}
GraphicBufferMapper会尝试由高到低,创建不同版本GrallocMapper,如果调用GrallocMapper的isLoaded方法返回true,说明创建成功。
Gralloc4Mapper是HIDL版本的service,Gralloc5Mapper是AIDL版本的service,接下来以最新的Gralloc5Mapper为例看看创建过程:
static const Gralloc5 &getInstance() {
static Gralloc5 instance = []() {
// 1.
auto allocator = waitForAllocator();
if (!allocator) {
return Gralloc5{};
}
// 2.
void *so = loadIMapperLibrary();
if (!so) {
return Gralloc5{};
}
// 3.
auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
AIMapper *mapper = nullptr;
// 4.
AIMapper_Error error = loadIMapper(&mapper);
if (error != AIMAPPER_ERROR_NONE) {
ALOGE("AIMapper_loadIMapper failed %d", error);
return Gralloc5{};
}
return Gralloc5{std::move(allocator), mapper};
}();
return instance;
}
Gralloc5Mapper::Gralloc5Mapper() {
mMapper = getInstance().mapper;
}
Gralloc5Mapper的构造函数会调用静态方法getInstance:
- 调用waitForAllocator获取IAllocator服务;
- IAllocator服务获取成功后获取IMapper lib的名称,打开lib;
- 获取AIMapper_loadIMapper函数指针;
- 创建AIMapper对象,将获取的IAllocator服务和AIMapper对象打包为Gralloc5。
static const auto kIAllocatorServiceName = IAllocator::descriptor + std::string("/default");
static std::shared_ptr<IAllocator> waitForAllocator() {
if (__builtin_available(android 31, *)) {
if (!AServiceManager_isDeclared(kIAllocatorServiceName.c_str())) {
return nullptr;
}
auto allocator = IAllocator::fromBinder(
ndk::SpAIBinder(AServiceManager_waitForService(kIAllocatorServiceName.c_str())));
if (!allocator) {
ALOGE("AIDL IAllocator declared but failed to get service");
return nullptr;
}
int32_t version = 0;
if (!allocator->getInterfaceVersion(&version).isOk()) {
ALOGE("Failed to query interface version");
return nullptr;
}
if (version < kIAllocatorMinimumVersion) {
return nullptr;
}
return allocator;
} else {
return nullptr;
}
}
waitForAllocator其实就是在获取android.hardware.graphics.allocator/default这个服务。
static void *loadIMapperLibrary() {
static void *imapperLibrary = []() -> void * {
auto allocator = waitForAllocator();
std::string mapperSuffix;
auto status = allocator->getIMapperLibrarySuffix(&mapperSuffix);
if (!status.isOk()) {
ALOGE("Failed to get IMapper library suffix");
return nullptr;
}
std::string lib_name = "mapper." + mapperSuffix + ".so";
void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
if (!so) {
ALOGE("Failed to load %s", lib_name.c_str());
}
return so;
}();
return imapperLibrary;
}
查看了早前的Gralloc4实现,看到除了IAllocator service外,还有一个IMapper service。从loadIMapperLibrary这里大致可以了解到,在Gralloc5中已经移除IMapper service了,会直接通过加载lib获取IMapper对象,lib名为mapper.xxx.so。