blob: 854ecfabc83d2561cf60785e20292709221d791b [file] [log] [blame]
Mark Salyzyn655b9492014-10-02 11:12:28 -07001/*
2** Copyright 2014, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17#include <ctype.h>
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070018#include <pthread.h>
19#include <stdlib.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070020#include <string.h>
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070021#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
22#include <sys/_system_properties.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070023
24#include <android/log.h>
25
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080026static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
27
28static void lock()
29{
30 /*
31 * If we trigger a signal handler in the middle of locked activity and the
32 * signal handler logs a message, we could get into a deadlock state.
33 */
34 pthread_mutex_lock(&lock_loggable);
35}
36
37static void unlock()
38{
39 pthread_mutex_unlock(&lock_loggable);
40}
41
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070042struct cache {
43 const prop_info *pinfo;
44 uint32_t serial;
45 char c;
46};
47
Mark Salyzyn233e4752015-12-04 10:59:45 -080048#define BOOLEAN_TRUE 0xFF
49#define BOOLEAN_FALSE 0xFE
50
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070051static void refresh_cache(struct cache *cache, const char *key)
Mark Salyzyn655b9492014-10-02 11:12:28 -070052{
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070053 uint32_t serial;
Mark Salyzyn655b9492014-10-02 11:12:28 -070054 char buf[PROP_VALUE_MAX];
55
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070056 if (!cache->pinfo) {
57 cache->pinfo = __system_property_find(key);
58 if (!cache->pinfo) {
59 return;
60 }
Mark Salyzyn655b9492014-10-02 11:12:28 -070061 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070062 serial = __system_property_serial(cache->pinfo);
63 if (serial == cache->serial) {
64 return;
65 }
66 cache->serial = serial;
67 __system_property_read(cache->pinfo, 0, buf);
Mark Salyzyn233e4752015-12-04 10:59:45 -080068 switch(buf[0]) {
69 case 't': case 'T':
70 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
71 break;
72 case 'f': case 'F':
73 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
74 break;
75 default:
76 cache->c = buf[0];
77 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070078}
Mark Salyzyn655b9492014-10-02 11:12:28 -070079
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080080static int __android_log_level(const char *tag, int default_prio)
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070081{
82 /* sizeof() is used on this array below */
83 static const char log_namespace[] = "persist.log.tag.";
84 static const size_t base_offset = 8; /* skip "persist." */
85 /* calculate the size of our key temporary buffer */
86 const size_t taglen = (tag && *tag) ? strlen(tag) : 0;
87 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
88 char key[sizeof(log_namespace) + taglen];
89 char *kp;
90 size_t i;
91 char c = 0;
92 /*
93 * Single layer cache of four properties. Priorities are:
94 * log.tag.<tag>
95 * persist.log.tag.<tag>
96 * log.tag
97 * persist.log.tag
98 * Where the missing tag matches all tags and becomes the
99 * system global default. We do not support ro.log.tag* .
100 */
101 static char *last_tag;
102 static uint32_t global_serial;
103 uint32_t current_global_serial;
104 static struct cache tag_cache[2] = {
105 { NULL, -1, 0 },
106 { NULL, -1, 0 }
107 };
108 static struct cache global_cache[2] = {
109 { NULL, -1, 0 },
110 { NULL, -1, 0 }
111 };
112
113 strcpy(key, log_namespace);
114
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800115 lock();
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700116
117 current_global_serial = __system_property_area_serial();
118
119 if (taglen) {
120 uint32_t current_local_serial = current_global_serial;
121
Mark Salyzyn0cda0762015-10-02 10:00:38 -0700122 if (!last_tag || (last_tag[0] != tag[0]) || strcmp(last_tag + 1, tag + 1)) {
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700123 /* invalidate log.tag.<tag> cache */
124 for(i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
125 tag_cache[i].pinfo = NULL;
126 tag_cache[i].serial = -1;
127 tag_cache[i].c = '\0';
128 }
129 free(last_tag);
130 last_tag = NULL;
131 current_global_serial = -1;
132 }
133 if (!last_tag) {
134 last_tag = strdup(tag);
135 }
Mark Salyzyn655b9492014-10-02 11:12:28 -0700136 strcpy(key + sizeof(log_namespace) - 1, tag);
137
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700138 kp = key;
139 for(i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
140 if (current_local_serial != global_serial) {
141 refresh_cache(&tag_cache[i], kp);
142 }
143
144 if (tag_cache[i].c) {
145 c = tag_cache[i].c;
146 break;
147 }
148
149 kp = key + base_offset;
Mark Salyzynd4b2a742014-10-08 15:58:40 -0700150 }
Mark Salyzyn655b9492014-10-02 11:12:28 -0700151 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700152
153 switch (toupper(c)) { /* if invalid, resort to global */
154 case 'V':
155 case 'D':
156 case 'I':
157 case 'W':
158 case 'E':
159 case 'F': /* Not officially supported */
160 case 'A':
161 case 'S':
Mark Salyzyn233e4752015-12-04 10:59:45 -0800162 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700163 break;
164 default:
165 /* clear '.' after log.tag */
166 key[sizeof(log_namespace) - 2] = '\0';
167
168 kp = key;
169 for(i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
170 if (current_global_serial != global_serial) {
171 refresh_cache(&global_cache[i], kp);
172 }
173
174 if (global_cache[i].c) {
175 c = global_cache[i].c;
176 break;
177 }
178
179 kp = key + base_offset;
180 }
181 break;
182 }
183
184 global_serial = current_global_serial;
185
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800186 unlock();
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700187
188 switch (toupper(c)) {
189 case 'V': return ANDROID_LOG_VERBOSE;
190 case 'D': return ANDROID_LOG_DEBUG;
191 case 'I': return ANDROID_LOG_INFO;
192 case 'W': return ANDROID_LOG_WARN;
193 case 'E': return ANDROID_LOG_ERROR;
194 case 'F': /* FALLTHRU */ /* Not officially supported */
195 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzyn233e4752015-12-04 10:59:45 -0800196 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700197 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
Mark Salyzyn655b9492014-10-02 11:12:28 -0700198 }
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800199 return default_prio;
Mark Salyzyn655b9492014-10-02 11:12:28 -0700200}
201
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800202int __android_log_is_loggable(int prio, const char *tag, int default_prio)
Mark Salyzyn655b9492014-10-02 11:12:28 -0700203{
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800204 int logLevel = __android_log_level(tag, default_prio);
Mark Salyzyn655b9492014-10-02 11:12:28 -0700205 return logLevel >= 0 && prio >= logLevel;
206}
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700207
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800208/*
209 * Timestamp state generally remains constant, since a change is
210 * rare, we can accept a trylock failure gracefully. Use a separate
211 * lock from is_loggable to keep contention down b/25563384.
212 */
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800213static pthread_mutex_t lock_clockid = PTHREAD_MUTEX_INITIALIZER;
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800214
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800215clockid_t android_log_clockid()
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700216{
217 static struct cache r_time_cache = { NULL, -1, 0 };
218 static struct cache p_time_cache = { NULL, -1, 0 };
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800219 char c;
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700220
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800221 if (pthread_mutex_trylock(&lock_clockid)) {
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800222 /* We are willing to accept some race in this context */
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800223 if (!(c = p_time_cache.c)) {
224 c = r_time_cache.c;
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800225 }
226 } else {
227 static uint32_t serial;
228 uint32_t current_serial = __system_property_area_serial();
229 if (current_serial != serial) {
230 refresh_cache(&r_time_cache, "ro.logd.timestamp");
231 refresh_cache(&p_time_cache, "persist.logd.timestamp");
232 serial = current_serial;
233 }
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800234 if (!(c = p_time_cache.c)) {
235 c = r_time_cache.c;
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800236 }
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700237
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800238 pthread_mutex_unlock(&lock_clockid);
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700239 }
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700240
Mark Salyzyn11a3e702015-12-01 15:57:25 -0800241 return (tolower(c) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700242}
Mark Salyzyn233e4752015-12-04 10:59:45 -0800243
244/*
245 * security state generally remains constant, since a change is
246 * rare, we can accept a trylock failure gracefully.
247 */
248static pthread_mutex_t lock_security = PTHREAD_MUTEX_INITIALIZER;
249
250int __android_log_security()
251{
252 static struct cache r_do_cache = { NULL, -1, BOOLEAN_FALSE };
253 static struct cache p_security_cache = { NULL, -1, BOOLEAN_FALSE };
254 int retval;
255
256 if (pthread_mutex_trylock(&lock_security)) {
257 /* We are willing to accept some race in this context */
258 retval = (r_do_cache.c != BOOLEAN_FALSE) && r_do_cache.c &&
259 (p_security_cache.c == BOOLEAN_TRUE);
260 } else {
261 static uint32_t serial;
262 uint32_t current_serial = __system_property_area_serial();
263 if (current_serial != serial) {
264 refresh_cache(&r_do_cache, "ro.device_owner");
265 refresh_cache(&p_security_cache, "persist.logd.security");
266 serial = current_serial;
267 }
268 retval = (r_do_cache.c != BOOLEAN_FALSE) && r_do_cache.c &&
269 (p_security_cache.c == BOOLEAN_TRUE);
270
271 pthread_mutex_unlock(&lock_security);
272 }
273
274 return retval;
275}