RTCStatsCollector: Utilize network thread to minimize thread hops.

(This is a re-upload of https://codereview.webrtc.org/2567243003/, the
CQ stopped working there.)

The previously used WebRtcSession::GetTransportStats did a synchronous
invoke per channel (voice, video, data) on the signaling thread to the
network thread - e.g. 3 blocking invokes.

It is replaced by WebRtcSession::GetStats[_s] which can be invoked on
the signaling thread or on any thread if a ChannelNamePairs argument is
present (provided by WebRtcSession::GetChannelNamePairs on the signaling
thread).

With these changes, and changes allowing the getting of certificates
from any thread, the RTCStatsCollector can turn the 3 blocking thread
invokes into 1 non-blocking invoke.

BUG=webrtc:6875, chromium:627816

Review-Url: https://codereview.webrtc.org/2583883002
Cr-Commit-Position: refs/heads/master@{#15672}
diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc
index a6d691c..3628544 100644
--- a/webrtc/api/rtcstatscollector.cc
+++ b/webrtc/api/rtcstatscollector.cc
@@ -416,9 +416,32 @@
     invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
         rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnSignalingThread,
             rtc::scoped_refptr<RTCStatsCollector>(this), timestamp_us));
+
+    // TODO(hbos): No stats are gathered by
+    // |ProducePartialResultsOnWorkerThread|, remove it.
     invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
         rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnWorkerThread,
             rtc::scoped_refptr<RTCStatsCollector>(this), timestamp_us));
+
+    // Prepare |channel_names_| and |media_info_| for use in
+    // |ProducePartialResultsOnNetworkThread|.
+    channel_name_pairs_.reset(new ChannelNamePairs());
+    if (pc_->session()->voice_channel()) {
+      channel_name_pairs_->voice = rtc::Optional<ChannelNamePair>(
+          ChannelNamePair(pc_->session()->voice_channel()->content_name(),
+                          pc_->session()->voice_channel()->transport_name()));
+    }
+    if (pc_->session()->video_channel()) {
+      channel_name_pairs_->video = rtc::Optional<ChannelNamePair>(
+          ChannelNamePair(pc_->session()->video_channel()->content_name(),
+                          pc_->session()->video_channel()->transport_name()));
+    }
+    if (pc_->session()->data_channel()) {
+      channel_name_pairs_->data = rtc::Optional<ChannelNamePair>(
+          ChannelNamePair(pc_->session()->data_channel()->content_name(),
+                          pc_->session()->data_channel()->transport_name()));
+    }
+    media_info_.reset(PrepareMediaInfo_s().release());
     invoker_.AsyncInvoke<void>(RTC_FROM_HERE, network_thread_,
         rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnNetworkThread,
             rtc::scoped_refptr<RTCStatsCollector>(this), timestamp_us));
@@ -436,23 +459,6 @@
   rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(
       timestamp_us);
 
-  SessionStats session_stats;
-  if (pc_->session()->GetTransportStats(&session_stats)) {
-    std::map<std::string, CertificateStatsPair> transport_cert_stats =
-        PrepareTransportCertificateStats(session_stats);
-    MediaInfo media_info = PrepareMediaInfo(session_stats);
-
-    ProduceCertificateStats_s(
-        timestamp_us, transport_cert_stats, report.get());
-    ProduceCodecStats_s(
-        timestamp_us, media_info, report.get());
-    ProduceIceCandidateAndPairStats_s(
-        timestamp_us, session_stats, report.get());
-    ProduceRTPStreamStats_s(
-        timestamp_us, session_stats, media_info, report.get());
-    ProduceTransportStats_s(
-        timestamp_us, session_stats, transport_cert_stats, report.get());
-  }
   ProduceDataChannelStats_s(timestamp_us, report.get());
   ProduceMediaStreamAndTrackStats_s(timestamp_us, report.get());
   ProducePeerConnectionStats_s(timestamp_us, report.get());
@@ -466,13 +472,8 @@
   rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(
       timestamp_us);
 
-  // TODO(hbos): Gather stats on worker thread.
-  // pc_->session()'s channels are owned by the signaling thread but there are
-  // some stats that are gathered on the worker thread. Instead of a synchronous
-  // invoke on "s->w" we could to the "w" work here asynchronously if it wasn't
-  // for the ownership issue. Synchronous invokes in other places makes it
-  // difficult to introduce locks without introducing deadlocks and the channels
-  // are not reference counted.
+  // TODO(hbos): There are no stats to be gathered on this thread, remove this
+  // method.
 
   AddPartialResults(report);
 }
@@ -483,13 +484,23 @@
   rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(
       timestamp_us);
 
