Setup all registered datasources on config change

A producer can have multiple datasources with the same name registered.
This CL makes sure all of them are correctly set up and started after
a config change (previously only the first one was set up).

Bug: crbug.com/1465310
Change-Id: I25de24879106e1412ef537cd008aa3ad7397c1e6
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 154b931..fe593e3 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -1120,6 +1120,14 @@
     *cfg_data_source.mutable_producer_name_regex_filter() =
         new_producer_name_regex_filter;
 
+    // Get the list of producers that are already set up.
+    std::unordered_set<uint16_t> set_up_producers;
+    auto& ds_instances = tracing_session->data_source_instances;
+    for (auto instance_it = ds_instances.begin();
+         instance_it != ds_instances.end(); ++instance_it) {
+      set_up_producers.insert(instance_it->first);
+    }
+
     // Scan all the registered data sources with a matching name.
     auto range = data_sources_.equal_range(cfg_data_source.config().name());
     for (auto it = range.first; it != range.second; it++) {
@@ -1134,19 +1142,9 @@
         continue;
       }
 
-      bool already_setup = false;
-      auto& ds_instances = tracing_session->data_source_instances;
-      for (auto instance_it = ds_instances.begin();
-           instance_it != ds_instances.end(); ++instance_it) {
-        if (instance_it->first == it->second.producer_id &&
-            instance_it->second.data_source_name ==
-                cfg_data_source.config().name()) {
-          already_setup = true;
-          break;
-        }
-      }
-
-      if (already_setup)
+      // If this producer is already set up, we assume that all datasources
+      // in it started already.
+      if (set_up_producers.count(it->second.producer_id))
         continue;
 
       // If it wasn't previously setup, set it up now.
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index 3eb3671..6262db6 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -1606,6 +1606,62 @@
   Mock::VerifyAndClearExpectations(producer3.get());
 }
 
+TEST_F(TracingServiceImplTest, ProducerNameFilterChangeTwoDataSources) {
+  std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
+  consumer->Connect(svc.get());
+
+  std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
+  producer1->Connect(svc.get(), "mock_producer_1");
+  producer1->RegisterDataSource("data_source");
+
+  std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
+  producer2->Connect(svc.get(), "mock_producer_2");
+  producer2->RegisterDataSource("data_source");
+  producer2->RegisterDataSource("data_source");
+
+  TraceConfig trace_config;
+  trace_config.add_buffers()->set_size_kb(128);
+  auto* data_source = trace_config.add_data_sources();
+  data_source->mutable_config()->set_name("data_source");
+  *data_source->add_producer_name_filter() = "mock_producer_1";
+
+  // Enable tracing with only mock_producer_1 enabled;
+  // the rest should not start up.
+  consumer->EnableTracing(trace_config);
+
+  producer1->WaitForTracingSetup();
+  EXPECT_CALL(*producer1, SetupDataSource(_, _)).Times(1);
+  EXPECT_CALL(*producer1, StartDataSource(_, _)).Times(1);
+
+  task_runner.RunUntilIdle();
+  Mock::VerifyAndClearExpectations(producer1.get());
+  Mock::VerifyAndClearExpectations(producer2.get());
+
+  // Enable mock_producer_2, both instances of "data_source" should start
+  *data_source->add_producer_name_regex_filter() = ".*_producer_[2]";
+  consumer->ChangeTraceConfig(trace_config);
+
+  producer2->WaitForTracingSetup();
+  EXPECT_CALL(*producer2, SetupDataSource(_, _)).Times(2);
+  EXPECT_CALL(*producer2, StartDataSource(_, _)).Times(2);
+
+  task_runner.RunUntilIdle();
+  Mock::VerifyAndClearExpectations(producer1.get());
+  Mock::VerifyAndClearExpectations(producer2.get());
+
+  consumer->DisableTracing();
+  consumer->FreeBuffers();
+
+  EXPECT_CALL(*producer1, StopDataSource(_)).Times(1);
+  EXPECT_CALL(*producer2, StopDataSource(_)).Times(2);
+
+  consumer->WaitForTracingDisabled();
+
+  task_runner.RunUntilIdle();
+  Mock::VerifyAndClearExpectations(producer1.get());
+  Mock::VerifyAndClearExpectations(producer2.get());
+}
+
 TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
   std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
   consumer->Connect(svc.get());