blob: c71cbcfc11cc07c48f0d8394cb4abb6787df8d70 [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
17#include <ctype.h>
Mark Salyzync1584562015-03-12 15:46:29 -070018#include <pthread.h>
Mark Salyzyne4553732016-09-26 13:21:05 -070019#include <stdbool.h>
Mark Salyzync1584562015-03-12 15:46:29 -070020#include <stdlib.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070021#include <string.h>
Mark Salyzync1584562015-03-12 15:46:29 -070022#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
23#include <sys/_system_properties.h>
Mark Salyzyne4553732016-09-26 13:21:05 -070024#include <unistd.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070025
Mark Salyzyne4553732016-09-26 13:21:05 -070026#include <private/android_logger.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070027
Mark Salyzyn018a96d2016-03-01 13:45:42 -080028#include "log_portability.h"
Mark Salyzynbe1d3c22016-03-10 08:25:33 -080029
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080030static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
31
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080032static int lock() {
33 /*
34 * If we trigger a signal handler in the middle of locked activity and the
35 * signal handler logs a message, we could get into a deadlock state.
36 */
37 /*
38 * Any contention, and we can turn around and use the non-cached method
39 * in less time than the system call associated with a mutex to deal with
40 * the contention.
41 */
42 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080043}
44
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080045static void unlock() {
46 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080047}
48
Mark Salyzync1584562015-03-12 15:46:29 -070049struct cache {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080050 const prop_info* pinfo;
51 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -070052};
53
54struct cache_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080055 struct cache cache;
56 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070057};
58
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080059static int check_cache(struct cache* cache) {
60 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzyna67d8a52015-12-21 12:32:48 -080061}
62
Mark Salyzynffbd86f2015-12-04 10:59:45 -080063#define BOOLEAN_TRUE 0xFF
64#define BOOLEAN_FALSE 0xFE
65
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080066static void refresh_cache(struct cache_char* cache, const char* key) {
67 char buf[PROP_VALUE_MAX];
Mark Salyzyn95687052014-10-02 11:12:28 -070068
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080069 if (!cache->cache.pinfo) {
70 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -070071 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080072 return;
Mark Salyzyn95687052014-10-02 11:12:28 -070073 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080074 }
75 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
76 __system_property_read(cache->cache.pinfo, 0, buf);
77 switch (buf[0]) {
78 case 't':
79 case 'T':
80 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
81 break;
82 case 'f':
83 case 'F':
84 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
85 break;
Mark Salyzynffbd86f2015-12-04 10:59:45 -080086 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080087 cache->c = buf[0];
88 }
Mark Salyzync1584562015-03-12 15:46:29 -070089}
Mark Salyzyn95687052014-10-02 11:12:28 -070090
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080091static int __android_log_level(const char* tag, size_t len, int default_prio) {
92 /* sizeof() is used on this array below */
93 static const char log_namespace[] = "persist.log.tag.";
94 static const size_t base_offset = 8; /* skip "persist." */
95 /* calculate the size of our key temporary buffer */
96 const size_t taglen = tag ? len : 0;
97 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Mark Salyzynd24dc952017-04-05 10:11:09 -070098 char key[sizeof(log_namespace) + taglen];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080099 char* kp;
100 size_t i;
101 char c = 0;
102 /*
103 * Single layer cache of four properties. Priorities are:
104 * log.tag.<tag>
105 * persist.log.tag.<tag>
106 * log.tag
107 * persist.log.tag
108 * Where the missing tag matches all tags and becomes the
109 * system global default. We do not support ro.log.tag* .
110 */
Mark Salyzynd24dc952017-04-05 10:11:09 -0700111 static char* last_tag;
112 static size_t last_tag_len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800113 static uint32_t global_serial;
114 /* some compilers erroneously see uninitialized use. !not_locked */
115 uint32_t current_global_serial = 0;
116 static struct cache_char tag_cache[2];
117 static struct cache_char global_cache[2];
118 int change_detected;
119 int global_change_detected;
120 int not_locked;
121
122 strcpy(key, log_namespace);
123
124 global_change_detected = change_detected = not_locked = lock();
125
126 if (!not_locked) {
Mark Salyzync1584562015-03-12 15:46:29 -0700127 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800128 * check all known serial numbers to changes.
Mark Salyzync1584562015-03-12 15:46:29 -0700129 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800130 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
131 if (check_cache(&tag_cache[i].cache)) {
132 change_detected = 1;
133 }
134 }
135 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
136 if (check_cache(&global_cache[i].cache)) {
137 global_change_detected = 1;
138 }
139 }
Mark Salyzync1584562015-03-12 15:46:29 -0700140
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800141 current_global_serial = __system_property_area_serial();
142 if (current_global_serial != global_serial) {
143 change_detected = 1;
144 global_change_detected = 1;
145 }
146 }
Mark Salyzync1584562015-03-12 15:46:29 -0700147
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800148 if (taglen) {
149 int local_change_detected = change_detected;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800150 if (!not_locked) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700151 if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
152 strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800153 /* invalidate log.tag.<tag> cache */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800154 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800155 tag_cache[i].cache.pinfo = NULL;
156 tag_cache[i].c = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800157 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700158 if (last_tag) last_tag[0] = '\0';
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800159 local_change_detected = 1;
160 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700161 if (!last_tag || !last_tag[0]) {
162 if (!last_tag) {
163 last_tag = calloc(1, len + 1);
164 last_tag_len = 0;
165 if (last_tag) last_tag_len = len + 1;
166 } else if (len >= last_tag_len) {
167 last_tag = realloc(last_tag, len + 1);
168 last_tag_len = 0;
169 if (last_tag) last_tag_len = len + 1;
170 }
171 if (last_tag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800172 strncpy(last_tag, tag, len);
173 last_tag[len] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800174 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800175 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800176 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800177 strncpy(key + sizeof(log_namespace) - 1, tag, len);
178 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700179
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800180 kp = key;
181 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
182 struct cache_char* cache = &tag_cache[i];
183 struct cache_char temp_cache;
Mark Salyzyn95687052014-10-02 11:12:28 -0700184
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800185 if (not_locked) {
186 temp_cache.cache.pinfo = NULL;
187 temp_cache.c = '\0';
188 cache = &temp_cache;
189 }
190 if (local_change_detected) {
191 refresh_cache(cache, kp);
192 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800193
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800194 if (cache->c) {
195 c = cache->c;
196 break;
197 }
Mark Salyzync1584562015-03-12 15:46:29 -0700198
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800199 kp = key + base_offset;
Mark Salyzyn95687052014-10-02 11:12:28 -0700200 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800201 }
Mark Salyzync1584562015-03-12 15:46:29 -0700202
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800203 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzync1584562015-03-12 15:46:29 -0700204 case 'V':
205 case 'D':
206 case 'I':
207 case 'W':
208 case 'E':
209 case 'F': /* Not officially supported */
210 case 'A':
211 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800212 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800213 break;
Mark Salyzync1584562015-03-12 15:46:29 -0700214 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800215 /* clear '.' after log.tag */
216 key[sizeof(log_namespace) - 2] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700217
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800218 kp = key;
219 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
220 struct cache_char* cache = &global_cache[i];
221 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800222
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800223 if (not_locked) {
224 temp_cache = *cache;
225 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
226 temp_cache.cache.pinfo = NULL;
227 temp_cache.c = '\0';
228 }
229 cache = &temp_cache;
Mark Salyzync1584562015-03-12 15:46:29 -0700230 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800231 if (global_change_detected) {
232 refresh_cache(cache, kp);
233 }
Mark Salyzync1584562015-03-12 15:46:29 -0700234
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800235 if (cache->c) {
236 c = cache->c;
237 break;
238 }
Mark Salyzync1584562015-03-12 15:46:29 -0700239
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800240 kp = key + base_offset;
241 }
242 break;
243 }
244
245 if (!not_locked) {
246 global_serial = current_global_serial;
247 unlock();
248 }
249
250 switch (toupper(c)) {
251 /* clang-format off */
Mark Salyzync1584562015-03-12 15:46:29 -0700252 case 'V': return ANDROID_LOG_VERBOSE;
253 case 'D': return ANDROID_LOG_DEBUG;
254 case 'I': return ANDROID_LOG_INFO;
255 case 'W': return ANDROID_LOG_WARN;
256 case 'E': return ANDROID_LOG_ERROR;
257 case 'F': /* FALLTHRU */ /* Not officially supported */
258 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800259 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Mark Salyzync1584562015-03-12 15:46:29 -0700260 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800261 /* clang-format on */
262 }
263 return default_prio;
264}
265
266LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag,
267 size_t len,
268 int default_prio) {
269 int logLevel = __android_log_level(tag, len, default_prio);
270 return logLevel >= 0 && prio >= logLevel;
271}
272
273LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag,
274 int default_prio) {
275 int logLevel =
276 __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
277 return logLevel >= 0 && prio >= logLevel;
278}
279
Steven Morelandd73be1b2017-04-13 23:48:57 -0700280LIBLOG_ABI_PUBLIC int __android_log_is_debuggable() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800281 static uint32_t serial;
282 static struct cache_char tag_cache;
283 static const char key[] = "ro.debuggable";
284 int ret;
285
286 if (tag_cache.c) { /* ro property does not change after set */
287 ret = tag_cache.c == '1';
288 } else if (lock()) {
289 struct cache_char temp_cache = { { NULL, -1 }, '\0' };
290 refresh_cache(&temp_cache, key);
291 ret = temp_cache.c == '1';
292 } else {
293 int change_detected = check_cache(&tag_cache.cache);
294 uint32_t current_serial = __system_property_area_serial();
295 if (current_serial != serial) {
296 change_detected = 1;
Mark Salyzyn95687052014-10-02 11:12:28 -0700297 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800298 if (change_detected) {
299 refresh_cache(&tag_cache, key);
300 serial = current_serial;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700301 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800302 ret = tag_cache.c == '1';
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700303
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800304 unlock();
305 }
306
307 return ret;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700308}
309
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800310/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800311 * For properties that are read often, but generally remain constant.
312 * Since a change is rare, we will accept a trylock failure gracefully.
313 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800314 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700315struct cache2_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800316 pthread_mutex_t lock;
317 uint32_t serial;
318 const char* key_persist;
319 struct cache_char cache_persist;
320 const char* key_ro;
321 struct cache_char cache_ro;
322 unsigned char (*const evaluate)(const struct cache2_char* self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800323};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800324
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800325static inline unsigned char do_cache2_char(struct cache2_char* self) {
326 uint32_t current_serial;
327 int change_detected;
328 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700329
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800330 if (pthread_mutex_trylock(&self->lock)) {
331 /* We are willing to accept some race in this context */
332 return self->evaluate(self);
333 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700334
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800335 change_detected = check_cache(&self->cache_persist.cache) ||
336 check_cache(&self->cache_ro.cache);
337 current_serial = __system_property_area_serial();
338 if (current_serial != self->serial) {
339 change_detected = 1;
340 }
341 if (change_detected) {
342 refresh_cache(&self->cache_persist, self->key_persist);
343 refresh_cache(&self->cache_ro, self->key_ro);
344 self->serial = current_serial;
345 }
346 c = self->evaluate(self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800347
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800348 pthread_mutex_unlock(&self->lock);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800349
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800350 return c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800351}
352
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800353static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
354 unsigned char c = self->cache_persist.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800355
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800356 if (c) {
357 return c;
358 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800359
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800360 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700361}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800362
363/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800364 * Timestamp state generally remains constant, but can change at any time
365 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800366 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800367LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
368 static struct cache2_char clockid = {
369 PTHREAD_MUTEX_INITIALIZER, 0,
370 "persist.logd.timestamp", { { NULL, -1 }, '\0' },
371 "ro.logd.timestamp", { { NULL, -1 }, '\0' },
372 evaluate_persist_ro
373 };
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800374
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800375 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC
376 : CLOCK_REALTIME;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800377}
378
379/*
380 * Security state generally remains constant, but the DO must be able
381 * to turn off logging should it become spammy after an attack is detected.
382 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800383static unsigned char evaluate_security(const struct cache2_char* self) {
384 unsigned char c = self->cache_ro.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800385
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800386 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800387}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800388
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800389LIBLOG_ABI_PUBLIC int __android_log_security() {
390 static struct cache2_char security = {
391 PTHREAD_MUTEX_INITIALIZER, 0,
392 "persist.logd.security", { { NULL, -1 }, BOOLEAN_FALSE },
393 "ro.device_owner", { { NULL, -1 }, BOOLEAN_FALSE },
394 evaluate_security
395 };
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800396
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800397 return do_cache2_char(&security);
Mark Salyzyne4553732016-09-26 13:21:05 -0700398}
399
400/*
401 * Interface that represents the logd buffer size determination so that others
402 * need not guess our intentions.
403 */
404
405/* Property helper */
406static bool check_flag(const char* prop, const char* flag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800407 const char* cp = strcasestr(prop, flag);
408 if (!cp) {
409 return false;
410 }
411 /* We only will document comma (,) */
412 static const char sep[] = ",:;|+ \t\f";
413 if ((cp != prop) && !strchr(sep, cp[-1])) {
414 return false;
415 }
416 cp += strlen(flag);
417 return !*cp || !!strchr(sep, *cp);
Mark Salyzyne4553732016-09-26 13:21:05 -0700418}
419
420/* cache structure */
421struct cache_property {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800422 struct cache cache;
423 char property[PROP_VALUE_MAX];
Mark Salyzyne4553732016-09-26 13:21:05 -0700424};
425
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800426static void refresh_cache_property(struct cache_property* cache,
427 const char* key) {
428 if (!cache->cache.pinfo) {
429 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700430 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800431 return;
Mark Salyzyne4553732016-09-26 13:21:05 -0700432 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800433 }
434 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
435 __system_property_read(cache->cache.pinfo, 0, cache->property);
Mark Salyzyne4553732016-09-26 13:21:05 -0700436}
437
438/* get boolean with the logger twist that supports eng adjustments */
439LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800440 int flag) {
441 struct cache_property property = { { NULL, -1 }, { 0 } };
442 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700443 char newkey[strlen("persist.") + strlen(key) + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800444 snprintf(newkey, sizeof(newkey), "ro.%s", key);
445 refresh_cache_property(&property, newkey);
446 property.cache.pinfo = NULL;
447 property.cache.serial = -1;
448 snprintf(newkey, sizeof(newkey), "persist.%s", key);
449 refresh_cache_property(&property, newkey);
450 property.cache.pinfo = NULL;
451 property.cache.serial = -1;
452 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700453
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800454 refresh_cache_property(&property, key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700455
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800456 if (check_flag(property.property, "true")) {
457 return true;
458 }
459 if (check_flag(property.property, "false")) {
460 return false;
461 }
462 if (check_flag(property.property, "eng")) {
463 flag |= BOOL_DEFAULT_FLAG_ENG;
464 }
465 /* this is really a "not" flag */
466 if (check_flag(property.property, "svelte")) {
467 flag |= BOOL_DEFAULT_FLAG_SVELTE;
468 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700469
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800470 /* Sanity Check */
471 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
472 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
473 flag |= BOOL_DEFAULT_TRUE;
474 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700475
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800476 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
477 __android_logger_property_get_bool("ro.config.low_ram",
478 BOOL_DEFAULT_FALSE)) {
479 return false;
480 }
481 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
482 return false;
483 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700484
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800485 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700486}
487
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800488LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) {
489 static long pages, pagesize;
490 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700491
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800492 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
493 return false;
494 }
495
496 if (!pages) {
497 pages = sysconf(_SC_PHYS_PAGES);
498 }
499 if (pages < 1) {
500 return true;
501 }
502
503 if (!pagesize) {
504 pagesize = sysconf(_SC_PAGESIZE);
505 if (pagesize <= 1) {
506 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700507 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800508 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700509
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800510 /* maximum memory impact a somewhat arbitrary ~3% */
511 pages = (pages + 31) / 32;
512 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700513
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800514 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
515 return true;
516 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700517
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800518 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700519}
520
521struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800522 pthread_mutex_t lock;
523 uint32_t serial;
524 const char* key_persist;
525 struct cache_property cache_persist;
526 const char* key_ro;
527 struct cache_property cache_ro;
528 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700529};
530
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800531static inline unsigned long do_cache2_property_size(
532 struct cache2_property_size* self) {
533 uint32_t current_serial;
534 int change_detected;
535 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700536
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800537 if (pthread_mutex_trylock(&self->lock)) {
538 /* We are willing to accept some race in this context */
539 return self->evaluate(self);
540 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700541
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800542 change_detected = check_cache(&self->cache_persist.cache) ||
543 check_cache(&self->cache_ro.cache);
544 current_serial = __system_property_area_serial();
545 if (current_serial != self->serial) {
546 change_detected = 1;
547 }
548 if (change_detected) {
549 refresh_cache_property(&self->cache_persist, self->key_persist);
550 refresh_cache_property(&self->cache_ro, self->key_ro);
551 self->serial = current_serial;
552 }
553 v = self->evaluate(self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700554
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800555 pthread_mutex_unlock(&self->lock);
Mark Salyzyne4553732016-09-26 13:21:05 -0700556
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800557 return v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700558}
559
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800560static unsigned long property_get_size_from_cache(
561 const struct cache_property* cache) {
562 char* cp;
563 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700564
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800565 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700566 case 'm':
567 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800568 value *= 1024;
Mark Salyzyne4553732016-09-26 13:21:05 -0700569 /* FALLTHRU */
570 case 'k':
571 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800572 value *= 1024;
Mark Salyzyne4553732016-09-26 13:21:05 -0700573 /* FALLTHRU */
574 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800575 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700576
577 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800578 value = 0;
579 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700580
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800581 if (!__android_logger_valid_buffer_size(value)) {
582 value = 0;
583 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700584
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800585 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700586}
587
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800588static unsigned long evaluate_property_get_size(
589 const struct cache2_property_size* self) {
590 unsigned long size = property_get_size_from_cache(&self->cache_persist);
591 if (size) {
592 return size;
593 }
594 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700595}
596
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800597LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) {
598 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
599 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
600 static struct cache2_property_size global = {
601 /* clang-format off */
602 PTHREAD_MUTEX_INITIALIZER, 0,
603 global_tunable, { { NULL, -1 }, {} },
604 global_default, { { NULL, -1 }, {} },
605 evaluate_property_get_size
606 /* clang-format on */
607 };
Mark Salyzynd24dc952017-04-05 10:11:09 -0700608 char key_persist[strlen(global_tunable) + strlen(".security") + 1];
609 char key_ro[strlen(global_default) + strlen(".security") + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800610 struct cache2_property_size local = {
611 /* clang-format off */
612 PTHREAD_MUTEX_INITIALIZER, 0,
613 key_persist, { { NULL, -1 }, {} },
614 key_ro, { { NULL, -1 }, {} },
615 evaluate_property_get_size
616 /* clang-format on */
617 };
618 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700619
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800620 default_size = do_cache2_property_size(&global);
621 if (!default_size) {
622 default_size = __android_logger_property_get_bool("ro.config.low_ram",
623 BOOL_DEFAULT_FALSE)
624 ? LOG_BUFFER_MIN_SIZE /* 64K */
625 : LOG_BUFFER_SIZE; /* 256K */
626 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700627
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800628 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
629 android_log_id_to_name(logId));
630 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default,
631 android_log_id_to_name(logId));
632 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700633
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800634 if (!property_size) {
635 property_size = default_size;
636 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700637
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800638 if (!property_size) {
639 property_size = LOG_BUFFER_SIZE;
640 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700641
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800642 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800643}