blob: abd48fcd45c977e0b5b27d08d616b98276afcf59 [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 Salyzyne4553732016-09-26 13:21:05 -070023#include <unistd.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070024
Tom Cherry0391a872020-01-16 15:58:02 -080025#include <algorithm>
Tom Cherry2ec6a532020-01-27 08:35:13 -080026#include <shared_mutex>
Tom Cherry0391a872020-01-16 15:58:02 -080027
Mark Salyzyne4553732016-09-26 13:21:05 -070028#include <private/android_logger.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070029
Tom Cherry2ec6a532020-01-27 08:35:13 -080030#include "logger_write.h"
31
Tom Cherrye2187bf2020-01-27 15:45:52 -080032#ifdef __ANDROID__
33#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
34#include <sys/_system_properties.h>
35
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080036static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
37
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080038static int lock() {
39 /*
40 * If we trigger a signal handler in the middle of locked activity and the
41 * signal handler logs a message, we could get into a deadlock state.
42 */
43 /*
44 * Any contention, and we can turn around and use the non-cached method
45 * in less time than the system call associated with a mutex to deal with
46 * the contention.
47 */
48 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080049}
50
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080051static void unlock() {
52 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080053}
54
Mark Salyzync1584562015-03-12 15:46:29 -070055struct cache {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080056 const prop_info* pinfo;
57 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -070058};
59
60struct cache_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080061 struct cache cache;
62 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070063};
64
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080065static int check_cache(struct cache* cache) {
66 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzyna67d8a52015-12-21 12:32:48 -080067}
68
Mark Salyzynffbd86f2015-12-04 10:59:45 -080069#define BOOLEAN_TRUE 0xFF
70#define BOOLEAN_FALSE 0xFE
71
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080072static void refresh_cache(struct cache_char* cache, const char* key) {
73 char buf[PROP_VALUE_MAX];
Mark Salyzyn95687052014-10-02 11:12:28 -070074
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080075 if (!cache->cache.pinfo) {
76 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -070077 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080078 return;
Mark Salyzyn95687052014-10-02 11:12:28 -070079 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080080 }
81 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
82 __system_property_read(cache->cache.pinfo, 0, buf);
83 switch (buf[0]) {
84 case 't':
85 case 'T':
86 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
87 break;
88 case 'f':
89 case 'F':
90 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
91 break;
Mark Salyzynffbd86f2015-12-04 10:59:45 -080092 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080093 cache->c = buf[0];
94 }
Mark Salyzync1584562015-03-12 15:46:29 -070095}
Mark Salyzyn95687052014-10-02 11:12:28 -070096
Tom Cherry0391a872020-01-16 15:58:02 -080097static int __android_log_level(const char* tag, size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080098 /* sizeof() is used on this array below */
99 static const char log_namespace[] = "persist.log.tag.";
100 static const size_t base_offset = 8; /* skip "persist." */
Tom Cherry2ec6a532020-01-27 08:35:13 -0800101
102 auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
103 if (tag == nullptr || len == 0) {
104 tag_lock.lock();
105 auto& tag_string = GetDefaultTag();
106 tag = tag_string.c_str();
107 len = tag_string.size();
108 }
109
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800110 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Tom Cherry2ec6a532020-01-27 08:35:13 -0800111 char key[sizeof(log_namespace) + len];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800112 char* kp;
113 size_t i;
114 char c = 0;
115 /*
116 * Single layer cache of four properties. Priorities are:
117 * log.tag.<tag>
118 * persist.log.tag.<tag>
119 * log.tag
120 * persist.log.tag
121 * Where the missing tag matches all tags and becomes the
122 * system global default. We do not support ro.log.tag* .
123 */
Mark Salyzynd24dc952017-04-05 10:11:09 -0700124 static char* last_tag;
125 static size_t last_tag_len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800126 static uint32_t global_serial;
127 /* some compilers erroneously see uninitialized use. !not_locked */
128 uint32_t current_global_serial = 0;
129 static struct cache_char tag_cache[2];
130 static struct cache_char global_cache[2];
131 int change_detected;
132 int global_change_detected;
133 int not_locked;
134
135 strcpy(key, log_namespace);
136
137 global_change_detected = change_detected = not_locked = lock();
138
139 if (!not_locked) {
Mark Salyzync1584562015-03-12 15:46:29 -0700140 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800141 * check all known serial numbers to changes.
Mark Salyzync1584562015-03-12 15:46:29 -0700142 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800143 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
144 if (check_cache(&tag_cache[i].cache)) {
145 change_detected = 1;
146 }
147 }
148 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
149 if (check_cache(&global_cache[i].cache)) {
150 global_change_detected = 1;
151 }
152 }
Mark Salyzync1584562015-03-12 15:46:29 -0700153
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800154 current_global_serial = __system_property_area_serial();
155 if (current_global_serial != global_serial) {
156 change_detected = 1;
157 global_change_detected = 1;
158 }
159 }
Mark Salyzync1584562015-03-12 15:46:29 -0700160
Tom Cherry2ec6a532020-01-27 08:35:13 -0800161 if (len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800162 int local_change_detected = change_detected;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800163 if (!not_locked) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700164 if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
165 strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800166 /* invalidate log.tag.<tag> cache */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800167 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800168 tag_cache[i].cache.pinfo = NULL;
169 tag_cache[i].c = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800170 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700171 if (last_tag) last_tag[0] = '\0';
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800172 local_change_detected = 1;
173 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700174 if (!last_tag || !last_tag[0]) {
175 if (!last_tag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800176 last_tag = static_cast<char*>(calloc(1, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700177 last_tag_len = 0;
178 if (last_tag) last_tag_len = len + 1;
179 } else if (len >= last_tag_len) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800180 last_tag = static_cast<char*>(realloc(last_tag, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700181 last_tag_len = 0;
182 if (last_tag) last_tag_len = len + 1;
183 }
184 if (last_tag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800185 strncpy(last_tag, tag, len);
186 last_tag[len] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800187 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800188 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800189 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800190 strncpy(key + sizeof(log_namespace) - 1, tag, len);
191 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700192
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800193 kp = key;
194 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
195 struct cache_char* cache = &tag_cache[i];
196 struct cache_char temp_cache;
Mark Salyzyn95687052014-10-02 11:12:28 -0700197
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800198 if (not_locked) {
199 temp_cache.cache.pinfo = NULL;
200 temp_cache.c = '\0';
201 cache = &temp_cache;
202 }
203 if (local_change_detected) {
204 refresh_cache(cache, kp);
205 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800206
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800207 if (cache->c) {
208 c = cache->c;
209 break;
210 }
Mark Salyzync1584562015-03-12 15:46:29 -0700211
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800212 kp = key + base_offset;
Mark Salyzyn95687052014-10-02 11:12:28 -0700213 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800214 }
Mark Salyzync1584562015-03-12 15:46:29 -0700215
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800216 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzync1584562015-03-12 15:46:29 -0700217 case 'V':
218 case 'D':
219 case 'I':
220 case 'W':
221 case 'E':
222 case 'F': /* Not officially supported */
223 case 'A':
224 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800225 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800226 break;
Mark Salyzync1584562015-03-12 15:46:29 -0700227 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800228 /* clear '.' after log.tag */
229 key[sizeof(log_namespace) - 2] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700230
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800231 kp = key;
232 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
233 struct cache_char* cache = &global_cache[i];
234 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800235
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800236 if (not_locked) {
237 temp_cache = *cache;
238 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
239 temp_cache.cache.pinfo = NULL;
240 temp_cache.c = '\0';
241 }
242 cache = &temp_cache;
Mark Salyzync1584562015-03-12 15:46:29 -0700243 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800244 if (global_change_detected) {
245 refresh_cache(cache, kp);
246 }
Mark Salyzync1584562015-03-12 15:46:29 -0700247
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800248 if (cache->c) {
249 c = cache->c;
250 break;
251 }
Mark Salyzync1584562015-03-12 15:46:29 -0700252
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800253 kp = key + base_offset;
254 }
255 break;
256 }
257
258 if (!not_locked) {
259 global_serial = current_global_serial;
260 unlock();
261 }
262
263 switch (toupper(c)) {
264 /* clang-format off */
Mark Salyzync1584562015-03-12 15:46:29 -0700265 case 'V': return ANDROID_LOG_VERBOSE;
266 case 'D': return ANDROID_LOG_DEBUG;
267 case 'I': return ANDROID_LOG_INFO;
268 case 'W': return ANDROID_LOG_WARN;
269 case 'E': return ANDROID_LOG_ERROR;
270 case 'F': /* FALLTHRU */ /* Not officially supported */
271 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800272 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Tom Cherry0391a872020-01-16 15:58:02 -0800273 case 'S': return ANDROID_LOG_SILENT;
Tom Cherry71ba1642019-01-10 10:37:36 -0800274 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800275 }
Tom Cherry0391a872020-01-16 15:58:02 -0800276 return -1;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800277}
278
Tom Cherry2d9779e2019-02-08 11:46:19 -0800279int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800280 int minimum_log_priority = __android_log_get_minimum_priority();
281 int property_log_level = __android_log_level(tag, len);
282
283 if (property_log_level >= 0 && minimum_log_priority != ANDROID_LOG_DEFAULT) {
284 return prio >= std::min(property_log_level, minimum_log_priority);
285 } else if (property_log_level >= 0) {
286 return prio >= property_log_level;
287 } else if (minimum_log_priority != ANDROID_LOG_DEFAULT) {
288 return prio >= minimum_log_priority;
289 } else {
290 return prio >= default_prio;
291 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800292}
293
Tom Cherry2d9779e2019-02-08 11:46:19 -0800294int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800295 auto len = tag ? strlen(tag) : 0;
296 return __android_log_is_loggable_len(prio, tag, len, default_prio);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800297}
298
Tom Cherry2d9779e2019-02-08 11:46:19 -0800299int __android_log_is_debuggable() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800300 static uint32_t serial;
301 static struct cache_char tag_cache;
302 static const char key[] = "ro.debuggable";
303 int ret;
304
305 if (tag_cache.c) { /* ro property does not change after set */
306 ret = tag_cache.c == '1';
307 } else if (lock()) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800308 struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800309 refresh_cache(&temp_cache, key);
310 ret = temp_cache.c == '1';
311 } else {
312 int change_detected = check_cache(&tag_cache.cache);
313 uint32_t current_serial = __system_property_area_serial();
314 if (current_serial != serial) {
315 change_detected = 1;
Mark Salyzyn95687052014-10-02 11:12:28 -0700316 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800317 if (change_detected) {
318 refresh_cache(&tag_cache, key);
319 serial = current_serial;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700320 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800321 ret = tag_cache.c == '1';
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700322
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800323 unlock();
324 }
325
326 return ret;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700327}
328
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800329/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800330 * For properties that are read often, but generally remain constant.
331 * Since a change is rare, we will accept a trylock failure gracefully.
332 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800333 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700334struct cache2_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800335 pthread_mutex_t lock;
336 uint32_t serial;
337 const char* key_persist;
338 struct cache_char cache_persist;
339 const char* key_ro;
340 struct cache_char cache_ro;
341 unsigned char (*const evaluate)(const struct cache2_char* self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800342};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800343
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800344static inline unsigned char do_cache2_char(struct cache2_char* self) {
345 uint32_t current_serial;
346 int change_detected;
347 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700348
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800349 if (pthread_mutex_trylock(&self->lock)) {
350 /* We are willing to accept some race in this context */
351 return self->evaluate(self);
352 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700353
Tom Cherry71ba1642019-01-10 10:37:36 -0800354 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800355 current_serial = __system_property_area_serial();
356 if (current_serial != self->serial) {
357 change_detected = 1;
358 }
359 if (change_detected) {
360 refresh_cache(&self->cache_persist, self->key_persist);
361 refresh_cache(&self->cache_ro, self->key_ro);
362 self->serial = current_serial;
363 }
364 c = self->evaluate(self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800365
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800366 pthread_mutex_unlock(&self->lock);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800367
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800368 return c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800369}
370
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800371static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
372 unsigned char c = self->cache_persist.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800373
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800374 if (c) {
375 return c;
376 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800377
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800378 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700379}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800380
381/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800382 * Timestamp state generally remains constant, but can change at any time
383 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800384 */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800385clockid_t android_log_clockid() {
Tom Cherry71ba1642019-01-10 10:37:36 -0800386 static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
387 "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
388 "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
389 evaluate_persist_ro};
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800390
Tom Cherry71ba1642019-01-10 10:37:36 -0800391 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800392}
393
394/*
395 * Security state generally remains constant, but the DO must be able
396 * to turn off logging should it become spammy after an attack is detected.
397 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800398static unsigned char evaluate_security(const struct cache2_char* self) {
399 unsigned char c = self->cache_ro.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800400
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800401 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800402}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800403
Tom Cherry2d9779e2019-02-08 11:46:19 -0800404int __android_log_security() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800405 static struct cache2_char security = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800406 PTHREAD_MUTEX_INITIALIZER, 0,
407 "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
Rubin Xu7a5cbfc2020-02-17 11:42:54 +0000408 "ro.organization_owned", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
Tom Cherry71ba1642019-01-10 10:37:36 -0800409 evaluate_security};
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800410
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800411 return do_cache2_char(&security);
Mark Salyzyne4553732016-09-26 13:21:05 -0700412}
413
414/*
415 * Interface that represents the logd buffer size determination so that others
416 * need not guess our intentions.
417 */
418
419/* Property helper */
420static bool check_flag(const char* prop, const char* flag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800421 const char* cp = strcasestr(prop, flag);
422 if (!cp) {
423 return false;
424 }
425 /* We only will document comma (,) */
426 static const char sep[] = ",:;|+ \t\f";
427 if ((cp != prop) && !strchr(sep, cp[-1])) {
428 return false;
429 }
430 cp += strlen(flag);
431 return !*cp || !!strchr(sep, *cp);
Mark Salyzyne4553732016-09-26 13:21:05 -0700432}
433
434/* cache structure */
435struct cache_property {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800436 struct cache cache;
437 char property[PROP_VALUE_MAX];
Mark Salyzyne4553732016-09-26 13:21:05 -0700438};
439
Tom Cherry71ba1642019-01-10 10:37:36 -0800440static void refresh_cache_property(struct cache_property* cache, const char* key) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800441 if (!cache->cache.pinfo) {
442 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700443 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800444 return;
Mark Salyzyne4553732016-09-26 13:21:05 -0700445 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800446 }
447 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
448 __system_property_read(cache->cache.pinfo, 0, cache->property);
Mark Salyzyne4553732016-09-26 13:21:05 -0700449}
450
451/* get boolean with the logger twist that supports eng adjustments */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800452bool __android_logger_property_get_bool(const char* key, int flag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800453 struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800454 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700455 char newkey[strlen("persist.") + strlen(key) + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800456 snprintf(newkey, sizeof(newkey), "ro.%s", key);
457 refresh_cache_property(&property, newkey);
458 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800459 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800460 snprintf(newkey, sizeof(newkey), "persist.%s", key);
461 refresh_cache_property(&property, newkey);
462 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800463 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800464 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700465
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800466 refresh_cache_property(&property, key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700467
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800468 if (check_flag(property.property, "true")) {
469 return true;
470 }
471 if (check_flag(property.property, "false")) {
472 return false;
473 }
Mark Salyzyn9fcaaba2017-04-18 08:43:16 -0700474 if (property.property[0]) {
475 flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
476 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800477 if (check_flag(property.property, "eng")) {
478 flag |= BOOL_DEFAULT_FLAG_ENG;
479 }
480 /* this is really a "not" flag */
481 if (check_flag(property.property, "svelte")) {
482 flag |= BOOL_DEFAULT_FLAG_SVELTE;
483 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700484
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800485 /* Sanity Check */
486 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
487 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
488 flag |= BOOL_DEFAULT_TRUE;
489 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700490
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800491 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
Tom Cherry71ba1642019-01-10 10:37:36 -0800492 __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800493 return false;
494 }
495 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
496 return false;
497 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700498
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800499 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700500}
501
Tom Cherry2d9779e2019-02-08 11:46:19 -0800502bool __android_logger_valid_buffer_size(unsigned long value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800503 static long pages, pagesize;
504 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700505
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800506 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
507 return false;
508 }
509
510 if (!pages) {
511 pages = sysconf(_SC_PHYS_PAGES);
512 }
513 if (pages < 1) {
514 return true;
515 }
516
517 if (!pagesize) {
518 pagesize = sysconf(_SC_PAGESIZE);
519 if (pagesize <= 1) {
520 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700521 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800522 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700523
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800524 /* maximum memory impact a somewhat arbitrary ~3% */
525 pages = (pages + 31) / 32;
526 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700527
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800528 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
529 return true;
530 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700531
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800532 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700533}
534
535struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800536 pthread_mutex_t lock;
537 uint32_t serial;
538 const char* key_persist;
539 struct cache_property cache_persist;
540 const char* key_ro;
541 struct cache_property cache_ro;
542 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700543};
544
Tom Cherry71ba1642019-01-10 10:37:36 -0800545static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800546 uint32_t current_serial;
547 int change_detected;
548 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700549
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800550 if (pthread_mutex_trylock(&self->lock)) {
551 /* We are willing to accept some race in this context */
552 return self->evaluate(self);
553 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700554
Tom Cherry71ba1642019-01-10 10:37:36 -0800555 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800556 current_serial = __system_property_area_serial();
557 if (current_serial != self->serial) {
558 change_detected = 1;
559 }
560 if (change_detected) {
561 refresh_cache_property(&self->cache_persist, self->key_persist);
562 refresh_cache_property(&self->cache_ro, self->key_ro);
563 self->serial = current_serial;
564 }
565 v = self->evaluate(self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700566
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800567 pthread_mutex_unlock(&self->lock);
Mark Salyzyne4553732016-09-26 13:21:05 -0700568
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800569 return v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700570}
571
Tom Cherry71ba1642019-01-10 10:37:36 -0800572static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800573 char* cp;
574 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700575
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800576 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700577 case 'm':
578 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800579 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800580 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700581 case 'k':
582 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800583 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800584 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700585 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800586 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700587
588 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800589 value = 0;
590 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700591
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800592 if (!__android_logger_valid_buffer_size(value)) {
593 value = 0;
594 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700595
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800596 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700597}
598
Tom Cherry71ba1642019-01-10 10:37:36 -0800599static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800600 unsigned long size = property_get_size_from_cache(&self->cache_persist);
601 if (size) {
602 return size;
603 }
604 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700605}
606
Tom Cherry2d9779e2019-02-08 11:46:19 -0800607unsigned long __android_logger_get_buffer_size(log_id_t logId) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800608 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
609 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
610 static struct cache2_property_size global = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800611 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800612 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800613 global_tunable, { { NULL, 0xFFFFFFFF }, {} },
614 global_default, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800615 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800616 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800617 };
Mark Salyzynd24dc952017-04-05 10:11:09 -0700618 char key_persist[strlen(global_tunable) + strlen(".security") + 1];
619 char key_ro[strlen(global_default) + strlen(".security") + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800620 struct cache2_property_size local = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800621 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800622 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800623 key_persist, { { NULL, 0xFFFFFFFF }, {} },
624 key_ro, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800625 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800626 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800627 };
628 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700629
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800630 default_size = do_cache2_property_size(&global);
631 if (!default_size) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800632 default_size = __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800633 ? LOG_BUFFER_MIN_SIZE /* 64K */
634 : LOG_BUFFER_SIZE; /* 256K */
635 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700636
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800637 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
638 android_log_id_to_name(logId));
Tom Cherry71ba1642019-01-10 10:37:36 -0800639 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800640 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700641
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800642 if (!property_size) {
643 property_size = default_size;
644 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700645
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800646 if (!property_size) {
647 property_size = LOG_BUFFER_SIZE;
648 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700649
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800650 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800651}
Tom Cherrye2187bf2020-01-27 15:45:52 -0800652
653#else
654
655int __android_log_is_loggable(int prio, const char*, int) {
656 int minimum_priority = __android_log_get_minimum_priority();
657 if (minimum_priority == ANDROID_LOG_DEFAULT) {
658 minimum_priority = ANDROID_LOG_INFO;
659 }
660 return prio >= minimum_priority;
661}
662
663int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
664 return __android_log_is_loggable(prio, nullptr, def);
665}
666
667int __android_log_is_debuggable() {
668 return 1;
669}
670
671#endif