1 /* 2 * Copyright 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 #define DEBUG false // STOPSHIP if true 17 #include "Log.h" 18 19 #include "StatsdStats.h" 20 21 #include <android/util/ProtoOutputStream.h> 22 #include "../stats_log_util.h" 23 #include "statslog.h" 24 #include "storage/StorageManager.h" 25 26 namespace android { 27 namespace os { 28 namespace statsd { 29 30 using android::util::FIELD_COUNT_REPEATED; 31 using android::util::FIELD_TYPE_BOOL; 32 using android::util::FIELD_TYPE_FLOAT; 33 using android::util::FIELD_TYPE_INT32; 34 using android::util::FIELD_TYPE_INT64; 35 using android::util::FIELD_TYPE_MESSAGE; 36 using android::util::FIELD_TYPE_STRING; 37 using android::util::ProtoOutputStream; 38 using std::lock_guard; 39 using std::map; 40 using std::shared_ptr; 41 using std::string; 42 using std::vector; 43 44 const int FIELD_ID_BEGIN_TIME = 1; 45 const int FIELD_ID_END_TIME = 2; 46 const int FIELD_ID_CONFIG_STATS = 3; 47 const int FIELD_ID_ATOM_STATS = 7; 48 const int FIELD_ID_UIDMAP_STATS = 8; 49 const int FIELD_ID_ANOMALY_ALARM_STATS = 9; 50 const int FIELD_ID_PERIODIC_ALARM_STATS = 12; 51 const int FIELD_ID_SYSTEM_SERVER_RESTART = 15; 52 const int FIELD_ID_LOGGER_ERROR_STATS = 16; 53 const int FIELD_ID_OVERFLOW = 18; 54 const int FIELD_ID_ACTIVATION_BROADCAST_GUARDRAIL = 19; 55 56 const int FIELD_ID_ATOM_STATS_TAG = 1; 57 const int FIELD_ID_ATOM_STATS_COUNT = 2; 58 59 const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1; 60 const int FIELD_ID_PERIODIC_ALARMS_REGISTERED = 1; 61 62 const int FIELD_ID_LOG_LOSS_STATS_TIME = 1; 63 const int FIELD_ID_LOG_LOSS_STATS_COUNT = 2; 64 const int FIELD_ID_LOG_LOSS_STATS_ERROR = 3; 65 const int FIELD_ID_LOG_LOSS_STATS_TAG = 4; 66 const int FIELD_ID_LOG_LOSS_STATS_UID = 5; 67 const int FIELD_ID_LOG_LOSS_STATS_PID = 6; 68 69 const int FIELD_ID_OVERFLOW_COUNT = 1; 70 const int FIELD_ID_OVERFLOW_MAX_HISTORY = 2; 71 const int FIELD_ID_OVERFLOW_MIN_HISTORY = 3; 72 73 const int FIELD_ID_CONFIG_STATS_UID = 1; 74 const int FIELD_ID_CONFIG_STATS_ID = 2; 75 const int FIELD_ID_CONFIG_STATS_CREATION = 3; 76 const int FIELD_ID_CONFIG_STATS_RESET = 19; 77 const int FIELD_ID_CONFIG_STATS_DELETION = 4; 78 const int FIELD_ID_CONFIG_STATS_METRIC_COUNT = 5; 79 const int FIELD_ID_CONFIG_STATS_CONDITION_COUNT = 6; 80 const int FIELD_ID_CONFIG_STATS_MATCHER_COUNT = 7; 81 const int FIELD_ID_CONFIG_STATS_ALERT_COUNT = 8; 82 const int FIELD_ID_CONFIG_STATS_VALID = 9; 83 const int FIELD_ID_CONFIG_STATS_BROADCAST = 10; 84 const int FIELD_ID_CONFIG_STATS_DATA_DROP_TIME = 11; 85 const int FIELD_ID_CONFIG_STATS_DATA_DROP_BYTES = 21; 86 const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME = 12; 87 const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES = 20; 88 const int FIELD_ID_CONFIG_STATS_MATCHER_STATS = 13; 89 const int FIELD_ID_CONFIG_STATS_CONDITION_STATS = 14; 90 const int FIELD_ID_CONFIG_STATS_METRIC_STATS = 15; 91 const int FIELD_ID_CONFIG_STATS_ALERT_STATS = 16; 92 const int FIELD_ID_CONFIG_STATS_METRIC_DIMENSION_IN_CONDITION_STATS = 17; 93 const int FIELD_ID_CONFIG_STATS_ANNOTATION = 18; 94 const int FIELD_ID_CONFIG_STATS_ACTIVATION = 22; 95 const int FIELD_ID_CONFIG_STATS_DEACTIVATION = 23; 96 const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT64 = 1; 97 const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT32 = 2; 98 99 const int FIELD_ID_MATCHER_STATS_ID = 1; 100 const int FIELD_ID_MATCHER_STATS_COUNT = 2; 101 const int FIELD_ID_CONDITION_STATS_ID = 1; 102 const int FIELD_ID_CONDITION_STATS_COUNT = 2; 103 const int FIELD_ID_METRIC_STATS_ID = 1; 104 const int FIELD_ID_METRIC_STATS_COUNT = 2; 105 const int FIELD_ID_ALERT_STATS_ID = 1; 106 const int FIELD_ID_ALERT_STATS_COUNT = 2; 107 108 const int FIELD_ID_UID_MAP_CHANGES = 1; 109 const int FIELD_ID_UID_MAP_BYTES_USED = 2; 110 const int FIELD_ID_UID_MAP_DROPPED_CHANGES = 3; 111 const int FIELD_ID_UID_MAP_DELETED_APPS = 4; 112 113 const int FIELD_ID_ACTIVATION_BROADCAST_GUARDRAIL_UID = 1; 114 const int FIELD_ID_ACTIVATION_BROADCAST_GUARDRAIL_TIME = 2; 115 116 const std::map<int, std::pair<size_t, size_t>> StatsdStats::kAtomDimensionKeySizeLimitMap = { 117 {android::util::BINDER_CALLS, {6000, 10000}}, 118 {android::util::LOOPER_STATS, {1500, 2500}}, 119 {android::util::CPU_TIME_PER_UID_FREQ, {6000, 10000}}, 120 }; 121 122 StatsdStats::StatsdStats() { 123 mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1); 124 mStartTimeSec = getWallClockSec(); 125 } 126 127 StatsdStats& StatsdStats::getInstance() { 128 static StatsdStats statsInstance; 129 return statsInstance; 130 } 131 132 void StatsdStats::addToIceBoxLocked(shared_ptr<ConfigStats>& stats) { 133 // The size of mIceBox grows strictly by one at a time. It won't be > kMaxIceBoxSize. 134 if (mIceBox.size() == kMaxIceBoxSize) { 135 mIceBox.pop_front(); 136 } 137 mIceBox.push_back(stats); 138 } 139 140 void StatsdStats::noteConfigReceived( 141 const ConfigKey& key, int metricsCount, int conditionsCount, int matchersCount, 142 int alertsCount, const std::list<std::pair<const int64_t, const int32_t>>& annotations, 143 bool isValid) { 144 lock_guard<std::mutex> lock(mLock); 145 int32_t nowTimeSec = getWallClockSec(); 146 147 // If there is an existing config for the same key, icebox the old config. 148 noteConfigRemovedInternalLocked(key); 149 150 shared_ptr<ConfigStats> configStats = std::make_shared<ConfigStats>(); 151 configStats->uid = key.GetUid(); 152 configStats->id = key.GetId(); 153 configStats->creation_time_sec = nowTimeSec; 154 configStats->metric_count = metricsCount; 155 configStats->condition_count = conditionsCount; 156 configStats->matcher_count = matchersCount; 157 configStats->alert_count = alertsCount; 158 configStats->is_valid = isValid; 159 for (auto& v : annotations) { 160 configStats->annotations.emplace_back(v); 161 } 162 163 if (isValid) { 164 mConfigStats[key] = configStats; 165 } else { 166 configStats->deletion_time_sec = nowTimeSec; 167 addToIceBoxLocked(configStats); 168 } 169 } 170 171 void StatsdStats::noteConfigRemovedInternalLocked(const ConfigKey& key) { 172 auto it = mConfigStats.find(key); 173 if (it != mConfigStats.end()) { 174 int32_t nowTimeSec = getWallClockSec(); 175 it->second->deletion_time_sec = nowTimeSec; 176 addToIceBoxLocked(it->second); 177 mConfigStats.erase(it); 178 } 179 } 180 181 void StatsdStats::noteConfigRemoved(const ConfigKey& key) { 182 lock_guard<std::mutex> lock(mLock); 183 noteConfigRemovedInternalLocked(key); 184 } 185 186 void StatsdStats::noteConfigResetInternalLocked(const ConfigKey& key) { 187 auto it = mConfigStats.find(key); 188 if (it != mConfigStats.end()) { 189 it->second->reset_time_sec = getWallClockSec(); 190 } 191 } 192 193 void StatsdStats::noteConfigReset(const ConfigKey& key) { 194 lock_guard<std::mutex> lock(mLock); 195 noteConfigResetInternalLocked(key); 196 } 197 198 void StatsdStats::noteLogLost(int32_t wallClockTimeSec, int32_t count, int32_t lastError, 199 int32_t lastTag, int32_t uid, int32_t pid) { 200 lock_guard<std::mutex> lock(mLock); 201 if (mLogLossStats.size() == kMaxLoggerErrors) { 202 mLogLossStats.pop_front(); 203 } 204 mLogLossStats.emplace_back(wallClockTimeSec, count, lastError, lastTag, uid, pid); 205 } 206 207 void StatsdStats::noteBroadcastSent(const ConfigKey& key) { 208 noteBroadcastSent(key, getWallClockSec()); 209 } 210 211 void StatsdStats::noteBroadcastSent(const ConfigKey& key, int32_t timeSec) { 212 lock_guard<std::mutex> lock(mLock); 213 auto it = mConfigStats.find(key); 214 if (it == mConfigStats.end()) { 215 ALOGE("Config key %s not found!", key.ToString().c_str()); 216 return; 217 } 218 if (it->second->broadcast_sent_time_sec.size() == kMaxTimestampCount) { 219 it->second->broadcast_sent_time_sec.pop_front(); 220 } 221 it->second->broadcast_sent_time_sec.push_back(timeSec); 222 } 223 224 void StatsdStats::noteActiveStatusChanged(const ConfigKey& key, bool activated) { 225 noteActiveStatusChanged(key, activated, getWallClockSec()); 226 } 227 228 void StatsdStats::noteActiveStatusChanged(const ConfigKey& key, bool activated, int32_t timeSec) { 229 lock_guard<std::mutex> lock(mLock); 230 auto it = mConfigStats.find(key); 231 if (it == mConfigStats.end()) { 232 ALOGE("Config key %s not found!", key.ToString().c_str()); 233 return; 234 } 235 auto& vec = activated ? it->second->activation_time_sec 236 : it->second->deactivation_time_sec; 237 if (vec.size() == kMaxTimestampCount) { 238 vec.pop_front(); 239 } 240 vec.push_back(timeSec); 241 } 242 243 void StatsdStats::noteActivationBroadcastGuardrailHit(const int uid) { 244 noteActivationBroadcastGuardrailHit(uid, getWallClockSec()); 245 } 246 247 void StatsdStats::noteActivationBroadcastGuardrailHit(const int uid, const int32_t timeSec) { 248 lock_guard<std::mutex> lock(mLock); 249 auto& guardrailTimes = mActivationBroadcastGuardrailStats[uid]; 250 if (guardrailTimes.size() == kMaxTimestampCount) { 251 guardrailTimes.pop_front(); 252 } 253 guardrailTimes.push_back(timeSec); 254 } 255 256 void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes) { 257 noteDataDropped(key, totalBytes, getWallClockSec()); 258 } 259 260 void StatsdStats::noteEventQueueOverflow(int64_t oldestEventTimestampNs) { 261 lock_guard<std::mutex> lock(mLock); 262 263 mOverflowCount++; 264 265 int64_t history = getElapsedRealtimeNs() - oldestEventTimestampNs; 266 267 if (history > mMaxQueueHistoryNs) { 268 mMaxQueueHistoryNs = history; 269 } 270 271 if (history < mMinQueueHistoryNs) { 272 mMinQueueHistoryNs = history; 273 } 274 } 275 276 void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes, int32_t timeSec) { 277 lock_guard<std::mutex> lock(mLock); 278 auto it = mConfigStats.find(key); 279 if (it == mConfigStats.end()) { 280 ALOGE("Config key %s not found!", key.ToString().c_str()); 281 return; 282 } 283 if (it->second->data_drop_time_sec.size() == kMaxTimestampCount) { 284 it->second->data_drop_time_sec.pop_front(); 285 it->second->data_drop_bytes.pop_front(); 286 } 287 it->second->data_drop_time_sec.push_back(timeSec); 288 it->second->data_drop_bytes.push_back(totalBytes); 289 } 290 291 void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes) { 292 noteMetricsReportSent(key, num_bytes, getWallClockSec()); 293 } 294 295 void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes, 296 int32_t timeSec) { 297 lock_guard<std::mutex> lock(mLock); 298 auto it = mConfigStats.find(key); 299 if (it == mConfigStats.end()) { 300 ALOGE("Config key %s not found!", key.ToString().c_str()); 301 return; 302 } 303 if (it->second->dump_report_stats.size() == kMaxTimestampCount) { 304 it->second->dump_report_stats.pop_front(); 305 } 306 it->second->dump_report_stats.push_back(std::make_pair(timeSec, num_bytes)); 307 } 308 309 void StatsdStats::noteUidMapDropped(int deltas) { 310 lock_guard<std::mutex> lock(mLock); 311 mUidMapStats.dropped_changes += mUidMapStats.dropped_changes + deltas; 312 } 313 314 void StatsdStats::noteUidMapAppDeletionDropped() { 315 lock_guard<std::mutex> lock(mLock); 316 mUidMapStats.deleted_apps++; 317 } 318 319 void StatsdStats::setUidMapChanges(int changes) { 320 lock_guard<std::mutex> lock(mLock); 321 mUidMapStats.changes = changes; 322 } 323 324 void StatsdStats::setCurrentUidMapMemory(int bytes) { 325 lock_guard<std::mutex> lock(mLock); 326 mUidMapStats.bytes_used = bytes; 327 } 328 329 void StatsdStats::noteConditionDimensionSize(const ConfigKey& key, const int64_t& id, int size) { 330 lock_guard<std::mutex> lock(mLock); 331 // if name doesn't exist before, it will create the key with count 0. 332 auto statsIt = mConfigStats.find(key); 333 if (statsIt == mConfigStats.end()) { 334 return; 335 } 336 337 auto& conditionSizeMap = statsIt->second->condition_stats; 338 if (size > conditionSizeMap[id]) { 339 conditionSizeMap[id] = size; 340 } 341 } 342 343 void StatsdStats::noteMetricDimensionSize(const ConfigKey& key, const int64_t& id, int size) { 344 lock_guard<std::mutex> lock(mLock); 345 // if name doesn't exist before, it will create the key with count 0. 346 auto statsIt = mConfigStats.find(key); 347 if (statsIt == mConfigStats.end()) { 348 return; 349 } 350 auto& metricsDimensionMap = statsIt->second->metric_stats; 351 if (size > metricsDimensionMap[id]) { 352 metricsDimensionMap[id] = size; 353 } 354 } 355 356 void StatsdStats::noteMetricDimensionInConditionSize( 357 const ConfigKey& key, const int64_t& id, int size) { 358 lock_guard<std::mutex> lock(mLock); 359 // if name doesn't exist before, it will create the key with count 0. 360 auto statsIt = mConfigStats.find(key); 361 if (statsIt == mConfigStats.end()) { 362 return; 363 } 364 auto& metricsDimensionMap = statsIt->second->metric_dimension_in_condition_stats; 365 if (size > metricsDimensionMap[id]) { 366 metricsDimensionMap[id] = size; 367 } 368 } 369 370 void StatsdStats::noteMatcherMatched(const ConfigKey& key, const int64_t& id) { 371 lock_guard<std::mutex> lock(mLock); 372 373 auto statsIt = mConfigStats.find(key); 374 if (statsIt == mConfigStats.end()) { 375 return; 376 } 377 statsIt->second->matcher_stats[id]++; 378 } 379 380 void StatsdStats::noteAnomalyDeclared(const ConfigKey& key, const int64_t& id) { 381 lock_guard<std::mutex> lock(mLock); 382 auto statsIt = mConfigStats.find(key); 383 if (statsIt == mConfigStats.end()) { 384 return; 385 } 386 statsIt->second->alert_stats[id]++; 387 } 388 389 void StatsdStats::noteRegisteredAnomalyAlarmChanged() { 390 lock_guard<std::mutex> lock(mLock); 391 mAnomalyAlarmRegisteredStats++; 392 } 393 394 void StatsdStats::noteRegisteredPeriodicAlarmChanged() { 395 lock_guard<std::mutex> lock(mLock); 396 mPeriodicAlarmRegisteredStats++; 397 } 398 399 void StatsdStats::updateMinPullIntervalSec(int pullAtomId, long intervalSec) { 400 lock_guard<std::mutex> lock(mLock); 401 mPulledAtomStats[pullAtomId].minPullIntervalSec = 402 std::min(mPulledAtomStats[pullAtomId].minPullIntervalSec, intervalSec); 403 } 404 405 void StatsdStats::notePull(int pullAtomId) { 406 lock_guard<std::mutex> lock(mLock); 407 mPulledAtomStats[pullAtomId].totalPull++; 408 } 409 410 void StatsdStats::notePullFromCache(int pullAtomId) { 411 lock_guard<std::mutex> lock(mLock); 412 mPulledAtomStats[pullAtomId].totalPullFromCache++; 413 } 414 415 void StatsdStats::notePullTime(int pullAtomId, int64_t pullTimeNs) { 416 lock_guard<std::mutex> lock(mLock); 417 auto& pullStats = mPulledAtomStats[pullAtomId]; 418 pullStats.maxPullTimeNs = std::max(pullStats.maxPullTimeNs, pullTimeNs); 419 pullStats.avgPullTimeNs = (pullStats.avgPullTimeNs * pullStats.numPullTime + pullTimeNs) / 420 (pullStats.numPullTime + 1); 421 pullStats.numPullTime += 1; 422 } 423 424 void StatsdStats::notePullDelay(int pullAtomId, int64_t pullDelayNs) { 425 lock_guard<std::mutex> lock(mLock); 426 auto& pullStats = mPulledAtomStats[pullAtomId]; 427 pullStats.maxPullDelayNs = std::max(pullStats.maxPullDelayNs, pullDelayNs); 428 pullStats.avgPullDelayNs = 429 (pullStats.avgPullDelayNs * pullStats.numPullDelay + pullDelayNs) / 430 (pullStats.numPullDelay + 1); 431 pullStats.numPullDelay += 1; 432 } 433 434 void StatsdStats::notePullDataError(int pullAtomId) { 435 lock_guard<std::mutex> lock(mLock); 436 mPulledAtomStats[pullAtomId].dataError++; 437 } 438 439 void StatsdStats::notePullTimeout(int pullAtomId) { 440 lock_guard<std::mutex> lock(mLock); 441 mPulledAtomStats[pullAtomId].pullTimeout++; 442 } 443 444 void StatsdStats::notePullExceedMaxDelay(int pullAtomId) { 445 lock_guard<std::mutex> lock(mLock); 446 mPulledAtomStats[pullAtomId].pullExceedMaxDelay++; 447 } 448 449 void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) { 450 lock_guard<std::mutex> lock(mLock); 451 452 if (atomId <= android::util::kMaxPushedAtomId) { 453 mPushedAtomStats[atomId]++; 454 } else { 455 if (mNonPlatformPushedAtomStats.size() < kMaxNonPlatformPushedAtoms) { 456 mNonPlatformPushedAtomStats[atomId]++; 457 } 458 } 459 } 460 461 void StatsdStats::noteSystemServerRestart(int32_t timeSec) { 462 lock_guard<std::mutex> lock(mLock); 463 464 if (mSystemServerRestartSec.size() == kMaxSystemServerRestarts) { 465 mSystemServerRestartSec.pop_front(); 466 } 467 mSystemServerRestartSec.push_back(timeSec); 468 } 469 470 void StatsdStats::notePullFailed(int atomId) { 471 lock_guard<std::mutex> lock(mLock); 472 mPulledAtomStats[atomId].pullFailed++; 473 } 474 475 void StatsdStats::noteStatsCompanionPullFailed(int atomId) { 476 lock_guard<std::mutex> lock(mLock); 477 mPulledAtomStats[atomId].statsCompanionPullFailed++; 478 } 479 480 void StatsdStats::noteStatsCompanionPullBinderTransactionFailed(int atomId) { 481 lock_guard<std::mutex> lock(mLock); 482 mPulledAtomStats[atomId].statsCompanionPullBinderTransactionFailed++; 483 } 484 485 void StatsdStats::noteEmptyData(int atomId) { 486 lock_guard<std::mutex> lock(mLock); 487 mPulledAtomStats[atomId].emptyData++; 488 } 489 490 void StatsdStats::notePullerCallbackRegistrationChanged(int atomId, bool registered) { 491 lock_guard<std::mutex> lock(mLock); 492 if (registered) { 493 mPulledAtomStats[atomId].registeredCount++; 494 } else { 495 mPulledAtomStats[atomId].unregisteredCount++; 496 } 497 } 498 499 void StatsdStats::noteHardDimensionLimitReached(int64_t metricId) { 500 lock_guard<std::mutex> lock(mLock); 501 getAtomMetricStats(metricId).hardDimensionLimitReached++; 502 } 503 504 void StatsdStats::noteLateLogEventSkipped(int64_t metricId) { 505 lock_guard<std::mutex> lock(mLock); 506 getAtomMetricStats(metricId).lateLogEventSkipped++; 507 } 508 509 void StatsdStats::noteSkippedForwardBuckets(int64_t metricId) { 510 lock_guard<std::mutex> lock(mLock); 511 getAtomMetricStats(metricId).skippedForwardBuckets++; 512 } 513 514 void StatsdStats::noteBadValueType(int64_t metricId) { 515 lock_guard<std::mutex> lock(mLock); 516 getAtomMetricStats(metricId).badValueType++; 517 } 518 519 void StatsdStats::noteBucketDropped(int64_t metricId) { 520 lock_guard<std::mutex> lock(mLock); 521 getAtomMetricStats(metricId).bucketDropped++; 522 } 523 524 void StatsdStats::noteBucketUnknownCondition(int64_t metricId) { 525 lock_guard<std::mutex> lock(mLock); 526 getAtomMetricStats(metricId).bucketUnknownCondition++; 527 } 528 529 void StatsdStats::noteConditionChangeInNextBucket(int64_t metricId) { 530 lock_guard<std::mutex> lock(mLock); 531 getAtomMetricStats(metricId).conditionChangeInNextBucket++; 532 } 533 534 void StatsdStats::noteInvalidatedBucket(int64_t metricId) { 535 lock_guard<std::mutex> lock(mLock); 536 getAtomMetricStats(metricId).invalidatedBucket++; 537 } 538 539 void StatsdStats::noteBucketCount(int64_t metricId) { 540 lock_guard<std::mutex> lock(mLock); 541 getAtomMetricStats(metricId).bucketCount++; 542 } 543 544 void StatsdStats::noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs) { 545 lock_guard<std::mutex> lock(mLock); 546 AtomMetricStats& pullStats = getAtomMetricStats(metricId); 547 pullStats.maxBucketBoundaryDelayNs = 548 std::max(pullStats.maxBucketBoundaryDelayNs, timeDelayNs); 549 pullStats.minBucketBoundaryDelayNs = 550 std::min(pullStats.minBucketBoundaryDelayNs, timeDelayNs); 551 } 552 553 StatsdStats::AtomMetricStats& StatsdStats::getAtomMetricStats(int64_t metricId) { 554 auto atomMetricStatsIter = mAtomMetricStats.find(metricId); 555 if (atomMetricStatsIter != mAtomMetricStats.end()) { 556 return atomMetricStatsIter->second; 557 } 558 auto emplaceResult = mAtomMetricStats.emplace(metricId, AtomMetricStats()); 559 return emplaceResult.first->second; 560 } 561 562 void StatsdStats::reset() { 563 lock_guard<std::mutex> lock(mLock); 564 resetInternalLocked(); 565 } 566 567 void StatsdStats::resetInternalLocked() { 568 // Reset the historical data, but keep the active ConfigStats 569 mStartTimeSec = getWallClockSec(); 570 mIceBox.clear(); 571 std::fill(mPushedAtomStats.begin(), mPushedAtomStats.end(), 0); 572 mNonPlatformPushedAtomStats.clear(); 573 mAnomalyAlarmRegisteredStats = 0; 574 mPeriodicAlarmRegisteredStats = 0; 575 mSystemServerRestartSec.clear(); 576 mLogLossStats.clear(); 577 mOverflowCount = 0; 578 mMinQueueHistoryNs = kInt64Max; 579 mMaxQueueHistoryNs = 0; 580 for (auto& config : mConfigStats) { 581 config.second->broadcast_sent_time_sec.clear(); 582 config.second->activation_time_sec.clear(); 583 config.second->deactivation_time_sec.clear(); 584 config.second->data_drop_time_sec.clear(); 585 config.second->data_drop_bytes.clear(); 586 config.second->dump_report_stats.clear(); 587 config.second->annotations.clear(); 588 config.second->matcher_stats.clear(); 589 config.second->condition_stats.clear(); 590 config.second->metric_stats.clear(); 591 config.second->metric_dimension_in_condition_stats.clear(); 592 config.second->alert_stats.clear(); 593 } 594 for (auto& pullStats : mPulledAtomStats) { 595 pullStats.second.totalPull = 0; 596 pullStats.second.totalPullFromCache = 0; 597 pullStats.second.avgPullTimeNs = 0; 598 pullStats.second.maxPullTimeNs = 0; 599 pullStats.second.numPullTime = 0; 600 pullStats.second.avgPullDelayNs = 0; 601 pullStats.second.maxPullDelayNs = 0; 602 pullStats.second.numPullDelay = 0; 603 pullStats.second.dataError = 0; 604 pullStats.second.pullTimeout = 0; 605 pullStats.second.pullExceedMaxDelay = 0; 606 pullStats.second.registeredCount = 0; 607 pullStats.second.unregisteredCount = 0; 608 } 609 mAtomMetricStats.clear(); 610 mActivationBroadcastGuardrailStats.clear(); 611 } 612 613 string buildTimeString(int64_t timeSec) { 614 time_t t = timeSec; 615 struct tm* tm = localtime(&t); 616 char timeBuffer[80]; 617 strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p", tm); 618 return string(timeBuffer); 619 } 620 621 void StatsdStats::dumpStats(int out) const { 622 lock_guard<std::mutex> lock(mLock); 623 time_t t = mStartTimeSec; 624 struct tm* tm = localtime(&t); 625 char timeBuffer[80]; 626 strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm); 627 dprintf(out, "Stats collection start second: %s\n", timeBuffer); 628 dprintf(out, "%lu Config in icebox: \n", (unsigned long)mIceBox.size()); 629 for (const auto& configStats : mIceBox) { 630 dprintf(out, 631 "Config {%d_%lld}: creation=%d, deletion=%d, reset=%d, #metric=%d, #condition=%d, " 632 "#matcher=%d, #alert=%d, valid=%d\n", 633 configStats->uid, (long long)configStats->id, configStats->creation_time_sec, 634 configStats->deletion_time_sec, configStats->reset_time_sec, 635 configStats->metric_count, configStats->condition_count, configStats->matcher_count, 636 configStats->alert_count, configStats->is_valid); 637 638 for (const auto& broadcastTime : configStats->broadcast_sent_time_sec) { 639 dprintf(out, "\tbroadcast time: %d\n", broadcastTime); 640 } 641 642 for (const int& activationTime : configStats->activation_time_sec) { 643 dprintf(out, "\tactivation time: %d\n", activationTime); 644 } 645 646 for (const int& deactivationTime : configStats->deactivation_time_sec) { 647 dprintf(out, "\tdeactivation time: %d\n", deactivationTime); 648 } 649 650 auto dropTimePtr = configStats->data_drop_time_sec.begin(); 651 auto dropBytesPtr = configStats->data_drop_bytes.begin(); 652 for (int i = 0; i < (int)configStats->data_drop_time_sec.size(); 653 i++, dropTimePtr++, dropBytesPtr++) { 654 dprintf(out, "\tdata drop time: %d with size %lld", *dropTimePtr, 655 (long long)*dropBytesPtr); 656 } 657 } 658 dprintf(out, "%lu Active Configs\n", (unsigned long)mConfigStats.size()); 659 for (auto& pair : mConfigStats) { 660 auto& configStats = pair.second; 661 dprintf(out, 662 "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, " 663 "#matcher=%d, #alert=%d, valid=%d\n", 664 configStats->uid, (long long)configStats->id, configStats->creation_time_sec, 665 configStats->deletion_time_sec, configStats->metric_count, 666 configStats->condition_count, configStats->matcher_count, configStats->alert_count, 667 configStats->is_valid); 668 for (const auto& annotation : configStats->annotations) { 669 dprintf(out, "\tannotation: %lld, %d\n", (long long)annotation.first, 670 annotation.second); 671 } 672 673 for (const auto& broadcastTime : configStats->broadcast_sent_time_sec) { 674 dprintf(out, "\tbroadcast time: %s(%lld)\n", buildTimeString(broadcastTime).c_str(), 675 (long long)broadcastTime); 676 } 677 678 for (const int& activationTime : configStats->activation_time_sec) { 679 dprintf(out, "\tactivation time: %d\n", activationTime); 680 } 681 682 for (const int& deactivationTime : configStats->deactivation_time_sec) { 683 dprintf(out, "\tdeactivation time: %d\n", deactivationTime); 684 } 685 686 auto dropTimePtr = configStats->data_drop_time_sec.begin(); 687 auto dropBytesPtr = configStats->data_drop_bytes.begin(); 688 for (int i = 0; i < (int)configStats->data_drop_time_sec.size(); 689 i++, dropTimePtr++, dropBytesPtr++) { 690 dprintf(out, "\tdata drop time: %s(%lld) with %lld bytes\n", 691 buildTimeString(*dropTimePtr).c_str(), (long long)*dropTimePtr, 692 (long long)*dropBytesPtr); 693 } 694 695 for (const auto& dump : configStats->dump_report_stats) { 696 dprintf(out, "\tdump report time: %s(%lld) bytes: %lld\n", 697 buildTimeString(dump.first).c_str(), (long long)dump.first, 698 (long long)dump.second); 699 } 700 701 for (const auto& stats : pair.second->matcher_stats) { 702 dprintf(out, "matcher %lld matched %d times\n", (long long)stats.first, stats.second); 703 } 704 705 for (const auto& stats : pair.second->condition_stats) { 706 dprintf(out, "condition %lld max output tuple size %d\n", (long long)stats.first, 707 stats.second); 708 } 709 710 for (const auto& stats : pair.second->condition_stats) { 711 dprintf(out, "metrics %lld max output tuple size %d\n", (long long)stats.first, 712 stats.second); 713 } 714 715 for (const auto& stats : pair.second->alert_stats) { 716 dprintf(out, "alert %lld declared %d times\n", (long long)stats.first, stats.second); 717 } 718 } 719 dprintf(out, "********Disk Usage stats***********\n"); 720 StorageManager::printStats(out); 721 dprintf(out, "********Pushed Atom stats***********\n"); 722 const size_t atomCounts = mPushedAtomStats.size(); 723 for (size_t i = 2; i < atomCounts; i++) { 724 if (mPushedAtomStats[i] > 0) { 725 dprintf(out, "Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]); 726 } 727 } 728 for (const auto& pair : mNonPlatformPushedAtomStats) { 729 dprintf(out, "Atom %lu->%d\n", (unsigned long)pair.first, pair.second); 730 } 731 732 dprintf(out, "********Pulled Atom stats***********\n"); 733 for (const auto& pair : mPulledAtomStats) { 734 dprintf(out, 735 "Atom %d->(total pull)%ld, (pull from cache)%ld, " 736 "(pull failed)%ld, (min pull interval)%ld \n" 737 " (average pull time nanos)%lld, (max pull time nanos)%lld, (average pull delay " 738 "nanos)%lld, " 739 " (max pull delay nanos)%lld, (data error)%ld\n" 740 " (pull timeout)%ld, (pull exceed max delay)%ld\n" 741 " (registered count) %ld, (unregistered count) %ld\n", 742 (int)pair.first, (long)pair.second.totalPull, (long)pair.second.totalPullFromCache, 743 (long)pair.second.pullFailed, (long)pair.second.minPullIntervalSec, 744 (long long)pair.second.avgPullTimeNs, (long long)pair.second.maxPullTimeNs, 745 (long long)pair.second.avgPullDelayNs, (long long)pair.second.maxPullDelayNs, 746 pair.second.dataError, pair.second.pullTimeout, pair.second.pullExceedMaxDelay, 747 pair.second.registeredCount, pair.second.unregisteredCount); 748 } 749 750 if (mAnomalyAlarmRegisteredStats > 0) { 751 dprintf(out, "********AnomalyAlarmStats stats***********\n"); 752 dprintf(out, "Anomaly alarm registrations: %d\n", mAnomalyAlarmRegisteredStats); 753 } 754 755 if (mPeriodicAlarmRegisteredStats > 0) { 756 dprintf(out, "********SubscriberAlarmStats stats***********\n"); 757 dprintf(out, "Subscriber alarm registrations: %d\n", mPeriodicAlarmRegisteredStats); 758 } 759 760 dprintf(out, "UID map stats: bytes=%d, changes=%d, deleted=%d, changes lost=%d\n", 761 mUidMapStats.bytes_used, mUidMapStats.changes, mUidMapStats.deleted_apps, 762 mUidMapStats.dropped_changes); 763 764 for (const auto& restart : mSystemServerRestartSec) { 765 dprintf(out, "System server restarts at %s(%lld)\n", buildTimeString(restart).c_str(), 766 (long long)restart); 767 } 768 769 for (const auto& loss : mLogLossStats) { 770 dprintf(out, 771 "Log loss: %lld (wall clock sec) - %d (count), %d (last error), %d (last tag), %d " 772 "(uid), %d (pid)\n", 773 (long long)loss.mWallClockSec, loss.mCount, loss.mLastError, loss.mLastTag, 774 loss.mUid, loss.mPid); 775 } 776 777 dprintf(out, "Event queue overflow: %d; MaxHistoryNs: %lld; MinHistoryNs: %lld\n", 778 mOverflowCount, (long long)mMaxQueueHistoryNs, (long long)mMinQueueHistoryNs); 779 780 if (mActivationBroadcastGuardrailStats.size() > 0) { 781 dprintf(out, "********mActivationBroadcastGuardrail stats***********\n"); 782 for (const auto& pair: mActivationBroadcastGuardrailStats) { 783 dprintf(out, "Uid %d: Times: ", pair.first); 784 for (const auto& guardrailHitTime : pair.second) { 785 dprintf(out, "%d ", guardrailHitTime); 786 } 787 } 788 dprintf(out, "\n"); 789 } 790 } 791 792 void addConfigStatsToProto(const ConfigStats& configStats, ProtoOutputStream* proto) { 793 uint64_t token = 794 proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CONFIG_STATS); 795 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_UID, configStats.uid); 796 proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_ID, (long long)configStats.id); 797 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_CREATION, configStats.creation_time_sec); 798 if (configStats.reset_time_sec != 0) { 799 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_RESET, configStats.reset_time_sec); 800 } 801 if (configStats.deletion_time_sec != 0) { 802 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DELETION, 803 configStats.deletion_time_sec); 804 } 805 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_METRIC_COUNT, configStats.metric_count); 806 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_CONDITION_COUNT, 807 configStats.condition_count); 808 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_MATCHER_COUNT, configStats.matcher_count); 809 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_ALERT_COUNT, configStats.alert_count); 810 proto->write(FIELD_TYPE_BOOL | FIELD_ID_CONFIG_STATS_VALID, configStats.is_valid); 811 812 for (const auto& broadcast : configStats.broadcast_sent_time_sec) { 813 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_BROADCAST | FIELD_COUNT_REPEATED, 814 broadcast); 815 } 816 817 for (const auto& activation : configStats.activation_time_sec) { 818 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_ACTIVATION | FIELD_COUNT_REPEATED, 819 activation); 820 } 821 822 for (const auto& deactivation : configStats.deactivation_time_sec) { 823 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DEACTIVATION | FIELD_COUNT_REPEATED, 824 deactivation); 825 } 826 827 for (const auto& drop_time : configStats.data_drop_time_sec) { 828 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DATA_DROP_TIME | FIELD_COUNT_REPEATED, 829 drop_time); 830 } 831 832 for (const auto& drop_bytes : configStats.data_drop_bytes) { 833 proto->write( 834 FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_DATA_DROP_BYTES | FIELD_COUNT_REPEATED, 835 (long long)drop_bytes); 836 } 837 838 for (const auto& dump : configStats.dump_report_stats) { 839 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME | 840 FIELD_COUNT_REPEATED, 841 dump.first); 842 } 843 844 for (const auto& dump : configStats.dump_report_stats) { 845 proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES | 846 FIELD_COUNT_REPEATED, 847 (long long)dump.second); 848 } 849 850 for (const auto& annotation : configStats.annotations) { 851 uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | 852 FIELD_ID_CONFIG_STATS_ANNOTATION); 853 proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_ANNOTATION_INT64, 854 (long long)annotation.first); 855 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_ANNOTATION_INT32, annotation.second); 856 proto->end(token); 857 } 858 859 for (const auto& pair : configStats.matcher_stats) { 860 uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | 861 FIELD_ID_CONFIG_STATS_MATCHER_STATS); 862 proto->write(FIELD_TYPE_INT64 | FIELD_ID_MATCHER_STATS_ID, (long long)pair.first); 863 proto->write(FIELD_TYPE_INT32 | FIELD_ID_MATCHER_STATS_COUNT, pair.second); 864 proto->end(tmpToken); 865 } 866 867 for (const auto& pair : configStats.condition_stats) { 868 uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | 869 FIELD_ID_CONFIG_STATS_CONDITION_STATS); 870 proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_STATS_ID, (long long)pair.first); 871 proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONDITION_STATS_COUNT, pair.second); 872 proto->end(tmpToken); 873 } 874 875 for (const auto& pair : configStats.metric_stats) { 876 uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | 877 FIELD_ID_CONFIG_STATS_METRIC_STATS); 878 proto->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_STATS_ID, (long long)pair.first); 879 proto->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_STATS_COUNT, pair.second); 880 proto->end(tmpToken); 881 } 882 for (const auto& pair : configStats.metric_dimension_in_condition_stats) { 883 uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | 884 FIELD_ID_CONFIG_STATS_METRIC_DIMENSION_IN_CONDITION_STATS); 885 proto->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_STATS_ID, (long long)pair.first); 886 proto->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_STATS_COUNT, pair.second); 887 proto->end(tmpToken); 888 } 889 890 for (const auto& pair : configStats.alert_stats) { 891 uint64_t tmpToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | 892 FIELD_ID_CONFIG_STATS_ALERT_STATS); 893 proto->write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_STATS_ID, (long long)pair.first); 894 proto->write(FIELD_TYPE_INT32 | FIELD_ID_ALERT_STATS_COUNT, pair.second); 895 proto->end(tmpToken); 896 } 897 898 proto->end(token); 899 } 900 901 void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) { 902 lock_guard<std::mutex> lock(mLock); 903 904 ProtoOutputStream proto; 905 proto.write(FIELD_TYPE_INT32 | FIELD_ID_BEGIN_TIME, mStartTimeSec); 906 proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)getWallClockSec()); 907 908 for (const auto& configStats : mIceBox) { 909 addConfigStatsToProto(*configStats, &proto); 910 } 911 912 for (auto& pair : mConfigStats) { 913 addConfigStatsToProto(*(pair.second), &proto); 914 } 915 916 const size_t atomCounts = mPushedAtomStats.size(); 917 for (size_t i = 2; i < atomCounts; i++) { 918 if (mPushedAtomStats[i] > 0) { 919 uint64_t token = 920 proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_STATS | FIELD_COUNT_REPEATED); 921 proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_TAG, (int32_t)i); 922 proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_COUNT, mPushedAtomStats[i]); 923 proto.end(token); 924 } 925 } 926 927 for (const auto& pair : mNonPlatformPushedAtomStats) { 928 uint64_t token = 929 proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_STATS | FIELD_COUNT_REPEATED); 930 proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_TAG, pair.first); 931 proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_COUNT, pair.second); 932 proto.end(token); 933 } 934 935 for (const auto& pair : mPulledAtomStats) { 936 android::os::statsd::writePullerStatsToStream(pair, &proto); 937 } 938 939 for (const auto& pair : mAtomMetricStats) { 940 android::os::statsd::writeAtomMetricStatsToStream(pair, &proto); 941 } 942 943 if (mAnomalyAlarmRegisteredStats > 0) { 944 uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS); 945 proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED, 946 mAnomalyAlarmRegisteredStats); 947 proto.end(token); 948 } 949 950 if (mPeriodicAlarmRegisteredStats > 0) { 951 uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PERIODIC_ALARM_STATS); 952 proto.write(FIELD_TYPE_INT32 | FIELD_ID_PERIODIC_ALARMS_REGISTERED, 953 mPeriodicAlarmRegisteredStats); 954 proto.end(token); 955 } 956 957 uint64_t uidMapToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS); 958 proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_CHANGES, mUidMapStats.changes); 959 proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_BYTES_USED, mUidMapStats.bytes_used); 960 proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DROPPED_CHANGES, mUidMapStats.dropped_changes); 961 proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DELETED_APPS, mUidMapStats.deleted_apps); 962 proto.end(uidMapToken); 963 964 for (const auto& error : mLogLossStats) { 965 uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_LOGGER_ERROR_STATS | 966 FIELD_COUNT_REPEATED); 967 proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_TIME, error.mWallClockSec); 968 proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_COUNT, error.mCount); 969 proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_ERROR, error.mLastError); 970 proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_TAG, error.mLastTag); 971 proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_UID, error.mUid); 972 proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_PID, error.mPid); 973 proto.end(token); 974 } 975 976 if (mOverflowCount > 0) { 977 uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_OVERFLOW); 978 proto.write(FIELD_TYPE_INT32 | FIELD_ID_OVERFLOW_COUNT, (int32_t)mOverflowCount); 979 proto.write(FIELD_TYPE_INT64 | FIELD_ID_OVERFLOW_MAX_HISTORY, 980 (long long)mMaxQueueHistoryNs); 981 proto.write(FIELD_TYPE_INT64 | FIELD_ID_OVERFLOW_MIN_HISTORY, 982 (long long)mMinQueueHistoryNs); 983 proto.end(token); 984 } 985 986 for (const auto& restart : mSystemServerRestartSec) { 987 proto.write(FIELD_TYPE_INT32 | FIELD_ID_SYSTEM_SERVER_RESTART | FIELD_COUNT_REPEATED, 988 restart); 989 } 990 991 for (const auto& pair: mActivationBroadcastGuardrailStats) { 992 uint64_t token = proto.start(FIELD_TYPE_MESSAGE | 993 FIELD_ID_ACTIVATION_BROADCAST_GUARDRAIL | 994 FIELD_COUNT_REPEATED); 995 proto.write(FIELD_TYPE_INT32 | FIELD_ID_ACTIVATION_BROADCAST_GUARDRAIL_UID, 996 (int32_t) pair.first); 997 for (const auto& guardrailHitTime : pair.second) { 998 proto.write(FIELD_TYPE_INT32 | FIELD_ID_ACTIVATION_BROADCAST_GUARDRAIL_TIME | 999 FIELD_COUNT_REPEATED, 1000 guardrailHitTime); 1001 } 1002 proto.end(token); 1003 } 1004 1005 output->clear(); 1006 size_t bufferSize = proto.size(); 1007 output->resize(bufferSize); 1008 1009 size_t pos = 0; 1010 sp<android::util::ProtoReader> reader = proto.data(); 1011 while (reader->readBuffer() != NULL) { 1012 size_t toRead = reader->currentToRead(); 1013 std::memcpy(&((*output)[pos]), reader->readBuffer(), toRead); 1014 pos += toRead; 1015 reader->move(toRead); 1016 } 1017 1018 if (reset) { 1019 resetInternalLocked(); 1020 } 1021 1022 VLOG("reset=%d, returned proto size %lu", reset, (unsigned long)bufferSize); 1023 } 1024 1025 } // namespace statsd 1026 } // namespace os 1027 } // namespace android 1028