/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2018-2019. All rights reserved. * Description: Gralloc * Author: Hisilicon * Created: 2019.11.07 */ #include "gralloc_debug.h" #include #include #include #include #include #include #include "mali_gralloc_formats.h" static bool g_debug_dump_enable = false; static bool g_debug_capture_enable = false; static pthread_mutex_t g_ionbuffer_dump_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_frambuffer_dump_lock = PTHREAD_MUTEX_INITIALIZER; static void gralloc_dump_string(android::String8 &buf, const char *fmt, ...) { va_list args; va_start(args, fmt); buf.appendFormatV(fmt, args); va_end(args); } static int gralloc_debug_pid2name(pid_t pid, char *process_name, int name_len) { ssize_t size; if (pid < 0) { ALOGE("Invalid pid %d and return", pid); return GRALLOC_FAILURE; } sprintf_s(process_name, name_len, "/proc/%d/cmdline", pid); int fd = open(process_name, O_RDONLY); if (fd == -1) { return GRALLOC_FAILURE; } size = read(fd, process_name, name_len); if (size > 0) { process_name[size] = '\0'; } close(fd); return GRALLOC_SUCCESS; } void gralloc_debug_dump_ionbuffer(const private_internal_handle_t *handle, bool is_retain) { android::String8 dump_strings; char process_name[PATH_MAX]; int ret; if (handle == nullptr) { GRALLOC_ERROR_INFO(); return; } ret = gralloc_debug_pid2name(getpid(), process_name, PATH_MAX - 1); if (ret == GRALLOC_FAILURE) { return; } pthread_mutex_lock(&g_ionbuffer_dump_lock); gralloc_dump_string(dump_strings, "---------------------[%s] dump gralloc ionbuffer info start: ------------------------\n", is_retain ? "retain " : "release"); gralloc_dump_string(dump_strings, "---------------------process name : %s------------------------\n", process_name); gralloc_dump_string(dump_strings, " handle | addr | width | height |pixel_stride|bytes_stride|" " size | format |internal format|consumer usage|producer usage| fd | AFBC |\n"); gralloc_dump_string(dump_strings, "------------+------------+-------+--------+------------+------------+" "----------+----------+---------------+--------------+--------------+-----------+------+\n"); gralloc_dump_string(dump_strings, " %010" PRIxPTR " | %010" PRIxPTR " | %5d | %5d | %5d | %5d |" " %8d | %08x | %09" PRIx64 " | %09" PRIx64 " | %09" PRIx64 " | %08x | %4d |\n", handle, handle->addr, handle->width, handle->height, handle->pixel_stride, handle->bytes_stride, handle->size, handle->format, handle->internal_format, handle->consumer_usage, handle->producer_usage, handle->fd, ((handle->internal_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK) != 0) ? true : false); gralloc_dump_string(dump_strings, "-------------------------dump gralloc ionbuffer info end :------------------------\n"); pthread_mutex_unlock(&g_ionbuffer_dump_lock); ALOGD("%s", dump_strings.string()); } void gralloc_debug_capture_ionbuffer(const private_internal_handle_t *handle) { char file_path[PATH_MAX]; char real_path[PATH_MAX]; char process_path_name[PATH_MAX]; android::String8 string8_name; static int count = 0; int fd; int ret; pid_t pid; int len; if (handle == nullptr || handle->base == nullptr) { GRALLOC_ERROR_INFO(); return; } pid = getpid(); ret = gralloc_debug_pid2name(pid, process_path_name, PATH_MAX - 1); if (ret == GRALLOC_FAILURE) { return; } string8_name = android::String8(process_path_name, PATH_MAX); if (realpath(DUMP_CAPTURE_DIR, real_path) == nullptr) { return; } len = snprintf_s(file_path, PATH_MAX, PATH_MAX - 1, "%s/process-%s_pid-%d_format-%d_w-%d_h-%d_stride-%d_count-%d", real_path, string8_name.getPathLeaf().string(), pid, handle->format, handle->width, handle->height, handle->pixel_stride, count++); if (len < 0) { GRALLOC_ERROR_INFO(); return; } fd = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); /* 0644: rw,r,r */ if (fd != -1) { write(fd, (void *)handle->base, handle->size); close(fd); } ALOGD("gralloc capture ionbuffer finish"); } void gralloc_debug_dump_framebuffer(const private_internal_handle_t *handle, const private_module_t *m) { android::String8 dump_strings; char process_name[PATH_MAX]; int ret; unsigned int id; if (handle == nullptr || m == nullptr) { GRALLOC_ERROR_INFO(); return; } ret = gralloc_debug_pid2name(getpid(), process_name, PATH_MAX - 1); if (ret == GRALLOC_FAILURE) { return; } pthread_mutex_lock(&g_frambuffer_dump_lock); id = (reinterpret_cast(m))->reserved[0]; gralloc_dump_string(dump_strings, "-------------------------dump gralloc framebuffer info start :------------------------\n"); gralloc_dump_string(dump_strings, " handle | address | width | height | internal width | internal height |" " stride | format |internal format|consumer usage|producer usage| fd | AFBC |\n"); gralloc_dump_string(dump_strings, "----------+----------+-------+--------+----------------+-----------------+--------+" "----------+---------------+--------------+--------------+----------+------+\n"); gralloc_dump_string(dump_strings, " %08" PRIxPTR " | %08" PRIxPTR " | %5d | %5d | %5d | %5d | %5d |" " %08x | %09" PRIx64 " | %09" PRIx64 " | %09" PRIx64 " | %08x | %4d |\n", handle, handle->addr, handle->width, handle->height, handle->internal_width, handle->internal_height, handle->pixel_stride, handle->format, handle->internal_format, handle->consumer_usage, handle->producer_usage, handle->fd, ((handle->internal_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK) != 0) ? true : false); gralloc_dump_string(dump_strings, "---------------------------------------------------------------------\n"); gralloc_dump_string(dump_strings, " fb | xres | yres | xdpi | ydpi | fps | numBuffers | swapInterval\n"); gralloc_dump_string(dump_strings, "---- +----- +------+-------+--------+------+------------+------------+\n"); gralloc_dump_string(dump_strings, " %d | %d | %d | %3.3f | %3.3f | %3.3f| %d | %d |\n", id, m->vinfo[id].xres, m->vinfo[id].yres, m->xdpi[id], m->ydpi[id], m->fps[id], m->numBuffers[id], m->swapInterval[id]); gralloc_dump_string(dump_strings, "--------------------------dump Gralloc framebuffer info end :-------------------------\n"); pthread_mutex_unlock(&g_frambuffer_dump_lock); ALOGD("%s", dump_strings.string()); } void gralloc_debug_update_config(void) { char property[PROPERTY_VALUE_MAX]; property_get(GRALLOC_PROPERTY_DEBUG_DUMP, property, "false"); if (strcmp(property, "true") == 0) { g_debug_dump_enable = true; } else { g_debug_dump_enable = false; } property_get(GRALLOC_PROPERTY_DEBUG_CAPTURE, property, "false"); if (strcmp(property, "true") == 0) { g_debug_capture_enable = true; } else { g_debug_capture_enable = false; } } bool gralloc_debug_dump_is_enabled(void) { return g_debug_dump_enable; } bool gralloc_debug_capture_is_enabled(void) { return g_debug_capture_enable; }