Home | History | Annotate | Download | only in guardrail
      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