Implementing `ResetToDefault` for sensors.

Here we introduce a new attribute `reset_to_default` which is provided by the caller while invoking ConfigureCollection that resets the sampling interval of the resource for the given identifier (or all depending on the config).

Tested:
 UT

#tlbmc
#tlbmc-hft

PiperOrigin-RevId: 761831503
Change-Id: Ia1eca9ba59aff14fa8c287c94aebafa499f0ce71
diff --git a/tlbmc/collector/collector.h b/tlbmc/collector/collector.h
index c160400..2fc6764 100644
--- a/tlbmc/collector/collector.h
+++ b/tlbmc/collector/collector.h
@@ -29,6 +29,7 @@
     int sampling_interval_ms = INT_MIN;
     // The key of the resource to be collected.
     std::string key;
+    bool reset_to_default = false;  // Reset to default.
   };
   virtual ~Collector() = default;
   virtual nlohmann::json ToJson() const = 0;
diff --git a/tlbmc/collector/sensor_collector.cc b/tlbmc/collector/sensor_collector.cc
index 0de23eb..d004748 100644
--- a/tlbmc/collector/sensor_collector.cc
+++ b/tlbmc/collector/sensor_collector.cc
@@ -44,6 +44,9 @@
 #include "google/protobuf/json/json.h"
 #include "google/protobuf/util/json_util.h"
 
+constexpr absl::Duration kDefaultSensorSamplingInterval =
+    absl::Milliseconds(1000);
+
 namespace milotic_tlbmc {
 
 namespace {
@@ -56,7 +59,7 @@
   absl::flat_hash_map<absl::Duration, std::vector<std::weak_ptr<Sensor>>>
       sensors_by_interval;
   for (const auto& sensor : sensors) {
-    absl::Duration interval = absl::Milliseconds(1000);
+    absl::Duration interval = kDefaultSensorSamplingInterval;
     if (params.override_sensor_sampling_interval_ms.has_value()) {
       LOG(INFO) << "Overriding sensor sampling interval to "
                 << *params.override_sensor_sampling_interval_ms;
@@ -383,42 +386,71 @@
 }
 
 absl::Status SensorCollector::ConfigureCollection(const Config& config) const {
-  // Default behavior is to configure all sensors with the given interval
-  // unless a key is specified.
-  // If the sampling interval is not set, then it's an error as there is no
-  // other configuration requirement for the sensor as of now.
-  if (config.sampling_interval_ms <= 0) {
-    return absl::InvalidArgumentError(absl::StrCat(
-        "Invalid sampling interval: ", config.sampling_interval_ms));
+  // Either sampling interval must be greater than 0 or caller should be
+  // requesting to reset to default. If both are false, then it's an invalid
+  // configuration.
+  if (config.sampling_interval_ms <= 0 && !config.reset_to_default) {
+    return absl::InvalidArgumentError(
+        "Sampling interval must be greater than 0 or reset_to_default must be "
+        "true");
   }
 
-  bool configure_all_sensors = config.key.empty();
-  bool configuration_applied = false;
+  // Get the sampling interval for the sensor.
+  // This is invoked in two scenarios:
+  // 1. We need to extract the sampling interval from the sensor when config
+  //    requires resetting to default.
+  // 2. We need to extract the interval from the configuration ignoring the
+  //    static refresh interval of the sensor. This is the case when we are
+  //    dynamically changing the sampling interval of a sensor.
+  auto get_sampling_interval = [](const std::shared_ptr<Sensor>& sensor,
+                                  const Config& config) {
+    if (config.sampling_interval_ms > 0) {
+      return absl::Milliseconds(config.sampling_interval_ms);
+    }
+    absl::Duration static_refresh_interval = DecodeGoogleApiProto(
+        sensor->GetSensorAttributesStatic().static_refresh_interval());
+    if (static_refresh_interval > absl::ZeroDuration()) {
+      LOG(WARNING) << "Using static refresh interval: "
+                   << static_refresh_interval
+                   << " for sensor: " << sensor->GetKey();
+      return static_refresh_interval;
+    }
+    LOG(WARNING) << "Using default sensor sampling interval: "
+                 << kDefaultSensorSamplingInterval
+                 << " for sensor: " << sensor->GetKey();
+    return kDefaultSensorSamplingInterval;
+  };
+
+  bool any_sensor_configured = false;
   for (const auto& [_, key_to_sensor] : sensor_table_) {
-    if (configure_all_sensors) {
-      // Configure all sensors with the given interval.
-      for (const auto& [key, _] : key_to_sensor) {
+    // If the key is empty, then we need to configure all the sensors in the
+    // board config.
+    if (config.key.empty()) {
+      for (const auto& [key, sensor] : key_to_sensor) {
+        absl::Duration interval = get_sampling_interval(sensor, config);
+        // It's assumed sensor_key_to_task_id always contains the key if it's in
+        // sensor_table_
         thread_manager_->task_scheduler->UpdateTaskPeriod(
-            thread_manager_->sensor_key_to_task_id.find(key)->second,
-            absl::Milliseconds(config.sampling_interval_ms));
+            thread_manager_->sensor_key_to_task_id.at(key), interval);
+        any_sensor_configured = true;
       }
-      continue;
     }
 
+    // If the key is not empty, then we need to configure the sensor with the
+    // given key.
     auto it = key_to_sensor.find(config.key);
-    if (it == key_to_sensor.end()) {
-      return absl::NotFoundError(
-          absl::StrCat("Sensor not found: ", config.key));
+    if (it != key_to_sensor.end()) {
+      thread_manager_->task_scheduler->UpdateTaskPeriod(
+          thread_manager_->sensor_key_to_task_id.at(config.key),
+          get_sampling_interval(it->second, config));
+      any_sensor_configured = true;
+      break;
     }
-    thread_manager_->task_scheduler->UpdateTaskPeriod(
-        thread_manager_->sensor_key_to_task_id.find(config.key)->second,
-        absl::Milliseconds(config.sampling_interval_ms));
-    configuration_applied = true;
   }
-  if (configuration_applied) {
-    return absl::OkStatus();
-  }
-  return absl::NotFoundError("No task found to update.");
+
+  return any_sensor_configured
+             ? absl::OkStatus()
+             : absl::NotFoundError("No sensor found for configuration");
 }
 
 absl::StatusOr<std::unique_ptr<SensorCollector>> SensorCollector::Create(
diff --git a/tlbmc/collector/sensor_collector.h b/tlbmc/collector/sensor_collector.h
index f395a54..357ed3a 100644
--- a/tlbmc/collector/sensor_collector.h
+++ b/tlbmc/collector/sensor_collector.h
@@ -1,6 +1,8 @@
 #ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SENSOR_COLLECTOR_H_
 #define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SENSOR_COLLECTOR_H_
 
+#include <atomic>
+#include <climits>
 #include <cstddef>
 #include <memory>
 #include <optional>