| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "libmemtrack_wrapper.h" |
| |
| #include <dlfcn.h> |
| |
| #include "logging.h" |
| |
| namespace { |
| |
| // Init memtrack service. Removed in the latest version. |
| int (*memtrack_init)(void); |
| |
| // Allocate and dispose memory stats. |
| libmemtrack_proc* (*memtrack_proc_new)(void); |
| void (*memtrack_proc_destroy)(libmemtrack_proc* p); |
| |
| // Query memory stats for given process. |
| int (*memtrack_proc_get)(libmemtrack_proc* p, pid_t pid); |
| |
| // Since memory stats is opaque structure, there are helpers to parse it. |
| ssize_t (*memtrack_proc_graphics_total)(libmemtrack_proc* p); |
| ssize_t (*memtrack_proc_graphics_pss)(libmemtrack_proc* p); |
| ssize_t (*memtrack_proc_gl_total)(libmemtrack_proc* p); |
| ssize_t (*memtrack_proc_gl_pss)(libmemtrack_proc* p); |
| ssize_t (*memtrack_proc_other_total)(libmemtrack_proc* p); |
| ssize_t (*memtrack_proc_other_pss)(libmemtrack_proc* p); |
| |
| typedef ssize_t (*libmemtrack_getter_t)(libmemtrack_proc*); |
| |
| bool g_initialized = false; |
| bool g_broken = false; |
| |
| template <typename T> |
| void Import(T** func, void* lib, const char* name) { |
| *(reinterpret_cast<void**>(func)) = dlsym(lib, name); |
| } |
| |
| bool ImportLibmemtrackSymbols(void* handle) { |
| Import(&memtrack_init, handle, "memtrack_init"); |
| Import(&memtrack_proc_new, handle, "memtrack_proc_new"); |
| Import(&memtrack_proc_destroy, handle, "memtrack_proc_destroy"); |
| Import(&memtrack_proc_get, handle, "memtrack_proc_get"); |
| Import(&memtrack_proc_graphics_total, handle, "memtrack_proc_graphics_total"); |
| Import(&memtrack_proc_graphics_pss, handle, "memtrack_proc_graphics_pss"); |
| Import(&memtrack_proc_gl_total, handle, "memtrack_proc_gl_total"); |
| Import(&memtrack_proc_gl_pss, handle, "memtrack_proc_gl_pss"); |
| Import(&memtrack_proc_other_total, handle, "memtrack_proc_other_total"); |
| Import(&memtrack_proc_other_pss, handle, "memtrack_proc_other_pss"); |
| |
| if (!memtrack_proc_new || !memtrack_proc_destroy || !memtrack_proc_get) { |
| LogError("Couldn't use libmemtrack. Probably it's API has been changed."); |
| return false; |
| } |
| // Initialization is required on pre-O Android. |
| if (memtrack_init && memtrack_init() != 0) { |
| LogError("Failed to initialize libmemtrack. " |
| "Probably implementation is missing in the ROM."); |
| return false; |
| } |
| return true; |
| } |
| |
| bool LazyOpenLibmemtrack() { |
| if (g_initialized) |
| return true; |
| if (g_broken) |
| return false; |
| |
| void *handle = dlopen("libmemtrack.so", RTLD_GLOBAL | RTLD_NOW); |
| if (handle == nullptr) { |
| LogError("Failed to open libmemtrack library."); |
| g_broken = true; |
| return false; |
| } |
| |
| if (!ImportLibmemtrackSymbols(handle)) { |
| dlclose(handle); |
| g_broken = true; |
| return false; |
| } |
| |
| g_initialized = true; |
| return true; |
| } |
| |
| uint64_t GetOrZero(libmemtrack_getter_t getter, libmemtrack_proc* proc) { |
| if (!getter || !proc) |
| return 0; |
| return static_cast<uint64_t>(getter(proc)); |
| } |
| |
| } // namespace |
| |
| MemtrackProc::MemtrackProc(int pid) { |
| if (!LazyOpenLibmemtrack()) |
| return; |
| |
| proc_ = memtrack_proc_new(); |
| if (!proc_) { |
| LogError("Failed to create libmemtrack proc. " |
| "Probably it's API has been changed."); |
| return; |
| } |
| |
| if (memtrack_proc_get(proc_, pid) != 0) { |
| // Don't log an error since not every process has memtrack stats. |
| memtrack_proc_destroy(proc_); |
| proc_ = nullptr; |
| } |
| } |
| |
| MemtrackProc::~MemtrackProc() { |
| if (proc_) |
| memtrack_proc_destroy(proc_); |
| } |
| |
| uint64_t MemtrackProc::graphics_total() const { |
| return GetOrZero(memtrack_proc_graphics_total, proc_); |
| } |
| |
| uint64_t MemtrackProc::graphics_pss() const { |
| return GetOrZero(memtrack_proc_graphics_pss, proc_); |
| } |
| |
| uint64_t MemtrackProc::gl_total() const { |
| return GetOrZero(memtrack_proc_gl_total, proc_); |
| } |
| |
| uint64_t MemtrackProc::gl_pss() const { |
| return GetOrZero(memtrack_proc_gl_pss, proc_); |
| } |
| |
| uint64_t MemtrackProc::other_total() const { |
| return GetOrZero(memtrack_proc_other_total, proc_); |
| } |
| |
| uint64_t MemtrackProc::other_pss() const { |
| return GetOrZero(memtrack_proc_other_pss, proc_); |
| } |