blob: a53c92b81dee3fc36ced607a9120ec02913adee0 [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
Tom Cherry0391a872020-01-16 15:58:02 -080027#include <algorithm>
28
Mark Salyzyne4553732016-09-26 13:21:05 -070029#include <private/android_logger.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070030
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080031static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
32
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080033static int lock() {
34 /*
35 * If we trigger a signal handler in the middle of locked activity and the
36 * signal handler logs a message, we could get into a deadlock state.
37 */
38 /*
39 * Any contention, and we can turn around and use the non-cached method
40 * in less time than the system call associated with a mutex to deal with
41 * the contention.
42 */
43 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080044}
45
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080046static void unlock() {
47 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080048}
49
Mark Salyzync1584562015-03-12 15:46:29 -070050struct cache {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080051 const prop_info* pinfo;
52 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -070053};
54
55struct cache_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080056 struct cache cache;
57 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070058};
59
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080060static int check_cache(struct cache* cache) {
61 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzyna67d8a52015-12-21 12:32:48 -080062}
63
Mark Salyzynffbd86f2015-12-04 10:59:45 -080064#define BOOLEAN_TRUE 0xFF
65#define BOOLEAN_FALSE 0xFE
66
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080067static void refresh_cache(struct cache_char* cache, const char* key) {
68 char buf[PROP_VALUE_MAX];
Mark Salyzyn95687052014-10-02 11:12:28 -070069
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080070 if (!cache->cache.pinfo) {
71 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -070072 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080073 return;
Mark Salyzyn95687052014-10-02 11:12:28 -070074 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080075 }
76 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
77 __system_property_read(cache->cache.pinfo, 0, buf);
78 switch (buf[0]) {
79 case 't':
80 case 'T':
81 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
82 break;
83 case 'f':
84 case 'F':
85 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
86 break;
Mark Salyzynffbd86f2015-12-04 10:59:45 -080087 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080088 cache->c = buf[0];
89 }
Mark Salyzync1584562015-03-12 15:46:29 -070090}
Mark Salyzyn95687052014-10-02 11:12:28 -070091
Tom Cherry0391a872020-01-16 15:58:02 -080092static int __android_log_level(const char* tag, size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080093 /* sizeof() is used on this array below */
94 static const char log_namespace[] = "persist.log.tag.";
95 static const size_t base_offset = 8; /* skip "persist." */
96 /* calculate the size of our key temporary buffer */
97 const size_t taglen = tag ? len : 0;
98 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Mark Salyzynd24dc952017-04-05 10:11:09 -070099 char key[sizeof(log_namespace) + taglen];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800100 char* kp;
101 size_t i;
102 char c = 0;
103 /*
104 * Single layer cache of four properties. Priorities are:
105 * log.tag.<tag>
106 * persist.log.tag.<tag>
107 * log.tag
108 * persist.log.tag
109 * Where the missing tag matches all tags and becomes the
110 * system global default. We do not support ro.log.tag* .
111 */
Mark Salyzynd24dc952017-04-05 10:11:09 -0700112 static char* last_tag;
113 static size_t last_tag_len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800114 static uint32_t global_serial;
115 /* some compilers erroneously see uninitialized use. !not_locked */
116 uint32_t current_global_serial = 0;
117 static struct cache_char tag_cache[2];
118 static struct cache_char global_cache[2];
119 int change_detected;
120 int global_change_detected;
121 int not_locked;
122
123 strcpy(key, log_namespace);
124
125 global_change_detected = change_detected = not_locked = lock();
126
127 if (!not_locked) {
Mark Salyzync1584562015-03-12 15:46:29 -0700128 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800129 * check all known serial numbers to changes.
Mark Salyzync1584562015-03-12 15:46:29 -0700130 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800131 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
132 if (check_cache(&tag_cache[i].cache)) {
133 change_detected = 1;
134 }
135 }
136 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
137 if (check_cache(&global_cache[i].cache)) {
138 global_change_detected = 1;
139 }
140 }
Mark Salyzync1584562015-03-12 15:46:29 -0700141
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800142 current_global_serial = __system_property_area_serial();
143 if (current_global_serial != global_serial) {
144 change_detected = 1;
145 global_change_detected = 1;
146 }
147 }
Mark Salyzync1584562015-03-12 15:46:29 -0700148
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800149 if (taglen) {
150 int local_change_detected = change_detected;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800151 if (!not_locked) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700152 if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
153 strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800154 /* invalidate log.tag.<tag> cache */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800155 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800156 tag_cache[i].cache.pinfo = NULL;
157 tag_cache[i].c = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800158 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700159 if (last_tag) last_tag[0] = '\0';
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800160 local_change_detected = 1;
161 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700162 if (!last_tag || !last_tag[0]) {
163 if (!last_tag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800164 last_tag = static_cast<char*>(calloc(1, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700165 last_tag_len = 0;
166 if (last_tag) last_tag_len = len + 1;
167 } else if (len >= last_tag_len) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800168 last_tag = static_cast<char*>(realloc(last_tag, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700169 last_tag_len = 0;
170 if (last_tag) last_tag_len = len + 1;
171 }
172 if (last_tag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800173 strncpy(last_tag, tag, len);
174 last_tag[len] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800175 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800176 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800177 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800178 strncpy(key + sizeof(log_namespace) - 1, tag, len);
179 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700180
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800181 kp = key;
182 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
183 struct cache_char* cache = &tag_cache[i];
184 struct cache_char temp_cache;
Mark Salyzyn95687052014-10-02 11:12:28 -0700185
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800186 if (not_locked) {
187 temp_cache.cache.pinfo = NULL;
188 temp_cache.c = '\0';
189 cache = &temp_cache;
190 }
191 if (local_change_detected) {
192 refresh_cache(cache, kp);
193 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800194
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800195 if (cache->c) {
196 c = cache->c;
197 break;
198 }
Mark Salyzync1584562015-03-12 15:46:29 -0700199
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800200 kp = key + base_offset;
Mark Salyzyn95687052014-10-02 11:12:28 -0700201 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800202 }
Mark Salyzync1584562015-03-12 15:46:29 -0700203
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800204 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzync1584562015-03-12 15:46:29 -0700205 case 'V':
206 case 'D':
207 case 'I':
208 case 'W':
209 case 'E':
210 case 'F': /* Not officially supported */
211 case 'A':
212 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800213 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800214 break;
Mark Salyzync1584562015-03-12 15:46:29 -0700215 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800216 /* clear '.' after log.tag */
217 key[sizeof(log_namespace) - 2] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700218
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800219 kp = key;
220 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
221 struct cache_char* cache = &global_cache[i];
222 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800223
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800224 if (not_locked) {
225 temp_cache = *cache;
226 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
227 temp_cache.cache.pinfo = NULL;
228 temp_cache.c = '\0';
229 }
230 cache = &temp_cache;
Mark Salyzync1584562015-03-12 15:46:29 -0700231 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800232 if (global_change_detected) {
233 refresh_cache(cache, kp);
234 }
Mark Salyzync1584562015-03-12 15:46:29 -0700235
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800236 if (cache->c) {
237 c = cache->c;
238 break;
239 }
Mark Salyzync1584562015-03-12 15:46:29 -0700240
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800241 kp = key + base_offset;
242 }
243 break;
244 }
245
246 if (!not_locked) {
247 global_serial = current_global_serial;
248 unlock();
249 }
250
251 switch (toupper(c)) {
252 /* clang-format off */
Mark Salyzync1584562015-03-12 15:46:29 -0700253 case 'V': return ANDROID_LOG_VERBOSE;
254 case 'D': return ANDROID_LOG_DEBUG;
255 case 'I': return ANDROID_LOG_INFO;
256 case 'W': return ANDROID_LOG_WARN;
257 case 'E': return ANDROID_LOG_ERROR;
258 case 'F': /* FALLTHRU */ /* Not officially supported */
259 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800260 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Tom Cherry0391a872020-01-16 15:58:02 -0800261 case 'S': return ANDROID_LOG_SILENT;
Tom Cherry71ba1642019-01-10 10:37:36 -0800262 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800263 }
Tom Cherry0391a872020-01-16 15:58:02 -0800264 return -1;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800265}
266
Tom Cherry2d9779e2019-02-08 11:46:19 -0800267int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800268 int minimum_log_priority = __android_log_get_minimum_priority();
269 int property_log_level = __android_log_level(tag, len);
270
271 if (property_log_level >= 0 && minimum_log_priority != ANDROID_LOG_DEFAULT) {
272 return prio >= std::min(property_log_level, minimum_log_priority);
273 } else if (property_log_level >= 0) {
274 return prio >= property_log_level;
275 } else if (minimum_log_priority != ANDROID_LOG_DEFAULT) {
276 return prio >= minimum_log_priority;
277 } else {
278 return prio >= default_prio;
279 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800280}
281
Tom Cherry2d9779e2019-02-08 11:46:19 -0800282int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800283 auto len = tag ? strlen(tag) : 0;
284 return __android_log_is_loggable_len(prio, tag, len, default_prio);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800285}
286
Tom Cherry2d9779e2019-02-08 11:46:19 -0800287int __android_log_is_debuggable() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800288 static uint32_t serial;
289 static struct cache_char tag_cache;
290 static const char key[] = "ro.debuggable";
291 int ret;
292
293 if (tag_cache.c) { /* ro property does not change after set */
294 ret = tag_cache.c == '1';
295 } else if (lock()) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800296 struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800297 refresh_cache(&temp_cache, key);
298 ret = temp_cache.c == '1';
299 } else {
300 int change_detected = check_cache(&tag_cache.cache);
301 uint32_t current_serial = __system_property_area_serial();
302 if (current_serial != serial) {
303 change_detected = 1;
Mark Salyzyn95687052014-10-02 11:12:28 -0700304 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800305 if (change_detected) {
306 refresh_cache(&tag_cache, key);
307 serial = current_serial;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700308 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800309 ret = tag_cache.c == '1';
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700310
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800311 unlock();
312 }
313
314 return ret;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700315}
316
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800317/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800318 * For properties that are read often, but generally remain constant.
319 * Since a change is rare, we will accept a trylock failure gracefully.
320 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800321 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700322struct cache2_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800323 pthread_mutex_t lock;
324 uint32_t serial;
325 const char* key_persist;
326 struct cache_char cache_persist;
327 const char* key_ro;
328 struct cache_char cache_ro;
329 unsigned char (*const evaluate)(const struct cache2_char* self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800330};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800331
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800332static inline unsigned char do_cache2_char(struct cache2_char* self) {
333 uint32_t current_serial;
334 int change_detected;
335 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700336
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800337 if (pthread_mutex_trylock(&self->lock)) {
338 /* We are willing to accept some race in this context */
339 return self->evaluate(self);
340 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700341
Tom Cherry71ba1642019-01-10 10:37:36 -0800342 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800343 current_serial = __system_property_area_serial();
344 if (current_serial != self->serial) {
345 change_detected = 1;
346 }
347 if (change_detected) {
348 refresh_cache(&self->cache_persist, self->key_persist);
349 refresh_cache(&self->cache_ro, self->key_ro);
350 self->serial = current_serial;
351 }
352 c = self->evaluate(self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800353
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800354 pthread_mutex_unlock(&self->lock);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800355
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800356 return c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800357}
358
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800359static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
360 unsigned char c = self->cache_persist.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800361
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800362 if (c) {
363 return c;
364 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800365
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800366 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700367}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800368
369/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800370 * Timestamp state generally remains constant, but can change at any time
371 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800372 */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800373clockid_t android_log_clockid() {
Tom Cherry71ba1642019-01-10 10:37:36 -0800374 static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
375 "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
376 "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
377 evaluate_persist_ro};
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800378
Tom Cherry71ba1642019-01-10 10:37:36 -0800379 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800380}
381
382/*
383 * Security state generally remains constant, but the DO must be able
384 * to turn off logging should it become spammy after an attack is detected.
385 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800386static unsigned char evaluate_security(const struct cache2_char* self) {
387 unsigned char c = self->cache_ro.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800388
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800389 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800390}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800391
Tom Cherry2d9779e2019-02-08 11:46:19 -0800392int __android_log_security() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800393 static struct cache2_char security = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800394 PTHREAD_MUTEX_INITIALIZER, 0,
395 "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
396 "ro.device_owner", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
397 evaluate_security};
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800398
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800399 return do_cache2_char(&security);
Mark Salyzyne4553732016-09-26 13:21:05 -0700400}
401
402/*
403 * Interface that represents the logd buffer size determination so that others
404 * need not guess our intentions.
405 */
406
407/* Property helper */
408static bool check_flag(const char* prop, const char* flag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800409 const char* cp = strcasestr(prop, flag);
410 if (!cp) {
411 return false;
412 }
413 /* We only will document comma (,) */
414 static const char sep[] = ",:;|+ \t\f";
415 if ((cp != prop) && !strchr(sep, cp[-1])) {
416 return false;
417 }
418 cp += strlen(flag);
419 return !*cp || !!strchr(sep, *cp);
Mark Salyzyne4553732016-09-26 13:21:05 -0700420}
421
422/* cache structure */
423struct cache_property {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800424 struct cache cache;
425 char property[PROP_VALUE_MAX];
Mark Salyzyne4553732016-09-26 13:21:05 -0700426};
427
Tom Cherry71ba1642019-01-10 10:37:36 -0800428static void refresh_cache_property(struct cache_property* cache, const char* key) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800429 if (!cache->cache.pinfo) {
430 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700431 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800432 return;
Mark Salyzyne4553732016-09-26 13:21:05 -0700433 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800434 }
435 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
436 __system_property_read(cache->cache.pinfo, 0, cache->property);
Mark Salyzyne4553732016-09-26 13:21:05 -0700437}
438
439/* get boolean with the logger twist that supports eng adjustments */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800440bool __android_logger_property_get_bool(const char* key, int flag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800441 struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800442 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;
Tom Cherry71ba1642019-01-10 10:37:36 -0800447 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800448 snprintf(newkey, sizeof(newkey), "persist.%s", key);
449 refresh_cache_property(&property, newkey);
450 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800451 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800452 }
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) &&
Tom Cherry71ba1642019-01-10 10:37:36 -0800480 __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800481 return false;
482 }
483 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
484 return false;
485 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700486
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800487 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700488}
489
Tom Cherry2d9779e2019-02-08 11:46:19 -0800490bool __android_logger_valid_buffer_size(unsigned long value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800491 static long pages, pagesize;
492 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700493
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800494 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
495 return false;
496 }
497
498 if (!pages) {
499 pages = sysconf(_SC_PHYS_PAGES);
500 }
501 if (pages < 1) {
502 return true;
503 }
504
505 if (!pagesize) {
506 pagesize = sysconf(_SC_PAGESIZE);
507 if (pagesize <= 1) {
508 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700509 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800510 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700511
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800512 /* maximum memory impact a somewhat arbitrary ~3% */
513 pages = (pages + 31) / 32;
514 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700515
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800516 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
517 return true;
518 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700519
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800520 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700521}
522
523struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800524 pthread_mutex_t lock;
525 uint32_t serial;
526 const char* key_persist;
527 struct cache_property cache_persist;
528 const char* key_ro;
529 struct cache_property cache_ro;
530 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700531};
532
Tom Cherry71ba1642019-01-10 10:37:36 -0800533static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800534 uint32_t current_serial;
535 int change_detected;
536 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700537
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800538 if (pthread_mutex_trylock(&self->lock)) {
539 /* We are willing to accept some race in this context */
540 return self->evaluate(self);
541 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700542
Tom Cherry71ba1642019-01-10 10:37:36 -0800543 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800544 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
Tom Cherry71ba1642019-01-10 10:37:36 -0800560static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800561 char* cp;
562 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700563
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800564 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700565 case 'm':
566 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800567 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800568 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700569 case 'k':
570 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800571 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800572 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700573 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800574 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700575
576 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800577 value = 0;
578 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700579
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800580 if (!__android_logger_valid_buffer_size(value)) {
581 value = 0;
582 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700583
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800584 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700585}
586
Tom Cherry71ba1642019-01-10 10:37:36 -0800587static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800588 unsigned long size = property_get_size_from_cache(&self->cache_persist);
589 if (size) {
590 return size;
591 }
592 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700593}
594
Tom Cherry2d9779e2019-02-08 11:46:19 -0800595unsigned long __android_logger_get_buffer_size(log_id_t logId) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800596 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
597 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
598 static struct cache2_property_size global = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800599 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800600 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800601 global_tunable, { { NULL, 0xFFFFFFFF }, {} },
602 global_default, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800603 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800604 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800605 };
Mark Salyzynd24dc952017-04-05 10:11:09 -0700606 char key_persist[strlen(global_tunable) + strlen(".security") + 1];
607 char key_ro[strlen(global_default) + strlen(".security") + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800608 struct cache2_property_size local = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800609 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800610 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800611 key_persist, { { NULL, 0xFFFFFFFF }, {} },
612 key_ro, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800613 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800614 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800615 };
616 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700617
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800618 default_size = do_cache2_property_size(&global);
619 if (!default_size) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800620 default_size = __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800621 ? LOG_BUFFER_MIN_SIZE /* 64K */
622 : LOG_BUFFER_SIZE; /* 256K */
623 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700624
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800625 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
626 android_log_id_to_name(logId));
Tom Cherry71ba1642019-01-10 10:37:36 -0800627 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800628 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700629
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800630 if (!property_size) {
631 property_size = default_size;
632 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700633
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800634 if (!property_size) {
635 property_size = LOG_BUFFER_SIZE;
636 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700637
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800638 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800639}