From a4e72b79147157a4aa637535ab69bd9a864080fc Mon Sep 17 00:00:00 2001 From: Qingsi Wang Date: Mon, 12 Feb 2018 10:34:18 -0800 Subject: [PATCH] Add RtcEventLog to AppRTCMobile with preference setting. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable diagnostic packet and event recording as in the "webrtc-internal" setting in Chromium. Bug: webrtc:8859 Change-Id: I1d4a19e0dd60133cdd0d4e18a55780623b65653c Reviewed-on: https://webrtc-review.googlesource.com/49541 Commit-Queue: Qingsi Wang Reviewed-by: Sami Kalliomäki Cr-Commit-Position: refs/heads/master@{#21987} --- examples/BUILD.gn | 1 + examples/androidapp/res/values/strings.xml | 4 + examples/androidapp/res/xml/preferences.xml | 9 ++- .../src/org/appspot/apprtc/CallActivity.java | 9 ++- .../org/appspot/apprtc/ConnectActivity.java | 6 ++ .../appspot/apprtc/PeerConnectionClient.java | 57 ++++++++++++-- .../src/org/appspot/apprtc/RtcEventLog.java | 74 +++++++++++++++++++ .../org/appspot/apprtc/SettingsActivity.java | 6 +- .../apprtc/test/PeerConnectionClientTest.java | 12 +-- 9 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 examples/androidapp/src/org/appspot/apprtc/RtcEventLog.java diff --git a/examples/BUILD.gn b/examples/BUILD.gn index a8abe97c8a..f39e23aea4 100644 --- a/examples/BUILD.gn +++ b/examples/BUILD.gn @@ -83,6 +83,7 @@ if (is_android) { "androidapp/src/org/appspot/apprtc/HudFragment.java", "androidapp/src/org/appspot/apprtc/PeerConnectionClient.java", "androidapp/src/org/appspot/apprtc/RoomParametersFetcher.java", + "androidapp/src/org/appspot/apprtc/RtcEventLog.java", "androidapp/src/org/appspot/apprtc/SettingsActivity.java", "androidapp/src/org/appspot/apprtc/SettingsFragment.java", "androidapp/src/org/appspot/apprtc/TCPChannelClient.java", diff --git a/examples/androidapp/res/values/strings.xml b/examples/androidapp/res/values/strings.xml index 231475f587..4aec2c1850 100644 --- a/examples/androidapp/res/values/strings.xml +++ b/examples/androidapp/res/values/strings.xml @@ -213,4 +213,8 @@ Debug performance tracing. Debug performance tracing. false + + enable_rtceventlog_key + Enable RtcEventLog. + false diff --git a/examples/androidapp/res/xml/preferences.xml b/examples/androidapp/res/xml/preferences.xml index c9fe750d9e..e8b9547b6f 100644 --- a/examples/androidapp/res/xml/preferences.xml +++ b/examples/androidapp/res/xml/preferences.xml @@ -229,13 +229,18 @@ android:key="@string/pref_displayhud_key" android:title="@string/pref_displayhud_title" android:dialogTitle="@string/pref_displayhud_dlg" - android:defaultValue="@string/pref_displayhud_default" /> + android:defaultValue="@string/pref_displayhud_default" /> + android:defaultValue="@string/pref_tracing_default" /> + + diff --git a/examples/androidapp/src/org/appspot/apprtc/CallActivity.java b/examples/androidapp/src/org/appspot/apprtc/CallActivity.java index 19ff9efc94..70d0e40df5 100644 --- a/examples/androidapp/src/org/appspot/apprtc/CallActivity.java +++ b/examples/androidapp/src/org/appspot/apprtc/CallActivity.java @@ -117,6 +117,7 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven public static final String EXTRA_PROTOCOL = "org.appspot.apprtc.PROTOCOL"; public static final String EXTRA_NEGOTIATED = "org.appspot.apprtc.NEGOTIATED"; public static final String EXTRA_ID = "org.appspot.apprtc.ID"; + public static final String EXTRA_ENABLE_RTCEVENTLOG = "org.appspot.apprtc.ENABLE_RTCEVENTLOG"; private static final int CAPTURE_PERMISSION_REQUEST_CODE = 1; @@ -242,7 +243,7 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven final Intent intent = getIntent(); // Create peer connection client. - peerConnectionClient = new PeerConnectionClient(); + peerConnectionClient = new PeerConnectionClient(getApplicationContext()); // Create video renderers. pipRenderer.init(peerConnectionClient.getRenderContext(), null); @@ -335,7 +336,8 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven intent.getBooleanExtra(EXTRA_DISABLE_BUILT_IN_AGC, false), intent.getBooleanExtra(EXTRA_DISABLE_BUILT_IN_NS, false), intent.getBooleanExtra(EXTRA_ENABLE_LEVEL_CONTROL, false), - intent.getBooleanExtra(EXTRA_DISABLE_WEBRTC_AGC_AND_HPF, false), dataChannelParameters); + intent.getBooleanExtra(EXTRA_DISABLE_WEBRTC_AGC_AND_HPF, false), + intent.getBooleanExtra(EXTRA_ENABLE_RTCEVENTLOG, false), dataChannelParameters); commandLineRun = intent.getBooleanExtra(EXTRA_CMDLINE, false); int runTimeMs = intent.getIntExtra(EXTRA_RUNTIME, 0); @@ -384,8 +386,7 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven options.networkIgnoreMask = 0; peerConnectionClient.setPeerConnectionFactoryOptions(options); } - peerConnectionClient.createPeerConnectionFactory( - getApplicationContext(), peerConnectionParameters, CallActivity.this); + peerConnectionClient.createPeerConnectionFactory(peerConnectionParameters, CallActivity.this); if (screencaptureEnabled) { startScreenCapture(); diff --git a/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java b/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java index 28add759c0..17b2f8da0d 100644 --- a/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java +++ b/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java @@ -430,6 +430,11 @@ public class ConnectActivity extends Activity { boolean tracing = sharedPrefGetBoolean(R.string.pref_tracing_key, CallActivity.EXTRA_TRACING, R.string.pref_tracing_default, useValuesFromIntent); + // Check Enable RtcEventLog. + boolean rtcEventLogEnabled = sharedPrefGetBoolean(R.string.pref_enable_rtceventlog_key, + CallActivity.EXTRA_ENABLE_RTCEVENTLOG, R.string.pref_enable_rtceventlog_default, + useValuesFromIntent); + // Get datachannel options boolean dataChannelEnabled = sharedPrefGetBoolean(R.string.pref_enable_datachannel_key, CallActivity.EXTRA_DATA_CHANNEL_ENABLED, R.string.pref_enable_datachannel_default, @@ -481,6 +486,7 @@ public class ConnectActivity extends Activity { intent.putExtra(CallActivity.EXTRA_AUDIOCODEC, audioCodec); intent.putExtra(CallActivity.EXTRA_DISPLAY_HUD, displayHud); intent.putExtra(CallActivity.EXTRA_TRACING, tracing); + intent.putExtra(CallActivity.EXTRA_ENABLE_RTCEVENTLOG, rtcEventLogEnabled); intent.putExtra(CallActivity.EXTRA_CMDLINE, commandLineRun); intent.putExtra(CallActivity.EXTRA_RUNTIME, runTimeMs); diff --git a/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java b/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java index 9ed48f52f8..961e2e8448 100644 --- a/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java +++ b/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java @@ -13,16 +13,21 @@ package org.appspot.apprtc; import android.content.Context; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.preference.PreferenceManager; import android.util.Log; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ExecutorService; @@ -105,6 +110,7 @@ public class PeerConnectionClient { private static final int HD_VIDEO_WIDTH = 1280; private static final int HD_VIDEO_HEIGHT = 720; private static final int BPS_IN_KBPS = 1000; + private static final String RTCEVENTLOG_OUTPUT_DIR_NAME = "rtc_event_log"; // Executor thread is started once in private ctor and is used for all // peer connection API calls to ensure new peer connection factory is @@ -115,6 +121,7 @@ public class PeerConnectionClient { private final SDPObserver sdpObserver = new SDPObserver(); private final EglBase rootEglBase; + private final Context appContext; private PeerConnectionFactory factory; private PeerConnection peerConnection; PeerConnectionFactory.Options options = null; @@ -154,6 +161,8 @@ public class PeerConnectionClient { private AudioTrack localAudioTrack; private DataChannel dataChannel; private boolean dataChannelEnabled; + // Enable RtcEventLog. + private RtcEventLog rtcEventLog; /** * Peer connection parameters. @@ -201,6 +210,7 @@ public class PeerConnectionClient { public final boolean disableBuiltInNS; public final boolean enableLevelControl; public final boolean disableWebRtcAGCAndHPF; + public final boolean enableRtcEventLog; private final DataChannelParameters dataChannelParameters; public PeerConnectionParameters(boolean videoCallEnabled, boolean loopback, boolean tracing, @@ -208,11 +218,11 @@ public class PeerConnectionClient { boolean videoCodecHwAcceleration, boolean videoFlexfecEnabled, int audioStartBitrate, String audioCodec, boolean noAudioProcessing, boolean aecDump, boolean useOpenSLES, boolean disableBuiltInAEC, boolean disableBuiltInAGC, boolean disableBuiltInNS, - boolean enableLevelControl, boolean disableWebRtcAGCAndHPF) { + boolean enableLevelControl, boolean disableWebRtcAGCAndHPF, boolean enableRtcEventLog) { this(videoCallEnabled, loopback, tracing, videoWidth, videoHeight, videoFps, videoMaxBitrate, videoCodec, videoCodecHwAcceleration, videoFlexfecEnabled, audioStartBitrate, audioCodec, noAudioProcessing, aecDump, useOpenSLES, disableBuiltInAEC, disableBuiltInAGC, - disableBuiltInNS, enableLevelControl, disableWebRtcAGCAndHPF, null); + disableBuiltInNS, enableLevelControl, disableWebRtcAGCAndHPF, enableRtcEventLog, null); } public PeerConnectionParameters(boolean videoCallEnabled, boolean loopback, boolean tracing, @@ -220,7 +230,7 @@ public class PeerConnectionClient { boolean videoCodecHwAcceleration, boolean videoFlexfecEnabled, int audioStartBitrate, String audioCodec, boolean noAudioProcessing, boolean aecDump, boolean useOpenSLES, boolean disableBuiltInAEC, boolean disableBuiltInAGC, boolean disableBuiltInNS, - boolean enableLevelControl, boolean disableWebRtcAGCAndHPF, + boolean enableLevelControl, boolean disableWebRtcAGCAndHPF, boolean enableRtcEventLog, DataChannelParameters dataChannelParameters) { this.videoCallEnabled = videoCallEnabled; this.loopback = loopback; @@ -242,6 +252,7 @@ public class PeerConnectionClient { this.disableBuiltInNS = disableBuiltInNS; this.enableLevelControl = enableLevelControl; this.disableWebRtcAGCAndHPF = disableWebRtcAGCAndHPF; + this.enableRtcEventLog = enableRtcEventLog; this.dataChannelParameters = dataChannelParameters; } } @@ -293,15 +304,19 @@ public class PeerConnectionClient { void onPeerConnectionError(final String description); } - public PeerConnectionClient() { + public PeerConnectionClient(Context appContext) { + if (appContext == null) { + throw new NullPointerException("The application context is null"); + } rootEglBase = EglBase.create(); + this.appContext = appContext; } public void setPeerConnectionFactoryOptions(PeerConnectionFactory.Options options) { this.options = options; } - public void createPeerConnectionFactory(final Context context, + public void createPeerConnectionFactory( final PeerConnectionParameters peerConnectionParameters, final PeerConnectionEvents events) { this.peerConnectionParameters = peerConnectionParameters; this.events = events; @@ -328,7 +343,7 @@ public class PeerConnectionClient { executor.execute(new Runnable() { @Override public void run() { - createPeerConnectionFactoryInternal(context); + createPeerConnectionFactoryInternal(); } }); } @@ -357,6 +372,7 @@ public class PeerConnectionClient { try { createMediaConstraintsInternal(); createPeerConnectionInternal(); + maybeCreateAndStartRtcEventLog(); } catch (Exception e) { reportError("Failed to create peer connection: " + e.getMessage()); throw e; @@ -378,7 +394,7 @@ public class PeerConnectionClient { return videoCallEnabled; } - private void createPeerConnectionFactoryInternal(Context context) { + private void createPeerConnectionFactoryInternal() { isError = false; // Initialize field trials. @@ -422,7 +438,7 @@ public class PeerConnectionClient { "Initialize WebRTC. Field trials: " + fieldTrials + " Enable video HW acceleration: " + peerConnectionParameters.videoCodecHwAcceleration); PeerConnectionFactory.initialize( - PeerConnectionFactory.InitializationOptions.builder(context) + PeerConnectionFactory.InitializationOptions.builder(appContext) .setFieldTrials(fieldTrials) .setEnableVideoHwAcceleration(peerConnectionParameters.videoCodecHwAcceleration) .setEnableInternalTracer(true) @@ -664,6 +680,26 @@ public class PeerConnectionClient { Log.d(TAG, "Peer connection created."); } + private File createRtcEventLogOutputFile() { + DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_hhmm_ss", Locale.getDefault()); + Date date = new Date(); + final String outputFileName = "event_log_" + dateFormat.format(date) + ".log"; + return new File( + appContext.getDir(RTCEVENTLOG_OUTPUT_DIR_NAME, Context.MODE_PRIVATE), outputFileName); + } + + private void maybeCreateAndStartRtcEventLog() { + if (appContext == null || peerConnection == null) { + return; + } + if (!peerConnectionParameters.enableRtcEventLog) { + Log.d(TAG, "RtcEventLog is disabled."); + return; + } + rtcEventLog = new RtcEventLog(peerConnection); + rtcEventLog.start(createRtcEventLogOutputFile()); + } + private void closeInternal() { if (factory != null && peerConnectionParameters.aecDump) { factory.stopAecDump(); @@ -674,6 +710,11 @@ public class PeerConnectionClient { dataChannel.dispose(); dataChannel = null; } + if (rtcEventLog != null) { + // RtcEventLog should stop before the peer connection is disposed. + rtcEventLog.stop(); + rtcEventLog = null; + } if (peerConnection != null) { peerConnection.dispose(); peerConnection = null; diff --git a/examples/androidapp/src/org/appspot/apprtc/RtcEventLog.java b/examples/androidapp/src/org/appspot/apprtc/RtcEventLog.java new file mode 100644 index 0000000000..e1cf8ce2b4 --- /dev/null +++ b/examples/androidapp/src/org/appspot/apprtc/RtcEventLog.java @@ -0,0 +1,74 @@ +/* + * Copyright 2018 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. + */ + +package org.appspot.apprtc; + +import android.content.Context; +import android.os.ParcelFileDescriptor; +import android.util.Log; +import java.io.File; +import java.io.IOException; +import org.webrtc.PeerConnection; + +public class RtcEventLog { + private static final String TAG = "RtcEventLog"; + private static final int OUTPUT_FILE_MAX_BYTES = 10_000_000; + private final PeerConnection peerConnection; + private RtcEventLogState state = RtcEventLogState.INACTIVE; + + enum RtcEventLogState { + INACTIVE, + STARTED, + STOPPED, + } + + public RtcEventLog(PeerConnection peerConnection) { + if (peerConnection == null) { + throw new NullPointerException("The peer connection is null."); + } + this.peerConnection = peerConnection; + } + + public void start(final File outputFile) { + if (state == RtcEventLogState.STARTED) { + Log.e(TAG, "RtcEventLog has already started."); + return; + } + final ParcelFileDescriptor fileDescriptor; + try { + fileDescriptor = ParcelFileDescriptor.open(outputFile, + ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_CREATE + | ParcelFileDescriptor.MODE_TRUNCATE); + } catch (IOException e) { + Log.e(TAG, "Failed to create a new file", e); + return; + } + + // Passes ownership of the file to WebRTC. + boolean success = + peerConnection.startRtcEventLog(fileDescriptor.detachFd(), OUTPUT_FILE_MAX_BYTES); + if (!success) { + Log.e(TAG, "Failed to start RTC event log."); + return; + } + state = RtcEventLogState.STARTED; + Log.d(TAG, "RtcEventLog started."); + } + + public void stop() { + if (state != RtcEventLogState.STARTED) { + Log.e(TAG, "RtcEventLog was not started."); + return; + } + peerConnection.stopRtcEventLog(); + state = RtcEventLogState.STOPPED; + Log.d(TAG, "RtcEventLog stopped."); + } +} \ No newline at end of file diff --git a/examples/androidapp/src/org/appspot/apprtc/SettingsActivity.java b/examples/androidapp/src/org/appspot/apprtc/SettingsActivity.java index 43b8a0a662..152bb7d968 100644 --- a/examples/androidapp/src/org/appspot/apprtc/SettingsActivity.java +++ b/examples/androidapp/src/org/appspot/apprtc/SettingsActivity.java @@ -53,6 +53,7 @@ public class SettingsActivity extends Activity implements OnSharedPreferenceChan private String keyPrefRoomServerUrl; private String keyPrefDisplayHud; private String keyPrefTracing; + private String keyprefEnabledRtcEventLog; private String keyprefEnableDataChannel; private String keyprefOrdered; @@ -102,6 +103,7 @@ public class SettingsActivity extends Activity implements OnSharedPreferenceChan keyPrefRoomServerUrl = getString(R.string.pref_room_server_url_key); keyPrefDisplayHud = getString(R.string.pref_displayhud_key); keyPrefTracing = getString(R.string.pref_tracing_key); + keyprefEnabledRtcEventLog = getString(R.string.pref_enable_rtceventlog_key); // Display the fragment as the main content. settingsFragment = new SettingsFragment(); @@ -158,6 +160,7 @@ public class SettingsActivity extends Activity implements OnSharedPreferenceChan updateSummary(sharedPreferences, keyPrefRoomServerUrl); updateSummaryB(sharedPreferences, keyPrefDisplayHud); updateSummaryB(sharedPreferences, keyPrefTracing); + updateSummaryB(sharedPreferences, keyprefEnabledRtcEventLog); if (!Camera2Enumerator.isSupported(this)) { Preference camera2Preference = settingsFragment.findPreference(keyprefCamera2); @@ -241,7 +244,8 @@ public class SettingsActivity extends Activity implements OnSharedPreferenceChan || key.equals(keyPrefDisplayHud) || key.equals(keyprefEnableDataChannel) || key.equals(keyprefOrdered) - || key.equals(keyprefNegotiated)) { + || key.equals(keyprefNegotiated) + || key.equals(keyprefEnabledRtcEventLog)) { updateSummaryB(sharedPreferences, key); } else if (key.equals(keyprefSpeakerphone)) { updateSummaryList(sharedPreferences, key); diff --git a/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java b/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java index 56eb3f7284..c9c74b7990 100644 --- a/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java +++ b/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java @@ -315,13 +315,13 @@ public class PeerConnectionClientTest implements PeerConnectionEvents { null, null, null, // clientId, wssUrl, wssPostUrl. null, null); // offerSdp, iceCandidates. - PeerConnectionClient client = new PeerConnectionClient(); + PeerConnectionClient client = + new PeerConnectionClient(InstrumentationRegistry.getTargetContext()); PeerConnectionFactory.Options options = new PeerConnectionFactory.Options(); options.networkIgnoreMask = 0; options.disableNetworkMonitor = true; client.setPeerConnectionFactoryOptions(options); - client.createPeerConnectionFactory( - InstrumentationRegistry.getTargetContext(), peerConnectionParameters, this); + client.createPeerConnectionFactory(peerConnectionParameters, this); client.createPeerConnection(localRenderer, remoteRenderer, videoCapturer, signalingParameters); client.createOffer(); return client; @@ -345,7 +345,8 @@ public class PeerConnectionClientTest implements PeerConnectionEvents { false, /* noAudioProcessing */ false, /* aecDump */ false /* useOpenSLES */, false /* disableBuiltInAEC */, false /* disableBuiltInAGC */, - false /* disableBuiltInNS */, false /* enableLevelControl */, false /* disableWebRtcAGC */); + false /* disableBuiltInNS */, false /* enableLevelControl */, false /* disableWebRtcAGC */, + false /* enableRtcEventLog */); } private VideoCapturer createCameraCapturer(boolean captureToTexture) { @@ -380,7 +381,8 @@ public class PeerConnectionClientTest implements PeerConnectionEvents { false, /* noAudioProcessing */ false, /* aecDump */ false /* useOpenSLES */, false /* disableBuiltInAEC */, false /* disableBuiltInAGC */, - false /* disableBuiltInNS */, false /* enableLevelControl */, false /* disableWebRtcAGC */); + false /* disableBuiltInNS */, false /* enableLevelControl */, false /* disableWebRtcAGC */, + false /* enableRtcEventLog */); } @Before