blob: 11be8279fb44849c635a9c113963faf10232b4e6 [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 }
Mark Salyzyn9fcaaba2017-04-18 08:43:16 -0700462 if (property.property[0]) {
463 flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
464 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800465 if (check_flag(property.property, "eng")) {
466 flag |= BOOL_DEFAULT_FLAG_ENG;
467 }
468 /* this is really a "not" flag */
469 if (check_flag(property.property, "svelte")) {
470 flag |= BOOL_DEFAULT_FLAG_SVELTE;
471 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700472
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800473 /* Sanity Check */
474 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
475 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
476 flag |= BOOL_DEFAULT_TRUE;
477 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700478
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800479 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
480 __android_logger_property_get_bool("ro.config.low_ram",
481 BOOL_DEFAULT_FALSE)) {
482 return false;
483 }
484 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
485 return false;
486 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700487
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800488 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700489}
490
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800491LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) {
492 static long pages, pagesize;
493 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700494
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800495 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
496 return false;
497 }
498
499 if (!pages) {
500 pages = sysconf(_SC_PHYS_PAGES);
501 }
502 if (pages < 1) {
503 return true;
504 }
505
506 if (!pagesize) {
507 pagesize = sysconf(_SC_PAGESIZE);
508 if (pagesize <= 1) {
509 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700510 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800511 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700512
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800513 /* maximum memory impact a somewhat arbitrary ~3% */
514 pages = (pages + 31) / 32;
515 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700516
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800517 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
518 return true;
519 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700520
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800521 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700522}
523
524struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800525 pthread_mutex_t lock;
526 uint32_t serial;
527 const char* key_persist;
528 struct cache_property cache_persist;
529 const char* key_ro;
530 struct cache_property cache_ro;
531 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700532};
533
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800534static inline unsigned long do_cache2_property_size(
535 struct cache2_property_size* self) {
536 uint32_t current_serial;
537 int change_detected;
538 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700539
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800540 if (pthread_mutex_trylock(&self->lock)) {
541 /* We are willing to accept some race in this context */
542 return self->evaluate(self);
543 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700544
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800545 change_detected = check_cache(&self->cache_persist.cache) ||
546 check_cache(&self->cache_ro.cache);
547 current_serial = __system_property_area_serial();
548 if (current_serial != self->serial) {
549 change_detected = 1;
550 }
551 if (change_detected) {
552 refresh_cache_property(&self->cache_persist, self->key_persist);
553 refresh_cache_property(&self->cache_ro, self->key_ro);
554 self->serial = current_serial;
555 }
556 v = self->evaluate(self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700557
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800558 pthread_mutex_unlock(&self->lock);
Mark Salyzyne4553732016-09-26 13:21:05 -0700559
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800560 return v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700561}
562
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800563static unsigned long property_get_size_from_cache(
564 const struct cache_property* cache) {
565 char* cp;
566 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700567
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800568 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700569 case 'm':
570 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800571 value *= 1024;
Mark Salyzyne4553732016-09-26 13:21:05 -0700572 /* FALLTHRU */
573 case 'k':
574 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800575 value *= 1024;
Mark Salyzyne4553732016-09-26 13:21:05 -0700576 /* FALLTHRU */
577 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800578 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700579
580 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800581 value = 0;
582 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700583
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800584 if (!__android_logger_valid_buffer_size(value)) {
585 value = 0;
586 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700587
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800588 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700589}
590
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800591static unsigned long evaluate_property_get_size(
592 const struct cache2_property_size* self) {
593 unsigned long size = property_get_size_from_cache(&self->cache_persist);
594 if (size) {
595 return size;
596 }
597 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700598}
599
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800600LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) {
601 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
602 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
603 static struct cache2_property_size global = {
604 /* clang-format off */
605 PTHREAD_MUTEX_INITIALIZER, 0,
606 global_tunable, { { NULL, -1 }, {} },
607 global_default, { { NULL, -1 }, {} },
608 evaluate_property_get_size
609 /* clang-format on */
610 };
Mark Salyzynd24dc952017-04-05 10:11:09 -0700611 char key_persist[strlen(global_tunable) + strlen(".security") + 1];
612 char key_ro[strlen(global_default) + strlen(".security") + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800613 struct cache2_property_size local = {
614 /* clang-format off */
615 PTHREAD_MUTEX_INITIALIZER, 0,
616 key_persist, { { NULL, -1 }, {} },
617 key_ro, { { NULL, -1 }, {} },
618 evaluate_property_get_size
619 /* clang-format on */
620 };
621 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700622
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800623 default_size = do_cache2_property_size(&global);
624 if (!default_size) {
625 default_size = __android_logger_property_get_bool("ro.config.low_ram",
626 BOOL_DEFAULT_FALSE)
627 ? LOG_BUFFER_MIN_SIZE /* 64K */
628 : LOG_BUFFER_SIZE; /* 256K */
629 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700630
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800631 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
632 android_log_id_to_name(logId));
633 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default,
634 android_log_id_to_name(logId));
635 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700636
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800637 if (!property_size) {
638 property_size = default_size;
639 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700640
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800641 if (!property_size) {
642 property_size = LOG_BUFFER_SIZE;
643 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700644
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800645 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800646}