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 "../metrics/CountMetricProducer.h"
     29 #include "../metrics/DurationMetricProducer.h"
     30 #include "../metrics/EventMetricProducer.h"
     31 #include "../metrics/GaugeMetricProducer.h"
     32 #include "../metrics/ValueMetricProducer.h"
     33 
     34 #include "stats_util.h"
     35 #include "statslog.h"
     36 
     37 using std::set;
     38 using std::string;
     39 using std::unordered_map;
     40 using std::vector;
     41 
     42 namespace android {
     43 namespace os {
     44 namespace statsd {
     45 
     46 namespace {
     47 
     48 bool hasLeafNode(const FieldMatcher& matcher) {
     49     if (!matcher.has_field()) {
     50         return false;
     51     }
     52     for (int i = 0; i < matcher.child_size(); ++i) {
     53         if (hasLeafNode(matcher.child(i))) {
     54             return true;
     55         }
     56     }
     57     return true;
     58 }
     59 
     60 }  // namespace
     61 
     62 bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
     63                                  const bool usedForDimension,
     64                                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
     65                                  const unordered_map<int64_t, int>& logTrackerMap,
     66                                  unordered_map<int, std::vector<int>>& trackerToMetricMap,
     67                                  int& logTrackerIndex) {
     68     auto logTrackerIt = logTrackerMap.find(what);
     69     if (logTrackerIt == logTrackerMap.end()) {
     70         ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)what);
     71         return false;
     72     }
     73     if (usedForDimension && allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
     74         ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
     75               "the \"what\" can only about one atom type.",
     76               (long long)what);
     77         return false;
     78     }
     79     logTrackerIndex = logTrackerIt->second;
     80     auto& metric_list = trackerToMetricMap[logTrackerIndex];
     81     metric_list.push_back(metricIndex);
     82     return true;
     83 }
     84 
     85 bool handleMetricWithConditions(
     86         const int64_t condition, const int metricIndex,
     87         const unordered_map<int64_t, int>& conditionTrackerMap,
     88         const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
     89                 links,
     90         vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
     91         unordered_map<int, std::vector<int>>& conditionToMetricMap) {
     92     auto condition_it = conditionTrackerMap.find(condition);
     93     if (condition_it == conditionTrackerMap.end()) {
     94         ALOGW("cannot find Predicate \"%lld\" in the config", (long long)condition);
     95         return false;
     96     }
     97 
     98     for (const auto& link : links) {
     99         auto it = conditionTrackerMap.find(link.condition());
    100         if (it == conditionTrackerMap.end()) {
    101             ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
    102             return false;
    103         }
    104         allConditionTrackers[condition_it->second]->setSliced(true);
    105         allConditionTrackers[it->second]->setSliced(true);
    106         // TODO: We need to verify the link is valid.
    107     }
    108     conditionIndex = condition_it->second;
    109 
    110     // will create new vector if not exist before.
    111     auto& metricList = conditionToMetricMap[condition_it->second];
    112     metricList.push_back(metricIndex);
    113     return true;
    114 }
    115 
    116 bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
    117                      unordered_map<int64_t, int>& logTrackerMap,
    118                      vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
    119     vector<AtomMatcher> matcherConfigs;
    120     const int atomMatcherCount = config.atom_matcher_size();
    121     matcherConfigs.reserve(atomMatcherCount);
    122     allAtomMatchers.reserve(atomMatcherCount);
    123 
    124     for (int i = 0; i < atomMatcherCount; i++) {
    125         const AtomMatcher& logMatcher = config.atom_matcher(i);
    126 
    127         int index = allAtomMatchers.size();
    128         switch (logMatcher.contents_case()) {
    129             case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
    130                 allAtomMatchers.push_back(new SimpleLogMatchingTracker(
    131                         logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap));
    132                 break;
    133             case AtomMatcher::ContentsCase::kCombination:
    134                 allAtomMatchers.push_back(
    135                         new CombinationLogMatchingTracker(logMatcher.id(), index));
    136                 break;
    137             default:
    138                 ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
    139                 return false;
    140                 // continue;
    141         }
    142         if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) {
    143             ALOGE("Duplicate AtomMatcher found!");
    144             return false;
    145         }
    146         logTrackerMap[logMatcher.id()] = index;
    147         matcherConfigs.push_back(logMatcher);
    148     }
    149 
    150     vector<bool> stackTracker2(allAtomMatchers.size(), false);
    151     for (auto& matcher : allAtomMatchers) {
    152         if (!matcher->init(matcherConfigs, allAtomMatchers, logTrackerMap, stackTracker2)) {
    153             return false;
    154         }
    155         // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
    156         const set<int>& tagIds = matcher->getAtomIds();
    157         allTagIds.insert(tagIds.begin(), tagIds.end());
    158     }
    159     return true;
    160 }
    161 
    162 /**
    163  * A StateTracker is built from a SimplePredicate which has only "start", and no "stop"
    164  * or "stop_all". The start must be an atom matcher that matches a state atom. It must
    165  * have dimension, the dimension must be the state atom's primary fields plus exclusive state
    166  * field. For example, the StateTracker is used in tracking UidProcessState and ScreenState.
    167  *
    168  */
    169 bool isStateTracker(const SimplePredicate& simplePredicate, vector<Matcher>* primaryKeys) {
    170     // 1. must not have "stop". must have "dimension"
    171     if (!simplePredicate.has_stop() && simplePredicate.has_dimensions()) {
    172         // TODO: need to check the start atom matcher too.
    173         auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(
    174                 simplePredicate.dimensions().field());
    175         // 2. must be based on a state atom.
    176         if (it != android::util::AtomsInfo::kStateAtomsFieldOptions.end()) {
    177             // 3. dimension must be primary fields + state field IN ORDER
    178             size_t expectedDimensionCount = it->second.primaryFields.size() + 1;
    179             vector<Matcher> dimensions;
    180             translateFieldMatcher(simplePredicate.dimensions(), &dimensions);
    181             if (dimensions.size() != expectedDimensionCount) {
    182                 return false;
    183             }
    184             // 3.1 check the primary fields first.
    185             size_t index = 0;
    186             for (const auto& field : it->second.primaryFields) {
    187                 Matcher matcher = getSimpleMatcher(it->first, field);
    188                 if (!(matcher == dimensions[index])) {
    189                     return false;
    190                 }
    191                 primaryKeys->push_back(matcher);
    192                 index++;
    193             }
    194             Matcher stateFieldMatcher =
    195                     getSimpleMatcher(it->first, it->second.exclusiveField);
    196             // 3.2 last dimension should be the exclusive field.
    197             if (!(dimensions.back() == stateFieldMatcher)) {
    198                 return false;
    199             }
    200             return true;
    201         }
    202     }
    203     return false;
    204 }  // namespace statsd
    205 
    206 bool initConditions(const ConfigKey& key, const StatsdConfig& config,
    207                     const unordered_map<int64_t, int>& logTrackerMap,
    208                     unordered_map<int64_t, int>& conditionTrackerMap,
    209                     vector<sp<ConditionTracker>>& allConditionTrackers,
    210                     unordered_map<int, std::vector<int>>& trackerToConditionMap) {
    211     vector<Predicate> conditionConfigs;
    212     const int conditionTrackerCount = config.predicate_size();
    213     conditionConfigs.reserve(conditionTrackerCount);
    214     allConditionTrackers.reserve(conditionTrackerCount);
    215 
    216     for (int i = 0; i < conditionTrackerCount; i++) {
    217         const Predicate& condition = config.predicate(i);
    218         int index = allConditionTrackers.size();
    219         switch (condition.contents_case()) {
    220             case Predicate::ContentsCase::kSimplePredicate: {
    221                 vector<Matcher> primaryKeys;
    222                 if (isStateTracker(condition.simple_predicate(), &primaryKeys)) {
    223                     allConditionTrackers.push_back(new StateTracker(key, condition.id(), index,
    224                                                                     condition.simple_predicate(),
    225                                                                     logTrackerMap, primaryKeys));
    226                 } else {
    227                     allConditionTrackers.push_back(new SimpleConditionTracker(
    228                             key, condition.id(), index, condition.simple_predicate(),
    229                             logTrackerMap));
    230                 }
    231                 break;
    232             }
    233             case Predicate::ContentsCase::kCombination: {
    234                 allConditionTrackers.push_back(
    235                         new CombinationConditionTracker(condition.id(), index));
    236                 break;
    237             }
    238             default:
    239                 ALOGE("Predicate \"%lld\" malformed", (long long)condition.id());
    240                 return false;
    241         }
    242         if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
    243             ALOGE("Duplicate Predicate found!");
    244             return false;
    245         }
    246         conditionTrackerMap[condition.id()] = index;
    247         conditionConfigs.push_back(condition);
    248     }
    249 
    250     vector<bool> stackTracker(allConditionTrackers.size(), false);
    251     for (size_t i = 0; i < allConditionTrackers.size(); i++) {
    252         auto& conditionTracker = allConditionTrackers[i];
    253         if (!conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
    254                                     stackTracker)) {
    255             return false;
    256         }
    257         for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) {
    258             auto& conditionList = trackerToConditionMap[trackerIndex];
    259             conditionList.push_back(i);
    260         }
    261     }
    262     return true;
    263 }
    264 
    265 bool initMetrics(const ConfigKey& key, const StatsdConfig& config,
    266                  const int64_t timeBaseTimeNs, const int64_t currentTimeNs,
    267                  UidMap& uidMap, const unordered_map<int64_t, int>& logTrackerMap,
    268                  const unordered_map<int64_t, int>& conditionTrackerMap,
    269                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
    270                  vector<sp<ConditionTracker>>& allConditionTrackers,
    271                  vector<sp<MetricProducer>>& allMetricProducers,
    272                  unordered_map<int, std::vector<int>>& conditionToMetricMap,
    273                  unordered_map<int, std::vector<int>>& trackerToMetricMap,
    274                  unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
    275     sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
    276     const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
    277                                 config.event_metric_size() + config.value_metric_size();
    278     allMetricProducers.reserve(allMetricsCount);
    279     StatsPullerManager statsPullerManager;
    280 
    281     // Build MetricProducers for each metric defined in config.
    282     // build CountMetricProducer
    283     for (int i = 0; i < config.count_metric_size(); i++) {
    284         const CountMetric& metric = config.count_metric(i);
    285         if (!metric.has_what()) {
    286             ALOGW("cannot find \"what\" in CountMetric \"%lld\"", (long long)metric.id());
    287             return false;
    288         }
    289 
    290         int metricIndex = allMetricProducers.size();
    291         metricMap.insert({metric.id(), metricIndex});
    292         int trackerIndex;
    293         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
    294                                          metric.has_dimensions_in_what(),
    295                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
    296                                          trackerIndex)) {
    297             return false;
    298         }
    299 
    300         int conditionIndex = -1;
    301         if (metric.has_condition()) {
    302             bool good = handleMetricWithConditions(
    303                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    304                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    305             if (!good) {
    306                 return false;
    307             }
    308         } else {
    309             if (metric.links_size() > 0) {
    310                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    311                 return false;
    312             }
    313         }
    314 
    315         sp<MetricProducer> countProducer =
    316                 new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
    317         allMetricProducers.push_back(countProducer);
    318     }
    319 
    320     // build DurationMetricProducer
    321     for (int i = 0; i < config.duration_metric_size(); i++) {
    322         int metricIndex = allMetricProducers.size();
    323         const DurationMetric& metric = config.duration_metric(i);
    324         metricMap.insert({metric.id(), metricIndex});
    325 
    326         auto what_it = conditionTrackerMap.find(metric.what());
    327         if (what_it == conditionTrackerMap.end()) {
    328             ALOGE("DurationMetric's \"what\" is invalid");
    329             return false;
    330         }
    331 
    332         const Predicate& durationWhat = config.predicate(what_it->second);
    333 
    334         if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
    335             ALOGE("DurationMetric's \"what\" must be a simple condition");
    336             return false;
    337         }
    338 
    339         const auto& simplePredicate = durationWhat.simple_predicate();
    340 
    341         bool nesting = simplePredicate.count_nesting();
    342 
    343         int trackerIndices[3] = {-1, -1, -1};
    344         if (!simplePredicate.has_start() ||
    345             !handleMetricWithLogTrackers(simplePredicate.start(), metricIndex,
    346                                          metric.has_dimensions_in_what(), allAtomMatchers,
    347                                          logTrackerMap, trackerToMetricMap, trackerIndices[0])) {
    348             ALOGE("Duration metrics must specify a valid the start event matcher");
    349             return false;
    350         }
    351 
    352         if (simplePredicate.has_stop() &&
    353             !handleMetricWithLogTrackers(simplePredicate.stop(), metricIndex,
    354                                          metric.has_dimensions_in_what(), allAtomMatchers,
    355                                          logTrackerMap, trackerToMetricMap, trackerIndices[1])) {
    356             return false;
    357         }
    358 
    359         if (simplePredicate.has_stop_all() &&
    360             !handleMetricWithLogTrackers(simplePredicate.stop_all(), metricIndex,
    361                                          metric.has_dimensions_in_what(), allAtomMatchers,
    362                                          logTrackerMap, trackerToMetricMap, trackerIndices[2])) {
    363             return false;
    364         }
    365 
    366         FieldMatcher internalDimensions = simplePredicate.dimensions();
    367 
    368         int conditionIndex = -1;
    369 
    370         if (metric.has_condition()) {
    371             bool good = handleMetricWithConditions(
    372                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    373                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    374             if (!good) {
    375                 return false;
    376             }
    377         } else {
    378             if (metric.links_size() > 0) {
    379                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    380                 return false;
    381             }
    382         }
    383 
    384         sp<MetricProducer> durationMetric = new DurationMetricProducer(
    385                 key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
    386                 trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs);
    387 
    388         allMetricProducers.push_back(durationMetric);
    389     }
    390 
    391     // build EventMetricProducer
    392     for (int i = 0; i < config.event_metric_size(); i++) {
    393         int metricIndex = allMetricProducers.size();
    394         const EventMetric& metric = config.event_metric(i);
    395         metricMap.insert({metric.id(), metricIndex});
    396         if (!metric.has_id() || !metric.has_what()) {
    397             ALOGW("cannot find the metric name or what in config");
    398             return false;
    399         }
    400         int trackerIndex;
    401         if (!handleMetricWithLogTrackers(metric.what(), metricIndex, false, allAtomMatchers,
    402                                          logTrackerMap, trackerToMetricMap, trackerIndex)) {
    403             return false;
    404         }
    405 
    406         int conditionIndex = -1;
    407         if (metric.has_condition()) {
    408             bool good = handleMetricWithConditions(
    409                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    410                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    411             if (!good) {
    412                 return false;
    413             }
    414         } else {
    415             if (metric.links_size() > 0) {
    416                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    417                 return false;
    418             }
    419         }
    420 
    421         sp<MetricProducer> eventMetric =
    422                 new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
    423 
    424         allMetricProducers.push_back(eventMetric);
    425     }
    426 
    427     // build ValueMetricProducer
    428     for (int i = 0; i < config.value_metric_size(); i++) {
    429         const ValueMetric& metric = config.value_metric(i);
    430         if (!metric.has_what()) {
    431             ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
    432             return false;
    433         }
    434 
    435         int metricIndex = allMetricProducers.size();
    436         metricMap.insert({metric.id(), metricIndex});
    437         int trackerIndex;
    438         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
    439                                          metric.has_dimensions_in_what(),
    440                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
    441                                          trackerIndex)) {
    442             return false;
    443         }
    444 
    445         sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
    446         // If it is pulled atom, it should be simple matcher with one tagId.
    447         if (atomMatcher->getAtomIds().size() != 1) {
    448             return false;
    449         }
    450         int atomTagId = *(atomMatcher->getAtomIds().begin());
    451         int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
    452 
    453         int conditionIndex = -1;
    454         if (metric.has_condition()) {
    455             bool good = handleMetricWithConditions(
    456                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    457                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    458             if (!good) {
    459                 return false;
    460             }
    461         } else {
    462             if (metric.links_size() > 0) {
    463                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    464                 return false;
    465             }
    466         }
    467 
    468         sp<MetricProducer> valueProducer = new ValueMetricProducer(key, metric, conditionIndex,
    469                                                                    wizard, pullTagId,
    470                                                                    timeBaseTimeNs, currentTimeNs);
    471         allMetricProducers.push_back(valueProducer);
    472     }
    473 
    474     // Gauge metrics.
    475     for (int i = 0; i < config.gauge_metric_size(); i++) {
    476         const GaugeMetric& metric = config.gauge_metric(i);
    477         if (!metric.has_what()) {
    478             ALOGW("cannot find \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
    479             return false;
    480         }
    481 
    482         if ((!metric.gauge_fields_filter().has_include_all() ||
    483              (metric.gauge_fields_filter().include_all() == false)) &&
    484             !hasLeafNode(metric.gauge_fields_filter().fields())) {
    485             ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
    486             return false;
    487         }
    488         if ((metric.gauge_fields_filter().has_include_all() &&
    489              metric.gauge_fields_filter().include_all() == true) &&
    490             hasLeafNode(metric.gauge_fields_filter().fields())) {
    491             ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
    492             return false;
    493         }
    494 
    495         int metricIndex = allMetricProducers.size();
    496         metricMap.insert({metric.id(), metricIndex});
    497         int trackerIndex;
    498         if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
    499                                          metric.has_dimensions_in_what(),
    500                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
    501                                          trackerIndex)) {
    502             return false;
    503         }
    504 
    505         sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
    506         // If it is pulled atom, it should be simple matcher with one tagId.
    507         if (atomMatcher->getAtomIds().size() != 1) {
    508             return false;
    509         }
    510         int atomTagId = *(atomMatcher->getAtomIds().begin());
    511         int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
    512 
    513         int conditionIndex = -1;
    514         if (metric.has_condition()) {
    515             bool good = handleMetricWithConditions(
    516                     metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
    517                     allConditionTrackers, conditionIndex, conditionToMetricMap);
    518             if (!good) {
    519                 return false;
    520             }
    521         } else {
    522             if (metric.links_size() > 0) {
    523                 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
    524                 return false;
    525             }
    526         }
    527 
    528         sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
    529                 key, metric, conditionIndex, wizard, pullTagId, timeBaseTimeNs, currentTimeNs);
    530         allMetricProducers.push_back(gaugeProducer);
    531     }
    532     for (int i = 0; i < config.no_report_metric_size(); ++i) {
    533         const auto no_report_metric = config.no_report_metric(i);
    534         if (metricMap.find(no_report_metric) == metricMap.end()) {
    535             ALOGW("no_report_metric %lld not exist", no_report_metric);
    536             return false;
    537         }
    538         noReportMetricIds.insert(no_report_metric);
    539     }
    540     for (auto it : allMetricProducers) {
    541         uidMap.addListener(it);
    542     }
    543     return true;
    544 }
    545 
    546 bool initAlerts(const StatsdConfig& config,
    547                 const unordered_map<int64_t, int>& metricProducerMap,
    548                 const sp<AlarmMonitor>& anomalyAlarmMonitor,
    549                 vector<sp<MetricProducer>>& allMetricProducers,
    550                 vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
    551     unordered_map<int64_t, int> anomalyTrackerMap;
    552     for (int i = 0; i < config.alert_size(); i++) {
    553         const Alert& alert = config.alert(i);
    554         const auto& itr = metricProducerMap.find(alert.metric_id());
    555         if (itr == metricProducerMap.end()) {
    556             ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
    557                   (long long)alert.metric_id());
    558             return false;
    559         }
    560         if (!alert.has_trigger_if_sum_gt()) {
    561             ALOGW("invalid alert: missing threshold");
    562             return false;
    563         }
    564         if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
    565             ALOGW("invalid alert: threshold=%f num_buckets= %d",
    566                   alert.trigger_if_sum_gt(), alert.num_buckets());
    567             return false;
    568         }
    569         const int metricIndex = itr->second;
    570         sp<MetricProducer> metric = allMetricProducers[metricIndex];
    571         sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
    572         if (anomalyTracker == nullptr) {
    573             // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
    574             return false;
    575         }
    576         anomalyTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
    577         allAnomalyTrackers.push_back(anomalyTracker);
    578     }
    579     for (int i = 0; i < config.subscription_size(); ++i) {
    580         const Subscription& subscription = config.subscription(i);
    581         if (subscription.rule_type() != Subscription::ALERT) {
    582             continue;
    583         }
    584         if (subscription.subscriber_information_case() ==
    585             Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
    586             ALOGW("subscription \"%lld\" has no subscriber info.\"",
    587                 (long long)subscription.id());
    588             return false;
    589         }
    590         const auto& itr = anomalyTrackerMap.find(subscription.rule_id());
    591         if (itr == anomalyTrackerMap.end()) {
    592             ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
    593                 (long long)subscription.id(), (long long)subscription.rule_id());
    594             return false;
    595         }
    596         const int anomalyTrackerIndex = itr->second;
    597         allAnomalyTrackers[anomalyTrackerIndex]->addSubscription(subscription);
    598     }
    599     return true;
    600 }
    601 
    602 bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
    603                 const sp<AlarmMonitor>& periodicAlarmMonitor,
    604                 const int64_t timeBaseNs, const int64_t currentTimeNs,
    605                 vector<sp<AlarmTracker>>& allAlarmTrackers) {
    606     unordered_map<int64_t, int> alarmTrackerMap;
    607     int64_t startMillis = timeBaseNs / 1000 / 1000;
    608     int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
    609     for (int i = 0; i < config.alarm_size(); i++) {
    610         const Alarm& alarm = config.alarm(i);
    611         if (alarm.offset_millis() <= 0) {
    612             ALOGW("Alarm offset_millis should be larger than 0.");
    613             return false;
    614         }
    615         if (alarm.period_millis() <= 0) {
    616             ALOGW("Alarm period_millis should be larger than 0.");
    617             return false;
    618         }
    619         alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
    620         allAlarmTrackers.push_back(
    621             new AlarmTracker(startMillis, currentTimeMillis,
    622                              alarm, key, periodicAlarmMonitor));
    623     }
    624     for (int i = 0; i < config.subscription_size(); ++i) {
    625         const Subscription& subscription = config.subscription(i);
    626         if (subscription.rule_type() != Subscription::ALARM) {
    627             continue;
    628         }
    629         if (subscription.subscriber_information_case() ==
    630             Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
    631             ALOGW("subscription \"%lld\" has no subscriber info.\"",
    632                 (long long)subscription.id());
    633             return false;
    634         }
    635         const auto& itr = alarmTrackerMap.find(subscription.rule_id());
    636         if (itr == alarmTrackerMap.end()) {
    637             ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
    638                 (long long)subscription.id(), (long long)subscription.rule_id());
    639             return false;
    640         }
    641         const int trackerIndex = itr->second;
    642         allAlarmTrackers[trackerIndex]->addSubscription(subscription);
    643     }
    644     return true;
    645 }
    646 
    647 bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
    648                       const sp<AlarmMonitor>& anomalyAlarmMonitor,
    649                       const sp<AlarmMonitor>& periodicAlarmMonitor,
    650                       const int64_t timeBaseNs, const int64_t currentTimeNs,
    651                       set<int>& allTagIds,
    652                       vector<sp<LogMatchingTracker>>& allAtomMatchers,
    653                       vector<sp<ConditionTracker>>& allConditionTrackers,
    654                       vector<sp<MetricProducer>>& allMetricProducers,
    655                       vector<sp<AnomalyTracker>>& allAnomalyTrackers,
    656                       vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
    657                       unordered_map<int, std::vector<int>>& conditionToMetricMap,
    658                       unordered_map<int, std::vector<int>>& trackerToMetricMap,
    659                       unordered_map<int, std::vector<int>>& trackerToConditionMap,
    660                       std::set<int64_t>& noReportMetricIds) {
    661     unordered_map<int64_t, int> logTrackerMap;
    662     unordered_map<int64_t, int> conditionTrackerMap;
    663     unordered_map<int64_t, int> metricProducerMap;
    664 
    665     if (!initLogTrackers(config, uidMap, logTrackerMap, allAtomMatchers, allTagIds)) {
    666         ALOGE("initLogMatchingTrackers failed");
    667         return false;
    668     }
    669     VLOG("initLogMatchingTrackers succeed...");
    670 
    671     if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers,
    672                         trackerToConditionMap)) {
    673         ALOGE("initConditionTrackers failed");
    674         return false;
    675     }
    676 
    677     if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap,
    678                      logTrackerMap, conditionTrackerMap,
    679                      allAtomMatchers, allConditionTrackers, allMetricProducers,
    680                      conditionToMetricMap, trackerToMetricMap, metricProducerMap,
    681                      noReportMetricIds)) {
    682         ALOGE("initMetricProducers failed");
    683         return false;
    684     }
    685     if (!initAlerts(config, metricProducerMap, anomalyAlarmMonitor, allMetricProducers,
    686                     allAnomalyTrackers)) {
    687         ALOGE("initAlerts failed");
    688         return false;
    689     }
    690     if (!initAlarms(config, key, periodicAlarmMonitor,
    691                     timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
    692         ALOGE("initAlarms failed");
    693         return false;
    694     }
    695 
    696     return true;
    697 }
    698 
    699 }  // namespace statsd
    700 }  // namespace os
    701 }  // namespace android
    702