广告
首先帮我朋友打个广告 我们一起在运营一个视频号 感兴趣的可以帮忙点击右边这个小铃铛 铃铛
序
其实越往底下走在很多人嘴里就会变得很玄乎,变得不可思议,这里的gralloc就是一个native service,只是分装了一些调用接口,上层只是利用这些平台提供的接口组织业务场景而已,本质的来说完全可以把 ps -A | grep hardware 所有进程看成一个后台app即可,例如xxxcomposexxx等等,在我看来Android就是由一个一个app组织起来的
还是那句话,逆水行舟不进则退,我是发现00后的同事质素越来越高了
如有小伙伴需要 笔者可提供所有原材料供二次编辑 whsgzcy@foxmail.com
本文阐述的预期
1.只做对架构理解上的辅助case
一、从一个架构图开始
Gralloc 图形缓冲是一段保存图形数据的内存,这是一段共享的内存,Fence机制释放也是大多数都是通过memcpXXX等c++函数完成,也就是把指针重新指向一个地址,在Android系统中,Gralloc负责分配图形缓冲,也就是你要什么样的Buffer在此会给你申请一段Buffer,他是由一个结构体描述出来的,也就是我们通常看到的GraphicBuffer,并在业务层用数据组织起来,业务场景中再包裹一个结构体 并按照需要设置为FREE、DEQUEUED、QUEUED、ACQUIRED、FREE等等
Gralloc是一个独立的进程,native service,hal的接口是
/hardware/interfaces/graphics/allocator/2.0/IAllocator.hal
/**
...
28 * @param descriptor Properties of the buffers to allocate. This must be
29 * obtained from IMapper::createDescriptor().
...
42 allocate(BufferDescriptor descriptor, uint32_t count)
43 generates (Error error,
44 uint32_t stride,
45 vec<handle> buffers);
第一个参数descriptor 包含了缓冲layer的宽、高等其他格式参数,第二个是申请的个数,申请成功后图形缓冲以handle的格式返回
IAllocator 创建 在 HIDL_FETCH_IAllocator
/hardware/interfaces/graphics/mapper/2.0/default/passthrough.cpp
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
17 #include <mapper-passthrough/2.0/GrallocLoader.h>
18
19 using android::hardware::graphics::mapper::V2_0::IMapper;
20 using android::hardware::graphics::mapper::V2_0::passthrough::GrallocLoader;
21
22 extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
23 return GrallocLoader::load();
24 }
/hardware/interfaces/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
39 class GrallocLoader {
40 public:
41 static IAllocator* load() {
42 const hw_module_t* module = loadModule();
43 if (!module) {
44 return nullptr;
45 }
46 auto hal = createHal(module);
47 if (!hal) {
48 return nullptr;
49 }
50 return createAllocator(std::move(hal));
51 }
// load the gralloc module
54 static const hw_module_t* loadModule() {
55 const hw_module_t* module;
56 int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
57 if (error) {
58 ALOGE("failed to get gralloc module");
59 return nullptr;
60 }
61
62 return module;
63 }
加载loadModule id为GRALLOC_HARDWARE_MODULE_ID对象,createHal适配层可获取设备抽象出的对象,收到缓冲请求后再交给设备对象处理,创建IAllocator在createAllocator中创建AllocatorImpl,该对象收到请求后交给适配层对象处理
启动Gralloc服务
/hardware/interfaces/graphics/allocator/2.0/default/service.cpp
using android::hardware::defaultPassthroughServiceImplementation;
24 using android::hardware::graphics::allocator::V2_0::IAllocator;
25
26 int main() {
27 return defaultPassthroughServiceImplementation<IAllocator>(4);
28 }
29
上述代码不是很多,接下来分析分配图形缓冲流程
/frameworks/native/libs/ui/Gralloc2.cpp
Gralloc2Allocator::Gralloc2Allocator(const Gralloc2Mapper& mapper) : mMapper(mapper) {
364 mAllocator = IAllocator::getService();
365 if (mAllocator == nullptr) {
366 ALOGW("allocator 2.x is not supported");
367 return;
368 }
369 }
5 status_t Gralloc2Allocator::allocate(std::string /*requestorName*/, uint32_t width, uint32_t height,
386 PixelFormat format, uint32_t layerCount, uint64_t usage,
387 uint32_t bufferCount, uint32_t* outStride,
388 buffer_handle_t* outBufferHandles, bool importBuffers) const {
389 IMapper::BufferDescriptorInfo descriptorInfo = {};
390 descriptorInfo.width = width;
391 descriptorInfo.height = height;
392 descriptorInfo.layerCount = layerCount;
393 descriptorInfo.format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
394 descriptorInfo.usage = usage;
395
396 BufferDescriptor descriptor;
397 status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
398 static_cast<void*>(&descriptor));
399 if (error != NO_ERROR) {
400 return error;
401 }
402
403 auto ret = mAllocator->allocate(descriptor, bufferCount,
404 [&](const auto& tmpError, const auto& tmpStride,
405 const auto& tmpBuffers) {
406 error = static_cast<status_t>(tmpError);
407 if (tmpError != Error::NONE) {
408 return;
409 }
410
411 if (importBuffers) {
412 for (uint32_t i = 0; i < bufferCount; i++) {
413 error = mMapper.importBuffer(tmpBuffers[i],
414 &outBufferHandles[i]);
415 if (error != NO_ERROR) {
416 for (uint32_t j = 0; j < i; j++) {
417 mMapper.freeBuffer(outBufferHandles[j]);
418 outBufferHandles[j] = nullptr;
419 }
420 return;
421 }
422 }
423 } else {
424 for (uint32_t i = 0; i < bufferCount; i++) {
425 outBufferHandles[i] = native_handle_clone(
426 tmpBuffers[i].getNativeHandle());
427 if (!outBufferHandles[i]) {
428 for (uint32_t j = 0; j < i; j++) {
429 auto buffer = const_cast<native_handle_t*>(
430 outBufferHandles[j]);
431 native_handle_close(buffer);
432 native_handle_delete(buffer);
433 outBufferHandles[j] = nullptr;
434 }
435 }
436 }
437 }
438 *outStride = tmpStride;
439 });
440
441 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
442 hardware::IPCThreadState::self()->flushCommands();
443
444 return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
这里主要是allocate成功之后将句柄通过outBufferHandles返回调用者,AllocatorImpl收到请求后转到适配层 调用gralloc_alloc_buffer
/hardware/libhardware/modules/gralloc/gralloc.cpp
167 static int gralloc_alloc_buffer(alloc_device_t* dev,
168 size_t size, int /*usage*/, buffer_handle_t* pHandle)
169 {
170 int err = 0;
171 int fd = -1;
172
173 size = roundUpToPageSize(size);
174
175 fd = ashmem_create_region("gralloc-buffer", size);
176 if (fd < 0) {
177 ALOGE("couldn't create ashmem (%s)", strerror(-errno));
178 err = -errno;
179 }
180
181 if (err == 0) {
182 private_handle_t* hnd = new private_handle_t(fd, size, 0);
183 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
184 dev->common.module);
185 err = mapBuffer(module, hnd);
186 if (err == 0) {
187 *pHandle = hnd;
188 }
189 }
190
191 ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
192
193 return err;
194 }
通过ashmem_create_region分配内存,得到文件描述符,客户进程拿到文件描述符通过mmap操作得到缓冲区地址
图形显示系统缓存图形数据是用GraphicBuffer表示
/frameworks/native/libs/nativebase/include/nativebase/nativebase.h
typedef struct ANativeWindowBuffer
67 {
68 #ifdef __cplusplus
69 ANativeWindowBuffer() {
70 common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
71 common.version = sizeof(ANativeWindowBuffer);
72 memset(common.reserved, 0, sizeof(common.reserved));
73 }
74
75 // Implement the methods that sp<ANativeWindowBuffer> expects so that it
76 // can be used to automatically refcount ANativeWindowBuffer's.
77 void incStrong(const void* /*id*/) const {
78 common.incRef(const_cast<android_native_base_t*>(&common));
79 }
80 void decStrong(const void* /*id*/) const {
81 common.decRef(const_cast<android_native_base_t*>(&common));
82 }
83 #endif
84
85 struct android_native_base_t common;
86
87 int width;
88 int height;
89 int stride;
90 int format;
91 int usage_deprecated;
92 uintptr_t layerCount;
93
94 void* reserved[1];
95
96 const native_handle_t* handle;
97 uint64_t usage;
98
99 // we needed extra space for storing the 64-bits usage flags
100 // the number of slots to use from reserved_proc depends on the
101 // architecture.
102 void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
103 } ANativeWindowBuffer_t;
104
/frameworks/native/libs/ui/include/ui/GraphicBuffer.h
49 class GraphicBuffer
50 : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
51 public Flattenable<GraphicBuffer>
52 {
53 friend class Flattenable<GraphicBuffer>;
GraphicBuffer继承于ANativeWindowBuffer,handle用户保存缓存对应文件描述符,创建GraphicBuffer代码如下
/frameworks/native/libs/ui/GraphicBuffer.cpp
4 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
85 uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
86 : GraphicBuffer() {
87 mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
88 std::move(requestorName));
89 }
申请成功后缓冲保存到handle中,使用者得到GraphicBuffer对象后需要取出地址才能保存图形数据
status_t GraphicBuffer::unlock()
286 {
287 status_t res = getBufferMapper().unlock(handle);
288 return res;
289 }
290
291 status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
292 int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
293 const Rect lockBounds(width, height);
294 status_t res =
295 lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
296 return res;
297 }
298
299 status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
300 int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
301 return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
302 }
303
304 status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
305 const Rect& rect, void** vaddr, int fenceFd,
306 int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
307 if (rect.left < 0 || rect.right > width ||
308 rect.top < 0 || rect.bottom > height) {
309 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
310 rect.left, rect.top, rect.right, rect.bottom,
311 width, height);
312 return BAD_VALUE;
313 }
314
315 status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, inConsumerUsage, rect,
316 vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
317
318 return res;
319 }
应用程序调用lockAsync可以获取缓冲区地址,此时应用程序就可以渲染、queuebuffer操作,后续分享会继续
其实这块分配的业务比较直接,一般问题都是在上层APP,例如闪屏、卡顿等,按照我现有的经验可以排查内存是否存在泄露等