logger_write.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Copyright (C) 2007-2016 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. #include <errno.h>
  17. #include <stdatomic.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <sys/time.h>
  21. #ifdef __BIONIC__
  22. #include <android/set_abort_message.h>
  23. #endif
  24. #include <log/event_tag_map.h>
  25. #include <log/log_transport.h>
  26. #include <private/android_filesystem_config.h>
  27. #include <private/android_logger.h>
  28. #include "config_read.h" /* __android_log_config_read_close() definition */
  29. #include "config_write.h"
  30. #include "log_portability.h"
  31. #include "logger.h"
  32. #include "uio.h"
  33. #define LOG_BUF_SIZE 1024
  34. static int __write_to_log_init(log_id_t, struct iovec* vec, size_t nr);
  35. static int (*write_to_log)(log_id_t, struct iovec* vec, size_t nr) = __write_to_log_init;
  36. /*
  37. * This is used by the C++ code to decide if it should write logs through
  38. * the C code. Basically, if /dev/socket/logd is available, we're running in
  39. * the simulator rather than a desktop tool and want to use the device.
  40. */
  41. static enum { kLogUninitialized, kLogNotAvailable, kLogAvailable } g_log_status = kLogUninitialized;
  42. static int check_log_uid_permissions() {
  43. #if defined(__ANDROID__)
  44. uid_t uid = __android_log_uid();
  45. /* Matches clientHasLogCredentials() in logd */
  46. if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
  47. uid = geteuid();
  48. if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
  49. gid_t gid = getgid();
  50. if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
  51. gid = getegid();
  52. if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
  53. int num_groups;
  54. gid_t* groups;
  55. num_groups = getgroups(0, NULL);
  56. if (num_groups <= 0) {
  57. return -EPERM;
  58. }
  59. groups = static_cast<gid_t*>(calloc(num_groups, sizeof(gid_t)));
  60. if (!groups) {
  61. return -ENOMEM;
  62. }
  63. num_groups = getgroups(num_groups, groups);
  64. while (num_groups > 0) {
  65. if (groups[num_groups - 1] == AID_LOG) {
  66. break;
  67. }
  68. --num_groups;
  69. }
  70. free(groups);
  71. if (num_groups <= 0) {
  72. return -EPERM;
  73. }
  74. }
  75. }
  76. }
  77. }
  78. #endif
  79. return 0;
  80. }
  81. static void __android_log_cache_available(struct android_log_transport_write* node) {
  82. uint32_t i;
  83. if (node->logMask) {
  84. return;
  85. }
  86. for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
  87. if (node->write && (i != LOG_ID_KERNEL) &&
  88. ((i != LOG_ID_SECURITY) || (check_log_uid_permissions() == 0)) &&
  89. (!node->available || ((*node->available)(static_cast<log_id_t>(i)) >= 0))) {
  90. node->logMask |= 1 << i;
  91. }
  92. }
  93. }
  94. extern "C" int __android_log_dev_available() {
  95. struct android_log_transport_write* node;
  96. if (list_empty(&__android_log_transport_write)) {
  97. return kLogUninitialized;
  98. }
  99. write_transport_for_each(node, &__android_log_transport_write) {
  100. __android_log_cache_available(node);
  101. if (node->logMask) {
  102. return kLogAvailable;
  103. }
  104. }
  105. return kLogNotAvailable;
  106. }
  107. #if defined(__ANDROID__)
  108. static atomic_uintptr_t tagMap;
  109. #endif
  110. /*
  111. * Release any logger resources. A new log write will immediately re-acquire.
  112. */
  113. void __android_log_close() {
  114. struct android_log_transport_write* transport;
  115. #if defined(__ANDROID__)
  116. EventTagMap* m;
  117. #endif
  118. __android_log_lock();
  119. write_to_log = __write_to_log_init;
  120. /*
  121. * Threads that are actively writing at this point are not held back
  122. * by a lock and are at risk of dropping the messages with a return code
  123. * -EBADF. Prefer to return error code than add the overhead of a lock to
  124. * each log writing call to guarantee delivery. In addition, anyone
  125. * calling this is doing so to release the logging resources and shut down,
  126. * for them to do so with outstanding log requests in other threads is a
  127. * disengenuous use of this function.
  128. */
  129. write_transport_for_each(transport, &__android_log_persist_write) {
  130. if (transport->close) {
  131. (*transport->close)();
  132. }
  133. }
  134. write_transport_for_each(transport, &__android_log_transport_write) {
  135. if (transport->close) {
  136. (*transport->close)();
  137. }
  138. }
  139. __android_log_config_write_close();
  140. #if defined(__ANDROID__)
  141. /*
  142. * Additional risk here somewhat mitigated by immediately unlock flushing
  143. * the processor cache. The multi-threaded race that we choose to accept,
  144. * to minimize locking, is an atomic_load in a writer picking up a value
  145. * just prior to entering this routine. There will be an use after free.
  146. *
  147. * Again, anyone calling this is doing so to release the logging resources
  148. * is most probably going to quiesce then shut down; or to restart after
  149. * a fork so the risk should be non-existent. For this reason we
  150. * choose a mitigation stance for efficiency instead of incuring the cost
  151. * of a lock for every log write.
  152. */
  153. m = (EventTagMap*)atomic_exchange(&tagMap, (uintptr_t)0);
  154. #endif
  155. __android_log_unlock();
  156. #if defined(__ANDROID__)
  157. if (m != (EventTagMap*)(uintptr_t)-1LL) android_closeEventTagMap(m);
  158. #endif
  159. }
  160. /* log_init_lock assumed */
  161. static int __write_to_log_initialize() {
  162. struct android_log_transport_write* transport;
  163. struct listnode* n;
  164. int i = 0, ret = 0;
  165. __android_log_config_write();
  166. write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
  167. __android_log_cache_available(transport);
  168. if (!transport->logMask) {
  169. list_remove(&transport->node);
  170. continue;
  171. }
  172. if (!transport->open || ((*transport->open)() < 0)) {
  173. if (transport->close) {
  174. (*transport->close)();
  175. }
  176. list_remove(&transport->node);
  177. continue;
  178. }
  179. ++ret;
  180. }
  181. write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
  182. __android_log_cache_available(transport);
  183. if (!transport->logMask) {
  184. list_remove(&transport->node);
  185. continue;
  186. }
  187. if (!transport->open || ((*transport->open)() < 0)) {
  188. if (transport->close) {
  189. (*transport->close)();
  190. }
  191. list_remove(&transport->node);
  192. continue;
  193. }
  194. ++i;
  195. }
  196. if (!ret && !i) {
  197. return -ENODEV;
  198. }
  199. return ret;
  200. }
  201. /*
  202. * Extract a 4-byte value from a byte stream. le32toh open coded
  203. */
  204. static inline uint32_t get4LE(const uint8_t* src) {
  205. return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
  206. }
  207. static int __write_to_log_daemon(log_id_t log_id, struct iovec* vec, size_t nr) {
  208. struct android_log_transport_write* node;
  209. int ret, save_errno;
  210. struct timespec ts;
  211. size_t len, i;
  212. for (len = i = 0; i < nr; ++i) {
  213. len += vec[i].iov_len;
  214. }
  215. if (!len) {
  216. return -EINVAL;
  217. }
  218. save_errno = errno;
  219. #if defined(__ANDROID__)
  220. clock_gettime(android_log_clockid(), &ts);
  221. if (log_id == LOG_ID_SECURITY) {
  222. if (vec[0].iov_len < 4) {
  223. errno = save_errno;
  224. return -EINVAL;
  225. }
  226. ret = check_log_uid_permissions();
  227. if (ret < 0) {
  228. errno = save_errno;
  229. return ret;
  230. }
  231. if (!__android_log_security()) {
  232. /* If only we could reset downstream logd counter */
  233. errno = save_errno;
  234. return -EPERM;
  235. }
  236. } else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
  237. const char* tag;
  238. size_t len;
  239. EventTagMap *m, *f;
  240. if (vec[0].iov_len < 4) {
  241. errno = save_errno;
  242. return -EINVAL;
  243. }
  244. tag = NULL;
  245. len = 0;
  246. f = NULL;
  247. m = (EventTagMap*)atomic_load(&tagMap);
  248. if (!m) {
  249. ret = __android_log_trylock();
  250. m = (EventTagMap*)atomic_load(&tagMap); /* trylock flush cache */
  251. if (!m) {
  252. m = android_openEventTagMap(NULL);
  253. if (ret) { /* trylock failed, use local copy, mark for close */
  254. f = m;
  255. } else {
  256. if (!m) { /* One chance to open map file */
  257. m = (EventTagMap*)(uintptr_t)-1LL;
  258. }
  259. atomic_store(&tagMap, (uintptr_t)m);
  260. }
  261. }
  262. if (!ret) { /* trylock succeeded, unlock */
  263. __android_log_unlock();
  264. }
  265. }
  266. if (m && (m != (EventTagMap*)(uintptr_t)-1LL)) {
  267. tag = android_lookupEventTag_len(m, &len, get4LE(static_cast<uint8_t*>(vec[0].iov_base)));
  268. }
  269. ret = __android_log_is_loggable_len(ANDROID_LOG_INFO, tag, len, ANDROID_LOG_VERBOSE);
  270. if (f) { /* local copy marked for close */
  271. android_closeEventTagMap(f);
  272. }
  273. if (!ret) {
  274. errno = save_errno;
  275. return -EPERM;
  276. }
  277. } else {
  278. /* Validate the incoming tag, tag content can not split across iovec */
  279. char prio = ANDROID_LOG_VERBOSE;
  280. const char* tag = static_cast<const char*>(vec[0].iov_base);
  281. size_t len = vec[0].iov_len;
  282. if (!tag) {
  283. len = 0;
  284. }
  285. if (len > 0) {
  286. prio = *tag;
  287. if (len > 1) {
  288. --len;
  289. ++tag;
  290. } else {
  291. len = vec[1].iov_len;
  292. tag = ((const char*)vec[1].iov_base);
  293. if (!tag) {
  294. len = 0;
  295. }
  296. }
  297. }
  298. /* tag must be nul terminated */
  299. if (tag && strnlen(tag, len) >= len) {
  300. tag = NULL;
  301. }
  302. if (!__android_log_is_loggable_len(prio, tag, len - 1, ANDROID_LOG_VERBOSE)) {
  303. errno = save_errno;
  304. return -EPERM;
  305. }
  306. }
  307. #else
  308. /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
  309. {
  310. struct timeval tv;
  311. gettimeofday(&tv, NULL);
  312. ts.tv_sec = tv.tv_sec;
  313. ts.tv_nsec = tv.tv_usec * 1000;
  314. }
  315. #endif
  316. ret = 0;
  317. i = 1 << log_id;
  318. write_transport_for_each(node, &__android_log_transport_write) {
  319. if (node->logMask & i) {
  320. ssize_t retval;
  321. retval = (*node->write)(log_id, &ts, vec, nr);
  322. if (ret >= 0) {
  323. ret = retval;
  324. }
  325. }
  326. }
  327. write_transport_for_each(node, &__android_log_persist_write) {
  328. if (node->logMask & i) {
  329. (void)(*node->write)(log_id, &ts, vec, nr);
  330. }
  331. }
  332. errno = save_errno;
  333. return ret;
  334. }
  335. static int __write_to_log_init(log_id_t log_id, struct iovec* vec, size_t nr) {
  336. int ret, save_errno = errno;
  337. __android_log_lock();
  338. if (write_to_log == __write_to_log_init) {
  339. ret = __write_to_log_initialize();
  340. if (ret < 0) {
  341. __android_log_unlock();
  342. if (!list_empty(&__android_log_persist_write)) {
  343. __write_to_log_daemon(log_id, vec, nr);
  344. }
  345. errno = save_errno;
  346. return ret;
  347. }
  348. write_to_log = __write_to_log_daemon;
  349. }
  350. __android_log_unlock();
  351. ret = write_to_log(log_id, vec, nr);
  352. errno = save_errno;
  353. return ret;
  354. }
  355. int __android_log_write(int prio, const char* tag, const char* msg) {
  356. return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
  357. }
  358. int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) {
  359. struct iovec vec[3];
  360. char tmp_tag[32];
  361. if (!tag) tag = "";
  362. /* XXX: This needs to go! */
  363. #pragma clang diagnostic push
  364. #pragma clang diagnostic ignored "-Wstring-plus-int"
  365. if (bufID != LOG_ID_RADIO) {
  366. switch (tag[0]) {
  367. case 'H':
  368. if (strcmp(tag + 1, "HTC_RIL" + 1)) break;
  369. goto inform;
  370. case 'R':
  371. /* Any log tag with "RIL" as the prefix */
  372. if (strncmp(tag + 1, "RIL" + 1, strlen("RIL") - 1)) break;
  373. goto inform;
  374. case 'Q':
  375. /* Any log tag with "QC_RIL" as the prefix */
  376. if (strncmp(tag + 1, "QC_RIL" + 1, strlen("QC_RIL") - 1)) break;
  377. goto inform;
  378. case 'I':
  379. /* Any log tag with "IMS" as the prefix */
  380. if (strncmp(tag + 1, "IMS" + 1, strlen("IMS") - 1)) break;
  381. goto inform;
  382. case 'A':
  383. if (strcmp(tag + 1, "AT" + 1)) break;
  384. goto inform;
  385. case 'G':
  386. if (strcmp(tag + 1, "GSM" + 1)) break;
  387. goto inform;
  388. case 'S':
  389. if (strcmp(tag + 1, "STK" + 1) && strcmp(tag + 1, "SMS" + 1)) break;
  390. goto inform;
  391. case 'C':
  392. if (strcmp(tag + 1, "CDMA" + 1)) break;
  393. goto inform;
  394. case 'P':
  395. if (strcmp(tag + 1, "PHONE" + 1)) break;
  396. /* FALLTHRU */
  397. inform:
  398. bufID = LOG_ID_RADIO;
  399. snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
  400. tag = tmp_tag;
  401. [[fallthrough]];
  402. default:
  403. break;
  404. }
  405. }
  406. #pragma clang diagnostic pop
  407. #if __BIONIC__
  408. if (prio == ANDROID_LOG_FATAL) {
  409. android_set_abort_message(msg);
  410. }
  411. #endif
  412. vec[0].iov_base = (unsigned char*)&prio;
  413. vec[0].iov_len = 1;
  414. vec[1].iov_base = (void*)tag;
  415. vec[1].iov_len = strlen(tag) + 1;
  416. vec[2].iov_base = (void*)msg;
  417. vec[2].iov_len = strlen(msg) + 1;
  418. return write_to_log(static_cast<log_id_t>(bufID), vec, 3);
  419. }
  420. int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
  421. char buf[LOG_BUF_SIZE];
  422. vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
  423. return __android_log_write(prio, tag, buf);
  424. }
  425. int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
  426. va_list ap;
  427. char buf[LOG_BUF_SIZE];
  428. va_start(ap, fmt);
  429. vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
  430. va_end(ap);
  431. return __android_log_write(prio, tag, buf);
  432. }
  433. int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) {
  434. va_list ap;
  435. char buf[LOG_BUF_SIZE];
  436. va_start(ap, fmt);
  437. vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
  438. va_end(ap);
  439. return __android_log_buf_write(bufID, prio, tag, buf);
  440. }
  441. void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...) {
  442. char buf[LOG_BUF_SIZE];
  443. if (fmt) {
  444. va_list ap;
  445. va_start(ap, fmt);
  446. vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
  447. va_end(ap);
  448. } else {
  449. /* Msg not provided, log condition. N.B. Do not use cond directly as
  450. * format string as it could contain spurious '%' syntax (e.g.
  451. * "%d" in "blocks%devs == 0").
  452. */
  453. if (cond)
  454. snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
  455. else
  456. strcpy(buf, "Unspecified assertion failed");
  457. }
  458. // Log assertion failures to stderr for the benefit of "adb shell" users
  459. // and gtests (http://b/23675822).
  460. TEMP_FAILURE_RETRY(write(2, buf, strlen(buf)));
  461. TEMP_FAILURE_RETRY(write(2, "\n", 1));
  462. __android_log_write(ANDROID_LOG_FATAL, tag, buf);
  463. abort(); /* abort so we have a chance to debug the situation */
  464. /* NOTREACHED */
  465. }
  466. int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
  467. struct iovec vec[2];
  468. vec[0].iov_base = &tag;
  469. vec[0].iov_len = sizeof(tag);
  470. vec[1].iov_base = (void*)payload;
  471. vec[1].iov_len = len;
  472. return write_to_log(LOG_ID_EVENTS, vec, 2);
  473. }
  474. int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
  475. struct iovec vec[2];
  476. vec[0].iov_base = &tag;
  477. vec[0].iov_len = sizeof(tag);
  478. vec[1].iov_base = (void*)payload;
  479. vec[1].iov_len = len;
  480. return write_to_log(LOG_ID_STATS, vec, 2);
  481. }
  482. int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
  483. struct iovec vec[2];
  484. vec[0].iov_base = &tag;
  485. vec[0].iov_len = sizeof(tag);
  486. vec[1].iov_base = (void*)payload;
  487. vec[1].iov_len = len;
  488. return write_to_log(LOG_ID_SECURITY, vec, 2);
  489. }
  490. /*
  491. * Like __android_log_bwrite, but takes the type as well. Doesn't work
  492. * for the general case where we're generating lists of stuff, but very
  493. * handy if we just want to dump an integer into the log.
  494. */
  495. int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len) {
  496. struct iovec vec[3];
  497. vec[0].iov_base = &tag;
  498. vec[0].iov_len = sizeof(tag);
  499. vec[1].iov_base = &type;
  500. vec[1].iov_len = sizeof(type);
  501. vec[2].iov_base = (void*)payload;
  502. vec[2].iov_len = len;
  503. return write_to_log(LOG_ID_EVENTS, vec, 3);
  504. }
  505. /*
  506. * Like __android_log_bwrite, but used for writing strings to the
  507. * event log.
  508. */
  509. int __android_log_bswrite(int32_t tag, const char* payload) {
  510. struct iovec vec[4];
  511. char type = EVENT_TYPE_STRING;
  512. uint32_t len = strlen(payload);
  513. vec[0].iov_base = &tag;
  514. vec[0].iov_len = sizeof(tag);
  515. vec[1].iov_base = &type;
  516. vec[1].iov_len = sizeof(type);
  517. vec[2].iov_base = &len;
  518. vec[2].iov_len = sizeof(len);
  519. vec[3].iov_base = (void*)payload;
  520. vec[3].iov_len = len;
  521. return write_to_log(LOG_ID_EVENTS, vec, 4);
  522. }
  523. /*
  524. * Like __android_log_security_bwrite, but used for writing strings to the
  525. * security log.
  526. */
  527. int __android_log_security_bswrite(int32_t tag, const char* payload) {
  528. struct iovec vec[4];
  529. char type = EVENT_TYPE_STRING;
  530. uint32_t len = strlen(payload);
  531. vec[0].iov_base = &tag;
  532. vec[0].iov_len = sizeof(tag);
  533. vec[1].iov_base = &type;
  534. vec[1].iov_len = sizeof(type);
  535. vec[2].iov_base = &len;
  536. vec[2].iov_len = sizeof(len);
  537. vec[3].iov_base = (void*)payload;
  538. vec[3].iov_len = len;
  539. return write_to_log(LOG_ID_SECURITY, vec, 4);
  540. }
  541. static int __write_to_log_null(log_id_t log_id, struct iovec* vec, size_t nr) {
  542. size_t len, i;
  543. if ((log_id < LOG_ID_MIN) || (log_id >= LOG_ID_MAX)) {
  544. return -EINVAL;
  545. }
  546. for (len = i = 0; i < nr; ++i) {
  547. len += vec[i].iov_len;
  548. }
  549. if (!len) {
  550. return -EINVAL;
  551. }
  552. return len;
  553. }
  554. /* Following functions need access to our internal write_to_log status */
  555. int __android_log_transport;
  556. int android_set_log_transport(int transport_flag) {
  557. int retval;
  558. if (transport_flag < 0) {
  559. return -EINVAL;
  560. }
  561. retval = LOGGER_NULL;
  562. __android_log_lock();
  563. if (transport_flag & LOGGER_NULL) {
  564. write_to_log = __write_to_log_null;
  565. __android_log_unlock();
  566. return retval;
  567. }
  568. __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
  569. transport_flag &= LOGGER_LOGD | LOGGER_STDERR;
  570. if (__android_log_transport != transport_flag) {
  571. __android_log_transport = transport_flag;
  572. __android_log_config_write_close();
  573. __android_log_config_read_close();
  574. write_to_log = __write_to_log_init;
  575. /* generically we only expect these two values for write_to_log */
  576. } else if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
  577. write_to_log = __write_to_log_init;
  578. }
  579. retval = __android_log_transport;
  580. __android_log_unlock();
  581. return retval;
  582. }
  583. int android_get_log_transport() {
  584. int ret = LOGGER_DEFAULT;
  585. __android_log_lock();
  586. if (write_to_log == __write_to_log_null) {
  587. ret = LOGGER_NULL;
  588. } else {
  589. __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
  590. ret = __android_log_transport;
  591. if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
  592. ret = -EINVAL;
  593. }
  594. }
  595. __android_log_unlock();
  596. return ret;
  597. }