blob: 132d96f388c4ab56eb795bd31939c286abc61e0f [file] [log] [blame]
Mark Salyzyn655b9492014-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 Salyzyn500cd1c2015-03-12 15:46:29 -070018#include <pthread.h>
Mark Salyzyncbf691a2016-09-26 13:21:05 -070019#include <stdbool.h>
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070020#include <stdlib.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070021#include <string.h>
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070022#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
23#include <sys/_system_properties.h>
Mark Salyzyncbf691a2016-09-26 13:21:05 -070024#include <unistd.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070025
26#include <android/log.h>
Mark Salyzyncbf691a2016-09-26 13:21:05 -070027#include <log/logger.h>
28#include <private/android_logger.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070029
Mark Salyzyndd9094a2016-03-01 13:45:42 -080030#include "log_portability.h"
Mark Salyzyna5c22172016-03-10 08:25:33 -080031
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080032static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
33
Mark Salyzynd4860192015-12-21 12:32:48 -080034static int lock()
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080035{
36 /*
37 * If we trigger a signal handler in the middle of locked activity and the
38 * signal handler logs a message, we could get into a deadlock state.
39 */
Mark Salyzynd4860192015-12-21 12:32:48 -080040 /*
41 * Any contention, and we can turn around and use the non-cached method
42 * in less time than the system call associated with a mutex to deal with
43 * the contention.
44 */
45 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080046}
47
48static void unlock()
49{
50 pthread_mutex_unlock(&lock_loggable);
51}
52
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070053struct cache {
Mark Salyzyncbf691a2016-09-26 13:21:05 -070054 const prop_info* pinfo;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070055 uint32_t serial;
Mark Salyzyncbf691a2016-09-26 13:21:05 -070056};
57
58struct cache_char {
59 struct cache cache;
Mark Salyzyn4b2bc922015-12-08 14:52:11 -080060 unsigned char c;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070061};
62
Mark Salyzyncbf691a2016-09-26 13:21:05 -070063static int check_cache(struct cache* cache)
Mark Salyzynd4860192015-12-21 12:32:48 -080064{
65 return cache->pinfo
66 && __system_property_serial(cache->pinfo) != cache->serial;
67}
68
Mark Salyzyn233e4752015-12-04 10:59:45 -080069#define BOOLEAN_TRUE 0xFF
70#define BOOLEAN_FALSE 0xFE
71
Mark Salyzyncbf691a2016-09-26 13:21:05 -070072static void refresh_cache(struct cache_char* cache, const char* key)
Mark Salyzyn655b9492014-10-02 11:12:28 -070073{
74 char buf[PROP_VALUE_MAX];
75
Mark Salyzyncbf691a2016-09-26 13:21:05 -070076 if (!cache->cache.pinfo) {
77 cache->cache.pinfo = __system_property_find(key);
78 if (!cache->cache.pinfo) {
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070079 return;
80 }
Mark Salyzyn655b9492014-10-02 11:12:28 -070081 }
Mark Salyzyncbf691a2016-09-26 13:21:05 -070082 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
83 __system_property_read(cache->cache.pinfo, 0, buf);
Mark Salyzyn233e4752015-12-04 10:59:45 -080084 switch(buf[0]) {
85 case 't': case 'T':
86 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
87 break;
88 case 'f': case 'F':
89 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
90 break;
91 default:
92 cache->c = buf[0];
93 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070094}
Mark Salyzyn655b9492014-10-02 11:12:28 -070095
Mark Salyzyncbf691a2016-09-26 13:21:05 -070096static int __android_log_level(const char* tag, size_t len, int default_prio)
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070097{
98 /* 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." */
101 /* calculate the size of our key temporary buffer */
Mark Salyzyn29d0b832016-09-22 09:56:51 -0700102 const size_t taglen = tag ? len : 0;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700103 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700104 char key[sizeof(log_namespace) + taglen]; /* may be > PROP_NAME_MAX */
105 char* kp;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700106 size_t i;
107 char c = 0;
108 /*
109 * Single layer cache of four properties. Priorities are:
110 * log.tag.<tag>
111 * persist.log.tag.<tag>
112 * log.tag
113 * persist.log.tag
114 * Where the missing tag matches all tags and becomes the
115 * system global default. We do not support ro.log.tag* .
116 */
Colin Cross577e0062016-01-29 16:21:31 -0800117 static char last_tag[PROP_NAME_MAX];
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700118 static uint32_t global_serial;
Mark Salyzynf92d5e62015-12-22 10:49:02 -0800119 /* some compilers erroneously see uninitialized use. !not_locked */
120 uint32_t current_global_serial = 0;
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700121 static struct cache_char tag_cache[2];
122 static struct cache_char global_cache[2];
Mark Salyzynd4860192015-12-21 12:32:48 -0800123 int change_detected;
124 int global_change_detected;
125 int not_locked;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700126
127 strcpy(key, log_namespace);
128
Mark Salyzynd4860192015-12-21 12:32:48 -0800129 global_change_detected = change_detected = not_locked = lock();
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700130
Mark Salyzynd4860192015-12-21 12:32:48 -0800131 if (!not_locked) {
132 /*
133 * check all known serial numbers to changes.
134 */
135 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700136 if (check_cache(&tag_cache[i].cache)) {
Mark Salyzynd4860192015-12-21 12:32:48 -0800137 change_detected = 1;
138 }
139 }
140 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700141 if (check_cache(&global_cache[i].cache)) {
Mark Salyzynd4860192015-12-21 12:32:48 -0800142 global_change_detected = 1;
143 }
144 }
145
146 current_global_serial = __system_property_area_serial();
147 if (current_global_serial != global_serial) {
148 change_detected = 1;
149 global_change_detected = 1;
150 }
151 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700152
153 if (taglen) {
Mark Salyzynd4860192015-12-21 12:32:48 -0800154 int local_change_detected = change_detected;
155 if (!not_locked) {
Colin Cross577e0062016-01-29 16:21:31 -0800156 if (!last_tag[0]
Mark Salyzynd4860192015-12-21 12:32:48 -0800157 || (last_tag[0] != tag[0])
Mark Salyzyn29d0b832016-09-22 09:56:51 -0700158 || strncmp(last_tag + 1, tag + 1,
159 (len < sizeof(last_tag)) ?
160 (len - 1) :
161 (sizeof(last_tag) - 1))
162 || ((len < sizeof(last_tag)) && last_tag[len])) {
Mark Salyzynd4860192015-12-21 12:32:48 -0800163 /* invalidate log.tag.<tag> cache */
164 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700165 tag_cache[i].cache.pinfo = NULL;
Mark Salyzynd4860192015-12-21 12:32:48 -0800166 tag_cache[i].c = '\0';
167 }
Colin Cross577e0062016-01-29 16:21:31 -0800168 last_tag[0] = '\0';
Mark Salyzynd4860192015-12-21 12:32:48 -0800169 local_change_detected = 1;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700170 }
Colin Cross577e0062016-01-29 16:21:31 -0800171 if (!last_tag[0]) {
Mark Salyzyn29d0b832016-09-22 09:56:51 -0700172 if (len < sizeof(last_tag)) {
173 strncpy(last_tag, tag, len);
174 last_tag[len] = '\0';
175 } else {
176 strncpy(last_tag, tag, sizeof(last_tag));
177 }
Mark Salyzynd4860192015-12-21 12:32:48 -0800178 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700179 }
Mark Salyzyn29d0b832016-09-22 09:56:51 -0700180 strncpy(key + sizeof(log_namespace) - 1, tag, len);
181 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzyn655b9492014-10-02 11:12:28 -0700182
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700183 kp = key;
Mark Salyzynd4860192015-12-21 12:32:48 -0800184 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700185 struct cache_char* cache = &tag_cache[i];
186 struct cache_char temp_cache;
Mark Salyzynd4860192015-12-21 12:32:48 -0800187
188 if (not_locked) {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700189 temp_cache.cache.pinfo = NULL;
Mark Salyzynd4860192015-12-21 12:32:48 -0800190 temp_cache.c = '\0';
191 cache = &temp_cache;
192 }
193 if (local_change_detected) {
194 refresh_cache(cache, kp);
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700195 }
196
Mark Salyzynd4860192015-12-21 12:32:48 -0800197 if (cache->c) {
198 c = cache->c;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700199 break;
200 }
201
202 kp = key + base_offset;
Mark Salyzynd4b2a742014-10-08 15:58:40 -0700203 }
Mark Salyzyn655b9492014-10-02 11:12:28 -0700204 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700205
206 switch (toupper(c)) { /* if invalid, resort to global */
207 case 'V':
208 case 'D':
209 case 'I':
210 case 'W':
211 case 'E':
212 case 'F': /* Not officially supported */
213 case 'A':
214 case 'S':
Mark Salyzyn233e4752015-12-04 10:59:45 -0800215 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700216 break;
217 default:
218 /* clear '.' after log.tag */
219 key[sizeof(log_namespace) - 2] = '\0';
220
221 kp = key;
Mark Salyzynd4860192015-12-21 12:32:48 -0800222 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700223 struct cache_char* cache = &global_cache[i];
224 struct cache_char temp_cache;
Mark Salyzynd4860192015-12-21 12:32:48 -0800225
226 if (not_locked) {
227 temp_cache = *cache;
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700228 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
229 temp_cache.cache.pinfo = NULL;
Mark Salyzynd4860192015-12-21 12:32:48 -0800230 temp_cache.c = '\0';
231 }
232 cache = &temp_cache;
233 }
234 if (global_change_detected) {
235 refresh_cache(cache, kp);
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700236 }
237
Mark Salyzynd4860192015-12-21 12:32:48 -0800238 if (cache->c) {
239 c = cache->c;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700240 break;
241 }
242
243 kp = key + base_offset;
244 }
245 break;
246 }
247
Mark Salyzynd4860192015-12-21 12:32:48 -0800248 if (!not_locked) {
249 global_serial = current_global_serial;
250 unlock();
251 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700252
253 switch (toupper(c)) {
254 case 'V': return ANDROID_LOG_VERBOSE;
255 case 'D': return ANDROID_LOG_DEBUG;
256 case 'I': return ANDROID_LOG_INFO;
257 case 'W': return ANDROID_LOG_WARN;
258 case 'E': return ANDROID_LOG_ERROR;
259 case 'F': /* FALLTHRU */ /* Not officially supported */
260 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzyn233e4752015-12-04 10:59:45 -0800261 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700262 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
Mark Salyzyn655b9492014-10-02 11:12:28 -0700263 }
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800264 return default_prio;
Mark Salyzyn655b9492014-10-02 11:12:28 -0700265}
266
Mark Salyzyn29d0b832016-09-22 09:56:51 -0700267LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio,
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700268 const char* tag, size_t len,
Mark Salyzyn29d0b832016-09-22 09:56:51 -0700269 int default_prio)
270{
271 int logLevel = __android_log_level(tag, len, default_prio);
272 return logLevel >= 0 && prio >= logLevel;
273}
274
275LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio,
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700276 const char* tag,
Mark Salyzyna5c22172016-03-10 08:25:33 -0800277 int default_prio)
Mark Salyzyn655b9492014-10-02 11:12:28 -0700278{
Mark Salyzyn29d0b832016-09-22 09:56:51 -0700279 int logLevel = __android_log_level(tag,
280 (tag && *tag) ? strlen(tag) : 0,
281 default_prio);
Mark Salyzyn655b9492014-10-02 11:12:28 -0700282 return logLevel >= 0 && prio >= logLevel;
283}
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700284
Mark Salyzyn19551182016-03-25 15:50:46 -0700285LIBLOG_ABI_PRIVATE int __android_log_is_debuggable()
Mark Salyzyn509c1422016-03-25 15:50:46 -0700286{
287 static uint32_t serial;
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700288 static struct cache_char tag_cache;
Mark Salyzyn509c1422016-03-25 15:50:46 -0700289 static const char key[] = "ro.debuggable";
290 int ret;
291
292 if (tag_cache.c) { /* ro property does not change after set */
293 ret = tag_cache.c == '1';
294 } else if (lock()) {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700295 struct cache_char temp_cache = { { NULL, -1 }, '\0' };
Mark Salyzyn509c1422016-03-25 15:50:46 -0700296 refresh_cache(&temp_cache, key);
297 ret = temp_cache.c == '1';
298 } else {
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700299 int change_detected = check_cache(&tag_cache.cache);
Mark Salyzyn509c1422016-03-25 15:50:46 -0700300 uint32_t current_serial = __system_property_area_serial();
301 if (current_serial != serial) {
302 change_detected = 1;
303 }
304 if (change_detected) {
305 refresh_cache(&tag_cache, key);
306 serial = current_serial;
307 }
308 ret = tag_cache.c == '1';
309
310 unlock();
311 }
312
313 return ret;
314}
315
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800316/*
Mark Salyzynd4860192015-12-21 12:32:48 -0800317 * For properties that are read often, but generally remain constant.
318 * Since a change is rare, we will accept a trylock failure gracefully.
319 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800320 */
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700321struct cache2_char {
Mark Salyzynd4860192015-12-21 12:32:48 -0800322 pthread_mutex_t lock;
323 uint32_t serial;
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700324 const char* key_persist;
325 struct cache_char cache_persist;
326 const char* key_ro;
327 struct cache_char cache_ro;
328 unsigned char (*const evaluate)(const struct cache2_char *self);
Mark Salyzynd4860192015-12-21 12:32:48 -0800329};
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800330
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700331static inline unsigned char do_cache2_char(struct cache2_char *self)
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700332{
Mark Salyzynd4860192015-12-21 12:32:48 -0800333 uint32_t current_serial;
334 int change_detected;
335 unsigned char c;
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700336
Mark Salyzynd4860192015-12-21 12:32:48 -0800337 if (pthread_mutex_trylock(&self->lock)) {
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800338 /* We are willing to accept some race in this context */
Mark Salyzynd4860192015-12-21 12:32:48 -0800339 return self->evaluate(self);
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700340 }
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700341
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700342 change_detected = check_cache(&self->cache_persist.cache)
343 || check_cache(&self->cache_ro.cache);
Mark Salyzynd4860192015-12-21 12:32:48 -0800344 current_serial = __system_property_area_serial();
345 if (current_serial != self->serial) {
346 change_detected = 1;
347 }
348 if (change_detected) {
349 refresh_cache(&self->cache_persist, self->key_persist);
350 refresh_cache(&self->cache_ro, self->key_ro);
351 self->serial = current_serial;
352 }
353 c = self->evaluate(self);
354
355 pthread_mutex_unlock(&self->lock);
356
357 return c;
358}
359
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700360static unsigned char evaluate_persist_ro(const struct cache2_char *self)
Mark Salyzynd4860192015-12-21 12:32:48 -0800361{
362 unsigned char c = self->cache_persist.c;
363
364 if (c) {
365 return c;
366 }
367
368 return self->cache_ro.c;
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700369}
Mark Salyzyn233e4752015-12-04 10:59:45 -0800370
371/*
Mark Salyzynd4860192015-12-21 12:32:48 -0800372 * Timestamp state generally remains constant, but can change at any time
373 * to handle developer requirements.
Mark Salyzyn233e4752015-12-04 10:59:45 -0800374 */
Mark Salyzyna5c22172016-03-10 08:25:33 -0800375LIBLOG_ABI_PUBLIC clockid_t android_log_clockid()
Mark Salyzynd4860192015-12-21 12:32:48 -0800376{
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700377 static struct cache2_char clockid = {
Mark Salyzynd4860192015-12-21 12:32:48 -0800378 PTHREAD_MUTEX_INITIALIZER,
379 0,
380 "persist.logd.timestamp",
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700381 { { NULL, -1 }, '\0' },
Mark Salyzynd4860192015-12-21 12:32:48 -0800382 "ro.logd.timestamp",
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700383 { { NULL, -1 }, '\0' },
Mark Salyzynd4860192015-12-21 12:32:48 -0800384 evaluate_persist_ro
385 };
386
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700387 return (tolower(do_cache2_char(&clockid)) == 'm')
Mark Salyzynd4860192015-12-21 12:32:48 -0800388 ? CLOCK_MONOTONIC
389 : CLOCK_REALTIME;
390}
391
392/*
393 * Security state generally remains constant, but the DO must be able
394 * to turn off logging should it become spammy after an attack is detected.
395 */
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700396static unsigned char evaluate_security(const struct cache2_char *self)
Mark Salyzynd4860192015-12-21 12:32:48 -0800397{
398 unsigned char c = self->cache_ro.c;
399
400 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
401}
Mark Salyzyn233e4752015-12-04 10:59:45 -0800402
Mark Salyzyna5c22172016-03-10 08:25:33 -0800403LIBLOG_ABI_PUBLIC int __android_log_security()
Mark Salyzyn233e4752015-12-04 10:59:45 -0800404{
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700405 static struct cache2_char security = {
Mark Salyzynd4860192015-12-21 12:32:48 -0800406 PTHREAD_MUTEX_INITIALIZER,
407 0,
408 "persist.logd.security",
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700409 { { NULL, -1 }, BOOLEAN_FALSE },
Mark Salyzynd4860192015-12-21 12:32:48 -0800410 "ro.device_owner",
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700411 { { NULL, -1 }, BOOLEAN_FALSE },
Mark Salyzynd4860192015-12-21 12:32:48 -0800412 evaluate_security
413 };
Mark Salyzyn233e4752015-12-04 10:59:45 -0800414
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700415 return do_cache2_char(&security);
416}
417
418/*
419 * Interface that represents the logd buffer size determination so that others
420 * need not guess our intentions.
421 */
422
423/* Property helper */
424static bool check_flag(const char* prop, const char* flag) {
425 const char* cp = strcasestr(prop, flag);
426 if (!cp) {
427 return false;
428 }
429 /* We only will document comma (,) */
430 static const char sep[] = ",:;|+ \t\f";
431 if ((cp != prop) && !strchr(sep, cp[-1])) {
432 return false;
433 }
434 cp += strlen(flag);
435 return !*cp || !!strchr(sep, *cp);
436}
437
438/* cache structure */
439struct cache_property {
440 struct cache cache;
441 char property[PROP_VALUE_MAX];
442};
443
444static void refresh_cache_property(struct cache_property* cache, const char* key)
445{
446 if (!cache->cache.pinfo) {
447 cache->cache.pinfo = __system_property_find(key);
448 if (!cache->cache.pinfo) {
449 return;
450 }
451 }
452 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
453 __system_property_read(cache->cache.pinfo, 0, cache->property);
454}
455
456/* get boolean with the logger twist that supports eng adjustments */
457LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
458 int flag)
459{
460 struct cache_property property = { { NULL, -1 }, { 0 } };
461 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
462 char newkey[PROP_NAME_MAX];
463 snprintf(newkey, sizeof(newkey), "ro.%s", key);
464 refresh_cache_property(&property, newkey);
465 property.cache.pinfo = NULL;
466 property.cache.serial = -1;
467 snprintf(newkey, sizeof(newkey), "persist.%s", key);
468 refresh_cache_property(&property, newkey);
469 property.cache.pinfo = NULL;
470 property.cache.serial = -1;
471 }
472
473 refresh_cache_property(&property, key);
474
475 if (check_flag(property.property, "true")) {
476 return true;
477 }
478 if (check_flag(property.property, "false")) {
479 return false;
480 }
481 if (check_flag(property.property, "eng")) {
482 flag |= BOOL_DEFAULT_FLAG_ENG;
483 }
484 /* this is really a "not" flag */
485 if (check_flag(property.property, "svelte")) {
486 flag |= BOOL_DEFAULT_FLAG_SVELTE;
487 }
488
489 /* Sanity Check */
490 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
491 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
492 flag |= BOOL_DEFAULT_TRUE;
493 }
494
495 if ((flag & BOOL_DEFAULT_FLAG_SVELTE)
496 && __android_logger_property_get_bool("ro.config.low_ram",
497 BOOL_DEFAULT_FALSE)) {
498 return false;
499 }
500 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
501 return false;
502 }
503
504 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
505}
506
507LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value)
508{
509 static long pages, pagesize;
510 unsigned long maximum;
511
512 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
513 return false;
514 }
515
516 if (!pages) {
517 pages = sysconf(_SC_PHYS_PAGES);
518 }
519 if (pages < 1) {
520 return true;
521 }
522
523 if (!pagesize) {
524 pagesize = sysconf(_SC_PAGESIZE);
525 if (pagesize <= 1) {
526 pagesize = PAGE_SIZE;
527 }
528 }
529
530 /* maximum memory impact a somewhat arbitrary ~3% */
531 pages = (pages + 31) / 32;
532 maximum = pages * pagesize;
533
534 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
535 return true;
536 }
537
538 return value <= maximum;
539}
540
541struct cache2_property_size {
542 pthread_mutex_t lock;
543 uint32_t serial;
544 const char* key_persist;
545 struct cache_property cache_persist;
546 const char* key_ro;
547 struct cache_property cache_ro;
548 unsigned long (*const evaluate)(const struct cache2_property_size* self);
549};
550
551static inline unsigned long do_cache2_property_size(struct cache2_property_size* self)
552{
553 uint32_t current_serial;
554 int change_detected;
555 unsigned long v;
556
557 if (pthread_mutex_trylock(&self->lock)) {
558 /* We are willing to accept some race in this context */
559 return self->evaluate(self);
560 }
561
562 change_detected = check_cache(&self->cache_persist.cache)
563 || check_cache(&self->cache_ro.cache);
564 current_serial = __system_property_area_serial();
565 if (current_serial != self->serial) {
566 change_detected = 1;
567 }
568 if (change_detected) {
569 refresh_cache_property(&self->cache_persist, self->key_persist);
570 refresh_cache_property(&self->cache_ro, self->key_ro);
571 self->serial = current_serial;
572 }
573 v = self->evaluate(self);
574
575 pthread_mutex_unlock(&self->lock);
576
577 return v;
578}
579
580static unsigned long property_get_size_from_cache(const struct cache_property* cache)
581{
582 char* cp;
583 unsigned long value = strtoul(cache->property, &cp, 10);
584
585 switch(*cp) {
586 case 'm':
587 case 'M':
588 value *= 1024;
589 /* FALLTHRU */
590 case 'k':
591 case 'K':
592 value *= 1024;
593 /* FALLTHRU */
594 case '\0':
595 break;
596
597 default:
598 value = 0;
599 }
600
601 if (!__android_logger_valid_buffer_size(value)) {
602 value = 0;
603 }
604
605 return value;
606}
607
608static unsigned long evaluate_property_get_size(const struct cache2_property_size* self)
609{
610 unsigned long size = property_get_size_from_cache(&self->cache_persist);
611 if (size) {
612 return size;
613 }
614 return property_get_size_from_cache(&self->cache_ro);
615}
616
617LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId)
618{
619 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
620 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
621 static struct cache2_property_size global = {
622 PTHREAD_MUTEX_INITIALIZER,
623 0,
624 global_tunable,
625 { { NULL, -1 }, {} },
626 global_default,
627 { { NULL, -1 }, {} },
628 evaluate_property_get_size
629 };
630 char key_persist[PROP_NAME_MAX];
631 char key_ro[PROP_NAME_MAX];
632 struct cache2_property_size local = {
633 PTHREAD_MUTEX_INITIALIZER,
634 0,
635 key_persist,
636 { { NULL, -1 }, {} },
637 key_ro,
638 { { NULL, -1 }, {} },
639 evaluate_property_get_size
640 };
641 unsigned long property_size, default_size;
642
643 default_size = do_cache2_property_size(&global);
644 if (!default_size) {
645 default_size = __android_logger_property_get_bool("ro.config.low_ram",
646 BOOL_DEFAULT_FALSE)
647 ? LOG_BUFFER_MIN_SIZE /* 64K */
648 : LOG_BUFFER_SIZE; /* 256K */
649 }
650
651 snprintf(key_persist, sizeof(key_persist), "%s.%s",
652 global_tunable, android_log_id_to_name(logId));
653 snprintf(key_ro, sizeof(key_ro), "%s.%s",
654 global_default, android_log_id_to_name(logId));
655 property_size = do_cache2_property_size(&local);
656
657 if (!property_size) {
658 property_size = default_size;
659 }
660
661 if (!property_size) {
662 property_size = LOG_BUFFER_SIZE;
663 }
664
665 return property_size;
Mark Salyzyn233e4752015-12-04 10:59:45 -0800666}