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