-  // TODO(hbos): Gather stats on network thread.
-  // pc_->session()'s channels are owned by the signaling thread but there are
-  // some stats that are gathered on the network thread. Instead of a
-  // synchronous invoke on "s->n" we could to the "n" work here asynchronously
-  // if it wasn't for the ownership issue. Synchronous invokes in other places
-  // makes it difficult to introduce locks without introducing deadlocks and the
-  // channels are not reference counted.
+  std::unique_ptr<SessionStats> session_stats =
+      pc_->session()->GetStats(*channel_name_pairs_);
+  if (session_stats) {
+    std::map<std::string, CertificateStatsPair> transport_cert_stats =
+        PrepareTransportCertificateStats_n(*session_stats);
+
+    ProduceCertificateStats_n(
+        timestamp_us, transport_cert_stats, report.get());
+    ProduceCodecStats_n(
+        timestamp_us, *media_info_, report.get());
+    ProduceIceCandidateAndPairStats_n(
+        timestamp_us, *session_stats, report.get());
+    ProduceRTPStreamStats_n(
+        timestamp_us, *session_stats, *media_info_, report.get());
+    ProduceTransportStats_n(
+        timestamp_us, *session_stats, transport_cert_stats, report.get());
+  }
 
   AddPartialResults(report);
 }
@@ -534,11 +545,11 @@
   callbacks_.clear();
 }
 
-void RTCStatsCollector::ProduceCertificateStats_s(
+void RTCStatsCollector::ProduceCertificateStats_n(
     int64_t timestamp_us,
     const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
     RTCStatsReport* report) const {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(network_thread_->IsCurrent());
   for (const auto& transport_cert_stats_pair : transport_cert_stats) {
     if (transport_cert_stats_pair.second.local) {
       ProduceCertificateStatsFromSSLCertificateStats(
@@ -551,10 +562,10 @@
   }
 }
 
-void RTCStatsCollector::ProduceCodecStats_s(
+void RTCStatsCollector::ProduceCodecStats_n(
     int64_t timestamp_us, const MediaInfo& media_info,
     RTCStatsReport* report) const {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(network_thread_->IsCurrent());
   // Audio
   if (media_info.voice) {
     // Inbound
@@ -605,10 +616,10 @@
   }
 }
 
-void RTCStatsCollector::ProduceIceCandidateAndPairStats_s(
+void RTCStatsCollector::ProduceIceCandidateAndPairStats_n(
       int64_t timestamp_us, const SessionStats& session_stats,
       RTCStatsReport* report) const {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(network_thread_->IsCurrent());
   for (const auto& transport_stats : session_stats.transport_stats) {
     for (const auto& channel_stats : transport_stats.second.channel_stats) {
       std::string transport_id = RTCTransportStatsIDFromTransportChannel(
@@ -681,10 +692,10 @@
   report->AddStats(std::move(stats));
 }
 
-void RTCStatsCollector::ProduceRTPStreamStats_s(
+void RTCStatsCollector::ProduceRTPStreamStats_n(
     int64_t timestamp_us, const SessionStats& session_stats,
     const MediaInfo& media_info, RTCStatsReport* report) const {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(network_thread_->IsCurrent());
 
   // Audio
   if (media_info.voice) {
@@ -788,11 +799,11 @@
   }
 }
 
-void RTCStatsCollector::ProduceTransportStats_s(
+void RTCStatsCollector::ProduceTransportStats_n(
     int64_t timestamp_us, const SessionStats& session_stats,
     const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
     RTCStatsReport* report) const {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(network_thread_->IsCurrent());
   for (const auto& transport : session_stats.transport_stats) {
     // Get reference to RTCP channel, if it exists.
     std::string rtcp_transport_stats_id;
@@ -855,9 +866,9 @@
 }
 
 std::map<std::string, RTCStatsCollector::CertificateStatsPair>
-RTCStatsCollector::PrepareTransportCertificateStats(
+RTCStatsCollector::PrepareTransportCertificateStats_n(
     const SessionStats& session_stats) const {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(network_thread_->IsCurrent());
   std::map<std::string, CertificateStatsPair> transport_cert_stats;
   for (const auto& transport_stats : session_stats.transport_stats) {
     CertificateStatsPair certificate_stats_pair;
@@ -880,20 +891,21 @@
   return transport_cert_stats;
 }
 
-RTCStatsCollector::MediaInfo RTCStatsCollector::PrepareMediaInfo(
-    const SessionStats& session_stats) const {
-  MediaInfo media_info;
+std::unique_ptr<RTCStatsCollector::MediaInfo>
+RTCStatsCollector::PrepareMediaInfo_s() const {
+  RTC_DCHECK(signaling_thread_->IsCurrent());
+  std::unique_ptr<MediaInfo> media_info(new MediaInfo());
   if (pc_->session()->voice_channel()) {
     cricket::VoiceMediaInfo voice_media_info;
     if (pc_->session()->voice_channel()->GetStats(&voice_media_info)) {
-      media_info.voice = rtc::Optional<cricket::VoiceMediaInfo>(
+      media_info->voice = rtc::Optional<cricket::VoiceMediaInfo>(
           std::move(voice_media_info));
     }
   }
   if (pc_->session()->video_channel()) {
     cricket::VideoMediaInfo video_media_info;
     if (pc_->session()->video_channel()->GetStats(&video_media_info)) {
-      media_info.video = rtc::Optional<cricket::VideoMediaInfo>(
+      media_info->video = rtc::Optional<cricket::VideoMediaInfo>(
           std::move(video_media_info));
     }
   }