• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
Import(T ** func,void * lib,const char * name)37 void Import(T** func, void* lib, const char* name) {
38   *(reinterpret_cast<void**>(func)) = dlsym(lib, name);
39 }
40 
ImportLibmemtrackSymbols(void * handle)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 
LazyOpenLibmemtrack()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 
GetOrZero(libmemtrack_getter_t getter,libmemtrack_proc * proc)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 
MemtrackProc(int pid)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 
~MemtrackProc()115 MemtrackProc::~MemtrackProc() {
116   if (proc_)
117     memtrack_proc_destroy(proc_);
118 }
119 
graphics_total() const120 uint64_t MemtrackProc::graphics_total() const {
121   return GetOrZero(memtrack_proc_graphics_total, proc_);
122 }
123 
graphics_pss() const124 uint64_t MemtrackProc::graphics_pss() const {
125   return GetOrZero(memtrack_proc_graphics_pss, proc_);
126 }
127 
gl_total() const128 uint64_t MemtrackProc::gl_total() const {
129   return GetOrZero(memtrack_proc_gl_total, proc_);
130 }
131 
gl_pss() const132 uint64_t MemtrackProc::gl_pss() const {
133   return GetOrZero(memtrack_proc_gl_pss, proc_);
134 }
135 
other_total() const136 uint64_t MemtrackProc::other_total() const {
137   return GetOrZero(memtrack_proc_other_total, proc_);
138 }
139 
other_pss() const140 uint64_t MemtrackProc::other_pss() const {
141   return GetOrZero(memtrack_proc_other_pss, proc_);
142 }
143