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