Add ActivationType to EventActivation

This allows setting one metric with both IMMEDIATE and ACTIVATE_ON_BOOT
EventActivations

Also, if an on-boot Activation that is already active gets another
activation signal, ignore it.

Bug: 128880263
Fixes: 128880263
Test: statsd_test
Change-Id: I8d483882836c9abc184230b4a70d4734d49d93c3
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 2c8382d..0dc597b 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -222,6 +222,8 @@
     FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
+    FRIEND_TEST(StatsLogProcessorTest,
+            TestActivationOnBootMultipleActivationsDifferentActivationTypes);
 
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2);
diff --git a/cmds/statsd/src/active_config_list.proto b/cmds/statsd/src/active_config_list.proto
index 5ce396d..ef8e50b 100644
--- a/cmds/statsd/src/active_config_list.proto
+++ b/cmds/statsd/src/active_config_list.proto
@@ -24,7 +24,7 @@
 message ActiveEventActivation {
     optional int32 atom_matcher_index = 1;
 
-    // TIme left in activation. When this proto is loaded after device boot,
+    // Time left in activation. When this proto is loaded after device boot,
     // the activation should be set to active for this duration.
     optional int64 remaining_ttl_nanos = 2;
 }
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 2e682de..9ad7f09 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -109,8 +109,8 @@
     }
 }
 
-void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds,
-                                   int deactivationTrackerIndex) {
+void MetricProducer::addActivation(int activationTrackerIndex, const ActivationType& activationType,
+        int64_t ttl_seconds, int deactivationTrackerIndex) {
     std::lock_guard<std::mutex> lock(mMutex);
     // When a metric producer does not depend on any activation, its mIsActive is true.
     // Therefore, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
@@ -118,8 +118,8 @@
     if  (mEventActivationMap.empty()) {
         mIsActive = false;
     }
-    std::shared_ptr<Activation> activation = std::make_shared<Activation>();
-    activation->ttl_ns = ttl_seconds * NS_PER_SEC;
+    std::shared_ptr<Activation> activation =
+            std::make_shared<Activation>(activationType, ttl_seconds * NS_PER_SEC);
     mEventActivationMap.emplace(activationTrackerIndex, activation);
     if (-1 != deactivationTrackerIndex) {
         mEventDeactivationMap.emplace(deactivationTrackerIndex, activation);
@@ -131,13 +131,16 @@
     if (it == mEventActivationMap.end()) {
         return;
     }
-    if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT &&
-        it->second->state == ActivationState::kNotActive) {
-        it->second->state = ActivationState::kActiveOnBoot;
+    auto& activation = it->second;
+    if (ACTIVATE_ON_BOOT == activation->activationType) {
+        if (ActivationState::kNotActive == activation->state) {
+            activation->state = ActivationState::kActiveOnBoot;
+        }
+        // If the Activation is already active or set to kActiveOnBoot, do nothing.
         return;
     }
-    it->second->start_ns = elapsedTimestampNs;
-    it->second->state = ActivationState::kActive;
+    activation->start_ns = elapsedTimestampNs;
+    activation->state = ActivationState::kActive;
     mIsActive = true;
 }
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index aa04938..7676f59 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -233,12 +233,8 @@
         return isActiveLocked();
     }
 
-    void addActivation(int activationTrackerIndex, int64_t ttl_seconds,
-                       int deactivationTrackerIndex = -1);
-
-    inline void setActivationType(const MetricActivation::ActivationType& activationType) {
-        mActivationType = activationType;
-    }
+    void addActivation(int activationTrackerIndex, const ActivationType& activationType,
+            int64_t ttl_seconds, int deactivationTrackerIndex = -1);
 
     void prepareFistBucket() {
         std::lock_guard<std::mutex> lock(mMutex);
@@ -386,11 +382,16 @@
     mutable std::mutex mMutex;
 
     struct Activation {
-        Activation() : ttl_ns(0), start_ns(0), state(ActivationState::kNotActive)  {}
+        Activation(const ActivationType& activationType, const int64_t ttlNs)
+            : ttl_ns(ttlNs),
+              start_ns(0),
+              state(ActivationState::kNotActive),
+              activationType(activationType) {}
 
-        int64_t ttl_ns;
+        const int64_t ttl_ns;
         int64_t start_ns;
         ActivationState state;
+        const ActivationType activationType;
     };
     // When the metric producer has multiple activations, these activations are ORed to determine
     // whether the metric producer is ready to generate metrics.
@@ -401,8 +402,6 @@
 
     bool mIsActive;
 
-    MetricActivation::ActivationType mActivationType;
-
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
@@ -411,6 +410,8 @@
     FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
+    FRIEND_TEST(StatsLogProcessorTest,
+            TestActivationOnBootMultipleActivationsDifferentActivationTypes);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index e1a8175..818131e 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -288,6 +288,8 @@
     FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
+    FRIEND_TEST(StatsLogProcessorTest,
+            TestActivationOnBootMultipleActivationsDifferentActivationTypes);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 31b424e..b027fa0 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -727,7 +727,6 @@
             return false;
         }
         const sp<MetricProducer>& metric = allMetricProducers[metricTrackerIndex];
-        metric->setActivationType(metric_activation.activation_type());
         metricsWithActivation.push_back(metricTrackerIndex);
         for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
             const EventActivation& activation = metric_activation.event_activation(j);
@@ -740,6 +739,13 @@
             activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(
                 metricTrackerIndex);
 
+            ActivationType activationType;
+            if (activation.has_activation_type()) {
+                activationType = activation.activation_type();
+            } else {
+                activationType = metric_activation.activation_type();
+            }
+
             if (activation.has_deactivation_atom_matcher_id()) {
                 auto deactivationAtomMatcherIt =
                         logEventTrackerMap.find(activation.deactivation_atom_matcher_id());
@@ -750,10 +756,10 @@
                 const int deactivationMatcherIndex = deactivationAtomMatcherIt->second;
                 deactivationAtomTrackerToMetricMap[deactivationMatcherIndex]
                         .push_back(metricTrackerIndex);
-                metric->addActivation(atomMatcherIndex, activation.ttl_seconds(),
+                metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds(),
                                       deactivationMatcherIndex);
             } else {
-                metric->addActivation(atomMatcherIndex, activation.ttl_seconds());
+                metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds());
             }
         }
     }
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 2260b9b..4e419b6 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -377,21 +377,23 @@
   optional float probability_of_informing = 7 [default = 1.1];
 }
 
+enum ActivationType {
+  ACTIVATION_TYPE_UNKNOWN = 0;
+  ACTIVATE_IMMEDIATELY = 1;
+  ACTIVATE_ON_BOOT = 2;
+}
+
 message EventActivation {
   optional int64 atom_matcher_id = 1;
   optional int64 ttl_seconds = 2;
   optional int64 deactivation_atom_matcher_id = 3;
+  optional ActivationType activation_type = 4;
 }
 
 message MetricActivation {
   optional int64 metric_id = 1;
 
-  enum ActivationType {
-      UNKNOWN = 0;
-      ACTIVATE_IMMEDIATELY = 1;
-      ACTIVATE_ON_BOOT = 2;
-  }
-  optional ActivationType activation_type = 3;
+  optional ActivationType activation_type = 3 [deprecated = true];
 
   repeated EventActivation event_activation = 2;
 }