1956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn/*
2956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** Copyright 2014, The Android Open Source Project
3956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn**
4956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** Licensed under the Apache License, Version 2.0 (the "License");
5956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** you may not use this file except in compliance with the License.
6956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** You may obtain a copy of the License at
7956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn**
8956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn**     http://www.apache.org/licenses/LICENSE-2.0
9956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn**
10956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** Unless required by applicable law or agreed to in writing, software
11956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** distributed under the License is distributed on an "AS IS" BASIS,
12956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** See the License for the specific language governing permissions and
14956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn** limitations under the License.
15956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn*/
16956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn
17956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn#include <ctype.h>
18c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn#include <pthread.h>
19e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn#include <stdbool.h>
20c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn#include <stdlib.h>
21956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn#include <string.h>
22c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
23c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn#include <sys/_system_properties.h>
24e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn#include <unistd.h>
25956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn
26e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn#include <private/android_logger.h>
27956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn
28018a96d03f0d452bf078084eedcd5693da42308dMark Salyzyn#include "log_portability.h"
29be1d3c21b57d3e67c6a9682f3b2f0838486a3ee8Mark Salyzyn
302d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzynstatic pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
312d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn
322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic int lock() {
332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * If we trigger a signal handler in the middle of locked activity and the
352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * signal handler logs a message, we could get into a deadlock state.
362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   *  Any contention, and we can turn around and use the non-cached method
392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * in less time than the system call associated with a mutex to deal with
402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * the contention.
412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return pthread_mutex_trylock(&lock_loggable);
432d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn}
442d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn
452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void unlock() {
462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pthread_mutex_unlock(&lock_loggable);
472d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn}
482d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn
49c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzynstruct cache {
502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const prop_info* pinfo;
512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t serial;
52e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn};
53e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
54e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzynstruct cache_char {
552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache cache;
562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned char c;
57c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn};
58c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn
592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic int check_cache(struct cache* cache) {
602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
61a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn}
62a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn
63ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn#define BOOLEAN_TRUE 0xFF
64ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn#define BOOLEAN_FALSE 0xFE
65ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn
662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void refresh_cache(struct cache_char* cache, const char* key) {
672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char buf[PROP_VALUE_MAX];
68956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn
692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!cache->cache.pinfo) {
702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    cache->cache.pinfo = __system_property_find(key);
71e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    if (!cache->cache.pinfo) {
722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return;
732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  cache->cache.serial = __system_property_serial(cache->cache.pinfo);
762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  __system_property_read(cache->cache.pinfo, 0, buf);
772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  switch (buf[0]) {
782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    case 't':
792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    case 'T':
802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    case 'f':
832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    case 'F':
842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
86ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn    default:
872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      cache->c = buf[0];
882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
89c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn}
90c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn
912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic int __android_log_level(const char* tag, size_t len, int default_prio) {
922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* sizeof() is used on this array below */
932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const char log_namespace[] = "persist.log.tag.";
942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const size_t base_offset = 8; /* skip "persist." */
952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* calculate the size of our key temporary buffer */
962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const size_t taglen = tag ? len : 0;
972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
98d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn  char key[sizeof(log_namespace) + taglen];
992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char* kp;
1002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t i;
1012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char c = 0;
1022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
1032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Single layer cache of four properties. Priorities are:
1042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   *    log.tag.<tag>
1052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   *    persist.log.tag.<tag>
1062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   *    log.tag
1072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   *    persist.log.tag
1082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Where the missing tag matches all tags and becomes the
1092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * system global default. We do not support ro.log.tag* .
1102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
111d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn  static char* last_tag;
112d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn  static size_t last_tag_len;
1132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static uint32_t global_serial;
1142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* some compilers erroneously see uninitialized use. !not_locked */
1152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t current_global_serial = 0;
1162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static struct cache_char tag_cache[2];
1172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static struct cache_char global_cache[2];
1182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int change_detected;
1192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int global_change_detected;
1202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int not_locked;
1212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  strcpy(key, log_namespace);
1232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  global_change_detected = change_detected = not_locked = lock();
1252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!not_locked) {
127c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    /*
1282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn     *  check all known serial numbers to changes.
129c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn     */
1302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
1312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (check_cache(&tag_cache[i].cache)) {
1322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        change_detected = 1;
1332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
1342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
1352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
1362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (check_cache(&global_cache[i].cache)) {
1372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        global_change_detected = 1;
1382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
1392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
140c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn
1412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    current_global_serial = __system_property_area_serial();
1422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (current_global_serial != global_serial) {
1432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      change_detected = 1;
1442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      global_change_detected = 1;
1452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
1462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
147c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn
1482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (taglen) {
1492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    int local_change_detected = change_detected;
150a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn    if (!not_locked) {
151d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn      if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
152d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn          strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
1532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        /* invalidate log.tag.<tag> cache */
154a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn        for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
1552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          tag_cache[i].cache.pinfo = NULL;
1562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          tag_cache[i].c = '\0';
157a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn        }
158d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn        if (last_tag) last_tag[0] = '\0';
1592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        local_change_detected = 1;
1602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
161d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn      if (!last_tag || !last_tag[0]) {
162d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn        if (!last_tag) {
163d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn          last_tag = calloc(1, len + 1);
164d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn          last_tag_len = 0;
165d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn          if (last_tag) last_tag_len = len + 1;
166d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn        } else if (len >= last_tag_len) {
167d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn          last_tag = realloc(last_tag, len + 1);
168d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn          last_tag_len = 0;
169d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn          if (last_tag) last_tag_len = len + 1;
170d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn        }
171d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn        if (last_tag) {
1722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          strncpy(last_tag, tag, len);
1732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          last_tag[len] = '\0';
174a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn        }
1752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
1762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
1772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    strncpy(key + sizeof(log_namespace) - 1, tag, len);
1782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    key[sizeof(log_namespace) - 1 + len] = '\0';
1792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    kp = key;
1812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
1822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      struct cache_char* cache = &tag_cache[i];
1832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      struct cache_char temp_cache;
1842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (not_locked) {
1862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        temp_cache.cache.pinfo = NULL;
1872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        temp_cache.c = '\0';
1882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        cache = &temp_cache;
1892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
1902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (local_change_detected) {
1912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        refresh_cache(cache, kp);
1922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
1932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (cache->c) {
1952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        c = cache->c;
1962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        break;
1972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
198956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn
1992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      kp = key + base_offset;
200c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    }
2012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
202c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn
2032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  switch (toupper(c)) { /* if invalid, resort to global */
204c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'V':
205c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'D':
206c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'I':
207c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'W':
208c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'E':
209c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'F': /* Not officially supported */
210c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'A':
211c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'S':
212ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn    case BOOLEAN_FALSE: /* Not officially supported */
2132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
214c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    default:
2152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* clear '.' after log.tag */
2162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      key[sizeof(log_namespace) - 2] = '\0';
2172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      kp = key;
2192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
2202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        struct cache_char* cache = &global_cache[i];
2212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        struct cache_char temp_cache;
2222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (not_locked) {
2242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          temp_cache = *cache;
2252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
2262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            temp_cache.cache.pinfo = NULL;
2272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            temp_cache.c = '\0';
2282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          }
2292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          cache = &temp_cache;
2302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        }
2312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (global_change_detected) {
2322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          refresh_cache(cache, kp);
2331f028b2fdfd75fb8689e2da78320d178991a4731Mark Salyzyn        }
234c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn
2352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (cache->c) {
2362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          c = cache->c;
2372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          break;
2382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        }
239c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn
2402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        kp = key + base_offset;
2412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
2422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
2432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!not_locked) {
2462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    global_serial = current_global_serial;
2472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    unlock();
2482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  switch (toupper(c)) {
2512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* clang-format off */
252c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'V': return ANDROID_LOG_VERBOSE;
253c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'D': return ANDROID_LOG_DEBUG;
254c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'I': return ANDROID_LOG_INFO;
255c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'W': return ANDROID_LOG_WARN;
256c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'E': return ANDROID_LOG_ERROR;
257c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'F': /* FALLTHRU */ /* Not officially supported */
258c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'A': return ANDROID_LOG_FATAL;
259ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn    case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
260c158456f50817ac506f4eed780978e63dd222fe4Mark Salyzyn    case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
2612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* clang-format on */
2622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return default_prio;
264956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn}
265956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn
2662ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag,
2672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                    size_t len,
2682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                    int default_prio) {
2692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int logLevel = __android_log_level(tag, len, default_prio);
2702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return logLevel >= 0 && prio >= logLevel;
271807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn}
272807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn
2732ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag,
2742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                int default_prio) {
2752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int logLevel =
2762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
2772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return logLevel >= 0 && prio >= logLevel;
278956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn}
279500afc75325823c03dbdf6b2d56fd86e29f120f4Mark Salyzyn
280d73be1b96beab812b86f8174e7fc928291f0cb44Steven MorelandLIBLOG_ABI_PUBLIC int __android_log_is_debuggable() {
2812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static uint32_t serial;
2822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static struct cache_char tag_cache;
2832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const char key[] = "ro.debuggable";
2842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int ret;
2852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (tag_cache.c) { /* ro property does not change after set */
2872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ret = tag_cache.c == '1';
2882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else if (lock()) {
2892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    struct cache_char temp_cache = { { NULL, -1 }, '\0' };
2902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    refresh_cache(&temp_cache, key);
2912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ret = temp_cache.c == '1';
2922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else {
2932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    int change_detected = check_cache(&tag_cache.cache);
2942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    uint32_t current_serial = __system_property_area_serial();
2952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (current_serial != serial) {
2962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      change_detected = 1;
2977ef5249afacffe3901e3a602372c7d34cf655675Mark Salyzyn    }
2982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (change_detected) {
2992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      refresh_cache(&tag_cache, key);
3002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      serial = current_serial;
3012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
3022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ret = tag_cache.c == '1';
3032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    unlock();
3052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3067ef5249afacffe3901e3a602372c7d34cf655675Mark Salyzyn
3072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return ret;
3087ef5249afacffe3901e3a602372c7d34cf655675Mark Salyzyn}
3097ef5249afacffe3901e3a602372c7d34cf655675Mark Salyzyn
3102d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn/*
311a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn * For properties that are read often, but generally remain constant.
312a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn * Since a change is rare, we will accept a trylock failure gracefully.
313a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn * Use a separate lock from is_loggable to keep contention down b/25563384.
3142d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn */
315e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzynstruct cache2_char {
3162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pthread_mutex_t lock;
3172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t serial;
3182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* key_persist;
3192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache_char cache_persist;
3202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* key_ro;
3212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache_char cache_ro;
3222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned char (*const evaluate)(const struct cache2_char* self);
323a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn};
3242d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn
3252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic inline unsigned char do_cache2_char(struct cache2_char* self) {
3262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t current_serial;
3272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int change_detected;
3282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned char c;
3292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (pthread_mutex_trylock(&self->lock)) {
3312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* We are willing to accept some race in this context */
3322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return self->evaluate(self);
3332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  change_detected = check_cache(&self->cache_persist.cache) ||
3362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                    check_cache(&self->cache_ro.cache);
3372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  current_serial = __system_property_area_serial();
3382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (current_serial != self->serial) {
3392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    change_detected = 1;
3402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (change_detected) {
3422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    refresh_cache(&self->cache_persist, self->key_persist);
3432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    refresh_cache(&self->cache_ro, self->key_ro);
3442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    self->serial = current_serial;
3452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  c = self->evaluate(self);
3472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pthread_mutex_unlock(&self->lock);
3492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return c;
351a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn}
352a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn
3532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic unsigned char evaluate_persist_ro(const struct cache2_char* self) {
3542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned char c = self->cache_persist.c;
355a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn
3562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (c) {
3572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return c;
3582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
359a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn
3602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return self->cache_ro.c;
361500afc75325823c03dbdf6b2d56fd86e29f120f4Mark Salyzyn}
362ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn
363ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn/*
364a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn * Timestamp state generally remains constant, but can change at any time
365a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn * to handle developer requirements.
366ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn */
3672ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
3682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static struct cache2_char clockid = {
3692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    PTHREAD_MUTEX_INITIALIZER, 0,
3702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    "persist.logd.timestamp",  { { NULL, -1 }, '\0' },
3712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    "ro.logd.timestamp",       { { NULL, -1 }, '\0' },
3722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    evaluate_persist_ro
3732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  };
3742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC
3762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                    : CLOCK_REALTIME;
377a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn}
378a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn
379a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn/*
380a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn * Security state generally remains constant, but the DO must be able
381a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn * to turn off logging should it become spammy after an attack is detected.
382a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn */
3832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic unsigned char evaluate_security(const struct cache2_char* self) {
3842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned char c = self->cache_ro.c;
385ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn
3862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
387a67d8a53c744b4e873f666541b1854c704994da9Mark Salyzyn}
388ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn
3892ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC int __android_log_security() {
3902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static struct cache2_char security = {
3912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    PTHREAD_MUTEX_INITIALIZER, 0,
3922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    "persist.logd.security",   { { NULL, -1 }, BOOLEAN_FALSE },
3932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    "ro.device_owner",         { { NULL, -1 }, BOOLEAN_FALSE },
3942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    evaluate_security
3952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  };
3962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return do_cache2_char(&security);
398e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
399e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
400e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn/*
401e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn * Interface that represents the logd buffer size determination so that others
402e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn * need not guess our intentions.
403e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn */
404e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
405e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn/* Property helper */
406e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzynstatic bool check_flag(const char* prop, const char* flag) {
4072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* cp = strcasestr(prop, flag);
4082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!cp) {
4092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return false;
4102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* We only will document comma (,) */
4122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const char sep[] = ",:;|+ \t\f";
4132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((cp != prop) && !strchr(sep, cp[-1])) {
4142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return false;
4152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  cp += strlen(flag);
4172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return !*cp || !!strchr(sep, *cp);
418e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
419e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
420e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn/* cache structure */
421e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzynstruct cache_property {
4222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache cache;
4232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char property[PROP_VALUE_MAX];
424e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn};
425e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
4262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void refresh_cache_property(struct cache_property* cache,
4272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                   const char* key) {
4282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!cache->cache.pinfo) {
4292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    cache->cache.pinfo = __system_property_find(key);
430e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    if (!cache->cache.pinfo) {
4312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return;
432e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    }
4332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  cache->cache.serial = __system_property_serial(cache->cache.pinfo);
4352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  __system_property_read(cache->cache.pinfo, 0, cache->property);
436e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
437e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
438e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn/* get boolean with the logger twist that supports eng adjustments */
439e455373b57bc09551eaa2e595bcecbd39acf6a1aMark SalyzynLIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
4402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                           int flag) {
4412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache_property property = { { NULL, -1 }, { 0 } };
4422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
443d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn    char newkey[strlen("persist.") + strlen(key) + 1];
4442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    snprintf(newkey, sizeof(newkey), "ro.%s", key);
4452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    refresh_cache_property(&property, newkey);
4462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    property.cache.pinfo = NULL;
4472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    property.cache.serial = -1;
4482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    snprintf(newkey, sizeof(newkey), "persist.%s", key);
4492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    refresh_cache_property(&property, newkey);
4502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    property.cache.pinfo = NULL;
4512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    property.cache.serial = -1;
4522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  refresh_cache_property(&property, key);
4552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (check_flag(property.property, "true")) {
4572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return true;
4582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (check_flag(property.property, "false")) {
4602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return false;
4612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4629fcaaba85ddee7ca181901b7409ef3eb2962a7d8Mark Salyzyn  if (property.property[0]) {
4639fcaaba85ddee7ca181901b7409ef3eb2962a7d8Mark Salyzyn    flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
4649fcaaba85ddee7ca181901b7409ef3eb2962a7d8Mark Salyzyn  }
4652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (check_flag(property.property, "eng")) {
4662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    flag |= BOOL_DEFAULT_FLAG_ENG;
4672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* this is really a "not" flag */
4692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (check_flag(property.property, "svelte")) {
4702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    flag |= BOOL_DEFAULT_FLAG_SVELTE;
4712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* Sanity Check */
4742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
4752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
4762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    flag |= BOOL_DEFAULT_TRUE;
4772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
4802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      __android_logger_property_get_bool("ro.config.low_ram",
4812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                         BOOL_DEFAULT_FALSE)) {
4822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return false;
4832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
4852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return false;
4862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
489e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
490e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
4912ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) {
4922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static long pages, pagesize;
4932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned long maximum;
494e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
4952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
4962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return false;
4972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
498e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
4992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!pages) {
5002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    pages = sysconf(_SC_PHYS_PAGES);
5012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (pages < 1) {
5032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return true;
5042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
505e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!pagesize) {
5072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    pagesize = sysconf(_SC_PAGESIZE);
5082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (pagesize <= 1) {
5092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      pagesize = PAGE_SIZE;
510e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    }
5112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
512e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* maximum memory impact a somewhat arbitrary ~3% */
5142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pages = (pages + 31) / 32;
5152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  maximum = pages * pagesize;
516e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
5182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return true;
5192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
520e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return value <= maximum;
522e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
523e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
524e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzynstruct cache2_property_size {
5252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pthread_mutex_t lock;
5262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t serial;
5272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* key_persist;
5282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache_property cache_persist;
5292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* key_ro;
5302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache_property cache_ro;
5312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned long (*const evaluate)(const struct cache2_property_size* self);
532e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn};
533e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic inline unsigned long do_cache2_property_size(
5352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    struct cache2_property_size* self) {
5362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t current_serial;
5372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int change_detected;
5382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned long v;
5392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (pthread_mutex_trylock(&self->lock)) {
5412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* We are willing to accept some race in this context */
5422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return self->evaluate(self);
5432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  change_detected = check_cache(&self->cache_persist.cache) ||
5462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                    check_cache(&self->cache_ro.cache);
5472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  current_serial = __system_property_area_serial();
5482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (current_serial != self->serial) {
5492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    change_detected = 1;
5502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (change_detected) {
5522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    refresh_cache_property(&self->cache_persist, self->key_persist);
5532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    refresh_cache_property(&self->cache_ro, self->key_ro);
5542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    self->serial = current_serial;
5552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  v = self->evaluate(self);
5572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pthread_mutex_unlock(&self->lock);
5592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return v;
561e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
562e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic unsigned long property_get_size_from_cache(
5642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    const struct cache_property* cache) {
5652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char* cp;
5662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned long value = strtoul(cache->property, &cp, 10);
567e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  switch (*cp) {
569e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    case 'm':
570e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    case 'M':
5712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      value *= 1024;
572e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    /* FALLTHRU */
573e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    case 'k':
574e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    case 'K':
5752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      value *= 1024;
576e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    /* FALLTHRU */
577e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    case '\0':
5782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
579e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
580e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn    default:
5812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      value = 0;
5822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
583e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!__android_logger_valid_buffer_size(value)) {
5852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    value = 0;
5862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
587e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return value;
589e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
590e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
5912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic unsigned long evaluate_property_get_size(
5922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    const struct cache2_property_size* self) {
5932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned long size = property_get_size_from_cache(&self->cache_persist);
5942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (size) {
5952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return size;
5962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return property_get_size_from_cache(&self->cache_ro);
598e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn}
599e455373b57bc09551eaa2e595bcecbd39acf6a1aMark Salyzyn
6002ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) {
6012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const char global_tunable[] = "persist.logd.size"; /* Settings App */
6022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const char global_default[] = "ro.logd.size";      /* BoardConfig.mk */
6032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static struct cache2_property_size global = {
6042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* clang-format off */
6052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    PTHREAD_MUTEX_INITIALIZER, 0,
6062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    global_tunable, { { NULL, -1 }, {} },
6072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    global_default, { { NULL, -1 }, {} },
6082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    evaluate_property_get_size
6092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* clang-format on */
6102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  };
611d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn  char key_persist[strlen(global_tunable) + strlen(".security") + 1];
612d24dc95e871e8d201e894b36f4cd102af226287eMark Salyzyn  char key_ro[strlen(global_default) + strlen(".security") + 1];
6132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct cache2_property_size local = {
6142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* clang-format off */
6152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    PTHREAD_MUTEX_INITIALIZER, 0,
6162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    key_persist, { { NULL, -1 }, {} },
6172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    key_ro,      { { NULL, -1 }, {} },
6182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    evaluate_property_get_size
6192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* clang-format on */
6202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  };
6212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned long property_size, default_size;
6222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  default_size = do_cache2_property_size(&global);
6242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!default_size) {
6252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    default_size = __android_logger_property_get_bool("ro.config.low_ram",
6262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                      BOOL_DEFAULT_FALSE)
6272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                       ? LOG_BUFFER_MIN_SIZE /* 64K  */
6282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                       : LOG_BUFFER_SIZE;    /* 256K */
6292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
6302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
6322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn           android_log_id_to_name(logId));
6332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default,
6342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn           android_log_id_to_name(logId));
6352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  property_size = do_cache2_property_size(&local);
6362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!property_size) {
6382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    property_size = default_size;
6392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
6402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!property_size) {
6422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    property_size = LOG_BUFFER_SIZE;
6432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
6442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return property_size;
646ffbd86ff25583e2bdae0b6f958e46e40ad111b3dMark Salyzyn}
647