summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Salyzyn2017-03-09 10:09:43 -0600
committerMark Salyzyn2017-03-09 11:36:19 -0600
commit2ed51d708eda64516ec79ac6397f690de38f0075 (patch)
tree9ea938a4ee0461c443dc99e197827fc36ecd643b /liblog/properties.c
parentc1b3c8ef2629eac2a73aa4a95bf43a66edf4cd0f (diff)
downloadplatform-system-core-2ed51d708eda64516ec79ac6397f690de38f0075.tar.gz
platform-system-core-2ed51d708eda64516ec79ac6397f690de38f0075.tar.xz
platform-system-core-2ed51d708eda64516ec79ac6397f690de38f0075.zip
liblog: specify clang format
Switch coding style to match SideEffects: None Test: compile Bug: 27405083 Change-Id: Id426d5c5e3b18f2ceec22b31bbc9781aabf6bcca
Diffstat (limited to 'liblog/properties.c')
-rw-r--r--liblog/properties.c952
1 files changed, 463 insertions, 489 deletions
diff --git a/liblog/properties.c b/liblog/properties.c
index dda09e092..0b0ef5205 100644
--- a/liblog/properties.c
+++ b/liblog/properties.c
@@ -29,179 +29,173 @@
29 29
30static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER; 30static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
31 31
32static int lock() 32static int lock() {
33{ 33 /*
34 /* 34 * If we trigger a signal handler in the middle of locked activity and the
35 * If we trigger a signal handler in the middle of locked activity and the 35 * signal handler logs a message, we could get into a deadlock state.
36 * signal handler logs a message, we could get into a deadlock state. 36 */
37 */ 37 /*
38 /* 38 * Any contention, and we can turn around and use the non-cached method
39 * Any contention, and we can turn around and use the non-cached method 39 * in less time than the system call associated with a mutex to deal with
40 * in less time than the system call associated with a mutex to deal with 40 * the contention.
41 * the contention. 41 */
42 */ 42 return pthread_mutex_trylock(&lock_loggable);
43 return pthread_mutex_trylock(&lock_loggable);
44} 43}
45 44
46static void unlock() 45static void unlock() {
47{ 46 pthread_mutex_unlock(&lock_loggable);
48 pthread_mutex_unlock(&lock_loggable);
49} 47}
50 48
51struct cache { 49struct cache {
52 const prop_info* pinfo; 50 const prop_info* pinfo;
53 uint32_t serial; 51 uint32_t serial;
54}; 52};
55 53
56struct cache_char { 54struct cache_char {
57 struct cache cache; 55 struct cache cache;
58 unsigned char c; 56 unsigned char c;
59}; 57};
60 58
61static int check_cache(struct cache* cache) 59static int check_cache(struct cache* cache) {
62{ 60 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
63 return cache->pinfo
64 && __system_property_serial(cache->pinfo) != cache->serial;
65} 61}
66 62
67#define BOOLEAN_TRUE 0xFF 63#define BOOLEAN_TRUE 0xFF
68#define BOOLEAN_FALSE 0xFE 64#define BOOLEAN_FALSE 0xFE
69 65
70static void refresh_cache(struct cache_char* cache, const char* key) 66static void refresh_cache(struct cache_char* cache, const char* key) {
71{ 67 char buf[PROP_VALUE_MAX];
72 char buf[PROP_VALUE_MAX];
73 68
69 if (!cache->cache.pinfo) {
70 cache->cache.pinfo = __system_property_find(key);
74 if (!cache->cache.pinfo) { 71 if (!cache->cache.pinfo) {
75 cache->cache.pinfo = __system_property_find(key); 72 return;
76 if (!cache->cache.pinfo) { 73 }
77 return; 74 }
78 } 75 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
79 } 76 __system_property_read(cache->cache.pinfo, 0, buf);
80 cache->cache.serial = __system_property_serial(cache->cache.pinfo); 77 switch (buf[0]) {
81 __system_property_read(cache->cache.pinfo, 0, buf); 78 case 't':
82 switch(buf[0]) { 79 case 'T':
83 case 't': case 'T': 80 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
84 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE; 81 break;
85 break; 82 case 'f':
86 case 'f': case 'F': 83 case 'F':
87 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE; 84 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
88 break; 85 break;
89 default: 86 default:
90 cache->c = buf[0]; 87 cache->c = buf[0];
91 } 88 }
92} 89}
93 90
94static int __android_log_level(const char* tag, size_t len, int default_prio) 91static int __android_log_level(const char* tag, size_t len, int default_prio) {
95{ 92 /* sizeof() is used on this array below */
96 /* sizeof() is used on this array below */ 93 static const char log_namespace[] = "persist.log.tag.";
97 static const char log_namespace[] = "persist.log.tag."; 94 static const size_t base_offset = 8; /* skip "persist." */
98 static const size_t base_offset = 8; /* skip "persist." */ 95 /* calculate the size of our key temporary buffer */
99 /* calculate the size of our key temporary buffer */ 96 const size_t taglen = tag ? len : 0;
100 const size_t taglen = tag ? len : 0; 97 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
101 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */ 98 char key[sizeof(log_namespace) + taglen]; /* may be > PROP_NAME_MAX */
102 char key[sizeof(log_namespace) + taglen]; /* may be > PROP_NAME_MAX */ 99 char* kp;
103 char* kp; 100 size_t i;
104 size_t i; 101 char c = 0;
105 char c = 0; 102 /*
103 * Single layer cache of four properties. Priorities are:
104 * log.tag.<tag>
105 * persist.log.tag.<tag>
106 * log.tag
107 * persist.log.tag
108 * Where the missing tag matches all tags and becomes the
109 * system global default. We do not support ro.log.tag* .
110 */
111 static char last_tag[PROP_NAME_MAX];
112 static uint32_t global_serial;
113 /* some compilers erroneously see uninitialized use. !not_locked */
114 uint32_t current_global_serial = 0;
115 static struct cache_char tag_cache[2];
116 static struct cache_char global_cache[2];
117 int change_detected;
118 int global_change_detected;
119 int not_locked;
120
121 strcpy(key, log_namespace);
122
123 global_change_detected = change_detected = not_locked = lock();
124
125 if (!not_locked) {
106 /* 126 /*
107 * Single layer cache of four properties. Priorities are: 127 * check all known serial numbers to changes.
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 */ 128 */
115 static char last_tag[PROP_NAME_MAX]; 129 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
116 static uint32_t global_serial; 130 if (check_cache(&tag_cache[i].cache)) {
117 /* some compilers erroneously see uninitialized use. !not_locked */ 131 change_detected = 1;
118 uint32_t current_global_serial = 0; 132 }
119 static struct cache_char tag_cache[2]; 133 }
120 static struct cache_char global_cache[2]; 134 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
121 int change_detected; 135 if (check_cache(&global_cache[i].cache)) {
122 int global_change_detected; 136 global_change_detected = 1;
123 int not_locked; 137 }
124 138 }
125 strcpy(key, log_namespace);
126 139
127 global_change_detected = change_detected = not_locked = lock(); 140 current_global_serial = __system_property_area_serial();
141 if (current_global_serial != global_serial) {
142 change_detected = 1;
143 global_change_detected = 1;
144 }
145 }
128 146
147 if (taglen) {
148 int local_change_detected = change_detected;
129 if (!not_locked) { 149 if (!not_locked) {
130 /* 150 if (!last_tag[0] || (last_tag[0] != tag[0]) ||
131 * check all known serial numbers to changes. 151 strncmp(
132 */ 152 last_tag + 1, tag + 1,
153 (len < sizeof(last_tag)) ? (len - 1) : (sizeof(last_tag) - 1)) ||
154 ((len < sizeof(last_tag)) && last_tag[len])) {
155 /* invalidate log.tag.<tag> cache */
133 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) { 156 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
134 if (check_cache(&tag_cache[i].cache)) { 157 tag_cache[i].cache.pinfo = NULL;
135 change_detected = 1; 158 tag_cache[i].c = '\0';
136 }
137 }
138 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
139 if (check_cache(&global_cache[i].cache)) {
140 global_change_detected = 1;
141 }
142 } 159 }
143 160 last_tag[0] = '\0';
144 current_global_serial = __system_property_area_serial(); 161 local_change_detected = 1;
145 if (current_global_serial != global_serial) { 162 }
146 change_detected = 1; 163 if (!last_tag[0]) {
147 global_change_detected = 1; 164 if (len < sizeof(last_tag)) {
165 strncpy(last_tag, tag, len);
166 last_tag[len] = '\0';
167 } else {
168 strncpy(last_tag, tag, sizeof(last_tag));
148 } 169 }
149 } 170 }
150 171 }
151 if (taglen) { 172 strncpy(key + sizeof(log_namespace) - 1, tag, len);
152 int local_change_detected = change_detected; 173 key[sizeof(log_namespace) - 1 + len] = '\0';
153 if (!not_locked) { 174
154 if (!last_tag[0] 175 kp = key;
155 || (last_tag[0] != tag[0]) 176 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
156 || strncmp(last_tag + 1, tag + 1, 177 struct cache_char* cache = &tag_cache[i];
157 (len < sizeof(last_tag)) ? 178 struct cache_char temp_cache;
158 (len - 1) : 179
159 (sizeof(last_tag) - 1)) 180 if (not_locked) {
160 || ((len < sizeof(last_tag)) && last_tag[len])) { 181 temp_cache.cache.pinfo = NULL;
161 /* invalidate log.tag.<tag> cache */ 182 temp_cache.c = '\0';
162 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) { 183 cache = &temp_cache;
163 tag_cache[i].cache.pinfo = NULL; 184 }
164 tag_cache[i].c = '\0'; 185 if (local_change_detected) {
165 } 186 refresh_cache(cache, kp);
166 last_tag[0] = '\0'; 187 }
167 local_change_detected = 1; 188
168 } 189 if (cache->c) {
169 if (!last_tag[0]) { 190 c = cache->c;
170 if (len < sizeof(last_tag)) { 191 break;
171 strncpy(last_tag, tag, len); 192 }
172 last_tag[len] = '\0';
173 } else {
174 strncpy(last_tag, tag, sizeof(last_tag));
175 }
176 }
177 }
178 strncpy(key + sizeof(log_namespace) - 1, tag, len);
179 key[sizeof(log_namespace) - 1 + len] = '\0';
180 193
181 kp = key; 194 kp = key + base_offset;
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;
185
186 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 }
194
195 if (cache->c) {
196 c = cache->c;
197 break;
198 }
199
200 kp = key + base_offset;
201 }
202 } 195 }
196 }
203 197
204 switch (toupper(c)) { /* if invalid, resort to global */ 198 switch (toupper(c)) { /* if invalid, resort to global */
205 case 'V': 199 case 'V':
206 case 'D': 200 case 'D':
207 case 'I': 201 case 'I':
@@ -211,44 +205,45 @@ static int __android_log_level(const char* tag, size_t len, int default_prio)
211 case 'A': 205 case 'A':
212 case 'S': 206 case 'S':
213 case BOOLEAN_FALSE: /* Not officially supported */ 207 case BOOLEAN_FALSE: /* Not officially supported */
214 break; 208 break;
215 default: 209 default:
216 /* clear '.' after log.tag */ 210 /* clear '.' after log.tag */
217 key[sizeof(log_namespace) - 2] = '\0'; 211 key[sizeof(log_namespace) - 2] = '\0';
218 212
219 kp = key; 213 kp = key;
220 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) { 214 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
221 struct cache_char* cache = &global_cache[i]; 215 struct cache_char* cache = &global_cache[i];
222 struct cache_char temp_cache; 216 struct cache_char temp_cache;
223 217
224 if (not_locked) { 218 if (not_locked) {
225 temp_cache = *cache; 219 temp_cache = *cache;
226 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */ 220 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
227 temp_cache.cache.pinfo = NULL; 221 temp_cache.cache.pinfo = NULL;
228 temp_cache.c = '\0'; 222 temp_cache.c = '\0';
229 } 223 }
230 cache = &temp_cache; 224 cache = &temp_cache;
231 } 225 }
232 if (global_change_detected) { 226 if (global_change_detected) {
233 refresh_cache(cache, kp); 227 refresh_cache(cache, kp);
234 }
235
236 if (cache->c) {
237 c = cache->c;
238 break;
239 }
240
241 kp = key + base_offset;
242 } 228 }
243 break;
244 }
245 229
246 if (!not_locked) { 230 if (cache->c) {
247 global_serial = current_global_serial; 231 c = cache->c;
248 unlock(); 232 break;
249 } 233 }
250 234
251 switch (toupper(c)) { 235 kp = key + base_offset;
236 }
237 break;
238 }
239
240 if (!not_locked) {
241 global_serial = current_global_serial;
242 unlock();
243 }
244
245 switch (toupper(c)) {
246 /* clang-format off */
252 case 'V': return ANDROID_LOG_VERBOSE; 247 case 'V': return ANDROID_LOG_VERBOSE;
253 case 'D': return ANDROID_LOG_DEBUG; 248 case 'D': return ANDROID_LOG_DEBUG;
254 case 'I': return ANDROID_LOG_INFO; 249 case 'I': return ANDROID_LOG_INFO;
@@ -258,57 +253,53 @@ static int __android_log_level(const char* tag, size_t len, int default_prio)
258 case 'A': return ANDROID_LOG_FATAL; 253 case 'A': return ANDROID_LOG_FATAL;
259 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */ 254 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
260 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */ 255 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
261 } 256 /* clang-format on */
262 return default_prio; 257 }
258 return default_prio;
263} 259}
264 260
265LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, 261LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag,
266 const char* tag, size_t len, 262 size_t len,
267 int default_prio) 263 int default_prio) {
268{ 264 int logLevel = __android_log_level(tag, len, default_prio);
269 int logLevel = __android_log_level(tag, len, default_prio); 265 return logLevel >= 0 && prio >= logLevel;
270 return logLevel >= 0 && prio >= logLevel;
271} 266}
272 267
273LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, 268LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag,
274 const char* tag, 269 int default_prio) {
275 int default_prio) 270 int logLevel =
276{ 271 __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
277 int logLevel = __android_log_level(tag, 272 return logLevel >= 0 && prio >= logLevel;
278 (tag && *tag) ? strlen(tag) : 0,
279 default_prio);
280 return logLevel >= 0 && prio >= logLevel;
281} 273}
282 274
283LIBLOG_ABI_PRIVATE int __android_log_is_debuggable() 275LIBLOG_ABI_PRIVATE int __android_log_is_debuggable() {
284{ 276 static uint32_t serial;
285 static uint32_t serial; 277 static struct cache_char tag_cache;
286 static struct cache_char tag_cache; 278 static const char key[] = "ro.debuggable";
287 static const char key[] = "ro.debuggable"; 279 int ret;
288 int ret; 280
289 281 if (tag_cache.c) { /* ro property does not change after set */
290 if (tag_cache.c) { /* ro property does not change after set */ 282 ret = tag_cache.c == '1';
291 ret = tag_cache.c == '1'; 283 } else if (lock()) {
292 } else if (lock()) { 284 struct cache_char temp_cache = { { NULL, -1 }, '\0' };
293 struct cache_char temp_cache = { { NULL, -1 }, '\0' }; 285 refresh_cache(&temp_cache, key);
294 refresh_cache(&temp_cache, key); 286 ret = temp_cache.c == '1';
295 ret = temp_cache.c == '1'; 287 } else {
296 } else { 288 int change_detected = check_cache(&tag_cache.cache);
297 int change_detected = check_cache(&tag_cache.cache); 289 uint32_t current_serial = __system_property_area_serial();
298 uint32_t current_serial = __system_property_area_serial(); 290 if (current_serial != serial) {
299 if (current_serial != serial) { 291 change_detected = 1;
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 } 292 }
293 if (change_detected) {
294 refresh_cache(&tag_cache, key);
295 serial = current_serial;
296 }
297 ret = tag_cache.c == '1';
298
299 unlock();
300 }
310 301
311 return ret; 302 return ret;
312} 303}
313 304
314/* 305/*
@@ -317,100 +308,88 @@ LIBLOG_ABI_PRIVATE int __android_log_is_debuggable()
317 * Use a separate lock from is_loggable to keep contention down b/25563384. 308 * Use a separate lock from is_loggable to keep contention down b/25563384.
318 */ 309 */
319struct cache2_char { 310struct cache2_char {
320 pthread_mutex_t lock; 311 pthread_mutex_t lock;
321 uint32_t serial; 312 uint32_t serial;
322 const char* key_persist; 313 const char* key_persist;
323 struct cache_char cache_persist; 314 struct cache_char cache_persist;
324 const char* key_ro; 315 const char* key_ro;
325 struct cache_char cache_ro; 316 struct cache_char cache_ro;
326 unsigned char (*const evaluate)(const struct cache2_char *self); 317 unsigned char (*const evaluate)(const struct cache2_char* self);
327}; 318};
328 319
329static inline unsigned char do_cache2_char(struct cache2_char *self) 320static inline unsigned char do_cache2_char(struct cache2_char* self) {
330{ 321 uint32_t current_serial;
331 uint32_t current_serial; 322 int change_detected;
332 int change_detected; 323 unsigned char c;
333 unsigned char c; 324
334 325 if (pthread_mutex_trylock(&self->lock)) {
335 if (pthread_mutex_trylock(&self->lock)) { 326 /* We are willing to accept some race in this context */
336 /* We are willing to accept some race in this context */ 327 return self->evaluate(self);
337 return self->evaluate(self); 328 }
338 } 329
339 330 change_detected = check_cache(&self->cache_persist.cache) ||
340 change_detected = check_cache(&self->cache_persist.cache) 331 check_cache(&self->cache_ro.cache);
341 || check_cache(&self->cache_ro.cache); 332 current_serial = __system_property_area_serial();
342 current_serial = __system_property_area_serial(); 333 if (current_serial != self->serial) {
343 if (current_serial != self->serial) { 334 change_detected = 1;
344 change_detected = 1; 335 }
345 } 336 if (change_detected) {
346 if (change_detected) { 337 refresh_cache(&self->cache_persist, self->key_persist);
347 refresh_cache(&self->cache_persist, self->key_persist); 338 refresh_cache(&self->cache_ro, self->key_ro);
348 refresh_cache(&self->cache_ro, self->key_ro); 339 self->serial = current_serial;
349 self->serial = current_serial; 340 }
350 } 341 c = self->evaluate(self);
351 c = self->evaluate(self); 342
352 343 pthread_mutex_unlock(&self->lock);
353 pthread_mutex_unlock(&self->lock); 344
354 345 return c;
355 return c;
356} 346}
357 347
358static unsigned char evaluate_persist_ro(const struct cache2_char *self) 348static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
359{ 349 unsigned char c = self->cache_persist.c;
360 unsigned char c = self->cache_persist.c;
361 350
362 if (c) { 351 if (c) {
363 return c; 352 return c;
364 } 353 }
365 354
366 return self->cache_ro.c; 355 return self->cache_ro.c;
367} 356}
368 357
369/* 358/*
370 * Timestamp state generally remains constant, but can change at any time 359 * Timestamp state generally remains constant, but can change at any time
371 * to handle developer requirements. 360 * to handle developer requirements.
372 */ 361 */
373LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() 362LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
374{ 363 static struct cache2_char clockid = {
375 static struct cache2_char clockid = { 364 PTHREAD_MUTEX_INITIALIZER, 0,
376 PTHREAD_MUTEX_INITIALIZER, 365 "persist.logd.timestamp", { { NULL, -1 }, '\0' },
377 0, 366 "ro.logd.timestamp", { { NULL, -1 }, '\0' },
378 "persist.logd.timestamp", 367 evaluate_persist_ro
379 { { NULL, -1 }, '\0' }, 368 };
380 "ro.logd.timestamp", 369
381 { { NULL, -1 }, '\0' }, 370 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC
382 evaluate_persist_ro 371 : CLOCK_REALTIME;
383 };
384
385 return (tolower(do_cache2_char(&clockid)) == 'm')
386 ? CLOCK_MONOTONIC
387 : CLOCK_REALTIME;
388} 372}
389 373
390/* 374/*
391 * Security state generally remains constant, but the DO must be able 375 * 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. 376 * to turn off logging should it become spammy after an attack is detected.
393 */ 377 */
394static unsigned char evaluate_security(const struct cache2_char *self) 378static unsigned char evaluate_security(const struct cache2_char* self) {
395{ 379 unsigned char c = self->cache_ro.c;
396 unsigned char c = self->cache_ro.c;
397 380
398 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE); 381 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
399} 382}
400 383
401LIBLOG_ABI_PUBLIC int __android_log_security() 384LIBLOG_ABI_PUBLIC int __android_log_security() {
402{ 385 static struct cache2_char security = {
403 static struct cache2_char security = { 386 PTHREAD_MUTEX_INITIALIZER, 0,
404 PTHREAD_MUTEX_INITIALIZER, 387 "persist.logd.security", { { NULL, -1 }, BOOLEAN_FALSE },
405 0, 388 "ro.device_owner", { { NULL, -1 }, BOOLEAN_FALSE },
406 "persist.logd.security", 389 evaluate_security
407 { { NULL, -1 }, BOOLEAN_FALSE }, 390 };
408 "ro.device_owner", 391
409 { { NULL, -1 }, BOOLEAN_FALSE }, 392 return do_cache2_char(&security);
410 evaluate_security
411 };
412
413 return do_cache2_char(&security);
414} 393}
415 394
416/* 395/*
@@ -420,245 +399,240 @@ LIBLOG_ABI_PUBLIC int __android_log_security()
420 399
421/* Property helper */ 400/* Property helper */
422static bool check_flag(const char* prop, const char* flag) { 401static bool check_flag(const char* prop, const char* flag) {
423 const char* cp = strcasestr(prop, flag); 402 const char* cp = strcasestr(prop, flag);
424 if (!cp) { 403 if (!cp) {
425 return false; 404 return false;
426 } 405 }
427 /* We only will document comma (,) */ 406 /* We only will document comma (,) */
428 static const char sep[] = ",:;|+ \t\f"; 407 static const char sep[] = ",:;|+ \t\f";
429 if ((cp != prop) && !strchr(sep, cp[-1])) { 408 if ((cp != prop) && !strchr(sep, cp[-1])) {
430 return false; 409 return false;
431 } 410 }
432 cp += strlen(flag); 411 cp += strlen(flag);
433 return !*cp || !!strchr(sep, *cp); 412 return !*cp || !!strchr(sep, *cp);
434} 413}
435 414
436/* cache structure */ 415/* cache structure */
437struct cache_property { 416struct cache_property {
438 struct cache cache; 417 struct cache cache;
439 char property[PROP_VALUE_MAX]; 418 char property[PROP_VALUE_MAX];
440}; 419};
441 420
442static void refresh_cache_property(struct cache_property* cache, const char* key) 421static void refresh_cache_property(struct cache_property* cache,
443{ 422 const char* key) {
423 if (!cache->cache.pinfo) {
424 cache->cache.pinfo = __system_property_find(key);
444 if (!cache->cache.pinfo) { 425 if (!cache->cache.pinfo) {
445 cache->cache.pinfo = __system_property_find(key); 426 return;
446 if (!cache->cache.pinfo) {
447 return;
448 }
449 } 427 }
450 cache->cache.serial = __system_property_serial(cache->cache.pinfo); 428 }
451 __system_property_read(cache->cache.pinfo, 0, cache->property); 429 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
430 __system_property_read(cache->cache.pinfo, 0, cache->property);
452} 431}
453 432
454/* get boolean with the logger twist that supports eng adjustments */ 433/* get boolean with the logger twist that supports eng adjustments */
455LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key, 434LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
456 int flag) 435 int flag) {
457{ 436 struct cache_property property = { { NULL, -1 }, { 0 } };
458 struct cache_property property = { { NULL, -1 }, { 0 } }; 437 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
459 if (flag & BOOL_DEFAULT_FLAG_PERSIST) { 438 char newkey[PROP_NAME_MAX];
460 char newkey[PROP_NAME_MAX]; 439 snprintf(newkey, sizeof(newkey), "ro.%s", key);
461 snprintf(newkey, sizeof(newkey), "ro.%s", key); 440 refresh_cache_property(&property, newkey);
462 refresh_cache_property(&property, newkey); 441 property.cache.pinfo = NULL;
463 property.cache.pinfo = NULL; 442 property.cache.serial = -1;
464 property.cache.serial = -1; 443 snprintf(newkey, sizeof(newkey), "persist.%s", key);
465 snprintf(newkey, sizeof(newkey), "persist.%s", key); 444 refresh_cache_property(&property, newkey);
466 refresh_cache_property(&property, newkey); 445 property.cache.pinfo = NULL;
467 property.cache.pinfo = NULL; 446 property.cache.serial = -1;
468 property.cache.serial = -1; 447 }
469 } 448
470 449 refresh_cache_property(&property, key);
471 refresh_cache_property(&property, key); 450
472 451 if (check_flag(property.property, "true")) {
473 if (check_flag(property.property, "true")) { 452 return true;
474 return true; 453 }
475 } 454 if (check_flag(property.property, "false")) {
476 if (check_flag(property.property, "false")) { 455 return false;
477 return false; 456 }
478 } 457 if (check_flag(property.property, "eng")) {
479 if (check_flag(property.property, "eng")) { 458 flag |= BOOL_DEFAULT_FLAG_ENG;
480 flag |= BOOL_DEFAULT_FLAG_ENG; 459 }
481 } 460 /* this is really a "not" flag */
482 /* this is really a "not" flag */ 461 if (check_flag(property.property, "svelte")) {
483 if (check_flag(property.property, "svelte")) { 462 flag |= BOOL_DEFAULT_FLAG_SVELTE;
484 flag |= BOOL_DEFAULT_FLAG_SVELTE; 463 }
485 } 464
486 465 /* Sanity Check */
487 /* Sanity Check */ 466 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
488 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) { 467 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
489 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE; 468 flag |= BOOL_DEFAULT_TRUE;
490 flag |= BOOL_DEFAULT_TRUE; 469 }
491 } 470
492 471 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
493 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) 472 __android_logger_property_get_bool("ro.config.low_ram",
494 && __android_logger_property_get_bool("ro.config.low_ram", 473 BOOL_DEFAULT_FALSE)) {
495 BOOL_DEFAULT_FALSE)) { 474 return false;
496 return false; 475 }
497 } 476 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
498 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) { 477 return false;
499 return false; 478 }
500 } 479
501 480 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
502 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
503} 481}
504 482
505LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) 483LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) {
506{ 484 static long pages, pagesize;
507 static long pages, pagesize; 485 unsigned long maximum;
508 unsigned long maximum;
509 486
510 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) { 487 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
511 return false; 488 return false;
512 } 489 }
513 490
514 if (!pages) { 491 if (!pages) {
515 pages = sysconf(_SC_PHYS_PAGES); 492 pages = sysconf(_SC_PHYS_PAGES);
516 } 493 }
517 if (pages < 1) { 494 if (pages < 1) {
518 return true; 495 return true;
519 } 496 }
520 497
521 if (!pagesize) { 498 if (!pagesize) {
522 pagesize = sysconf(_SC_PAGESIZE); 499 pagesize = sysconf(_SC_PAGESIZE);
523 if (pagesize <= 1) { 500 if (pagesize <= 1) {
524 pagesize = PAGE_SIZE; 501 pagesize = PAGE_SIZE;
525 }
526 } 502 }
503 }
527 504
528 /* maximum memory impact a somewhat arbitrary ~3% */ 505 /* maximum memory impact a somewhat arbitrary ~3% */
529 pages = (pages + 31) / 32; 506 pages = (pages + 31) / 32;
530 maximum = pages * pagesize; 507 maximum = pages * pagesize;
531 508
532 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) { 509 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
533 return true; 510 return true;
534 } 511 }
535 512
536 return value <= maximum; 513 return value <= maximum;
537} 514}
538 515
539struct cache2_property_size { 516struct cache2_property_size {
540 pthread_mutex_t lock; 517 pthread_mutex_t lock;
541 uint32_t serial; 518 uint32_t serial;
542 const char* key_persist; 519 const char* key_persist;
543 struct cache_property cache_persist; 520 struct cache_property cache_persist;
544 const char* key_ro; 521 const char* key_ro;
545 struct cache_property cache_ro; 522 struct cache_property cache_ro;
546 unsigned long (*const evaluate)(const struct cache2_property_size* self); 523 unsigned long (*const evaluate)(const struct cache2_property_size* self);
547}; 524};
548 525
549static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) 526static inline unsigned long do_cache2_property_size(
550{ 527 struct cache2_property_size* self) {
551 uint32_t current_serial; 528 uint32_t current_serial;
552 int change_detected; 529 int change_detected;
553 unsigned long v; 530 unsigned long v;
554 531
555 if (pthread_mutex_trylock(&self->lock)) { 532 if (pthread_mutex_trylock(&self->lock)) {
556 /* We are willing to accept some race in this context */ 533 /* We are willing to accept some race in this context */
557 return self->evaluate(self); 534 return self->evaluate(self);
558 } 535 }
559 536
560 change_detected = check_cache(&self->cache_persist.cache) 537 change_detected = check_cache(&self->cache_persist.cache) ||
561 || check_cache(&self->cache_ro.cache); 538 check_cache(&self->cache_ro.cache);
562 current_serial = __system_property_area_serial(); 539 current_serial = __system_property_area_serial();
563 if (current_serial != self->serial) { 540 if (current_serial != self->serial) {
564 change_detected = 1; 541 change_detected = 1;
565 } 542 }
566 if (change_detected) { 543 if (change_detected) {
567 refresh_cache_property(&self->cache_persist, self->key_persist); 544 refresh_cache_property(&self->cache_persist, self->key_persist);
568 refresh_cache_property(&self->cache_ro, self->key_ro); 545 refresh_cache_property(&self->cache_ro, self->key_ro);
569 self->serial = current_serial; 546 self->serial = current_serial;
570 } 547 }
571 v = self->evaluate(self); 548 v = self->evaluate(self);
572 549
573 pthread_mutex_unlock(&self->lock); 550 pthread_mutex_unlock(&self->lock);
574 551
575 return v; 552 return v;
576} 553}
577 554
578static unsigned long property_get_size_from_cache(const struct cache_property* cache) 555static unsigned long property_get_size_from_cache(
579{ 556 const struct cache_property* cache) {
580 char* cp; 557 char* cp;
581 unsigned long value = strtoul(cache->property, &cp, 10); 558 unsigned long value = strtoul(cache->property, &cp, 10);
582 559
583 switch(*cp) { 560 switch (*cp) {
584 case 'm': 561 case 'm':
585 case 'M': 562 case 'M':
586 value *= 1024; 563 value *= 1024;
587 /* FALLTHRU */ 564 /* FALLTHRU */
588 case 'k': 565 case 'k':
589 case 'K': 566 case 'K':
590 value *= 1024; 567 value *= 1024;
591 /* FALLTHRU */ 568 /* FALLTHRU */
592 case '\0': 569 case '\0':
593 break; 570 break;
594 571
595 default: 572 default:
596 value = 0; 573 value = 0;
597 } 574 }
598 575
599 if (!__android_logger_valid_buffer_size(value)) { 576 if (!__android_logger_valid_buffer_size(value)) {
600 value = 0; 577 value = 0;
601 } 578 }
602 579
603 return value; 580 return value;
604} 581}
605 582
606static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) 583static unsigned long evaluate_property_get_size(
607{ 584 const struct cache2_property_size* self) {
608 unsigned long size = property_get_size_from_cache(&self->cache_persist); 585 unsigned long size = property_get_size_from_cache(&self->cache_persist);
609 if (size) { 586 if (size) {
610 return size; 587 return size;
611 } 588 }
612 return property_get_size_from_cache(&self->cache_ro); 589 return property_get_size_from_cache(&self->cache_ro);
613} 590}
614 591
615LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) 592LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) {
616{ 593 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
617 static const char global_tunable[] = "persist.logd.size"; /* Settings App */ 594 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
618 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */ 595 static struct cache2_property_size global = {
619 static struct cache2_property_size global = { 596 /* clang-format off */
620 PTHREAD_MUTEX_INITIALIZER, 597 PTHREAD_MUTEX_INITIALIZER, 0,
621 0, 598 global_tunable, { { NULL, -1 }, {} },
622 global_tunable, 599 global_default, { { NULL, -1 }, {} },
623 { { NULL, -1 }, {} }, 600 evaluate_property_get_size
624 global_default, 601 /* clang-format on */
625 { { NULL, -1 }, {} }, 602 };
626 evaluate_property_get_size 603 char key_persist[PROP_NAME_MAX];
627 }; 604 char key_ro[PROP_NAME_MAX];
628 char key_persist[PROP_NAME_MAX]; 605 struct cache2_property_size local = {
629 char key_ro[PROP_NAME_MAX]; 606 /* clang-format off */
630 struct cache2_property_size local = { 607 PTHREAD_MUTEX_INITIALIZER, 0,
631 PTHREAD_MUTEX_INITIALIZER, 608 key_persist, { { NULL, -1 }, {} },
632 0, 609 key_ro, { { NULL, -1 }, {} },
633 key_persist, 610 evaluate_property_get_size
634 { { NULL, -1 }, {} }, 611 /* clang-format on */
635 key_ro, 612 };
636 { { NULL, -1 }, {} }, 613 unsigned long property_size, default_size;
637 evaluate_property_get_size 614
638 }; 615 default_size = do_cache2_property_size(&global);
639 unsigned long property_size, default_size; 616 if (!default_size) {
640 617 default_size = __android_logger_property_get_bool("ro.config.low_ram",
641 default_size = do_cache2_property_size(&global); 618 BOOL_DEFAULT_FALSE)
642 if (!default_size) { 619 ? LOG_BUFFER_MIN_SIZE /* 64K */
643 default_size = __android_logger_property_get_bool("ro.config.low_ram", 620 : LOG_BUFFER_SIZE; /* 256K */
644 BOOL_DEFAULT_FALSE) 621 }
645 ? LOG_BUFFER_MIN_SIZE /* 64K */ 622
646 : LOG_BUFFER_SIZE; /* 256K */ 623 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
647 } 624 android_log_id_to_name(logId));
648 625 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default,
649 snprintf(key_persist, sizeof(key_persist), "%s.%s", 626 android_log_id_to_name(logId));
650 global_tunable, android_log_id_to_name(logId)); 627 property_size = do_cache2_property_size(&local);
651 snprintf(key_ro, sizeof(key_ro), "%s.%s", 628
652 global_default, android_log_id_to_name(logId)); 629 if (!property_size) {
653 property_size = do_cache2_property_size(&local); 630 property_size = default_size;
654 631 }
655 if (!property_size) { 632
656 property_size = default_size; 633 if (!property_size) {
657 } 634 property_size = LOG_BUFFER_SIZE;
658 635 }
659 if (!property_size) { 636
660 property_size = LOG_BUFFER_SIZE; 637 return property_size;
661 }
662
663 return property_size;
664} 638}