158310b49fc8a7a713b922319a849a419858db79eDan Albert/*
258310b49fc8a7a713b922319a849a419858db79eDan Albert * Copyright (C) 2015 The Android Open Source Project
358310b49fc8a7a713b922319a849a419858db79eDan Albert *
458310b49fc8a7a713b922319a849a419858db79eDan Albert * Licensed under the Apache License, Version 2.0 (the "License");
558310b49fc8a7a713b922319a849a419858db79eDan Albert * you may not use this file except in compliance with the License.
658310b49fc8a7a713b922319a849a419858db79eDan Albert * You may obtain a copy of the License at
758310b49fc8a7a713b922319a849a419858db79eDan Albert *
858310b49fc8a7a713b922319a849a419858db79eDan Albert *      http://www.apache.org/licenses/LICENSE-2.0
958310b49fc8a7a713b922319a849a419858db79eDan Albert *
1058310b49fc8a7a713b922319a849a419858db79eDan Albert * Unless required by applicable law or agreed to in writing, software
1158310b49fc8a7a713b922319a849a419858db79eDan Albert * distributed under the License is distributed on an "AS IS" BASIS,
1258310b49fc8a7a713b922319a849a419858db79eDan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1358310b49fc8a7a713b922319a849a419858db79eDan Albert * See the License for the specific language governing permissions and
1458310b49fc8a7a713b922319a849a419858db79eDan Albert * limitations under the License.
1558310b49fc8a7a713b922319a849a419858db79eDan Albert */
1658310b49fc8a7a713b922319a849a419858db79eDan Albert
17ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low#ifdef _WIN32
18ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low#include <windows.h>
19ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low#endif
20ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low
214f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include "android-base/logging.h"
2258310b49fc8a7a713b922319a849a419858db79eDan Albert
237a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#include <libgen.h>
247a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert
257a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert// For getprogname(3) or program_invocation_short_name.
267a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#if defined(__ANDROID__) || defined(__APPLE__)
277a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#include <stdlib.h>
287a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#elif defined(__GLIBC__)
297a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#include <errno.h>
307a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#endif
317a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert
3258310b49fc8a7a713b922319a849a419858db79eDan Albert#include <iostream>
3358310b49fc8a7a713b922319a849a419858db79eDan Albert#include <limits>
3458310b49fc8a7a713b922319a849a419858db79eDan Albert#include <sstream>
3558310b49fc8a7a713b922319a849a419858db79eDan Albert#include <string>
36b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#include <utility>
3758310b49fc8a7a713b922319a849a419858db79eDan Albert#include <vector>
3858310b49fc8a7a713b922319a849a419858db79eDan Albert
395c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#ifndef _WIN32
405c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#include <mutex>
415c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#endif
425c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
434f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include "android-base/macros.h"
444f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include "android-base/strings.h"
457dfb61dcdca8ee597f23b9acc365fb140b353fffDan Albert#include "cutils/threads.h"
4658310b49fc8a7a713b922319a849a419858db79eDan Albert
4758310b49fc8a7a713b922319a849a419858db79eDan Albert// Headers for LogMessage::LogLine.
4858310b49fc8a7a713b922319a849a419858db79eDan Albert#ifdef __ANDROID__
4958310b49fc8a7a713b922319a849a419858db79eDan Albert#include <android/set_abort_message.h>
5058310b49fc8a7a713b922319a849a419858db79eDan Albert#include "cutils/log.h"
5158310b49fc8a7a713b922319a849a419858db79eDan Albert#else
5258310b49fc8a7a713b922319a849a419858db79eDan Albert#include <sys/types.h>
5358310b49fc8a7a713b922319a849a419858db79eDan Albert#include <unistd.h>
5458310b49fc8a7a713b922319a849a419858db79eDan Albert#endif
5558310b49fc8a7a713b922319a849a419858db79eDan Albert
56c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes// For gettid.
57c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#if defined(__APPLE__)
58c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include "AvailabilityMacros.h"  // For MAC_OS_X_VERSION_MAX_ALLOWED
59c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <stdint.h>
60c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <stdlib.h>
61c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <sys/syscall.h>
62c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <sys/time.h>
63c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <unistd.h>
64c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(__linux__) && !defined(__ANDROID__)
65c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <syscall.h>
66c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <unistd.h>
67c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(_WIN32)
68c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <windows.h>
69c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#endif
70c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes
719dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#if defined(_WIN32)
729dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsentypedef uint32_t thread_id;
739dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#else
749dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsentypedef pid_t thread_id;
759dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#endif
769dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen
779dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsenstatic thread_id GetThreadId() {
78c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#if defined(__BIONIC__)
79c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes  return gettid();
80c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(__APPLE__)
81c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes  return syscall(SYS_thread_selfid);
82c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(__linux__)
83c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes  return syscall(__NR_gettid);
84c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(_WIN32)
85c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes  return GetCurrentThreadId();
86c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#endif
87c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes}
88c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes
895c19040b06b5bb61731e24ea6777c237dc23145dDan Albertnamespace {
905c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#ifndef _WIN32
915c19040b06b5bb61731e24ea6777c237dc23145dDan Albertusing std::mutex;
925c19040b06b5bb61731e24ea6777c237dc23145dDan Albertusing std::lock_guard;
935c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
945c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#if defined(__GLIBC__)
955c19040b06b5bb61731e24ea6777c237dc23145dDan Albertconst char* getprogname() {
965c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  return program_invocation_short_name;
975c19040b06b5bb61731e24ea6777c237dc23145dDan Albert}
985c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#endif
995c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1005c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#else
1015c19040b06b5bb61731e24ea6777c237dc23145dDan Albertconst char* getprogname() {
1025c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  static bool first = true;
1035c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  static char progname[MAX_PATH] = {};
1045c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1055c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  if (first) {
106bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    CHAR longname[MAX_PATH];
107bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    DWORD nchars = GetModuleFileNameA(nullptr, longname, arraysize(longname));
108bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    if ((nchars >= arraysize(longname)) || (nchars == 0)) {
109bdab59a8613c732df5d746328ff2268be8da13abSpencer Low      // String truncation or some other error.
110bdab59a8613c732df5d746328ff2268be8da13abSpencer Low      strcpy(progname, "<unknown>");
111bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    } else {
112bdab59a8613c732df5d746328ff2268be8da13abSpencer Low      strcpy(progname, basename(longname));
113bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    }
1145c19040b06b5bb61731e24ea6777c237dc23145dDan Albert    first = false;
1155c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  }
1165c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1175c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  return progname;
1185c19040b06b5bb61731e24ea6777c237dc23145dDan Albert}
1195c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1205c19040b06b5bb61731e24ea6777c237dc23145dDan Albertclass mutex {
1215c19040b06b5bb61731e24ea6777c237dc23145dDan Albert public:
1225c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  mutex() {
123bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    InitializeCriticalSection(&critical_section_);
1245c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  }
1255c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  ~mutex() {
126bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    DeleteCriticalSection(&critical_section_);
1275c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  }
1285c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1295c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  void lock() {
130bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    EnterCriticalSection(&critical_section_);
1315c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  }
1325c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1335c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  void unlock() {
134bdab59a8613c732df5d746328ff2268be8da13abSpencer Low    LeaveCriticalSection(&critical_section_);
1355c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  }
1365c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1375c19040b06b5bb61731e24ea6777c237dc23145dDan Albert private:
138bdab59a8613c732df5d746328ff2268be8da13abSpencer Low  CRITICAL_SECTION critical_section_;
1395c19040b06b5bb61731e24ea6777c237dc23145dDan Albert};
1405c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1415c19040b06b5bb61731e24ea6777c237dc23145dDan Alberttemplate <typename LockT>
1425c19040b06b5bb61731e24ea6777c237dc23145dDan Albertclass lock_guard {
1435c19040b06b5bb61731e24ea6777c237dc23145dDan Albert public:
1445c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  explicit lock_guard(LockT& lock) : lock_(lock) {
1455c19040b06b5bb61731e24ea6777c237dc23145dDan Albert    lock_.lock();
1465c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  }
1475c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1485c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  ~lock_guard() {
1495c19040b06b5bb61731e24ea6777c237dc23145dDan Albert    lock_.unlock();
1505c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  }
1515c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1525c19040b06b5bb61731e24ea6777c237dc23145dDan Albert private:
1535c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  LockT& lock_;
1545c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
1555c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  DISALLOW_COPY_AND_ASSIGN(lock_guard);
1565c19040b06b5bb61731e24ea6777c237dc23145dDan Albert};
1575c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#endif
1585c19040b06b5bb61731e24ea6777c237dc23145dDan Albert} // namespace
1595c19040b06b5bb61731e24ea6777c237dc23145dDan Albert
16058310b49fc8a7a713b922319a849a419858db79eDan Albertnamespace android {
16158310b49fc8a7a713b922319a849a419858db79eDan Albertnamespace base {
16258310b49fc8a7a713b922319a849a419858db79eDan Albert
1637df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& logging_lock = *new mutex();
16458310b49fc8a7a713b922319a849a419858db79eDan Albert
165b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#ifdef __ANDROID__
1667df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& gLogger = *new LogFunction(LogdLogger());
167b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#else
1687df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& gLogger = *new LogFunction(StderrLogger);
169b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#endif
170b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
1717a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albertstatic bool gInitialized = false;
17258310b49fc8a7a713b922319a849a419858db79eDan Albertstatic LogSeverity gMinimumLogSeverity = INFO;
1737df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
17458310b49fc8a7a713b922319a849a419858db79eDan Albert
175765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer LowLogSeverity GetMinimumLogSeverity() {
176765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low  return gMinimumLogSeverity;
177765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low}
178765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low
1797a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albertstatic const char* ProgramInvocationName() {
1807a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert  if (gProgramInvocationName == nullptr) {
1817a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert    gProgramInvocationName.reset(new std::string(getprogname()));
1827a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert  }
18358310b49fc8a7a713b922319a849a419858db79eDan Albert
1847a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert  return gProgramInvocationName->c_str();
18558310b49fc8a7a713b922319a849a419858db79eDan Albert}
18658310b49fc8a7a713b922319a849a419858db79eDan Albert
187b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
188b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert                  unsigned int line, const char* message) {
189bdab59a8613c732df5d746328ff2268be8da13abSpencer Low  static const char log_characters[] = "VDIWEF";
190bdab59a8613c732df5d746328ff2268be8da13abSpencer Low  static_assert(arraysize(log_characters) - 1 == FATAL + 1,
191bdab59a8613c732df5d746328ff2268be8da13abSpencer Low                "Mismatch in size of log_characters and values in LogSeverity");
192b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  char severity_char = log_characters[severity];
1937a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert  fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(),
194c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes          severity_char, getpid(), GetThreadId(), file, line, message);
195b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert}
196b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
197b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
198b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#ifdef __ANDROID__
199b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan AlbertLogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
200b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert}
201b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
202b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
203b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert    ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
204b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert    ANDROID_LOG_WARN,    ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
205b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert};
206b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
207b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert              "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
208b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert              "in LogSeverity");
209b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
210b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic const log_id kLogIdToAndroidLogId[] = {
211b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert    LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
212b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert};
213b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
214b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert              "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
215b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
216b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
217b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert                            const char* file, unsigned int line,
218b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert                            const char* message) {
219b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  int priority = kLogSeverityToAndroidLogPriority[severity];
220b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  if (id == DEFAULT) {
221b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert    id = default_log_id_;
222b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  }
223b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
224b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  log_id lg_id = kLogIdToAndroidLogId[id];
225b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
226b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  if (priority == ANDROID_LOG_FATAL) {
227b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert    __android_log_buf_print(lg_id, priority, tag, "%s:%u] %s", file, line,
228b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert                            message);
229b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  } else {
230b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert    __android_log_buf_print(lg_id, priority, tag, "%s", message);
231b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  }
232b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert}
233b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#endif
234b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
235b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid InitLogging(char* argv[], LogFunction&& logger) {
236b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  SetLogger(std::forward<LogFunction>(logger));
237b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  InitLogging(argv);
238b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert}
239b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
24058310b49fc8a7a713b922319a849a419858db79eDan Albertvoid InitLogging(char* argv[]) {
2417a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert  if (gInitialized) {
24258310b49fc8a7a713b922319a849a419858db79eDan Albert    return;
24358310b49fc8a7a713b922319a849a419858db79eDan Albert  }
24458310b49fc8a7a713b922319a849a419858db79eDan Albert
2457a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert  gInitialized = true;
2467a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert
24758310b49fc8a7a713b922319a849a419858db79eDan Albert  // Stash the command line for later use. We can use /proc/self/cmdline on
248363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  // Linux to recover this, but we don't have that luxury on the Mac/Windows,
249363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  // and there are a couple of argv[0] variants that are commonly used.
25058310b49fc8a7a713b922319a849a419858db79eDan Albert  if (argv != nullptr) {
2517a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert    gProgramInvocationName.reset(new std::string(basename(argv[0])));
25258310b49fc8a7a713b922319a849a419858db79eDan Albert  }
2537a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert
25458310b49fc8a7a713b922319a849a419858db79eDan Albert  const char* tags = getenv("ANDROID_LOG_TAGS");
25558310b49fc8a7a713b922319a849a419858db79eDan Albert  if (tags == nullptr) {
25658310b49fc8a7a713b922319a849a419858db79eDan Albert    return;
25758310b49fc8a7a713b922319a849a419858db79eDan Albert  }
25858310b49fc8a7a713b922319a849a419858db79eDan Albert
25947328c96d91ca71b57b8976df2df1fe51579a955Dan Albert  std::vector<std::string> specs = Split(tags, " ");
26058310b49fc8a7a713b922319a849a419858db79eDan Albert  for (size_t i = 0; i < specs.size(); ++i) {
26158310b49fc8a7a713b922319a849a419858db79eDan Albert    // "tag-pattern:[vdiwefs]"
26258310b49fc8a7a713b922319a849a419858db79eDan Albert    std::string spec(specs[i]);
26358310b49fc8a7a713b922319a849a419858db79eDan Albert    if (spec.size() == 3 && StartsWith(spec, "*:")) {
26458310b49fc8a7a713b922319a849a419858db79eDan Albert      switch (spec[2]) {
26558310b49fc8a7a713b922319a849a419858db79eDan Albert        case 'v':
26658310b49fc8a7a713b922319a849a419858db79eDan Albert          gMinimumLogSeverity = VERBOSE;
26758310b49fc8a7a713b922319a849a419858db79eDan Albert          continue;
26858310b49fc8a7a713b922319a849a419858db79eDan Albert        case 'd':
26958310b49fc8a7a713b922319a849a419858db79eDan Albert          gMinimumLogSeverity = DEBUG;
27058310b49fc8a7a713b922319a849a419858db79eDan Albert          continue;
27158310b49fc8a7a713b922319a849a419858db79eDan Albert        case 'i':
27258310b49fc8a7a713b922319a849a419858db79eDan Albert          gMinimumLogSeverity = INFO;
27358310b49fc8a7a713b922319a849a419858db79eDan Albert          continue;
27458310b49fc8a7a713b922319a849a419858db79eDan Albert        case 'w':
27558310b49fc8a7a713b922319a849a419858db79eDan Albert          gMinimumLogSeverity = WARNING;
27658310b49fc8a7a713b922319a849a419858db79eDan Albert          continue;
27758310b49fc8a7a713b922319a849a419858db79eDan Albert        case 'e':
27858310b49fc8a7a713b922319a849a419858db79eDan Albert          gMinimumLogSeverity = ERROR;
27958310b49fc8a7a713b922319a849a419858db79eDan Albert          continue;
28058310b49fc8a7a713b922319a849a419858db79eDan Albert        case 'f':
28158310b49fc8a7a713b922319a849a419858db79eDan Albert          gMinimumLogSeverity = FATAL;
28258310b49fc8a7a713b922319a849a419858db79eDan Albert          continue;
28358310b49fc8a7a713b922319a849a419858db79eDan Albert        // liblog will even suppress FATAL if you say 's' for silent, but that's
28458310b49fc8a7a713b922319a849a419858db79eDan Albert        // crazy!
28558310b49fc8a7a713b922319a849a419858db79eDan Albert        case 's':
28658310b49fc8a7a713b922319a849a419858db79eDan Albert          gMinimumLogSeverity = FATAL;
28758310b49fc8a7a713b922319a849a419858db79eDan Albert          continue;
28858310b49fc8a7a713b922319a849a419858db79eDan Albert      }
28958310b49fc8a7a713b922319a849a419858db79eDan Albert    }
29058310b49fc8a7a713b922319a849a419858db79eDan Albert    LOG(FATAL) << "unsupported '" << spec << "' in ANDROID_LOG_TAGS (" << tags
29158310b49fc8a7a713b922319a849a419858db79eDan Albert               << ")";
29258310b49fc8a7a713b922319a849a419858db79eDan Albert  }
29358310b49fc8a7a713b922319a849a419858db79eDan Albert}
29458310b49fc8a7a713b922319a849a419858db79eDan Albert
295b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid SetLogger(LogFunction&& logger) {
2965c19040b06b5bb61731e24ea6777c237dc23145dDan Albert  lock_guard<mutex> lock(logging_lock);
297b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  gLogger = std::move(logger);
298b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert}
299b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert
300bdab59a8613c732df5d746328ff2268be8da13abSpencer Lowstatic const char* GetFileBasename(const char* file) {
301363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  // We can't use basename(3) even on Unix because the Mac doesn't
302363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  // have a non-modifying basename.
303bdab59a8613c732df5d746328ff2268be8da13abSpencer Low  const char* last_slash = strrchr(file, '/');
304363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  if (last_slash != nullptr) {
305363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low    return last_slash + 1;
306363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  }
307363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low#if defined(_WIN32)
308363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  const char* last_backslash = strrchr(file, '\\');
309363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  if (last_backslash != nullptr) {
310363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low    return last_backslash + 1;
311363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  }
312363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low#endif
313363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low  return file;
314bdab59a8613c732df5d746328ff2268be8da13abSpencer Low}
315bdab59a8613c732df5d746328ff2268be8da13abSpencer Low
31658310b49fc8a7a713b922319a849a419858db79eDan Albert// This indirection greatly reduces the stack impact of having lots of
31758310b49fc8a7a713b922319a849a419858db79eDan Albert// checks/logging in a function.
31858310b49fc8a7a713b922319a849a419858db79eDan Albertclass LogMessageData {
31958310b49fc8a7a713b922319a849a419858db79eDan Albert public:
3200c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert  LogMessageData(const char* file, unsigned int line, LogId id,
321765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low                 LogSeverity severity, int error)
322bdab59a8613c732df5d746328ff2268be8da13abSpencer Low      : file_(GetFileBasename(file)),
3230c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert        line_number_(line),
3240c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert        id_(id),
3250c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert        severity_(severity),
326765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low        error_(error) {
32758310b49fc8a7a713b922319a849a419858db79eDan Albert  }
32858310b49fc8a7a713b922319a849a419858db79eDan Albert
32958310b49fc8a7a713b922319a849a419858db79eDan Albert  const char* GetFile() const {
33058310b49fc8a7a713b922319a849a419858db79eDan Albert    return file_;
33158310b49fc8a7a713b922319a849a419858db79eDan Albert  }
33258310b49fc8a7a713b922319a849a419858db79eDan Albert
33358310b49fc8a7a713b922319a849a419858db79eDan Albert  unsigned int GetLineNumber() const {
33458310b49fc8a7a713b922319a849a419858db79eDan Albert    return line_number_;
33558310b49fc8a7a713b922319a849a419858db79eDan Albert  }
33658310b49fc8a7a713b922319a849a419858db79eDan Albert
33758310b49fc8a7a713b922319a849a419858db79eDan Albert  LogSeverity GetSeverity() const {
33858310b49fc8a7a713b922319a849a419858db79eDan Albert    return severity_;
33958310b49fc8a7a713b922319a849a419858db79eDan Albert  }
34058310b49fc8a7a713b922319a849a419858db79eDan Albert
3410c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert  LogId GetId() const {
3420c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert    return id_;
3430c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert  }
3440c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert
34558310b49fc8a7a713b922319a849a419858db79eDan Albert  int GetError() const {
34658310b49fc8a7a713b922319a849a419858db79eDan Albert    return error_;
34758310b49fc8a7a713b922319a849a419858db79eDan Albert  }
34858310b49fc8a7a713b922319a849a419858db79eDan Albert
34958310b49fc8a7a713b922319a849a419858db79eDan Albert  std::ostream& GetBuffer() {
35058310b49fc8a7a713b922319a849a419858db79eDan Albert    return buffer_;
35158310b49fc8a7a713b922319a849a419858db79eDan Albert  }
35258310b49fc8a7a713b922319a849a419858db79eDan Albert
35358310b49fc8a7a713b922319a849a419858db79eDan Albert  std::string ToString() const {
35458310b49fc8a7a713b922319a849a419858db79eDan Albert    return buffer_.str();
35558310b49fc8a7a713b922319a849a419858db79eDan Albert  }
35658310b49fc8a7a713b922319a849a419858db79eDan Albert
35758310b49fc8a7a713b922319a849a419858db79eDan Albert private:
35858310b49fc8a7a713b922319a849a419858db79eDan Albert  std::ostringstream buffer_;
35958310b49fc8a7a713b922319a849a419858db79eDan Albert  const char* const file_;
36058310b49fc8a7a713b922319a849a419858db79eDan Albert  const unsigned int line_number_;
3610c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert  const LogId id_;
36258310b49fc8a7a713b922319a849a419858db79eDan Albert  const LogSeverity severity_;
36358310b49fc8a7a713b922319a849a419858db79eDan Albert  const int error_;
36458310b49fc8a7a713b922319a849a419858db79eDan Albert
36558310b49fc8a7a713b922319a849a419858db79eDan Albert  DISALLOW_COPY_AND_ASSIGN(LogMessageData);
36658310b49fc8a7a713b922319a849a419858db79eDan Albert};
36758310b49fc8a7a713b922319a849a419858db79eDan Albert
3680c055863ebb57c3446897e89c2c39a67442c1be4Dan AlbertLogMessage::LogMessage(const char* file, unsigned int line, LogId id,
36958310b49fc8a7a713b922319a849a419858db79eDan Albert                       LogSeverity severity, int error)
370765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low    : data_(new LogMessageData(file, line, id, severity, error)) {
37158310b49fc8a7a713b922319a849a419858db79eDan Albert}
37258310b49fc8a7a713b922319a849a419858db79eDan Albert
37358310b49fc8a7a713b922319a849a419858db79eDan AlbertLogMessage::~LogMessage() {
37458310b49fc8a7a713b922319a849a419858db79eDan Albert  // Finish constructing the message.
37558310b49fc8a7a713b922319a849a419858db79eDan Albert  if (data_->GetError() != -1) {
37658310b49fc8a7a713b922319a849a419858db79eDan Albert    data_->GetBuffer() << ": " << strerror(data_->GetError());
37758310b49fc8a7a713b922319a849a419858db79eDan Albert  }
37858310b49fc8a7a713b922319a849a419858db79eDan Albert  std::string msg(data_->ToString());
37958310b49fc8a7a713b922319a849a419858db79eDan Albert
380765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low  {
381765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low    // Do the actual logging with the lock held.
382765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low    lock_guard<mutex> lock(logging_lock);
383765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low    if (msg.find('\n') == std::string::npos) {
3840c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert      LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(),
385765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low              data_->GetSeverity(), msg.c_str());
386765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low    } else {
387765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low      msg += '\n';
388765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low      size_t i = 0;
389765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low      while (i < msg.size()) {
390765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low        size_t nl = msg.find('\n', i);
391765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low        msg[nl] = '\0';
392765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low        LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(),
393765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low                data_->GetSeverity(), &msg[i]);
394765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low        i = nl + 1;
395765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low      }
39658310b49fc8a7a713b922319a849a419858db79eDan Albert    }
39758310b49fc8a7a713b922319a849a419858db79eDan Albert  }
39858310b49fc8a7a713b922319a849a419858db79eDan Albert
39958310b49fc8a7a713b922319a849a419858db79eDan Albert  // Abort if necessary.
40058310b49fc8a7a713b922319a849a419858db79eDan Albert  if (data_->GetSeverity() == FATAL) {
40158310b49fc8a7a713b922319a849a419858db79eDan Albert#ifdef __ANDROID__
40258310b49fc8a7a713b922319a849a419858db79eDan Albert    android_set_abort_message(msg.c_str());
40358310b49fc8a7a713b922319a849a419858db79eDan Albert#endif
40458310b49fc8a7a713b922319a849a419858db79eDan Albert    abort();
40558310b49fc8a7a713b922319a849a419858db79eDan Albert  }
40658310b49fc8a7a713b922319a849a419858db79eDan Albert}
40758310b49fc8a7a713b922319a849a419858db79eDan Albert
40858310b49fc8a7a713b922319a849a419858db79eDan Albertstd::ostream& LogMessage::stream() {
40958310b49fc8a7a713b922319a849a419858db79eDan Albert  return data_->GetBuffer();
41058310b49fc8a7a713b922319a849a419858db79eDan Albert}
41158310b49fc8a7a713b922319a849a419858db79eDan Albert
4120c055863ebb57c3446897e89c2c39a67442c1be4Dan Albertvoid LogMessage::LogLine(const char* file, unsigned int line, LogId id,
413b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert                         LogSeverity severity, const char* message) {
4147a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert  const char* tag = ProgramInvocationName();
415b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert  gLogger(id, severity, tag, file, line, message);
41658310b49fc8a7a713b922319a849a419858db79eDan Albert}
41758310b49fc8a7a713b922319a849a419858db79eDan Albert
41858310b49fc8a7a713b922319a849a419858db79eDan AlbertScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
41958310b49fc8a7a713b922319a849a419858db79eDan Albert  old_ = gMinimumLogSeverity;
42058310b49fc8a7a713b922319a849a419858db79eDan Albert  gMinimumLogSeverity = level;
42158310b49fc8a7a713b922319a849a419858db79eDan Albert}
42258310b49fc8a7a713b922319a849a419858db79eDan Albert
42358310b49fc8a7a713b922319a849a419858db79eDan AlbertScopedLogSeverity::~ScopedLogSeverity() {
42458310b49fc8a7a713b922319a849a419858db79eDan Albert  gMinimumLogSeverity = old_;
42558310b49fc8a7a713b922319a849a419858db79eDan Albert}
42658310b49fc8a7a713b922319a849a419858db79eDan Albert
42758310b49fc8a7a713b922319a849a419858db79eDan Albert}  // namespace base
42858310b49fc8a7a713b922319a849a419858db79eDan Albert}  // namespace android
429