2014-10-02 18:12:28 +00:00
|
|
|
/*
|
|
|
|
** Copyright 2014, The Android Open Source Project
|
|
|
|
**
|
|
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
** you may not use this file except in compliance with the License.
|
|
|
|
** You may obtain a copy of the License at
|
|
|
|
**
|
|
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
**
|
|
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
** See the License for the specific language governing permissions and
|
|
|
|
** limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <ctype.h>
|
2015-03-12 22:46:29 +00:00
|
|
|
#include <pthread.h>
|
|
|
|
#include <stdlib.h>
|
2014-10-02 18:12:28 +00:00
|
|
|
#include <string.h>
|
2015-03-12 22:46:29 +00:00
|
|
|
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
|
|
|
#include <sys/_system_properties.h>
|
2014-10-02 18:12:28 +00:00
|
|
|
|
|
|
|
#include <android/log.h>
|
|
|
|
|
2015-03-12 22:46:29 +00:00
|
|
|
struct cache {
|
|
|
|
const prop_info *pinfo;
|
|
|
|
uint32_t serial;
|
|
|
|
char c;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void refresh_cache(struct cache *cache, const char *key)
|
2014-10-02 18:12:28 +00:00
|
|
|
{
|
2015-03-12 22:46:29 +00:00
|
|
|
uint32_t serial;
|
2014-10-02 18:12:28 +00:00
|
|
|
char buf[PROP_VALUE_MAX];
|
|
|
|
|
2015-03-12 22:46:29 +00:00
|
|
|
if (!cache->pinfo) {
|
|
|
|
cache->pinfo = __system_property_find(key);
|
|
|
|
if (!cache->pinfo) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
serial = __system_property_serial(cache->pinfo);
|
|
|
|
if (serial == cache->serial) {
|
|
|
|
return;
|
2014-10-02 18:12:28 +00:00
|
|
|
}
|
2015-03-12 22:46:29 +00:00
|
|
|
cache->serial = serial;
|
|
|
|
__system_property_read(cache->pinfo, 0, buf);
|
|
|
|
cache->c = buf[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
static int __android_log_level(const char *tag, int def)
|
|
|
|
{
|
|
|
|
/* sizeof() is used on this array below */
|
|
|
|
static const char log_namespace[] = "persist.log.tag.";
|
|
|
|
static const size_t base_offset = 8; /* skip "persist." */
|
|
|
|
/* calculate the size of our key temporary buffer */
|
|
|
|
const size_t taglen = (tag && *tag) ? strlen(tag) : 0;
|
|
|
|
/* sizeof(log_namespace) = strlen(log_namespace) + 1 */
|
|
|
|
char key[sizeof(log_namespace) + taglen];
|
|
|
|
char *kp;
|
|
|
|
size_t i;
|
|
|
|
char c = 0;
|
|
|
|
/*
|
|
|
|
* Single layer cache of four properties. Priorities are:
|
|
|
|
* log.tag.<tag>
|
|
|
|
* persist.log.tag.<tag>
|
|
|
|
* log.tag
|
|
|
|
* persist.log.tag
|
|
|
|
* Where the missing tag matches all tags and becomes the
|
|
|
|
* system global default. We do not support ro.log.tag* .
|
|
|
|
*/
|
|
|
|
static char *last_tag;
|
|
|
|
static uint32_t global_serial;
|
|
|
|
uint32_t current_global_serial;
|
|
|
|
static struct cache tag_cache[2] = {
|
|
|
|
{ NULL, -1, 0 },
|
|
|
|
{ NULL, -1, 0 }
|
|
|
|
};
|
|
|
|
static struct cache global_cache[2] = {
|
|
|
|
{ NULL, -1, 0 },
|
|
|
|
{ NULL, -1, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
strcpy(key, log_namespace);
|
|
|
|
|
|
|
|
pthread_mutex_lock(&lock);
|
|
|
|
|
|
|
|
current_global_serial = __system_property_area_serial();
|
|
|
|
|
|
|
|
if (taglen) {
|
|
|
|
uint32_t current_local_serial = current_global_serial;
|
2014-10-02 18:12:28 +00:00
|
|
|
|
2015-03-12 22:46:29 +00:00
|
|
|
if (!last_tag || strcmp(last_tag, tag)) {
|
|
|
|
/* invalidate log.tag.<tag> cache */
|
|
|
|
for(i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
|
|
|
|
tag_cache[i].pinfo = NULL;
|
|
|
|
tag_cache[i].serial = -1;
|
|
|
|
tag_cache[i].c = '\0';
|
|
|
|
}
|
|
|
|
free(last_tag);
|
|
|
|
last_tag = NULL;
|
|
|
|
current_global_serial = -1;
|
|
|
|
}
|
|
|
|
if (!last_tag) {
|
|
|
|
last_tag = strdup(tag);
|
|
|
|
}
|
2014-10-02 18:12:28 +00:00
|
|
|
strcpy(key + sizeof(log_namespace) - 1, tag);
|
|
|
|
|
2015-03-12 22:46:29 +00:00
|
|
|
kp = key;
|
|
|
|
for(i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
|
|
|
|
if (current_local_serial != global_serial) {
|
|
|
|
refresh_cache(&tag_cache[i], kp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tag_cache[i].c) {
|
|
|
|
c = tag_cache[i].c;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
kp = key + base_offset;
|
2014-10-02 18:12:28 +00:00
|
|
|
}
|
2015-03-12 22:46:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (toupper(c)) { /* if invalid, resort to global */
|
|
|
|
case 'V':
|
|
|
|
case 'D':
|
|
|
|
case 'I':
|
|
|
|
case 'W':
|
|
|
|
case 'E':
|
|
|
|
case 'F': /* Not officially supported */
|
|
|
|
case 'A':
|
|
|
|
case 'S':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* clear '.' after log.tag */
|
|
|
|
key[sizeof(log_namespace) - 2] = '\0';
|
|
|
|
|
|
|
|
kp = key;
|
|
|
|
for(i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
|
|
|
|
if (current_global_serial != global_serial) {
|
|
|
|
refresh_cache(&global_cache[i], kp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (global_cache[i].c) {
|
|
|
|
c = global_cache[i].c;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
kp = key + base_offset;
|
2014-10-08 22:58:40 +00:00
|
|
|
}
|
2015-03-12 22:46:29 +00:00
|
|
|
break;
|
2014-10-02 18:12:28 +00:00
|
|
|
}
|
2015-03-12 22:46:29 +00:00
|
|
|
|
|
|
|
global_serial = current_global_serial;
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
|
|
|
|
switch (toupper(c)) {
|
|
|
|
case 'V': return ANDROID_LOG_VERBOSE;
|
|
|
|
case 'D': return ANDROID_LOG_DEBUG;
|
|
|
|
case 'I': return ANDROID_LOG_INFO;
|
|
|
|
case 'W': return ANDROID_LOG_WARN;
|
|
|
|
case 'E': return ANDROID_LOG_ERROR;
|
|
|
|
case 'F': /* FALLTHRU */ /* Not officially supported */
|
|
|
|
case 'A': return ANDROID_LOG_FATAL;
|
|
|
|
case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
|
2014-10-02 18:12:28 +00:00
|
|
|
}
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
|
|
|
int __android_log_is_loggable(int prio, const char *tag, int def)
|
|
|
|
{
|
2014-10-08 22:58:40 +00:00
|
|
|
int logLevel = __android_log_level(tag, def);
|
2014-10-02 18:12:28 +00:00
|
|
|
return logLevel >= 0 && prio >= logLevel;
|
|
|
|
}
|