1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "libmemtrack_wrapper.h" 6 7 #include <dlfcn.h> 8 9 #include "logging.h" 10 11 namespace { 12 13 // Init memtrack service. Removed in the latest version. 14 int (*memtrack_init)(void); 15 16 // Allocate and dispose memory stats. 17 libmemtrack_proc* (*memtrack_proc_new)(void); 18 void (*memtrack_proc_destroy)(libmemtrack_proc* p); 19 20 // Query memory stats for given process. 21 int (*memtrack_proc_get)(libmemtrack_proc* p, pid_t pid); 22 23 // Since memory stats is opaque structure, there are helpers to parse it. 24 ssize_t (*memtrack_proc_graphics_total)(libmemtrack_proc* p); 25 ssize_t (*memtrack_proc_graphics_pss)(libmemtrack_proc* p); 26 ssize_t (*memtrack_proc_gl_total)(libmemtrack_proc* p); 27 ssize_t (*memtrack_proc_gl_pss)(libmemtrack_proc* p); 28 ssize_t (*memtrack_proc_other_total)(libmemtrack_proc* p); 29 ssize_t (*memtrack_proc_other_pss)(libmemtrack_proc* p); 30 31 typedef ssize_t (*libmemtrack_getter_t)(libmemtrack_proc*); 32 33 bool g_initialized = false; 34 bool g_broken = false; 35 36 template <typename T> 37 void Import(T** func, void* lib, const char* name) { 38 *(reinterpret_cast<void**>(func)) = dlsym(lib, name); 39 } 40 41 bool ImportLibmemtrackSymbols(void* handle) { 42 Import(&memtrack_init, handle, "memtrack_init"); 43 Import(&memtrack_proc_new, handle, "memtrack_proc_new"); 44 Import(&memtrack_proc_destroy, handle, "memtrack_proc_destroy"); 45 Import(&memtrack_proc_get, handle, "memtrack_proc_get"); 46 Import(&memtrack_proc_graphics_total, handle, "memtrack_proc_graphics_total"); 47 Import(&memtrack_proc_graphics_pss, handle, "memtrack_proc_graphics_pss"); 48 Import(&memtrack_proc_gl_total, handle, "memtrack_proc_gl_total"); 49 Import(&memtrack_proc_gl_pss, handle, "memtrack_proc_gl_pss"); 50 Import(&memtrack_proc_other_total, handle, "memtrack_proc_other_total"); 51 Import(&memtrack_proc_other_pss, handle, "memtrack_proc_other_pss"); 52 53 if (!memtrack_proc_new || !memtrack_proc_destroy || !memtrack_proc_get) { 54 LogError("Couldn't use libmemtrack. Probably it's API has been changed."); 55 return false; 56 } 57 // Initialization is required on pre-O Android. 58 if (memtrack_init && memtrack_init() != 0) { 59 LogError("Failed to initialize libmemtrack. " 60 "Probably implementation is missing in the ROM."); 61 return false; 62 } 63 return true; 64 } 65 66 bool LazyOpenLibmemtrack() { 67 if (g_initialized) 68 return true; 69 if (g_broken) 70 return false; 71 72 void *handle = dlopen("libmemtrack.so", RTLD_GLOBAL | RTLD_NOW); 73 if (handle == nullptr) { 74 LogError("Failed to open libmemtrack library."); 75 g_broken = true; 76 return false; 77 } 78 79 if (!ImportLibmemtrackSymbols(handle)) { 80 dlclose(handle); 81 g_broken = true; 82 return false; 83 } 84 85 g_initialized = true; 86 return true; 87 } 88 89 uint64_t GetOrZero(libmemtrack_getter_t getter, libmemtrack_proc* proc) { 90 if (!getter || !proc) 91 return 0; 92 return static_cast<uint64_t>(getter(proc)); 93 } 94 95 } // namespace 96 97 MemtrackProc::MemtrackProc(int pid) { 98 if (!LazyOpenLibmemtrack()) 99 return; 100 101 proc_ = memtrack_proc_new(); 102 if (!proc_) { 103 LogError("Failed to create libmemtrack proc. " 104 "Probably it's API has been changed."); 105 return; 106 } 107 108 if (memtrack_proc_get(proc_, pid) != 0) { 109 // Don't log an error since not every process has memtrack stats. 110 memtrack_proc_destroy(proc_); 111 proc_ = nullptr; 112 } 113 } 114 115 MemtrackProc::~MemtrackProc() { 116 if (proc_) 117 memtrack_proc_destroy(proc_); 118 } 119 120 uint64_t MemtrackProc::graphics_total() const { 121 return GetOrZero(memtrack_proc_graphics_total, proc_); 122 } 123 124 uint64_t MemtrackProc::graphics_pss() const { 125 return GetOrZero(memtrack_proc_graphics_pss, proc_); 126 } 127 128 uint64_t MemtrackProc::gl_total() const { 129 return GetOrZero(memtrack_proc_gl_total, proc_); 130 } 131 132 uint64_t MemtrackProc::gl_pss() const { 133 return GetOrZero(memtrack_proc_gl_pss, proc_); 134 } 135 136 uint64_t MemtrackProc::other_total() const { 137 return GetOrZero(memtrack_proc_other_total, proc_); 138 } 139 140 uint64_t MemtrackProc::other_pss() const { 141 return GetOrZero(memtrack_proc_other_pss, proc_); 142 } 143