blob: 2b2327c58d843012a9c49ee3c6707c2467f19137 [file] [log] [blame]
Mark Salyzyn95687052014-10-02 11:12:28 -07001/*
2** Copyright 2014, 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
Tom Cherry71ba1642019-01-10 10:37:36 -080017#include <log/log_properties.h>
18
Mark Salyzyn95687052014-10-02 11:12:28 -070019#include <ctype.h>
Mark Salyzync1584562015-03-12 15:46:29 -070020#include <pthread.h>
21#include <stdlib.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070022#include <string.h>
Mark Salyzync1584562015-03-12 15:46:29 -070023#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
24#include <sys/_system_properties.h>
Mark Salyzyne4553732016-09-26 13:21:05 -070025#include <unistd.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070026
Mark Salyzyne4553732016-09-26 13:21:05 -070027#include <private/android_logger.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070028
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080029static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
30
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080031static int lock() {
32 /*
33 * If we trigger a signal handler in the middle of locked activity and the
34 * signal handler logs a message, we could get into a deadlock state.
35 */
36 /*
37 * Any contention, and we can turn around and use the non-cached method
38 * in less time than the system call associated with a mutex to deal with
39 * the contention.
40 */
41 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080042}
43
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080044static void unlock() {
45 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080046}
47
Mark Salyzync1584562015-03-12 15:46:29 -070048struct cache {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080049 const prop_info* pinfo;
50 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -070051};
52
53struct cache_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080054 struct cache cache;
55 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070056};
57
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080058static int check_cache(struct cache* cache) {
59 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzyna67d8a52015-12-21 12:32:48 -080060}
61
Mark Salyzynffbd86f2015-12-04 10:59:45 -080062#define BOOLEAN_TRUE 0xFF
63#define BOOLEAN_FALSE 0xFE
64
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080065static void refresh_cache(struct cache_char* cache, const char* key) {
66 char buf[PROP_VALUE_MAX];
Mark Salyzyn95687052014-10-02 11:12:28 -070067
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080068 if (!cache->cache.pinfo) {
69 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -070070 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080071 return;
Mark Salyzyn95687052014-10-02 11:12:28 -070072 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080073 }
74 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
75 __system_property_read(cache->cache.pinfo, 0, buf);
76 switch (buf[0]) {
77 case 't':
78 case 'T':
79 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
80 break;
81 case 'f':
82 case 'F':
83 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
84 break;
Mark Salyzynffbd86f2015-12-04 10:59:45 -080085 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080086 cache->c = buf[0];
87 }
Mark Salyzync1584562015-03-12 15:46:29 -070088}
Mark Salyzyn95687052014-10-02 11:12:28 -070089
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080090static int __android_log_level(const char* tag, size_t len, int default_prio) {
91 /* sizeof() is used on this array below */
92 static const char log_namespace[] = "persist.log.tag.";
93 static const size_t base_offset = 8; /* skip "persist." */
94 /* calculate the size of our key temporary buffer */
95 const size_t taglen = tag ? len : 0;
96 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Mark Salyzynd24dc952017-04-05 10:11:09 -070097 char key[sizeof(log_namespace) + taglen];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080098 char* kp;
99 size_t i;
100 char c = 0;
101 /*
102 * Single layer cache of four properties. Priorities are:
103 * log.tag.<tag>
104 * persist.log.tag.<tag>
105 * log.tag
106 * persist.log.tag
107 * Where the missing tag matches all tags and becomes the
108 * system global default. We do not support ro.log.tag* .
109 */
Mark Salyzynd24dc952017-04-05 10:11:09 -0700110 static char* last_tag;
111 static size_t last_tag_len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800112 static uint32_t global_serial;
113 /* some compilers erroneously see uninitialized use. !not_locked */
114 uint32_t current_global_serial = 0;
115 static struct cache_char tag_cache[2];
116 static struct cache_char global_cache[2];
117 int change_detected;
118 int global_change_detected;
119 int not_locked;
120
121 strcpy(key, log_namespace);
122
123 global_change_detected = change_detected = not_locked = lock();
124
125 if (!not_locked) {
Mark Salyzync1584562015-03-12 15:46:29 -0700126 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800127 * check all known serial numbers to changes.
Mark Salyzync1584562015-03-12 15:46:29 -0700128 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800129 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
130 if (check_cache(&tag_cache[i].cache)) {
131 change_detected = 1;
132 }
133 }
134 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
135 if (check_cache(&global_cache[i].cache)) {
136 global_change_detected = 1;
137 }
138 }
Mark Salyzync1584562015-03-12 15:46:29 -0700139
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800140 current_global_serial = __system_property_area_serial();
141 if (current_global_serial != global_serial) {
142 change_detected = 1;
143 global_change_detected = 1;
144 }
145 }
Mark Salyzync1584562015-03-12 15:46:29 -0700146
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800147 if (taglen) {
148 int local_change_detected = change_detected;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800149 if (!not_locked) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700150 if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
151 strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800152 /* invalidate log.tag.<tag> cache */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800153 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800154 tag_cache[i].cache.pinfo = NULL;
155 tag_cache[i].c = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800156 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700157 if (last_tag) last_tag[0] = '\0';
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800158 local_change_detected = 1;
159 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700160 if (!last_tag || !last_tag[0]) {
161 if (!last_tag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800162 last_tag = static_cast<char*>(calloc(1, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700163 last_tag_len = 0;
164 if (last_tag) last_tag_len = len + 1;
165 } else if (len >= last_tag_len) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800166 last_tag = static_cast<char*>(realloc(last_tag, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700167 last_tag_len = 0;
168 if (last_tag) last_tag_len = len + 1;
169 }
170 if (last_tag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800171 strncpy(last_tag, tag, len);
172 last_tag[len] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800173 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800174 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800175 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800176 strncpy(key + sizeof(log_namespace) - 1, tag, len);
177 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700178
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800179 kp = key;
180 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
181 struct cache_char* cache = &tag_cache[i];
182 struct cache_char temp_cache;
Mark Salyzyn95687052014-10-02 11:12:28 -0700183
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800184 if (not_locked) {
185 temp_cache.cache.pinfo = NULL;
186 temp_cache.c = '\0';
187 cache = &temp_cache;
188 }
189 if (local_change_detected) {
190 refresh_cache(cache, kp);
191 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800192
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800193 if (cache->c) {
194 c = cache->c;
195 break;
196 }
Mark Salyzync1584562015-03-12 15:46:29 -0700197
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800198 kp = key + base_offset;
Mark Salyzyn95687052014-10-02 11:12:28 -0700199 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800200 }
Mark Salyzync1584562015-03-12 15:46:29 -0700201
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800202 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzync1584562015-03-12 15:46:29 -0700203 case 'V':
204 case 'D':
205 case 'I':
206 case 'W':
207 case 'E':
208 case 'F': /* Not officially supported */
209 case 'A':
210 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800211 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800212 break;
Mark Salyzync1584562015-03-12 15:46:29 -0700213 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800214 /* clear '.' after log.tag */
215 key[sizeof(log_namespace) - 2] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700216
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800217 kp = key;
218 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
219 struct cache_char* cache = &global_cache[i];
220 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800221
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800222 if (not_locked) {
223 temp_cache = *cache;
224 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
225 temp_cache.cache.pinfo = NULL;
226 temp_cache.c = '\0';
227 }
228 cache = &temp_cache;
Mark Salyzync1584562015-03-12 15:46:29 -0700229 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800230 if (global_change_detected) {
231 refresh_cache(cache, kp);
232 }
Mark Salyzync1584562015-03-12 15:46:29 -0700233
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800234 if (cache->c) {
235 c = cache->c;
236 break;
237 }
Mark Salyzync1584562015-03-12 15:46:29 -0700238
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800239 kp = key + base_offset;
240 }
241 break;
242 }
243
244 if (!not_locked) {
245 global_serial = current_global_serial;
246 unlock();
247 }
248
249 switch (toupper(c)) {
250 /* clang-format off */
Mark Salyzync1584562015-03-12 15:46:29 -0700251 case 'V': return ANDROID_LOG_VERBOSE;
252 case 'D': return ANDROID_LOG_DEBUG;
253 case 'I': return ANDROID_LOG_INFO;
254 case 'W': return ANDROID_LOG_WARN;
255 case 'E': return ANDROID_LOG_ERROR;
256 case 'F': /* FALLTHRU */ /* Not officially supported */
257 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800258 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Mark Salyzync1584562015-03-12 15:46:29 -0700259 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
Tom Cherry71ba1642019-01-10 10:37:36 -0800260 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800261 }
262 return default_prio;
263}
264
Tom Cherry2d9779e2019-02-08 11:46:19 -0800265int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800266 int logLevel = __android_log_level(tag, len, default_prio);
267 return logLevel >= 0 && prio >= logLevel;
268}
269
Tom Cherry2d9779e2019-02-08 11:46:19 -0800270int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800271 int logLevel = __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800272 return logLevel >= 0 && prio >= logLevel;
273}
274
Tom Cherry2d9779e2019-02-08 11:46:19 -0800275int __android_log_is_debuggable() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800276 static uint32_t serial;
277 static struct cache_char tag_cache;
278 static const char key[] = "ro.debuggable";
279 int ret;
280
281 if (tag_cache.c) { /* ro property does not change after set */
282 ret = tag_cache.c == '1';
283 } else if (lock()) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800284 struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800285 refresh_cache(&temp_cache, key);
286 ret = temp_cache.c == '1';
287 } else {
288 int change_detected = check_cache(&tag_cache.cache);
289 uint32_t current_serial = __system_property_area_serial();
290 if (current_serial != serial) {
291 change_detected = 1;
Mark Salyzyn95687052014-10-02 11:12:28 -0700292 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800293 if (change_detected) {
294 refresh_cache(&tag_cache, key);
295 serial = current_serial;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700296 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800297 ret = tag_cache.c == '1';
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700298
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800299 unlock();
300 }
301
302 return ret;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700303}
304
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800305/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800306 * For properties that are read often, but generally remain constant.
307 * Since a change is rare, we will accept a trylock failure gracefully.
308 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800309 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700310struct cache2_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800311 pthread_mutex_t lock;
312 uint32_t serial;
313 const char* key_persist;
314 struct cache_char cache_persist;
315 const char* key_ro;
316 struct cache_char cache_ro;
317 unsigned char (*const evaluate)(const struct cache2_char* self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800318};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800319
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800320static inline unsigned char do_cache2_char(struct cache2_char* self) {
321 uint32_t current_serial;
322 int change_detected;
323 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700324
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800325 if (pthread_mutex_trylock(&self->lock)) {
326 /* We are willing to accept some race in this context */
327 return self->evaluate(self);
328 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700329
Tom Cherry71ba1642019-01-10 10:37:36 -0800330 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800331 current_serial = __system_property_area_serial();
332 if (current_serial != self->serial) {
333 change_detected = 1;
334 }
335 if (change_detected) {
336 refresh_cache(&self->cache_persist, self->key_persist);
337 refresh_cache(&self->cache_ro, self->key_ro);
338 self->serial = current_serial;
339 }
340 c = self->evaluate(self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800341
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800342 pthread_mutex_unlock(&self->lock);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800343
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800344 return c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800345}
346
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800347static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
348 unsigned char c = self->cache_persist.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800349
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800350 if (c) {
351 return c;
352 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800353
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800354 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700355}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800356
357/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800358 * Timestamp state generally remains constant, but can change at any time
359 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800360 */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800361clockid_t android_log_clockid() {
Tom Cherry71ba1642019-01-10 10:37:36 -0800362 static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
363 "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
364 "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
365 evaluate_persist_ro};
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800366
Tom Cherry71ba1642019-01-10 10:37:36 -0800367 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800368}
369
370/*
371 * Security state generally remains constant, but the DO must be able
372 * to turn off logging should it become spammy after an attack is detected.
373 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800374static unsigned char evaluate_security(const struct cache2_char* self) {
375 unsigned char c = self->cache_ro.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800376
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800377 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800378}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800379
Tom Cherry2d9779e2019-02-08 11:46:19 -0800380int __android_log_security() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800381 static struct cache2_char security = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800382 PTHREAD_MUTEX_INITIALIZER, 0,
383 "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
384 "ro.device_owner", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
385 evaluate_security};
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800386
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800387 return do_cache2_char(&security);
Mark Salyzyne4553732016-09-26 13:21:05 -0700388}
389
390/*
391 * Interface that represents the logd buffer size determination so that others
392 * need not guess our intentions.
393 */
394
395/* Property helper */
396static bool check_flag(const char* prop, const char* flag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800397 const char* cp = strcasestr(prop, flag);
398 if (!cp) {
399 return false;
400 }
401 /* We only will document comma (,) */
402 static const char sep[] = ",:;|+ \t\f";
403 if ((cp != prop) && !strchr(sep, cp[-1])) {
404 return false;
405 }
406 cp += strlen(flag);
407 return !*cp || !!strchr(sep, *cp);
Mark Salyzyne4553732016-09-26 13:21:05 -0700408}
409
410/* cache structure */
411struct cache_property {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800412 struct cache cache;
413 char property[PROP_VALUE_MAX];
Mark Salyzyne4553732016-09-26 13:21:05 -0700414};
415
Tom Cherry71ba1642019-01-10 10:37:36 -0800416static void refresh_cache_property(struct cache_property* cache, const char* key) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800417 if (!cache->cache.pinfo) {
418 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700419 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800420 return;
Mark Salyzyne4553732016-09-26 13:21:05 -0700421 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800422 }
423 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
424 __system_property_read(cache->cache.pinfo, 0, cache->property);
Mark Salyzyne4553732016-09-26 13:21:05 -0700425}
426
427/* get boolean with the logger twist that supports eng adjustments */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800428bool __android_logger_property_get_bool(const char* key, int flag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800429 struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800430 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700431 char newkey[strlen("persist.") + strlen(key) + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800432 snprintf(newkey, sizeof(newkey), "ro.%s", key);
433 refresh_cache_property(&property, newkey);
434 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800435 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800436 snprintf(newkey, sizeof(newkey), "persist.%s", key);
437 refresh_cache_property(&property, newkey);
438 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800439 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800440 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700441
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800442 refresh_cache_property(&property, key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700443
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800444 if (check_flag(property.property, "true")) {
445 return true;
446 }
447 if (check_flag(property.property, "false")) {
448 return false;
449 }
Mark Salyzyn9fcaaba2017-04-18 08:43:16 -0700450 if (property.property[0]) {
451 flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
452 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800453 if (check_flag(property.property, "eng")) {
454 flag |= BOOL_DEFAULT_FLAG_ENG;
455 }
456 /* this is really a "not" flag */
457 if (check_flag(property.property, "svelte")) {
458 flag |= BOOL_DEFAULT_FLAG_SVELTE;
459 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700460
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800461 /* Sanity Check */
462 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
463 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
464 flag |= BOOL_DEFAULT_TRUE;
465 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700466
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800467 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
Tom Cherry71ba1642019-01-10 10:37:36 -0800468 __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800469 return false;
470 }
471 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
472 return false;
473 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700474
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800475 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700476}
477
Tom Cherry2d9779e2019-02-08 11:46:19 -0800478bool __android_logger_valid_buffer_size(unsigned long value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800479 static long pages, pagesize;
480 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700481
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800482 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
483 return false;
484 }
485
486 if (!pages) {
487 pages = sysconf(_SC_PHYS_PAGES);
488 }
489 if (pages < 1) {
490 return true;
491 }
492
493 if (!pagesize) {
494 pagesize = sysconf(_SC_PAGESIZE);
495 if (pagesize <= 1) {
496 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700497 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800498 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700499
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800500 /* maximum memory impact a somewhat arbitrary ~3% */
501 pages = (pages + 31) / 32;
502 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700503
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800504 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
505 return true;
506 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700507
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800508 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700509}
510
511struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800512 pthread_mutex_t lock;
513 uint32_t serial;
514 const char* key_persist;
515 struct cache_property cache_persist;
516 const char* key_ro;
517 struct cache_property cache_ro;
518 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700519};
520
Tom Cherry71ba1642019-01-10 10:37:36 -0800521static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800522 uint32_t current_serial;
523 int change_detected;
524 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700525
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800526 if (pthread_mutex_trylock(&self->lock)) {
527 /* We are willing to accept some race in this context */
528 return self->evaluate(self);
529 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700530
Tom Cherry71ba1642019-01-10 10:37:36 -0800531 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800532 current_serial = __system_property_area_serial();
533 if (current_serial != self->serial) {
534 change_detected = 1;
535 }
536 if (change_detected) {
537 refresh_cache_property(&self->cache_persist, self->key_persist);
538 refresh_cache_property(&self->cache_ro, self->key_ro);
539 self->serial = current_serial;
540 }
541 v = self->evaluate(self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700542
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800543 pthread_mutex_unlock(&self->lock);
Mark Salyzyne4553732016-09-26 13:21:05 -0700544
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800545 return v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700546}
547
Tom Cherry71ba1642019-01-10 10:37:36 -0800548static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800549 char* cp;
550 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700551
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800552 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700553 case 'm':
554 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800555 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800556 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700557 case 'k':
558 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800559 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800560 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700561 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800562 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700563
564 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800565 value = 0;
566 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700567
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800568 if (!__android_logger_valid_buffer_size(value)) {
569 value = 0;
570 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700571
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800572 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700573}
574
Tom Cherry71ba1642019-01-10 10:37:36 -0800575static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800576 unsigned long size = property_get_size_from_cache(&self->cache_persist);
577 if (size) {
578 return size;
579 }
580 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700581}
582
Tom Cherry2d9779e2019-02-08 11:46:19 -0800583unsigned long __android_logger_get_buffer_size(log_id_t logId) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800584 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
585 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
586 static struct cache2_property_size global = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800587 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800588 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800589 global_tunable, { { NULL, 0xFFFFFFFF }, {} },
590 global_default, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800591 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800592 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800593 };
Mark Salyzynd24dc952017-04-05 10:11:09 -0700594 char key_persist[strlen(global_tunable) + strlen(".security") + 1];
595 char key_ro[strlen(global_default) + strlen(".security") + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800596 struct cache2_property_size local = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800597 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800598 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800599 key_persist, { { NULL, 0xFFFFFFFF }, {} },
600 key_ro, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800601 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800602 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800603 };
604 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700605
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800606 default_size = do_cache2_property_size(&global);
607 if (!default_size) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800608 default_size = __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800609 ? LOG_BUFFER_MIN_SIZE /* 64K */
610 : LOG_BUFFER_SIZE; /* 256K */
611 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700612
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800613 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
614 android_log_id_to_name(logId));
Tom Cherry71ba1642019-01-10 10:37:36 -0800615 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800616 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700617
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800618 if (!property_size) {
619 property_size = default_size;
620 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700621
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800622 if (!property_size) {
623 property_size = LOG_BUFFER_SIZE;
624 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700625
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800626 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800627}