diff --git a/talk/app/webrtc/java/jni/peerconnection_jni.cc b/talk/app/webrtc/java/jni/peerconnection_jni.cc index de7e3dd0b7..e364b3ad86 100644 --- a/talk/app/webrtc/java/jni/peerconnection_jni.cc +++ b/talk/app/webrtc/java/jni/peerconnection_jni.cc @@ -76,6 +76,11 @@ #include "webrtc/video_engine/include/vie_base.h" #include "webrtc/voice_engine/include/voe_base.h" +#ifdef ANDROID +#include "webrtc/system_wrappers/interface/logcat_trace_context.h" +using webrtc::LogcatTraceContext; +#endif + using icu::UnicodeString; using webrtc::AudioSourceInterface; using webrtc::AudioTrackInterface; @@ -101,7 +106,6 @@ using webrtc::VideoRendererInterface; using webrtc::VideoSourceInterface; using webrtc::VideoTrackInterface; using webrtc::VideoTrackVector; -using webrtc::VideoRendererInterface; // Abort the process if |x| is false, emitting |msg|. #define CHECK(x, msg) \ @@ -1152,9 +1156,19 @@ JOW(void, Logging_nativeEnableTracing)( jint nativeSeverity) { std::string path = JavaToStdString(jni, j_path); if (nativeLevels != webrtc::kTraceNone) { - CHECK(!webrtc::Trace::SetTraceFile(path.c_str(), false), - "SetTraceFile failed"); webrtc::Trace::set_level_filter(nativeLevels); +#ifdef ANDROID + if (path != "logcat:") { +#endif + CHECK(webrtc::Trace::SetTraceFile(path.c_str(), false) == 0, + "SetTraceFile failed"); +#ifdef ANDROID + } else { + // Intentionally leak this to avoid needing to reason about its lifecycle. + // It keeps no state and functions only as a dispatch point. + static LogcatTraceContext* g_trace_callback = new LogcatTraceContext(); + } +#endif } talk_base::LogMessage::LogToDebug(nativeSeverity); } diff --git a/talk/app/webrtc/java/src/org/webrtc/Logging.java b/talk/app/webrtc/java/src/org/webrtc/Logging.java index f6918b8bf8..8b23dafb20 100644 --- a/talk/app/webrtc/java/src/org/webrtc/Logging.java +++ b/talk/app/webrtc/java/src/org/webrtc/Logging.java @@ -65,7 +65,8 @@ public class Logging { }; - // Enable tracing to |path| at |levels| and |severity|. + // Enable tracing to |path| of messages of |levels| and |severity|. + // On Android, use "logcat:" for |path| to send output there. public static void enableTracing( String path, EnumSet levels, Severity severity) { int nativeLevel = 0; diff --git a/talk/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java b/talk/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java index 3d3e6c44ef..d7380e02c3 100644 --- a/talk/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java +++ b/talk/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java @@ -478,17 +478,18 @@ public class PeerConnectionTest extends TestCase { @Test public void testCompleteSession() throws Exception { - // Uncomment to get ALL WebRTC tracing and SENSITIVE libjingle logging. - // Logging.enableTracing( - // "/tmp/PeerConnectionTest-log.txt", - // EnumSet.of(Logging.TraceLevel.TRACE_ALL), - // Logging.Severity.LS_SENSITIVE); - CountDownLatch testDone = new CountDownLatch(1); System.gc(); // Encourage any GC-related threads to start up. TreeSet threadsBeforeTest = allThreads(); PeerConnectionFactory factory = new PeerConnectionFactory(); + // Uncomment to get ALL WebRTC tracing and SENSITIVE libjingle logging. + // NOTE: this _must_ happen while |factory| is alive! + // Logging.enableTracing( + // "/tmp/PeerConnectionTest-log.txt", + // EnumSet.of(Logging.TraceLevel.TRACE_ALL), + // Logging.Severity.LS_SENSITIVE); + MediaConstraints pcConstraints = new MediaConstraints(); pcConstraints.mandatory.add( new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true")); diff --git a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java index 7c673d8139..b89e9acd90 100644 --- a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java +++ b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java @@ -104,12 +104,6 @@ public class AppRTCDemoActivity extends Activity } }); - // Uncomment to get ALL WebRTC tracing and SENSITIVE libjingle logging. - // Logging.enableTracing( - // "/sdcard/trace.txt", - // EnumSet.of(Logging.TraceLevel.TRACE_ALL), - // Logging.Severity.LS_SENSITIVE); - PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); wakeLock = powerManager.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AppRTCDemo"); @@ -191,6 +185,13 @@ public class AppRTCDemoActivity extends Activity pc = factory.createPeerConnection( iceServers, appRtcClient.pcConstraints(), pcObserver); + // Uncomment to get ALL WebRTC tracing and SENSITIVE libjingle logging. + // NOTE: this _must_ happen while |factory| is alive! + // Logging.enableTracing( + // "logcat:", + // EnumSet.of(Logging.TraceLevel.TRACE_ALL), + // Logging.Severity.LS_SENSITIVE); + { final PeerConnection finalPC = pc; final Runnable repeatedStatsLogger = new Runnable() { diff --git a/webrtc/system_wrappers/interface/logcat_trace_context.h b/webrtc/system_wrappers/interface/logcat_trace_context.h new file mode 100644 index 0000000000..d23e451f2e --- /dev/null +++ b/webrtc/system_wrappers/interface/logcat_trace_context.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGCAT_TRACE_CONTEXT_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGCAT_TRACE_CONTEXT_H_ + +#include "webrtc/system_wrappers/interface/trace.h" + +#ifndef ANDROID +#error This file only makes sense to include on Android! +#endif + +namespace webrtc { + +// Scoped helper class for directing Traces to Android's logcat facility. While +// this object lives, Trace output will be sent to logcat. +class LogcatTraceContext : public webrtc::TraceCallback { + public: + LogcatTraceContext(); + virtual ~LogcatTraceContext(); + + // TraceCallback impl. + virtual void Print(TraceLevel level, const char* message, int length); +}; + +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LOGCAT_TRACE_CONTEXT_H_ diff --git a/webrtc/system_wrappers/source/logcat_trace_context.cc b/webrtc/system_wrappers/source/logcat_trace_context.cc new file mode 100644 index 0000000000..313acc74e8 --- /dev/null +++ b/webrtc/system_wrappers/source/logcat_trace_context.cc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/system_wrappers/interface/logcat_trace_context.h" + +#include +#include + +#include "webrtc/system_wrappers/interface/logging.h" + +namespace webrtc { + +static android_LogPriority AndroidLogPriorityFromWebRtcLogLevel( + TraceLevel webrtc_level) { + // NOTE: this mapping is somewhat arbitrary. StateInfo and Info are mapped + // to DEBUG because they are highly verbose in webrtc code (which is + // unfortunate). + switch (webrtc_level) { + case webrtc::kTraceStateInfo: return ANDROID_LOG_DEBUG; + case webrtc::kTraceWarning: return ANDROID_LOG_WARN; + case webrtc::kTraceError: return ANDROID_LOG_ERROR; + case webrtc::kTraceCritical: return ANDROID_LOG_FATAL; + case webrtc::kTraceApiCall: return ANDROID_LOG_VERBOSE; + case webrtc::kTraceModuleCall: return ANDROID_LOG_VERBOSE; + case webrtc::kTraceMemory: return ANDROID_LOG_VERBOSE; + case webrtc::kTraceTimer: return ANDROID_LOG_VERBOSE; + case webrtc::kTraceStream: return ANDROID_LOG_VERBOSE; + case webrtc::kTraceDebug: return ANDROID_LOG_DEBUG; + case webrtc::kTraceInfo: return ANDROID_LOG_DEBUG; + case webrtc::kTraceTerseInfo: return ANDROID_LOG_INFO; + default: + LOG(LS_ERROR) << "Unexpected log level" << webrtc_level; + return ANDROID_LOG_FATAL; + } +} + +LogcatTraceContext::LogcatTraceContext() { + webrtc::Trace::CreateTrace(); + if (webrtc::Trace::SetTraceCallback(this) != 0) + assert(false); +} + +LogcatTraceContext::~LogcatTraceContext() { + if (webrtc::Trace::SetTraceCallback(NULL) != 0) + assert(false); + webrtc::Trace::ReturnTrace(); +} + +void LogcatTraceContext::Print(TraceLevel level, + const char* message, + int length) { + __android_log_print(AndroidLogPriorityFromWebRtcLogLevel(level), + "WEBRTC", "%.*s", length, message); +} + +} // namespace webrtc diff --git a/webrtc/system_wrappers/source/system_wrappers.gyp b/webrtc/system_wrappers/source/system_wrappers.gyp index 4f6d083383..0aa4932a14 100644 --- a/webrtc/system_wrappers/source/system_wrappers.gyp +++ b/webrtc/system_wrappers/source/system_wrappers.gyp @@ -38,6 +38,7 @@ '../interface/file_wrapper.h', '../interface/fix_interlocked_exchange_pointer_win.h', '../interface/list_wrapper.h', + '../interface/logcat_trace_context.h', '../interface/logging.h', '../interface/ref_count.h', '../interface/rw_lock_wrapper.h', @@ -82,6 +83,7 @@ 'file_impl.cc', 'file_impl.h', 'list_no_stl.cc', + 'logcat_trace_context.cc', 'logging.cc', 'logging_no_op.cc', 'rw_lock.cc', @@ -140,6 +142,11 @@ 'WEBRTC_CLOCK_TYPE_REALTIME', ], 'dependencies': [ 'cpu_features_android', ], + }, { # OS!="android" + 'sources!': [ + '../interface/logcat_trace_context.h', + 'logcat_trace_context.cc', + ], }], ['OS=="linux"', { 'defines': [