Add RtcEventLog to AppRTCMobile with preference setting.
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 <qingsi@google.com>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21987}
diff --git a/examples/BUILD.gn b/examples/BUILD.gn
index a8abe97..f39e23a 100644
--- a/examples/BUILD.gn
+++ b/examples/BUILD.gn
@@ -83,6 +83,7 @@
"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 231475f..4aec2c1 100644
--- a/examples/androidapp/res/values/strings.xml
+++ b/examples/androidapp/res/values/strings.xml
@@ -213,4 +213,8 @@
<string name="pref_tracing_title">Debug performance tracing.</string>
<string name="pref_tracing_dlg">Debug performance tracing.</string>
<string name="pref_tracing_default" translatable="false">false</string>
+
+ <string name="pref_enable_rtceventlog_key">enable_rtceventlog_key</string>
+ <string name="pref_enable_rtceventlog_title">Enable RtcEventLog.</string>
+ <string name="pref_enable_rtceventlog_default">false</string>
</resources>
diff --git a/examples/androidapp/res/xml/preferences.xml b/examples/androidapp/res/xml/preferences.xml
index c9fe750..e8b9547 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" />
<CheckBoxPreference
android:key="@string/pref_tracing_key"
android:title="@string/pref_tracing_title"
android:dialogTitle="@string/pref_tracing_dlg"
- android:defaultValue="@string/pref_tracing_default" />
+ android:defaultValue="@string/pref_tracing_default" />
+
+ <CheckBoxPreference
+ android:key="@string/pref_enable_rtceventlog_key"
+ android:title="@string/pref_enable_rtceventlog_title"
+ android:defaultValue="@string/pref_enable_rtceventlog_default"/>
</PreferenceCategory>
</PreferenceScreen>
diff --git a/examples/androidapp/src/org/appspot/apprtc/CallActivity.java b/examples/androidapp/src/org/appspot/apprtc/CallActivity.java
index 19ff9ef..70d0e40 100644
--- a/examples/androidapp/src/org/appspot/apprtc/CallActivity.java
+++ b/examples/androidapp/src/org/appspot/apprtc/CallActivity.java
@@ -117,6 +117,7 @@
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 @@
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 @@
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 @@
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 28add75..17b2f8da 100644
--- a/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java
+++ b/examples/androidapp/src/org/appspot/apprtc/ConnectActivity.java
@@ -430,6 +430,11 @@
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 @@
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 9ed48f5..961e2e8 100644
--- a/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java
+++ b/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java
@@ -13,16 +13,21 @@
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 @@
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 @@
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 @@
private AudioTrack localAudioTrack;
private DataChannel dataChannel;
private boolean dataChannelEnabled;
+ // Enable RtcEventLog.
+ private RtcEventLog rtcEventLog;
/**
* Peer connection parameters.
@@ -201,6 +210,7 @@
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 @@
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 @@
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 @@
this.disableBuiltInNS = disableBuiltInNS;
this.enableLevelControl = enableLevelControl;
this.disableWebRtcAGCAndHPF = disableWebRtcAGCAndHPF;
+ this.enableRtcEventLog = enableRtcEventLog;
this.dataChannelParameters = dataChannelParameters;
}
}
@@ -293,15 +304,19 @@
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 @@
executor.execute(new Runnable() {
@Override
public void run() {
- createPeerConnectionFactoryInternal(context);
+ createPeerConnectionFactoryInternal();
}
});
}
@@ -357,6 +372,7 @@
try {
createMediaConstraintsInternal();
createPeerConnectionInternal();
+ maybeCreateAndStartRtcEventLog();
} catch (Exception e) {
reportError("Failed to create peer connection: " + e.getMessage());
throw e;
@@ -378,7 +394,7 @@
return videoCallEnabled;
}
- private void createPeerConnectionFactoryInternal(Context context) {
+ private void createPeerConnectionFactoryInternal() {
isError = false;
// Initialize field trials.
@@ -422,7 +438,7 @@
"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 @@
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 @@
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 0000000..e1cf8ce
--- /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 43b8a0a..152bb7d 100644
--- a/examples/androidapp/src/org/appspot/apprtc/SettingsActivity.java
+++ b/examples/androidapp/src/org/appspot/apprtc/SettingsActivity.java
@@ -53,6 +53,7 @@
private String keyPrefRoomServerUrl;
private String keyPrefDisplayHud;
private String keyPrefTracing;
+ private String keyprefEnabledRtcEventLog;
private String keyprefEnableDataChannel;
private String keyprefOrdered;
@@ -102,6 +103,7 @@
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 @@
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 @@
|| 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 56eb3f7..c9c74b7 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 @@
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 @@
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 @@
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