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 
StatsdStats()122 StatsdStats::StatsdStats() {
123     mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
124     mStartTimeSec = getWallClockSec();
125 }
126 
getInstance()127 StatsdStats& StatsdStats::getInstance() {
128     static StatsdStats statsInstance;
129     return statsInstance;
130 }
131 
addToIceBoxLocked(shared_ptr<ConfigStats> & stats)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 
noteConfigReceived(const ConfigKey & key,int metricsCount,int conditionsCount,int matchersCount,int alertsCount,const std::list<std::pair<const int64_t,const int32_t>> & annotations,bool isValid)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 
noteConfigRemovedInternalLocked(const ConfigKey & key)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 
noteConfigRemoved(const ConfigKey & key)181 void StatsdStats::noteConfigRemoved(const ConfigKey& key) {
182     lock_guard<std::mutex> lock(mLock);
183     noteConfigRemovedInternalLocked(key);
184 }
185 
noteConfigResetInternalLocked(const ConfigKey & key)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 
noteConfigReset(const ConfigKey & key)193 void StatsdStats::noteConfigReset(const ConfigKey& key) {
194     lock_guard<std::mutex> lock(mLock);
195     noteConfigResetInternalLocked(key);
196 }
197 
noteLogLost(int32_t wallClockTimeSec,int32_t count,int32_t lastError,int32_t lastTag,int32_t uid,int32_t pid)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 
noteBroadcastSent(const ConfigKey & key)207 void StatsdStats::noteBroadcastSent(const ConfigKey& key) {
208     noteBroadcastSent(key, getWallClockSec());
209 }
210 
noteBroadcastSent(const ConfigKey & key,int32_t timeSec)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 
noteActiveStatusChanged(const ConfigKey & key,bool activated)224 void StatsdStats::noteActiveStatusChanged(const ConfigKey& key, bool activated) {
225     noteActiveStatusChanged(key, activated, getWallClockSec());
226 }
227 
noteActiveStatusChanged(const ConfigKey & key,bool activated,int32_t timeSec)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 
noteActivationBroadcastGuardrailHit(const int uid)243 void StatsdStats::noteActivationBroadcastGuardrailHit(const int uid) {
244     noteActivationBroadcastGuardrailHit(uid, getWallClockSec());
245 }
246 
noteActivationBroadcastGuardrailHit(const int uid,const int32_t timeSec)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 
noteDataDropped(const ConfigKey & key,const size_t totalBytes)256 void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes) {
257     noteDataDropped(key, totalBytes, getWallClockSec());
258 }
259 
noteEventQueueOverflow(int64_t oldestEventTimestampNs)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 
noteDataDropped(const ConfigKey & key,const size_t totalBytes,int32_t timeSec)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 
noteMetricsReportSent(const ConfigKey & key,const size_t num_bytes)291 void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes) {
292     noteMetricsReportSent(key, num_bytes, getWallClockSec());
293 }
294 
noteMetricsReportSent(const ConfigKey & key,const size_t num_bytes,int32_t timeSec)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 
noteUidMapDropped(int deltas)309 void StatsdStats::noteUidMapDropped(int deltas) {
310     lock_guard<std::mutex> lock(mLock);
311     mUidMapStats.dropped_changes += mUidMapStats.dropped_changes + deltas;
312 }
313 
noteUidMapAppDeletionDropped()314 void StatsdStats::noteUidMapAppDeletionDropped() {
315     lock_guard<std::mutex> lock(mLock);
316     mUidMapStats.deleted_apps++;
317 }
318 
setUidMapChanges(int changes)319 void StatsdStats::setUidMapChanges(int changes) {
320     lock_guard<std::mutex> lock(mLock);
321     mUidMapStats.changes = changes;
322 }
323 
setCurrentUidMapMemory(int bytes)324 void StatsdStats::setCurrentUidMapMemory(int bytes) {
325     lock_guard<std::mutex> lock(mLock);
326     mUidMapStats.bytes_used = bytes;
327 }
328 
noteConditionDimensionSize(const ConfigKey & key,const int64_t & id,int size)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 
noteMetricDimensionSize(const ConfigKey & key,const int64_t & id,int size)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 
noteMetricDimensionInConditionSize(const ConfigKey & key,const int64_t & id,int size)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 
noteMatcherMatched(const ConfigKey & key,const int64_t & id)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 
noteAnomalyDeclared(const ConfigKey & key,const int64_t & id)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 
noteRegisteredAnomalyAlarmChanged()389 void StatsdStats::noteRegisteredAnomalyAlarmChanged() {
390     lock_guard<std::mutex> lock(mLock);
391     mAnomalyAlarmRegisteredStats++;
392 }
393 
noteRegisteredPeriodicAlarmChanged()394 void StatsdStats::noteRegisteredPeriodicAlarmChanged() {
395     lock_guard<std::mutex> lock(mLock);
396     mPeriodicAlarmRegisteredStats++;
397 }
398 
updateMinPullIntervalSec(int pullAtomId,long intervalSec)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 
notePull(int pullAtomId)405 void StatsdStats::notePull(int pullAtomId) {
406     lock_guard<std::mutex> lock(mLock);
407     mPulledAtomStats[pullAtomId].totalPull++;
408 }
409 
notePullFromCache(int pullAtomId)410 void StatsdStats::notePullFromCache(int pullAtomId) {
411     lock_guard<std::mutex> lock(mLock);
412     mPulledAtomStats[pullAtomId].totalPullFromCache++;
413 }
414 
notePullTime(int pullAtomId,int64_t pullTimeNs)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 
notePullDelay(int pullAtomId,int64_t pullDelayNs)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 
notePullDataError(int pullAtomId)434 void StatsdStats::notePullDataError(int pullAtomId) {
435     lock_guard<std::mutex> lock(mLock);
436     mPulledAtomStats[pullAtomId].dataError++;
437 }
438 
notePullTimeout(int pullAtomId)439 void StatsdStats::notePullTimeout(int pullAtomId) {
440     lock_guard<std::mutex> lock(mLock);
441     mPulledAtomStats[pullAtomId].pullTimeout++;
442 }
443 
notePullExceedMaxDelay(int pullAtomId)444 void StatsdStats::notePullExceedMaxDelay(int pullAtomId) {
445     lock_guard<std::mutex> lock(mLock);
446     mPulledAtomStats[pullAtomId].pullExceedMaxDelay++;
447 }
448 
noteAtomLogged(int atomId,int32_t timeSec)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 
noteSystemServerRestart(int32_t timeSec)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 
notePullFailed(int atomId)470 void StatsdStats::notePullFailed(int atomId) {
471     lock_guard<std::mutex> lock(mLock);
472     mPulledAtomStats[atomId].pullFailed++;
473 }
474 
noteStatsCompanionPullFailed(int atomId)475 void StatsdStats::noteStatsCompanionPullFailed(int atomId) {
476     lock_guard<std::mutex> lock(mLock);
477     mPulledAtomStats[atomId].statsCompanionPullFailed++;
478 }
479 
noteStatsCompanionPullBinderTransactionFailed(int atomId)480 void StatsdStats::noteStatsCompanionPullBinderTransactionFailed(int atomId) {
481     lock_guard<std::mutex> lock(mLock);
482     mPulledAtomStats[atomId].statsCompanionPullBinderTransactionFailed++;
483 }
484 
noteEmptyData(int atomId)485 void StatsdStats::noteEmptyData(int atomId) {
486     lock_guard<std::mutex> lock(mLock);
487     mPulledAtomStats[atomId].emptyData++;
488 }
489 
notePullerCallbackRegistrationChanged(int atomId,bool registered)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 
noteHardDimensionLimitReached(int64_t metricId)499 void StatsdStats::noteHardDimensionLimitReached(int64_t metricId) {
500     lock_guard<std::mutex> lock(mLock);
501     getAtomMetricStats(metricId).hardDimensionLimitReached++;
502 }
503 
noteLateLogEventSkipped(int64_t metricId)504 void StatsdStats::noteLateLogEventSkipped(int64_t metricId) {
505     lock_guard<std::mutex> lock(mLock);
506     getAtomMetricStats(metricId).lateLogEventSkipped++;
507 }
508 
noteSkippedForwardBuckets(int64_t metricId)509 void StatsdStats::noteSkippedForwardBuckets(int64_t metricId) {
510     lock_guard<std::mutex> lock(mLock);
511     getAtomMetricStats(metricId).skippedForwardBuckets++;
512 }
513 
noteBadValueType(int64_t metricId)514 void StatsdStats::noteBadValueType(int64_t metricId) {
515     lock_guard<std::mutex> lock(mLock);
516     getAtomMetricStats(metricId).badValueType++;
517 }
518 
noteBucketDropped(int64_t metricId)519 void StatsdStats::noteBucketDropped(int64_t metricId) {
520     lock_guard<std::mutex> lock(mLock);
521     getAtomMetricStats(metricId).bucketDropped++;
522 }
523 
noteBucketUnknownCondition(int64_t metricId)524 void StatsdStats::noteBucketUnknownCondition(int64_t metricId) {
525     lock_guard<std::mutex> lock(mLock);
526     getAtomMetricStats(metricId).bucketUnknownCondition++;
527 }
528 
noteConditionChangeInNextBucket(int64_t metricId)529 void StatsdStats::noteConditionChangeInNextBucket(int64_t metricId) {
530     lock_guard<std::mutex> lock(mLock);
531     getAtomMetricStats(metricId).conditionChangeInNextBucket++;
532 }
533 
noteInvalidatedBucket(int64_t metricId)534 void StatsdStats::noteInvalidatedBucket(int64_t metricId) {
535     lock_guard<std::mutex> lock(mLock);
536     getAtomMetricStats(metricId).invalidatedBucket++;
537 }
538 
noteBucketCount(int64_t metricId)539 void StatsdStats::noteBucketCount(int64_t metricId) {
540     lock_guard<std::mutex> lock(mLock);
541     getAtomMetricStats(metricId).bucketCount++;
542 }
543 
noteBucketBoundaryDelayNs(int64_t metricId,int64_t timeDelayNs)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 
getAtomMetricStats(int64_t metricId)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 
reset()562 void StatsdStats::reset() {
563     lock_guard<std::mutex> lock(mLock);
564     resetInternalLocked();
565 }
566 
resetInternalLocked()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 
buildTimeString(int64_t timeSec)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 
dumpStats(int out) const621 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 
addConfigStatsToProto(const ConfigStats & configStats,ProtoOutputStream * proto)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 
dumpStats(std::vector<uint8_t> * output,bool reset)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