• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <memtrack/memtrack.h>
18 
19 #define LOG_TAG "memtrack"
20 
21 #include <log/log.h>
22 
23 #include <hardware/memtrack.h>
24 
25 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
26 
27 static const memtrack_module_t *module;
28 
29 struct memtrack_proc {
30     pid_t pid;
31     struct memtrack_proc_type {
32         enum memtrack_type type;
33         size_t num_records;
34         size_t allocated_records;
35         struct memtrack_record *records;
36     } types[MEMTRACK_NUM_TYPES];
37 };
38 
memtrack_init(void)39 int memtrack_init(void)
40 {
41     int err;
42 
43     if (module) {
44         return 0;
45     }
46 
47     err = hw_get_module(MEMTRACK_HARDWARE_MODULE_ID,
48             (hw_module_t const**)&module);
49     if (err) {
50         ALOGE("Couldn't load %s module (%s)", MEMTRACK_HARDWARE_MODULE_ID,
51                 strerror(-err));
52         return err;
53     }
54 
55     return module->init(module);
56 }
57 
memtrack_proc_new(void)58 struct memtrack_proc *memtrack_proc_new(void)
59 {
60     if (!module) {
61         return NULL;
62     }
63 
64     return calloc(sizeof(struct memtrack_proc), 1);
65 }
66 
memtrack_proc_destroy(struct memtrack_proc * p)67 void memtrack_proc_destroy(struct memtrack_proc *p)
68 {
69     enum memtrack_type i;
70 
71     if (p) {
72         for (i = 0; i < MEMTRACK_NUM_TYPES; i++) {
73             free(p->types[i].records);
74         }
75     }
76     free(p);
77 }
78 
memtrack_proc_get_type(struct memtrack_proc_type * t,pid_t pid,enum memtrack_type type)79 static int memtrack_proc_get_type(struct memtrack_proc_type *t,
80             pid_t pid, enum memtrack_type type)
81 {
82     size_t num_records = t->num_records;
83     int ret;
84 
85 retry:
86     ret = module->getMemory(module, pid, type, t->records, &num_records);
87     if (ret) {
88         t->num_records = 0;
89         return ret;
90     }
91     if (num_records > t->allocated_records) {
92         /* Need more records than allocated */
93         free(t->records);
94         t->records = calloc(sizeof(*t->records), num_records);
95         if (!t->records) {
96             return -ENOMEM;
97         }
98         t->allocated_records = num_records;
99         goto retry;
100     }
101     t->num_records = num_records;
102 
103     return 0;
104 }
105 
106 /* TODO: sanity checks on return values from HALs:
107  *   make sure no records have invalid flags set
108  *    - unknown flags
109  *    - too many flags of a single category
110  *    - missing ACCOUNTED/UNACCOUNTED
111  *   make sure there are not overlapping SHARED and SHARED_PSS records
112  */
memtrack_proc_sanity_check(struct memtrack_proc * p)113 static int memtrack_proc_sanity_check(struct memtrack_proc *p)
114 {
115     (void)p;
116     return 0;
117 }
118 
memtrack_proc_get(struct memtrack_proc * p,pid_t pid)119 int memtrack_proc_get(struct memtrack_proc *p, pid_t pid)
120 {
121     enum memtrack_type i;
122 
123     if (!module) {
124         return -EINVAL;
125     }
126 
127     if (!p) {
128         return -EINVAL;
129     }
130 
131     p->pid = pid;
132     for (i = 0; i < MEMTRACK_NUM_TYPES; i++) {
133         memtrack_proc_get_type(&p->types[i], pid, i);
134     }
135 
136     return memtrack_proc_sanity_check(p);
137 }
138 
memtrack_proc_sum(struct memtrack_proc * p,enum memtrack_type types[],size_t num_types,unsigned int flags)139 static ssize_t memtrack_proc_sum(struct memtrack_proc *p,
140             enum memtrack_type types[], size_t num_types,
141             unsigned int flags)
142 {
143     ssize_t sum = 0;
144     size_t i;
145     size_t j;
146 
147     for (i = 0; i < num_types; i++) {
148         enum memtrack_type type = types[i];
149         for (j = 0; j < p->types[type].num_records; j++) {
150             if ((p->types[type].records[j].flags & flags) == flags) {
151                 sum += p->types[type].records[j].size_in_bytes;
152             }
153         }
154     }
155 
156     return sum;
157 }
158 
memtrack_proc_graphics_total(struct memtrack_proc * p)159 ssize_t memtrack_proc_graphics_total(struct memtrack_proc *p)
160 {
161     enum memtrack_type types[] = { MEMTRACK_TYPE_GRAPHICS };
162     return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
163 }
164 
memtrack_proc_graphics_pss(struct memtrack_proc * p)165 ssize_t memtrack_proc_graphics_pss(struct memtrack_proc *p)
166 {
167     enum memtrack_type types[] = { MEMTRACK_TYPE_GRAPHICS };
168     return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
169                 MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
170 }
171 
memtrack_proc_gl_total(struct memtrack_proc * p)172 ssize_t memtrack_proc_gl_total(struct memtrack_proc *p)
173 {
174     enum memtrack_type types[] = { MEMTRACK_TYPE_GL };
175     return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
176 }
177 
memtrack_proc_gl_pss(struct memtrack_proc * p)178 ssize_t memtrack_proc_gl_pss(struct memtrack_proc *p)
179 {
180     enum memtrack_type types[] = { MEMTRACK_TYPE_GL };
181     return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
182                 MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
183 }
184 
memtrack_proc_other_total(struct memtrack_proc * p)185 ssize_t memtrack_proc_other_total(struct memtrack_proc *p)
186 {
187     enum memtrack_type types[] = { MEMTRACK_TYPE_MULTIMEDIA,
188                                         MEMTRACK_TYPE_CAMERA,
189                                         MEMTRACK_TYPE_OTHER };
190     return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
191 }
192 
memtrack_proc_other_pss(struct memtrack_proc * p)193 ssize_t memtrack_proc_other_pss(struct memtrack_proc *p)
194 {
195     enum memtrack_type types[] = { MEMTRACK_TYPE_MULTIMEDIA,
196                                         MEMTRACK_TYPE_CAMERA,
197                                         MEMTRACK_TYPE_OTHER };
198     return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
199                 MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
200 }
201