blob: 0b0ef52052f1f8084e2e8402f1e8f2209ceed4dc [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 */
98 char key[sizeof(log_namespace) + taglen]; /* may be > PROP_NAME_MAX */
99 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 */
111 static char last_tag[PROP_NAME_MAX];
112 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 Salyzyn2ed51d72017-03-09 08:09:43 -0800150 if (!last_tag[0] || (last_tag[0] != tag[0]) ||
151 strncmp(
152 last_tag + 1, tag + 1,
153 (len < sizeof(last_tag)) ? (len - 1) : (sizeof(last_tag) - 1)) ||
154 ((len < sizeof(last_tag)) && last_tag[len])) {
155 /* invalidate log.tag.<tag> cache */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800156 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800157 tag_cache[i].cache.pinfo = NULL;
158 tag_cache[i].c = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800159 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800160 last_tag[0] = '\0';
161 local_change_detected = 1;
162 }
163 if (!last_tag[0]) {
164 if (len < sizeof(last_tag)) {
165 strncpy(last_tag, tag, len);
166 last_tag[len] = '\0';
167 } else {
168 strncpy(last_tag, tag, sizeof(last_tag));
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800169 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800170 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800171 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800172 strncpy(key + sizeof(log_namespace) - 1, tag, len);
173 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700174
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800175 kp = key;
176 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
177 struct cache_char* cache = &tag_cache[i];
178 struct cache_char temp_cache;
Mark Salyzyn95687052014-10-02 11:12:28 -0700179
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800180 if (not_locked) {
181 temp_cache.cache.pinfo = NULL;
182 temp_cache.c = '\0';
183 cache = &temp_cache;
184 }
185 if (local_change_detected) {
186 refresh_cache(cache, kp);
187 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800188
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800189 if (cache->c) {
190 c = cache->c;
191 break;
192 }
Mark Salyzync1584562015-03-12 15:46:29 -0700193
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800194 kp = key + base_offset;
Mark Salyzyn95687052014-10-02 11:12:28 -0700195 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800196 }
Mark Salyzync1584562015-03-12 15:46:29 -0700197
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800198 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzync1584562015-03-12 15:46:29 -0700199 case 'V':
200 case 'D':
201 case 'I':
202 case 'W':
203 case 'E':
204 case 'F': /* Not officially supported */
205 case 'A':
206 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800207 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800208 break;
Mark Salyzync1584562015-03-12 15:46:29 -0700209 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800210 /* clear '.' after log.tag */
211 key[sizeof(log_namespace) - 2] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700212
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800213 kp = key;
214 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
215 struct cache_char* cache = &global_cache[i];
216 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800217
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800218 if (not_locked) {
219 temp_cache = *cache;
220 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
221 temp_cache.cache.pinfo = NULL;
222 temp_cache.c = '\0';
223 }
224 cache = &temp_cache;
Mark Salyzync1584562015-03-12 15:46:29 -0700225 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800226 if (global_change_detected) {
227 refresh_cache(cache, kp);
228 }
Mark Salyzync1584562015-03-12 15:46:29 -0700229
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800230 if (cache->c) {
231 c = cache->c;
232 break;
233 }
Mark Salyzync1584562015-03-12 15:46:29 -0700234
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800235 kp = key + base_offset;
236 }
237 break;
238 }
239
240 if (!not_locked) {
241 global_serial = current_global_serial;
242 unlock();
243 }
244
245 switch (toupper(c)) {
246 /* clang-format off */
Mark Salyzync1584562015-03-12 15:46:29 -0700247 case 'V': return ANDROID_LOG_VERBOSE;
248 case 'D': return ANDROID_LOG_DEBUG;
249 case 'I': return ANDROID_LOG_INFO;
250 case 'W': return ANDROID_LOG_WARN;
251 case 'E': return ANDROID_LOG_ERROR;
252 case 'F': /* FALLTHRU */ /* Not officially supported */
253 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800254 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Mark Salyzync1584562015-03-12 15:46:29 -0700255 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800256 /* clang-format on */
257 }
258 return default_prio;
259}
260
261LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag,
262 size_t len,
263 int default_prio) {
264 int logLevel = __android_log_level(tag, len, default_prio);
265 return logLevel >= 0 && prio >= logLevel;
266}
267
268LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag,
269 int default_prio) {
270 int logLevel =
271 __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
272 return logLevel >= 0 && prio >= logLevel;
273}
274
275LIBLOG_ABI_PRIVATE int __android_log_is_debuggable() {
276 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()) {
284 struct cache_char temp_cache = { { NULL, -1 }, '\0' };
285 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
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800330 change_detected = check_cache(&self->cache_persist.cache) ||
331 check_cache(&self->cache_ro.cache);
332 current_serial = __system_property_area_serial();
333 if (current_serial != self->serial) {
334 change_detected = 1;
335 }
336 if (change_detected) {
337 refresh_cache(&self->cache_persist, self->key_persist);
338 refresh_cache(&self->cache_ro, self->key_ro);
339 self->serial = current_serial;
340 }
341 c = self->evaluate(self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800342
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800343 pthread_mutex_unlock(&self->lock);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800344
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800345 return c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800346}
347
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800348static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
349 unsigned char c = self->cache_persist.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800350
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800351 if (c) {
352 return c;
353 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800354
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800355 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700356}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800357
358/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800359 * Timestamp state generally remains constant, but can change at any time
360 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800361 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800362LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
363 static struct cache2_char clockid = {
364 PTHREAD_MUTEX_INITIALIZER, 0,
365 "persist.logd.timestamp", { { NULL, -1 }, '\0' },
366 "ro.logd.timestamp", { { NULL, -1 }, '\0' },
367 evaluate_persist_ro
368 };
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800369
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800370 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC
371 : CLOCK_REALTIME;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800372}
373
374/*
375 * Security state generally remains constant, but the DO must be able
376 * to turn off logging should it become spammy after an attack is detected.
377 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800378static unsigned char evaluate_security(const struct cache2_char* self) {
379 unsigned char c = self->cache_ro.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800380
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800381 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800382}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800383
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800384LIBLOG_ABI_PUBLIC int __android_log_security() {
385 static struct cache2_char security = {
386 PTHREAD_MUTEX_INITIALIZER, 0,
387 "persist.logd.security", { { NULL, -1 }, BOOLEAN_FALSE },
388 "ro.device_owner", { { NULL, -1 }, BOOLEAN_FALSE },
389 evaluate_security
390 };
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800391
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800392 return do_cache2_char(&security);
Mark Salyzyne4553732016-09-26 13:21:05 -0700393}
394
395/*
396 * Interface that represents the logd buffer size determination so that others
397 * need not guess our intentions.
398 */
399
400/* Property helper */
401static bool check_flag(const char* prop, const char* flag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800402 const char* cp = strcasestr(prop, flag);
403 if (!cp) {
404 return false;
405 }
406 /* We only will document comma (,) */
407 static const char sep[] = ",:;|+ \t\f";
408 if ((cp != prop) && !strchr(sep, cp[-1])) {
409 return false;
410 }
411 cp += strlen(flag);
412 return !*cp || !!strchr(sep, *cp);
Mark Salyzyne4553732016-09-26 13:21:05 -0700413}
414
415/* cache structure */
416struct cache_property {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800417 struct cache cache;
418 char property[PROP_VALUE_MAX];
Mark Salyzyne4553732016-09-26 13:21:05 -0700419};
420
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800421static void refresh_cache_property(struct cache_property* cache,
422 const char* key) {
423 if (!cache->cache.pinfo) {
424 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700425 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800426 return;
Mark Salyzyne4553732016-09-26 13:21:05 -0700427 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800428 }
429 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
430 __system_property_read(cache->cache.pinfo, 0, cache->property);
Mark Salyzyne4553732016-09-26 13:21:05 -0700431}
432
433/* get boolean with the logger twist that supports eng adjustments */
434LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800435 int flag) {
436 struct cache_property property = { { NULL, -1 }, { 0 } };
437 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
438 char newkey[PROP_NAME_MAX];
439 snprintf(newkey, sizeof(newkey), "ro.%s", key);
440 refresh_cache_property(&property, newkey);
441 property.cache.pinfo = NULL;
442 property.cache.serial = -1;
443 snprintf(newkey, sizeof(newkey), "persist.%s", key);
444 refresh_cache_property(&property, newkey);
445 property.cache.pinfo = NULL;
446 property.cache.serial = -1;
447 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700448
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800449 refresh_cache_property(&property, key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700450
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800451 if (check_flag(property.property, "true")) {
452 return true;
453 }
454 if (check_flag(property.property, "false")) {
455 return false;
456 }
457 if (check_flag(property.property, "eng")) {
458 flag |= BOOL_DEFAULT_FLAG_ENG;
459 }
460 /* this is really a "not" flag */
461 if (check_flag(property.property, "svelte")) {
462 flag |= BOOL_DEFAULT_FLAG_SVELTE;
463 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700464
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800465 /* Sanity Check */
466 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
467 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
468 flag |= BOOL_DEFAULT_TRUE;
469 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700470
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800471 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
472 __android_logger_property_get_bool("ro.config.low_ram",
473 BOOL_DEFAULT_FALSE)) {
474 return false;
475 }
476 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
477 return false;
478 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700479
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800480 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700481}
482
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800483LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) {
484 static long pages, pagesize;
485 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700486
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800487 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
488 return false;
489 }
490
491 if (!pages) {
492 pages = sysconf(_SC_PHYS_PAGES);
493 }
494 if (pages < 1) {
495 return true;
496 }
497
498 if (!pagesize) {
499 pagesize = sysconf(_SC_PAGESIZE);
500 if (pagesize <= 1) {
501 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700502 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800503 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700504
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800505 /* maximum memory impact a somewhat arbitrary ~3% */
506 pages = (pages + 31) / 32;
507 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700508
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800509 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
510 return true;
511 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700512
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800513 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700514}
515
516struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800517 pthread_mutex_t lock;
518 uint32_t serial;
519 const char* key_persist;
520 struct cache_property cache_persist;
521 const char* key_ro;
522 struct cache_property cache_ro;
523 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700524};
525
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800526static inline unsigned long do_cache2_property_size(
527 struct cache2_property_size* self) {
528 uint32_t current_serial;
529 int change_detected;
530 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700531
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800532 if (pthread_mutex_trylock(&self->lock)) {
533 /* We are willing to accept some race in this context */
534 return self->evaluate(self);
535 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700536
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800537 change_detected = check_cache(&self->cache_persist.cache) ||
538 check_cache(&self->cache_ro.cache);
539 current_serial = __system_property_area_serial();
540 if (current_serial != self->serial) {
541 change_detected = 1;
542 }
543 if (change_detected) {
544 refresh_cache_property(&self->cache_persist, self->key_persist);
545 refresh_cache_property(&self->cache_ro, self->key_ro);
546 self->serial = current_serial;
547 }
548 v = self->evaluate(self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700549
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800550 pthread_mutex_unlock(&self->lock);
Mark Salyzyne4553732016-09-26 13:21:05 -0700551
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800552 return v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700553}
554
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800555static unsigned long property_get_size_from_cache(
556 const struct cache_property* cache) {
557 char* cp;
558 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700559
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800560 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700561 case 'm':
562 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800563 value *= 1024;
Mark Salyzyne4553732016-09-26 13:21:05 -0700564 /* FALLTHRU */
565 case 'k':
566 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800567 value *= 1024;
Mark Salyzyne4553732016-09-26 13:21:05 -0700568 /* FALLTHRU */
569 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800570 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700571
572 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800573 value = 0;
574 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700575
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800576 if (!__android_logger_valid_buffer_size(value)) {
577 value = 0;
578 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700579
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800580 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700581}
582
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800583static unsigned long evaluate_property_get_size(
584 const struct cache2_property_size* self) {
585 unsigned long size = property_get_size_from_cache(&self->cache_persist);
586 if (size) {
587 return size;
588 }
589 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700590}
591
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800592LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) {
593 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
594 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
595 static struct cache2_property_size global = {
596 /* clang-format off */
597 PTHREAD_MUTEX_INITIALIZER, 0,
598 global_tunable, { { NULL, -1 }, {} },
599 global_default, { { NULL, -1 }, {} },
600 evaluate_property_get_size
601 /* clang-format on */
602 };
603 char key_persist[PROP_NAME_MAX];
604 char key_ro[PROP_NAME_MAX];
605 struct cache2_property_size local = {
606 /* clang-format off */
607 PTHREAD_MUTEX_INITIALIZER, 0,
608 key_persist, { { NULL, -1 }, {} },
609 key_ro, { { NULL, -1 }, {} },
610 evaluate_property_get_size
611 /* clang-format on */
612 };
613 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700614
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800615 default_size = do_cache2_property_size(&global);
616 if (!default_size) {
617 default_size = __android_logger_property_get_bool("ro.config.low_ram",
618 BOOL_DEFAULT_FALSE)
619 ? LOG_BUFFER_MIN_SIZE /* 64K */
620 : LOG_BUFFER_SIZE; /* 256K */
621 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700622
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800623 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
624 android_log_id_to_name(logId));
625 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default,
626 android_log_id_to_name(logId));
627 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700628
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800629 if (!property_size) {
630 property_size = default_size;
631 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700632
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800633 if (!property_size) {
634 property_size = LOG_BUFFER_SIZE;
635 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700636
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800637 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800638}