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