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