blob: dda09e09282d4b2781854be138098ff68a9e34fa [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 Salyzyna67d8a52015-12-21 12:32:48 -080032static int lock()
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080033{
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 */
Mark Salyzyna67d8a52015-12-21 12:32:48 -080038 /*
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
46static void unlock()
47{
48 pthread_mutex_unlock(&lock_loggable);
49}
50
Mark Salyzync1584562015-03-12 15:46:29 -070051struct cache {
Mark Salyzyne4553732016-09-26 13:21:05 -070052 const prop_info* pinfo;
Mark Salyzync1584562015-03-12 15:46:29 -070053 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -070054};
55
56struct cache_char {
57 struct cache cache;
Mark Salyzynb004a7f2015-12-08 14:52:11 -080058 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070059};
60
Mark Salyzyne4553732016-09-26 13:21:05 -070061static int check_cache(struct cache* cache)
Mark Salyzyna67d8a52015-12-21 12:32:48 -080062{
63 return cache->pinfo
64 && __system_property_serial(cache->pinfo) != cache->serial;
65}
66
Mark Salyzynffbd86f2015-12-04 10:59:45 -080067#define BOOLEAN_TRUE 0xFF
68#define BOOLEAN_FALSE 0xFE
69
Mark Salyzyne4553732016-09-26 13:21:05 -070070static void refresh_cache(struct cache_char* cache, const char* key)
Mark Salyzyn95687052014-10-02 11:12:28 -070071{
72 char buf[PROP_VALUE_MAX];
73
Mark Salyzyne4553732016-09-26 13:21:05 -070074 if (!cache->cache.pinfo) {
75 cache->cache.pinfo = __system_property_find(key);
76 if (!cache->cache.pinfo) {
Mark Salyzync1584562015-03-12 15:46:29 -070077 return;
78 }
Mark Salyzyn95687052014-10-02 11:12:28 -070079 }
Mark Salyzyne4553732016-09-26 13:21:05 -070080 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
81 __system_property_read(cache->cache.pinfo, 0, buf);
Mark Salyzynffbd86f2015-12-04 10:59:45 -080082 switch(buf[0]) {
83 case 't': case 'T':
84 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
85 break;
86 case 'f': case 'F':
87 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
88 break;
89 default:
90 cache->c = buf[0];
91 }
Mark Salyzync1584562015-03-12 15:46:29 -070092}
Mark Salyzyn95687052014-10-02 11:12:28 -070093
Mark Salyzyne4553732016-09-26 13:21:05 -070094static int __android_log_level(const char* tag, size_t len, int default_prio)
Mark Salyzync1584562015-03-12 15:46:29 -070095{
96 /* sizeof() is used on this array below */
97 static const char log_namespace[] = "persist.log.tag.";
98 static const size_t base_offset = 8; /* skip "persist." */
99 /* calculate the size of our key temporary buffer */
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700100 const size_t taglen = tag ? len : 0;
Mark Salyzync1584562015-03-12 15:46:29 -0700101 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700102 char key[sizeof(log_namespace) + taglen]; /* may be > PROP_NAME_MAX */
103 char* kp;
Mark Salyzync1584562015-03-12 15:46:29 -0700104 size_t i;
105 char c = 0;
106 /*
107 * Single layer cache of four properties. Priorities are:
108 * log.tag.<tag>
109 * persist.log.tag.<tag>
110 * log.tag
111 * persist.log.tag
112 * Where the missing tag matches all tags and becomes the
113 * system global default. We do not support ro.log.tag* .
114 */
Colin Cross7a106f72016-01-29 16:21:31 -0800115 static char last_tag[PROP_NAME_MAX];
Mark Salyzync1584562015-03-12 15:46:29 -0700116 static uint32_t global_serial;
Mark Salyzyn31ca3c32015-12-22 10:49:02 -0800117 /* some compilers erroneously see uninitialized use. !not_locked */
118 uint32_t current_global_serial = 0;
Mark Salyzyne4553732016-09-26 13:21:05 -0700119 static struct cache_char tag_cache[2];
120 static struct cache_char global_cache[2];
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800121 int change_detected;
122 int global_change_detected;
123 int not_locked;
Mark Salyzync1584562015-03-12 15:46:29 -0700124
125 strcpy(key, log_namespace);
126
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800127 global_change_detected = change_detected = not_locked = lock();
Mark Salyzync1584562015-03-12 15:46:29 -0700128
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800129 if (!not_locked) {
130 /*
131 * check all known serial numbers to changes.
132 */
133 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700134 if (check_cache(&tag_cache[i].cache)) {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800135 change_detected = 1;
136 }
137 }
138 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700139 if (check_cache(&global_cache[i].cache)) {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800140 global_change_detected = 1;
141 }
142 }
143
144 current_global_serial = __system_property_area_serial();
145 if (current_global_serial != global_serial) {
146 change_detected = 1;
147 global_change_detected = 1;
148 }
149 }
Mark Salyzync1584562015-03-12 15:46:29 -0700150
151 if (taglen) {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800152 int local_change_detected = change_detected;
153 if (!not_locked) {
Colin Cross7a106f72016-01-29 16:21:31 -0800154 if (!last_tag[0]
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800155 || (last_tag[0] != tag[0])
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700156 || strncmp(last_tag + 1, tag + 1,
157 (len < sizeof(last_tag)) ?
158 (len - 1) :
159 (sizeof(last_tag) - 1))
160 || ((len < sizeof(last_tag)) && last_tag[len])) {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800161 /* invalidate log.tag.<tag> cache */
162 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700163 tag_cache[i].cache.pinfo = NULL;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800164 tag_cache[i].c = '\0';
165 }
Colin Cross7a106f72016-01-29 16:21:31 -0800166 last_tag[0] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800167 local_change_detected = 1;
Mark Salyzync1584562015-03-12 15:46:29 -0700168 }
Colin Cross7a106f72016-01-29 16:21:31 -0800169 if (!last_tag[0]) {
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700170 if (len < sizeof(last_tag)) {
171 strncpy(last_tag, tag, len);
172 last_tag[len] = '\0';
173 } else {
174 strncpy(last_tag, tag, sizeof(last_tag));
175 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800176 }
Mark Salyzync1584562015-03-12 15:46:29 -0700177 }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700178 strncpy(key + sizeof(log_namespace) - 1, tag, len);
179 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzyn95687052014-10-02 11:12:28 -0700180
Mark Salyzync1584562015-03-12 15:46:29 -0700181 kp = key;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800182 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700183 struct cache_char* cache = &tag_cache[i];
184 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800185
186 if (not_locked) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700187 temp_cache.cache.pinfo = NULL;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800188 temp_cache.c = '\0';
189 cache = &temp_cache;
190 }
191 if (local_change_detected) {
192 refresh_cache(cache, kp);
Mark Salyzync1584562015-03-12 15:46:29 -0700193 }
194
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800195 if (cache->c) {
196 c = cache->c;
Mark Salyzync1584562015-03-12 15:46:29 -0700197 break;
198 }
199
200 kp = key + base_offset;
Mark Salyzyn1f028b22014-10-08 15:58:40 -0700201 }
Mark Salyzyn95687052014-10-02 11:12:28 -0700202 }
Mark Salyzync1584562015-03-12 15:46:29 -0700203
204 switch (toupper(c)) { /* if invalid, resort to global */
205 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 Salyzync1584562015-03-12 15:46:29 -0700214 break;
215 default:
216 /* clear '.' after log.tag */
217 key[sizeof(log_namespace) - 2] = '\0';
218
219 kp = key;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800220 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700221 struct cache_char* cache = &global_cache[i];
222 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800223
224 if (not_locked) {
225 temp_cache = *cache;
Mark Salyzyne4553732016-09-26 13:21:05 -0700226 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
227 temp_cache.cache.pinfo = NULL;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800228 temp_cache.c = '\0';
229 }
230 cache = &temp_cache;
231 }
232 if (global_change_detected) {
233 refresh_cache(cache, kp);
Mark Salyzync1584562015-03-12 15:46:29 -0700234 }
235
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800236 if (cache->c) {
237 c = cache->c;
Mark Salyzync1584562015-03-12 15:46:29 -0700238 break;
239 }
240
241 kp = key + base_offset;
242 }
243 break;
244 }
245
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800246 if (!not_locked) {
247 global_serial = current_global_serial;
248 unlock();
249 }
Mark Salyzync1584562015-03-12 15:46:29 -0700250
251 switch (toupper(c)) {
252 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 Salyzyn95687052014-10-02 11:12:28 -0700261 }
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800262 return default_prio;
Mark Salyzyn95687052014-10-02 11:12:28 -0700263}
264
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700265LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio,
Mark Salyzyne4553732016-09-26 13:21:05 -0700266 const char* tag, size_t len,
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700267 int default_prio)
268{
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,
Mark Salyzyne4553732016-09-26 13:21:05 -0700274 const char* tag,
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800275 int default_prio)
Mark Salyzyn95687052014-10-02 11:12:28 -0700276{
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700277 int logLevel = __android_log_level(tag,
278 (tag && *tag) ? strlen(tag) : 0,
279 default_prio);
Mark Salyzyn95687052014-10-02 11:12:28 -0700280 return logLevel >= 0 && prio >= logLevel;
281}
Mark Salyzyn500afc72015-09-08 08:32:01 -0700282
Mark Salyzyn9ea359f2016-03-25 15:50:46 -0700283LIBLOG_ABI_PRIVATE int __android_log_is_debuggable()
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700284{
285 static uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -0700286 static struct cache_char tag_cache;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700287 static const char key[] = "ro.debuggable";
288 int ret;
289
290 if (tag_cache.c) { /* ro property does not change after set */
291 ret = tag_cache.c == '1';
292 } else if (lock()) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700293 struct cache_char temp_cache = { { NULL, -1 }, '\0' };
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700294 refresh_cache(&temp_cache, key);
295 ret = temp_cache.c == '1';
296 } else {
Mark Salyzyne4553732016-09-26 13:21:05 -0700297 int change_detected = check_cache(&tag_cache.cache);
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700298 uint32_t current_serial = __system_property_area_serial();
299 if (current_serial != serial) {
300 change_detected = 1;
301 }
302 if (change_detected) {
303 refresh_cache(&tag_cache, key);
304 serial = current_serial;
305 }
306 ret = tag_cache.c == '1';
307
308 unlock();
309 }
310
311 return ret;
312}
313
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800314/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800315 * For properties that are read often, but generally remain constant.
316 * Since a change is rare, we will accept a trylock failure gracefully.
317 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800318 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700319struct cache2_char {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800320 pthread_mutex_t lock;
321 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -0700322 const char* key_persist;
323 struct cache_char cache_persist;
324 const char* key_ro;
325 struct cache_char cache_ro;
326 unsigned char (*const evaluate)(const struct cache2_char *self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800327};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800328
Mark Salyzyne4553732016-09-26 13:21:05 -0700329static inline unsigned char do_cache2_char(struct cache2_char *self)
Mark Salyzyn500afc72015-09-08 08:32:01 -0700330{
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800331 uint32_t current_serial;
332 int change_detected;
333 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700334
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800335 if (pthread_mutex_trylock(&self->lock)) {
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800336 /* We are willing to accept some race in this context */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800337 return self->evaluate(self);
Mark Salyzyn500afc72015-09-08 08:32:01 -0700338 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700339
Mark Salyzyne4553732016-09-26 13:21:05 -0700340 change_detected = check_cache(&self->cache_persist.cache)
341 || check_cache(&self->cache_ro.cache);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800342 current_serial = __system_property_area_serial();
343 if (current_serial != self->serial) {
344 change_detected = 1;
345 }
346 if (change_detected) {
347 refresh_cache(&self->cache_persist, self->key_persist);
348 refresh_cache(&self->cache_ro, self->key_ro);
349 self->serial = current_serial;
350 }
351 c = self->evaluate(self);
352
353 pthread_mutex_unlock(&self->lock);
354
355 return c;
356}
357
Mark Salyzyne4553732016-09-26 13:21:05 -0700358static unsigned char evaluate_persist_ro(const struct cache2_char *self)
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800359{
360 unsigned char c = self->cache_persist.c;
361
362 if (c) {
363 return c;
364 }
365
366 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 */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800373LIBLOG_ABI_PUBLIC clockid_t android_log_clockid()
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800374{
Mark Salyzyne4553732016-09-26 13:21:05 -0700375 static struct cache2_char clockid = {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800376 PTHREAD_MUTEX_INITIALIZER,
377 0,
378 "persist.logd.timestamp",
Mark Salyzyne4553732016-09-26 13:21:05 -0700379 { { NULL, -1 }, '\0' },
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800380 "ro.logd.timestamp",
Mark Salyzyne4553732016-09-26 13:21:05 -0700381 { { NULL, -1 }, '\0' },
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800382 evaluate_persist_ro
383 };
384
Mark Salyzyne4553732016-09-26 13:21:05 -0700385 return (tolower(do_cache2_char(&clockid)) == 'm')
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800386 ? CLOCK_MONOTONIC
387 : CLOCK_REALTIME;
388}
389
390/*
391 * Security state generally remains constant, but the DO must be able
392 * to turn off logging should it become spammy after an attack is detected.
393 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700394static unsigned char evaluate_security(const struct cache2_char *self)
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800395{
396 unsigned char c = self->cache_ro.c;
397
398 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
399}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800400
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800401LIBLOG_ABI_PUBLIC int __android_log_security()
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800402{
Mark Salyzyne4553732016-09-26 13:21:05 -0700403 static struct cache2_char security = {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800404 PTHREAD_MUTEX_INITIALIZER,
405 0,
406 "persist.logd.security",
Mark Salyzyne4553732016-09-26 13:21:05 -0700407 { { NULL, -1 }, BOOLEAN_FALSE },
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800408 "ro.device_owner",
Mark Salyzyne4553732016-09-26 13:21:05 -0700409 { { NULL, -1 }, BOOLEAN_FALSE },
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800410 evaluate_security
411 };
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800412
Mark Salyzyne4553732016-09-26 13:21:05 -0700413 return do_cache2_char(&security);
414}
415
416/*
417 * Interface that represents the logd buffer size determination so that others
418 * need not guess our intentions.
419 */
420
421/* Property helper */
422static bool check_flag(const char* prop, const char* flag) {
423 const char* cp = strcasestr(prop, flag);
424 if (!cp) {
425 return false;
426 }
427 /* We only will document comma (,) */
428 static const char sep[] = ",:;|+ \t\f";
429 if ((cp != prop) && !strchr(sep, cp[-1])) {
430 return false;
431 }
432 cp += strlen(flag);
433 return !*cp || !!strchr(sep, *cp);
434}
435
436/* cache structure */
437struct cache_property {
438 struct cache cache;
439 char property[PROP_VALUE_MAX];
440};
441
442static void refresh_cache_property(struct cache_property* cache, const char* key)
443{
444 if (!cache->cache.pinfo) {
445 cache->cache.pinfo = __system_property_find(key);
446 if (!cache->cache.pinfo) {
447 return;
448 }
449 }
450 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
451 __system_property_read(cache->cache.pinfo, 0, cache->property);
452}
453
454/* get boolean with the logger twist that supports eng adjustments */
455LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
456 int flag)
457{
458 struct cache_property property = { { NULL, -1 }, { 0 } };
459 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
460 char newkey[PROP_NAME_MAX];
461 snprintf(newkey, sizeof(newkey), "ro.%s", key);
462 refresh_cache_property(&property, newkey);
463 property.cache.pinfo = NULL;
464 property.cache.serial = -1;
465 snprintf(newkey, sizeof(newkey), "persist.%s", key);
466 refresh_cache_property(&property, newkey);
467 property.cache.pinfo = NULL;
468 property.cache.serial = -1;
469 }
470
471 refresh_cache_property(&property, key);
472
473 if (check_flag(property.property, "true")) {
474 return true;
475 }
476 if (check_flag(property.property, "false")) {
477 return false;
478 }
479 if (check_flag(property.property, "eng")) {
480 flag |= BOOL_DEFAULT_FLAG_ENG;
481 }
482 /* this is really a "not" flag */
483 if (check_flag(property.property, "svelte")) {
484 flag |= BOOL_DEFAULT_FLAG_SVELTE;
485 }
486
487 /* Sanity Check */
488 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
489 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
490 flag |= BOOL_DEFAULT_TRUE;
491 }
492
493 if ((flag & BOOL_DEFAULT_FLAG_SVELTE)
494 && __android_logger_property_get_bool("ro.config.low_ram",
495 BOOL_DEFAULT_FALSE)) {
496 return false;
497 }
498 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
499 return false;
500 }
501
502 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
503}
504
505LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value)
506{
507 static long pages, pagesize;
508 unsigned long maximum;
509
510 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
511 return false;
512 }
513
514 if (!pages) {
515 pages = sysconf(_SC_PHYS_PAGES);
516 }
517 if (pages < 1) {
518 return true;
519 }
520
521 if (!pagesize) {
522 pagesize = sysconf(_SC_PAGESIZE);
523 if (pagesize <= 1) {
524 pagesize = PAGE_SIZE;
525 }
526 }
527
528 /* maximum memory impact a somewhat arbitrary ~3% */
529 pages = (pages + 31) / 32;
530 maximum = pages * pagesize;
531
532 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
533 return true;
534 }
535
536 return value <= maximum;
537}
538
539struct cache2_property_size {
540 pthread_mutex_t lock;
541 uint32_t serial;
542 const char* key_persist;
543 struct cache_property cache_persist;
544 const char* key_ro;
545 struct cache_property cache_ro;
546 unsigned long (*const evaluate)(const struct cache2_property_size* self);
547};
548
549static inline unsigned long do_cache2_property_size(struct cache2_property_size* self)
550{
551 uint32_t current_serial;
552 int change_detected;
553 unsigned long v;
554
555 if (pthread_mutex_trylock(&self->lock)) {
556 /* We are willing to accept some race in this context */
557 return self->evaluate(self);
558 }
559
560 change_detected = check_cache(&self->cache_persist.cache)
561 || check_cache(&self->cache_ro.cache);
562 current_serial = __system_property_area_serial();
563 if (current_serial != self->serial) {
564 change_detected = 1;
565 }
566 if (change_detected) {
567 refresh_cache_property(&self->cache_persist, self->key_persist);
568 refresh_cache_property(&self->cache_ro, self->key_ro);
569 self->serial = current_serial;
570 }
571 v = self->evaluate(self);
572
573 pthread_mutex_unlock(&self->lock);
574
575 return v;
576}
577
578static unsigned long property_get_size_from_cache(const struct cache_property* cache)
579{
580 char* cp;
581 unsigned long value = strtoul(cache->property, &cp, 10);
582
583 switch(*cp) {
584 case 'm':
585 case 'M':
586 value *= 1024;
587 /* FALLTHRU */
588 case 'k':
589 case 'K':
590 value *= 1024;
591 /* FALLTHRU */
592 case '\0':
593 break;
594
595 default:
596 value = 0;
597 }
598
599 if (!__android_logger_valid_buffer_size(value)) {
600 value = 0;
601 }
602
603 return value;
604}
605
606static unsigned long evaluate_property_get_size(const struct cache2_property_size* self)
607{
608 unsigned long size = property_get_size_from_cache(&self->cache_persist);
609 if (size) {
610 return size;
611 }
612 return property_get_size_from_cache(&self->cache_ro);
613}
614
615LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId)
616{
617 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
618 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
619 static struct cache2_property_size global = {
620 PTHREAD_MUTEX_INITIALIZER,
621 0,
622 global_tunable,
623 { { NULL, -1 }, {} },
624 global_default,
625 { { NULL, -1 }, {} },
626 evaluate_property_get_size
627 };
628 char key_persist[PROP_NAME_MAX];
629 char key_ro[PROP_NAME_MAX];
630 struct cache2_property_size local = {
631 PTHREAD_MUTEX_INITIALIZER,
632 0,
633 key_persist,
634 { { NULL, -1 }, {} },
635 key_ro,
636 { { NULL, -1 }, {} },
637 evaluate_property_get_size
638 };
639 unsigned long property_size, default_size;
640
641 default_size = do_cache2_property_size(&global);
642 if (!default_size) {
643 default_size = __android_logger_property_get_bool("ro.config.low_ram",
644 BOOL_DEFAULT_FALSE)
645 ? LOG_BUFFER_MIN_SIZE /* 64K */
646 : LOG_BUFFER_SIZE; /* 256K */
647 }
648
649 snprintf(key_persist, sizeof(key_persist), "%s.%s",
650 global_tunable, android_log_id_to_name(logId));
651 snprintf(key_ro, sizeof(key_ro), "%s.%s",
652 global_default, android_log_id_to_name(logId));
653 property_size = do_cache2_property_size(&local);
654
655 if (!property_size) {
656 property_size = default_size;
657 }
658
659 if (!property_size) {
660 property_size = LOG_BUFFER_SIZE;
661 }
662
663 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800664}