Home | History | Annotate | Download | only in metrics
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define DEBUG false  // STOPSHIP if true
     18 #include "Log.h"
     19 
     20 #include "metrics_manager_util.h"
     21 
     22 #include "../condition/CombinationConditionTracker.h"
     23 #include "../condition/SimpleConditionTracker.h"
     24 #include "../condition/StateTracker.h"
     25 #include "../external/StatsPullerManager.h"
     26 #include "../matchers/CombinationLogMatchingTracker.h"
     27 #include "../matchers/SimpleLogMatchingTracker.h"
     28 #include "../matchers/EventMatcherWizard.h"
     29 #include "../metrics/CountMetricProducer.h"
     30 #include "../metrics/DurationMetricProducer.h"
     31 #include "../metrics/EventMetricProducer.h"
     32 #include "../metrics/GaugeMetricProducer.h"
     33 #include "../metrics/ValueMetricProducer.h"
     34 
     35 #include "stats_util.h"
     36 #include "statslog.h"
     37 
     38 using std::set;
     39 using std::string;
     40 using std::unordered_map;
     41 using std::vector;
     42 
     43 namespace android {
     44 namespace os {
     45 namespace statsd {
     46 
     47 namespace {
     48 
     49 bool hasLeafNode(const FieldMatcher& matcher) {
     50     if (!matcher.has_field()) {
     51         return false;
     52     }
     53     for (int i = 0; i < matcher.child_size(); ++i) {
     54         if (hasLeafNode(matcher.child(i))) {
     55             return true;
     56         }
     57     }
     58     return true;
     59 }
     60 
     61 }  // namespace
     62 
     63 bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
     64                                  const bool usedForDimension,
     65                                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
     66                                  const unordered_map<int64_t, int>& logTrackerMap,
     67                                  unordered_map<int, std::vector<int>>& trackerToMetricMap,
     68                                  int& logTrackerIndex) {
     69     auto logTrackerIt = logTrackerMap.find(what);
     70     if (logTrackerIt == logTrackerMap.end()) {
     71         ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)what);
     72         return false;
     73     }
     74     if (usedForDimension && allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
     75         ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
     76               "the \"what\" can only about one atom type.",
     77               (long long)what);
     78         return false;
     79     }
     80     logTrackerIndex = logTrackerIt->second;
     81     auto& metric_list = trackerToMetricMap[logTrackerIndex];
     82     metric_list.push_back(metricIndex);
     83     return true;
     84 }
     85 
     86 bool handlePullMetricTriggerWithLogTrackers(
     87         const int64_t trigger, const int metricIndex,
     88         const vector<sp<LogMatchingTracker>>& allAtomMatchers,
     89         const unordered_map<int64_t, int>& logTrackerMap,
     90         unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
     91     auto logTrackerIt = logTrackerMap.find(trigger);
     92     if (logTrackerIt == logTrackerMap.end()) {
     93         ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)trigger);
     94         return false;
     95     }
     96     if (allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
     97         ALOGE("AtomMatcher \"%lld\" has more than one tag ids."
     98               "Trigger can only be one atom type.",
     99               (long long)trigger);
    100         return false;
    101     }
    102     logTrackerIndex = logTrackerIt->second;
    103     auto& metric_list = trackerToMetricMap[logTrackerIndex];
    104     metric_list.push_back(metricIndex);
    105     return true;
    106 }
    107 
    108 bool handleMetricWithConditions(
    109         const int64_t condition, const int metricIndex,
    110         const unordered_map<int64_t, int>& conditionTrackerMap,
    111         const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
    112                 links,
    113         vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
    114         unordered_map<int, std::vector<int>>& conditionToMetricMap) {
    115     auto condition_it = conditionTrackerMap.find(condition);
    116     if (condition_it == conditionTrackerMap.end()) {
    117         ALOGW("cannot find Predicate \"%lld\" in the config", (long long)condition);
    118         return false;
    119     }
    120 
    121     for (const auto& link : links) {
    122         auto it = conditionTrackerMap.find(link.condition());
    123         if (it == conditionTrackerMap.end()) {
    124             ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
    125             return false;
    126         }
    127         allConditionTrackers[condition_it->second]->setSliced(true);
    128         allConditionTrackers[it->second]->setSliced(true);
    129     }
    130     conditionIndex = condition_it->second;
    131 
    132     // will create new vector if not exist before.
    133     auto& metricList = conditionToMetricMap[condition_it->second];
    134     metricList.push_back(metricIndex);
    135     return true;
    136 }
    137 
    138 bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
    139                      unordered_map<int64_t, int>& logTrackerMap,
    140                      vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
    141     vector<AtomMatcher> matcherConfigs;
    142     const int atomMatcherCount = config.atom_matcher_size();
    143     matcherConfigs.reserve(atomMatcherCount);
    144     allAtomMatchers.reserve(atomMatcherCount);
    145 
    146     for (int i = 0; i < atomMatcherCount; i++) {
    147         const AtomMatcher& logMatcher = config.atom_matcher(i);
    148 
    149         int index = allAtomMatchers.size();
    150         switch (logMatcher.contents_case()) {
    151             case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
    152                 allAtomMatchers.push_back(new SimpleLogMatchingTracker(
    153                         logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap));
    154                 break;
    155             case AtomMatcher::ContentsCase::kCombination:
    156                 allAtomMatchers.push_back(
    157                         new CombinationLogMatchingTracker(logMatcher.id(), index));
    158                 break;
    159             default:
    160                 ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
    161                 return false;
    162                 // continue;
    163         }
    164         if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) {
    165             ALOGE("Duplicate AtomMatcher found!");
    166             return false;
    167         }
    168         logTrackerMap[logMatcher.id()] = index;
    169         matcherConfigs.push_back(logMatcher);
    170     }
    171 
    172     vector<bool> stackTracker2(allAtomMatchers.size(), false);
    173     for (auto& matcher : allAtomMatchers) {
    174         if (!matcher->init(matcherConfigs, allAtomMatchers, logTrackerMap, stackTracker2)) {
    175             return false;
    176         }
    177         // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
    178         const set<int>& tagIds = matcher->getAtomIds();
    179         allTagIds.insert(tagIds.begin(), tagIds.end());
    180     }
    181     return true;
    182 }
    183 
    184 /**
    185  * A StateTracker is built from a SimplePredicate which has only "start", and no "stop"
    186  * or "stop_all". The start must be an atom matcher that matches a state atom. It must
    187  * have dimension, the dimension must be the state atom's primary fields plus exclusive state
    188  * field. For example, the StateTracker is used in tracking UidProcessState and ScreenState.
    189  *
    190  */
    191 bool isStateTracker(const SimplePredicate& simplePredicate, vector<Matcher>* primaryKeys) {
    192     // 1. must not have "stop". must have "dimension"
    193     if (!simplePredicate.has_stop() && simplePredicate.has_dimensions()) {
    194         auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(
    195                 simplePredicate.dimensions().field());
    196         // 2. must be based on a state atom.
    197         if (it != android::util::AtomsInfo::kStateAtomsFieldOptions.end()) {
    198             // 3. dimension must be primary fields + state field IN ORDER
    199             size_t expectedDimensionCount = it->second.primaryFields.size() + 1;
    200             vector<Matcher> dimensions;
    201             translateFieldMatcher(simplePredicate.dimensions(), &dimensions);
    202             if (dimensions.size() != expectedDimensionCount) {
    203                 return false;
    204             }
    205             // 3.1 check the primary fields first.
    206             size_t index = 0;
    207             for (const auto& field : it->second.primaryFields) {
    208                 Matcher matcher = getSimpleMatcher(it->first, field);
    209                 if (!(matcher == dimensions[index])) {
    210                     return false;
    211                 }
    212                 primaryKeys->push_back(matcher);
    213                 index++;
    214             }
    215             Matcher stateFieldMatcher =
    216                     getSimpleMatcher(it->first, it->second.exclusiveField);
    217             // 3.2 last dimension should be the exclusive field.
    218             if (!(dimensions.back() == stateFieldMatcher)) {
    219                 return false;
    220             }
    221             return true;
    222         }
    223     }
    224     return false;
    225 }  // namespace statsd
    226 
    227 bool initConditions(const ConfigKey& key, const StatsdConfig& config,
    228                     const unordered_map<int64_t, int>& logTrackerMap,
    229                     unordered_map<int64_t, int>& conditionTrackerMap,
    230                     vector<sp<ConditionTracker>>& allConditionTrackers,
    231                     unordered_map<int, std::vector<int>>& trackerToConditionMap) {
    232     vector<Predicate> conditionConfigs;
    233     const int conditionTrackerCount = config.predicate_size();
    234     conditionConfigs.reserve(conditionTrackerCount);
    235     allConditionTrackers.reserve(conditionTrackerCount);
    236 
    237     for (int i = 0; i < conditionTrackerCount; i++) {
    238         const Predicate& condition = config.predicate(i);
    239         int index = allConditionTrackers.size();
    240         switch (condition.contents_case()) {
    241             case Predicate::ContentsCase::kSimplePredicate: {
    242                 vector<Matcher> primaryKeys;
    243                 if (isStateTracker(condition.simple_predicate(), &primaryKeys)) {
    244                     allConditionTrackers.push_back(new StateTracker(key, condition.id(), index,
    245                                                                     condition.simple_predicate(),
    246                                                                     logTrackerMap, primaryKeys));
    247                 } else {
    248                     allConditionTrackers.push_back(new SimpleConditionTracker(
    249                             key, condition.id(), index, condition.simple_predicate(),
    250                             logTrackerMap));
    251                 }
    252                 break;
    253             }
    254             case Predicate::ContentsCase::kCombination: {
    255                 allConditionTrackers.push_back(
    256                         new CombinationConditionTracker(condition.id(), index));
    257                 break;
    258             }
    259             default:
    260                 ALOGE("Predicate \"%lld\" malformed", (long long)condition.id());
    261                 return false;
    262         }
    263         if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
    264             ALOGE("Duplicate Predicate found!");
    265             return false;
    266         }
    267         conditionTrackerMap[condition.id()] = index;
    268         conditionConfigs.push_back(condition);
    269     }
    270 
    271     vector<bool> stackTracker(allConditionTrackers.size(), false);
    272     for (size_t i = 0; i < allConditionTrackers.size(); i++) {
    273         auto& conditionTracker = allConditionTrackers[i];
    274         if (!conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
    275                                     stackTracker)) {
    276             return false;
    277         }
    278         for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) {
    279             auto& conditionList = trackerToConditionMap[trackerIndex];
    280             conditionList.push_back(i);
    281         }
    282     }
    283     return true;
    284 }
    285 
    286 bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
    287                  const int64_t currentTimeNs, UidMap& uidMap,
    288                  const sp<StatsPullerManager>& pullerManager,
    289                  const unordered_map<int64_t, int>& logTrackerMap,
    290                  const unordered_map<int64_t, int>& conditionTrackerMap,
    291                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
    292                  vector<sp<ConditionTracker>>& allConditionTrackers,
    293                  vector<sp<MetricProducer>>& allMetricProducers,
    294                  unordered_map<int, std::vector<int>>& conditionToMetricMap,
    295                  unordered_map<int, std::vector<int>>& trackerToMetricMap,
    296                  unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
    297     sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
    298     sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchers);
    299     const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
    300                                 config.event_metric_size() + config.value_metric_size();
    301     allMetricProducers.reserve(allMetricsCount);
    302     StatsPullerManager statsPullerManager;
    303 
    304     // Build MetricProducers for each metric defined in config.
    305     // build CountMetricProducer
    306     for (int i = 0; i < config.count_metric_size(); i++) {
    307         const CountMetric& metric = config.count_metric(i);
    308         if (!metric.has_what()) {
    309             ALOGW("cannot find \"what\" in CountMetric \"%lld\"", (long long)metric.id());
    310             return false;
    311         }
    312 
    313         int metricIndex = allMetricProducers.size();
    314         metricMap.insert({metric.id(), metricIndex});
    315         int trackerIndex;
    316         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
    317                                          metric.has_dimensions_in_what(),
    318                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
    319                                          trackerIndex)) {
    320             return false;
    321         }
    322 
    323         int conditionIndex = -1;
    324         if (metric.has_condition()) {
    325             bool good = handleMetricWithConditions(
    326                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    327                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    328             if (!good) {
    329                 return false;
    330             }
    331         } else {
    332             if (metric.links_size() > 0) {
    333                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    334                 return false;
    335             }
    336         }
    337 
    338         sp<MetricProducer> countProducer =
    339                 new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs);
    340         allMetricProducers.push_back(countProducer);
    341     }
    342 
    343     // build DurationMetricProducer
    344     for (int i = 0; i < config.duration_metric_size(); i++) {
    345         int metricIndex = allMetricProducers.size();
    346         const DurationMetric& metric = config.duration_metric(i);
    347         metricMap.insert({metric.id(), metricIndex});
    348 
    349         auto what_it = conditionTrackerMap.find(metric.what());
    350         if (what_it == conditionTrackerMap.end()) {
    351             ALOGE("DurationMetric's \"what\" is invalid");
    352             return false;
    353         }
    354 
    355         const Predicate& durationWhat = config.predicate(what_it->second);
    356 
    357         if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
    358             ALOGE("DurationMetric's \"what\" must be a simple condition");
    359             return false;
    360         }
    361 
    362         const auto& simplePredicate = durationWhat.simple_predicate();
    363 
    364         bool nesting = simplePredicate.count_nesting();
    365 
    366         int trackerIndices[3] = {-1, -1, -1};
    367         if (!simplePredicate.has_start() ||
    368             !handleMetricWithLogTrackers(simplePredicate.start(), metricIndex,
    369                                          metric.has_dimensions_in_what(), allAtomMatchers,
    370                                          logTrackerMap, trackerToMetricMap, trackerIndices[0])) {
    371             ALOGE("Duration metrics must specify a valid the start event matcher");
    372             return false;
    373         }
    374 
    375         if (simplePredicate.has_stop() &&
    376             !handleMetricWithLogTrackers(simplePredicate.stop(), metricIndex,
    377                                          metric.has_dimensions_in_what(), allAtomMatchers,
    378                                          logTrackerMap, trackerToMetricMap, trackerIndices[1])) {
    379             return false;
    380         }
    381 
    382         if (simplePredicate.has_stop_all() &&
    383             !handleMetricWithLogTrackers(simplePredicate.stop_all(), metricIndex,
    384                                          metric.has_dimensions_in_what(), allAtomMatchers,
    385                                          logTrackerMap, trackerToMetricMap, trackerIndices[2])) {
    386             return false;
    387         }
    388 
    389         FieldMatcher internalDimensions = simplePredicate.dimensions();
    390 
    391         int conditionIndex = -1;
    392 
    393         if (metric.has_condition()) {
    394             bool good = handleMetricWithConditions(
    395                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    396                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    397             if (!good) {
    398                 return false;
    399             }
    400         } else {
    401             if (metric.links_size() > 0) {
    402                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    403                 return false;
    404             }
    405         }
    406 
    407         sp<MetricProducer> durationMetric = new DurationMetricProducer(
    408                 key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
    409                 trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs, currentTimeNs);
    410 
    411         allMetricProducers.push_back(durationMetric);
    412     }
    413 
    414     // build EventMetricProducer
    415     for (int i = 0; i < config.event_metric_size(); i++) {
    416         int metricIndex = allMetricProducers.size();
    417         const EventMetric& metric = config.event_metric(i);
    418         metricMap.insert({metric.id(), metricIndex});
    419         if (!metric.has_id() || !metric.has_what()) {
    420             ALOGW("cannot find the metric name or what in config");
    421             return false;
    422         }
    423         int trackerIndex;
    424         if (!handleMetricWithLogTrackers(metric.what(), metricIndex, false, allAtomMatchers,
    425                                          logTrackerMap, trackerToMetricMap, trackerIndex)) {
    426             return false;
    427         }
    428 
    429         int conditionIndex = -1;
    430         if (metric.has_condition()) {
    431             bool good = handleMetricWithConditions(
    432                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    433                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    434             if (!good) {
    435                 return false;
    436             }
    437         } else {
    438             if (metric.links_size() > 0) {
    439                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    440                 return false;
    441             }
    442         }
    443 
    444         sp<MetricProducer> eventMetric =
    445                 new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
    446 
    447         allMetricProducers.push_back(eventMetric);
    448     }
    449 
    450     // build ValueMetricProducer
    451     for (int i = 0; i < config.value_metric_size(); i++) {
    452         const ValueMetric& metric = config.value_metric(i);
    453         if (!metric.has_what()) {
    454             ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
    455             return false;
    456         }
    457         if (!metric.has_value_field()) {
    458             ALOGW("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
    459             return false;
    460         }
    461         std::vector<Matcher> fieldMatchers;
    462         translateFieldMatcher(metric.value_field(), &fieldMatchers);
    463         if (fieldMatchers.size() < 1) {
    464             ALOGW("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
    465             return false;
    466         }
    467 
    468         int metricIndex = allMetricProducers.size();
    469         metricMap.insert({metric.id(), metricIndex});
    470         int trackerIndex;
    471         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
    472                                          metric.has_dimensions_in_what(),
    473                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
    474                                          trackerIndex)) {
    475             return false;
    476         }
    477 
    478         sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
    479         // If it is pulled atom, it should be simple matcher with one tagId.
    480         if (atomMatcher->getAtomIds().size() != 1) {
    481             return false;
    482         }
    483         int atomTagId = *(atomMatcher->getAtomIds().begin());
    484         int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
    485 
    486         int conditionIndex = -1;
    487         if (metric.has_condition()) {
    488             bool good = handleMetricWithConditions(
    489                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    490                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    491             if (!good) {
    492                 return false;
    493             }
    494         } else {
    495             if (metric.links_size() > 0) {
    496                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    497                 return false;
    498             }
    499         }
    500 
    501         sp<MetricProducer> valueProducer = new ValueMetricProducer(
    502                 key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
    503                 timeBaseTimeNs, currentTimeNs, pullerManager);
    504         allMetricProducers.push_back(valueProducer);
    505     }
    506 
    507     // Gauge metrics.
    508     for (int i = 0; i < config.gauge_metric_size(); i++) {
    509         const GaugeMetric& metric = config.gauge_metric(i);
    510         if (!metric.has_what()) {
    511             ALOGW("cannot find \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
    512             return false;
    513         }
    514 
    515         if ((!metric.gauge_fields_filter().has_include_all() ||
    516              (metric.gauge_fields_filter().include_all() == false)) &&
    517             !hasLeafNode(metric.gauge_fields_filter().fields())) {
    518             ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
    519             return false;
    520         }
    521         if ((metric.gauge_fields_filter().has_include_all() &&
    522              metric.gauge_fields_filter().include_all() == true) &&
    523             hasLeafNode(metric.gauge_fields_filter().fields())) {
    524             ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
    525             return false;
    526         }
    527 
    528         int metricIndex = allMetricProducers.size();
    529         metricMap.insert({metric.id(), metricIndex});
    530         int trackerIndex;
    531         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
    532                                          metric.has_dimensions_in_what(),
    533                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
    534                                          trackerIndex)) {
    535             return false;
    536         }
    537 
    538         sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
    539         // For GaugeMetric atom, it should be simple matcher with one tagId.
    540         if (atomMatcher->getAtomIds().size() != 1) {
    541             return false;
    542         }
    543         int atomTagId = *(atomMatcher->getAtomIds().begin());
    544         int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
    545 
    546         int triggerTrackerIndex;
    547         int triggerAtomId = -1;
    548         if (metric.has_trigger_event()) {
    549             if (pullTagId == -1) {
    550                 ALOGW("Pull atom not specified for trigger");
    551                 return false;
    552             }
    553             // event_trigger should be used with FIRST_N_SAMPLES
    554             if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
    555                 return false;
    556             }
    557             if (!handlePullMetricTriggerWithLogTrackers(metric.trigger_event(), metricIndex,
    558                                                         allAtomMatchers, logTrackerMap,
    559                                                         trackerToMetricMap, triggerTrackerIndex)) {
    560                 return false;
    561             }
    562             sp<LogMatchingTracker> triggerAtomMatcher = allAtomMatchers.at(triggerTrackerIndex);
    563             triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
    564         }
    565 
    566         if (!metric.has_trigger_event() && pullTagId != -1 &&
    567             metric.sampling_type() == GaugeMetric::FIRST_N_SAMPLES) {
    568             ALOGW("FIRST_N_SAMPLES is only for pushed event or pull_on_trigger");
    569             return false;
    570         }
    571 
    572         int conditionIndex = -1;
    573         if (metric.has_condition()) {
    574             bool good = handleMetricWithConditions(
    575                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    576                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    577             if (!good) {
    578                 return false;
    579             }
    580         } else {
    581             if (metric.links_size() > 0) {
    582                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    583                 return false;
    584             }
    585         }
    586 
    587         sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
    588                 key, metric, conditionIndex, wizard,
    589                 trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId,
    590                 timeBaseTimeNs, currentTimeNs, pullerManager);
    591         allMetricProducers.push_back(gaugeProducer);
    592     }
    593     for (int i = 0; i < config.no_report_metric_size(); ++i) {
    594         const auto no_report_metric = config.no_report_metric(i);
    595         if (metricMap.find(no_report_metric) == metricMap.end()) {
    596             ALOGW("no_report_metric %lld not exist", no_report_metric);
    597             return false;
    598         }
    599         noReportMetricIds.insert(no_report_metric);
    600     }
    601     for (const auto& it : allMetricProducers) {
    602         uidMap.addListener(it);
    603     }
    604     return true;
    605 }
    606 
    607 bool initAlerts(const StatsdConfig& config,
    608                 const unordered_map<int64_t, int>& metricProducerMap,
    609                 const sp<AlarmMonitor>& anomalyAlarmMonitor,
    610                 vector<sp<MetricProducer>>& allMetricProducers,
    611                 vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
    612     unordered_map<int64_t, int> anomalyTrackerMap;
    613     for (int i = 0; i < config.alert_size(); i++) {
    614         const Alert& alert = config.alert(i);
    615         const auto& itr = metricProducerMap.find(alert.metric_id());
    616         if (itr == metricProducerMap.end()) {
    617             ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
    618                   (long long)alert.metric_id());
    619             return false;
    620         }
    621         if (!alert.has_trigger_if_sum_gt()) {
    622             ALOGW("invalid alert: missing threshold");
    623             return false;
    624         }
    625         if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
    626             ALOGW("invalid alert: threshold=%f num_buckets= %d",
    627                   alert.trigger_if_sum_gt(), alert.num_buckets());
    628             return false;
    629         }
    630         const int metricIndex = itr->second;
    631         sp<MetricProducer> metric = allMetricProducers[metricIndex];
    632         sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
    633         if (anomalyTracker == nullptr) {
    634             // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
    635             return false;
    636         }
    637         anomalyTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
    638         allAnomalyTrackers.push_back(anomalyTracker);
    639     }
    640     for (int i = 0; i < config.subscription_size(); ++i) {
    641         const Subscription& subscription = config.subscription(i);
    642         if (subscription.rule_type() != Subscription::ALERT) {
    643             continue;
    644         }
    645         if (subscription.subscriber_information_case() ==
    646             Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
    647             ALOGW("subscription \"%lld\" has no subscriber info.\"",
    648                 (long long)subscription.id());
    649             return false;
    650         }
    651         const auto& itr = anomalyTrackerMap.find(subscription.rule_id());
    652         if (itr == anomalyTrackerMap.end()) {
    653             ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
    654                 (long long)subscription.id(), (long long)subscription.rule_id());
    655             return false;
    656         }
    657         const int anomalyTrackerIndex = itr->second;
    658         allAnomalyTrackers[anomalyTrackerIndex]->addSubscription(subscription);
    659     }
    660     return true;
    661 }
    662 
    663 bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
    664                 const sp<AlarmMonitor>& periodicAlarmMonitor,
    665                 const int64_t timeBaseNs, const int64_t currentTimeNs,
    666                 vector<sp<AlarmTracker>>& allAlarmTrackers) {
    667     unordered_map<int64_t, int> alarmTrackerMap;
    668     int64_t startMillis = timeBaseNs / 1000 / 1000;
    669     int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
    670     for (int i = 0; i < config.alarm_size(); i++) {
    671         const Alarm& alarm = config.alarm(i);
    672         if (alarm.offset_millis() <= 0) {
    673             ALOGW("Alarm offset_millis should be larger than 0.");
    674             return false;
    675         }
    676         if (alarm.period_millis() <= 0) {
    677             ALOGW("Alarm period_millis should be larger than 0.");
    678             return false;
    679         }
    680         alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
    681         allAlarmTrackers.push_back(
    682             new AlarmTracker(startMillis, currentTimeMillis,
    683                              alarm, key, periodicAlarmMonitor));
    684     }
    685     for (int i = 0; i < config.subscription_size(); ++i) {
    686         const Subscription& subscription = config.subscription(i);
    687         if (subscription.rule_type() != Subscription::ALARM) {
    688             continue;
    689         }
    690         if (subscription.subscriber_information_case() ==
    691             Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
    692             ALOGW("subscription \"%lld\" has no subscriber info.\"",
    693                 (long long)subscription.id());
    694             return false;
    695         }
    696         const auto& itr = alarmTrackerMap.find(subscription.rule_id());
    697         if (itr == alarmTrackerMap.end()) {
    698             ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
    699                 (long long)subscription.id(), (long long)subscription.rule_id());
    700             return false;
    701         }
    702         const int trackerIndex = itr->second;
    703         allAlarmTrackers[trackerIndex]->addSubscription(subscription);
    704     }
    705     return true;
    706 }
    707 
    708 bool initMetricActivations(const ConfigKey& key, const StatsdConfig& config,
    709                            const int64_t currentTimeNs,
    710                            const unordered_map<int64_t, int> &logEventTrackerMap,
    711                            const unordered_map<int64_t, int> &metricProducerMap,
    712                            vector<sp<MetricProducer>>& allMetricProducers,
    713                            unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
    714                            unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
    715                            vector<int>& metricsWithActivation) {
    716     for (int i = 0; i < config.metric_activation_size(); ++i) {
    717         const MetricActivation& metric_activation = config.metric_activation(i);
    718         auto itr = metricProducerMap.find(metric_activation.metric_id());
    719         if (itr == metricProducerMap.end()) {
    720             ALOGE("Metric id not found in metric activation: %lld",
    721                 (long long)metric_activation.metric_id());
    722             return false;
    723         }
    724         const int metricTrackerIndex = itr->second;
    725         if (metricTrackerIndex < 0 || metricTrackerIndex >= (int)allMetricProducers.size()) {
    726             ALOGE("Invalid metric tracker index.");
    727             return false;
    728         }
    729         const sp<MetricProducer>& metric = allMetricProducers[metricTrackerIndex];
    730         metricsWithActivation.push_back(metricTrackerIndex);
    731         for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
    732             const EventActivation& activation = metric_activation.event_activation(j);
    733             auto logTrackerIt = logEventTrackerMap.find(activation.atom_matcher_id());
    734             if (logTrackerIt == logEventTrackerMap.end()) {
    735                 ALOGE("Atom matcher not found for event activation.");
    736                 return false;
    737             }
    738             const int atomMatcherIndex = logTrackerIt->second;
    739             activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(
    740                 metricTrackerIndex);
    741 
    742             ActivationType activationType;
    743             if (activation.has_activation_type()) {
    744                 activationType = activation.activation_type();
    745             } else {
    746                 activationType = metric_activation.activation_type();
    747             }
    748 
    749             if (activation.has_deactivation_atom_matcher_id()) {
    750                 auto deactivationAtomMatcherIt =
    751                         logEventTrackerMap.find(activation.deactivation_atom_matcher_id());
    752                 if (deactivationAtomMatcherIt == logEventTrackerMap.end()) {
    753                     ALOGE("Atom matcher not found for event deactivation.");
    754                     return false;
    755                 }
    756                 const int deactivationMatcherIndex = deactivationAtomMatcherIt->second;
    757                 deactivationAtomTrackerToMetricMap[deactivationMatcherIndex]
    758                         .push_back(metricTrackerIndex);
    759                 metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds(),
    760                                       deactivationMatcherIndex);
    761             } else {
    762                 metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds());
    763             }
    764         }
    765     }
    766     return true;
    767 }
    768 
    769 void prepareFirstBucket(const vector<sp<MetricProducer>>& allMetricProducers) {
    770     for (const auto& metric: allMetricProducers) {
    771         metric->prepareFirstBucket();
    772     }
    773 }
    774 
    775 bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
    776                       const sp<StatsPullerManager>& pullerManager,
    777                       const sp<AlarmMonitor>& anomalyAlarmMonitor,
    778                       const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
    779                       const int64_t currentTimeNs, set<int>& allTagIds,
    780                       vector<sp<LogMatchingTracker>>& allAtomMatchers,
    781                       vector<sp<ConditionTracker>>& allConditionTrackers,
    782                       vector<sp<MetricProducer>>& allMetricProducers,
    783                       vector<sp<AnomalyTracker>>& allAnomalyTrackers,
    784                       vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
    785                       unordered_map<int, std::vector<int>>& conditionToMetricMap,
    786                       unordered_map<int, std::vector<int>>& trackerToMetricMap,
    787                       unordered_map<int, std::vector<int>>& trackerToConditionMap,
    788                       unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
    789                       unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
    790                       vector<int>& metricsWithActivation,
    791                       std::set<int64_t>& noReportMetricIds) {
    792     unordered_map<int64_t, int> logTrackerMap;
    793     unordered_map<int64_t, int> conditionTrackerMap;
    794     unordered_map<int64_t, int> metricProducerMap;
    795 
    796     if (!initLogTrackers(config, uidMap, logTrackerMap, allAtomMatchers, allTagIds)) {
    797         ALOGE("initLogMatchingTrackers failed");
    798         return false;
    799     }
    800     VLOG("initLogMatchingTrackers succeed...");
    801 
    802     if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers,
    803                         trackerToConditionMap)) {
    804         ALOGE("initConditionTrackers failed");
    805         return false;
    806     }
    807 
    808     if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap, pullerManager, logTrackerMap,
    809                      conditionTrackerMap, allAtomMatchers, allConditionTrackers, allMetricProducers,
    810                      conditionToMetricMap, trackerToMetricMap, metricProducerMap,
    811                      noReportMetricIds)) {
    812         ALOGE("initMetricProducers failed");
    813         return false;
    814     }
    815     if (!initAlerts(config, metricProducerMap, anomalyAlarmMonitor, allMetricProducers,
    816                     allAnomalyTrackers)) {
    817         ALOGE("initAlerts failed");
    818         return false;
    819     }
    820     if (!initAlarms(config, key, periodicAlarmMonitor,
    821                     timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
    822         ALOGE("initAlarms failed");
    823         return false;
    824     }
    825     if (!initMetricActivations(key, config, currentTimeNs, logTrackerMap, metricProducerMap,
    826             allMetricProducers, activationAtomTrackerToMetricMap,
    827             deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
    828         ALOGE("initMetricActivations failed");
    829         return false;
    830     }
    831 
    832     prepareFirstBucket(allMetricProducers);
    833 
    834     return true;
    835 }
    836 
    837 }  // namespace statsd
    838 }  // namespace os
    839 }  // namespace android
    840