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