blob: 563531351fe0f682c9a04f44603c8fbb0a3089ac [file] [log] [blame]
Yangster-mac20877162017-12-22 17:19:39 -08001/*
2 * Copyright (C) 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
Yangster-mac9def8e32018-04-17 13:55:51 -070017#include "hash.h"
Yangster-mac20877162017-12-22 17:19:39 -080018#include "stats_log_util.h"
19
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080020#include <aidl/android/os/IStatsCompanionService.h>
yro59cc24d2018-02-13 20:17:32 -080021#include <private/android_filesystem_config.h>
Yangster-mac20877162017-12-22 17:19:39 -080022#include <set>
Yangster-mac330af582018-02-08 15:24:38 -080023#include <utils/SystemClock.h>
Yangster-mac20877162017-12-22 17:19:39 -080024
Jonathan Nguyena0e6de12020-01-28 18:33:55 -080025#include "statscompanion_util.h"
26
Yao Chenbbdd67d2018-10-24 12:15:56 -070027using android::util::AtomsInfo;
Yangster-mac20877162017-12-22 17:19:39 -080028using android::util::FIELD_COUNT_REPEATED;
29using android::util::FIELD_TYPE_BOOL;
Yao Chenbbdd67d2018-10-24 12:15:56 -070030using android::util::FIELD_TYPE_FIXED64;
Yangster-mac20877162017-12-22 17:19:39 -080031using android::util::FIELD_TYPE_FLOAT;
32using android::util::FIELD_TYPE_INT32;
33using android::util::FIELD_TYPE_INT64;
34using android::util::FIELD_TYPE_MESSAGE;
35using android::util::FIELD_TYPE_STRING;
Yao Chenbbdd67d2018-10-24 12:15:56 -070036using android::util::FIELD_TYPE_UINT64;
Yangster-mac20877162017-12-22 17:19:39 -080037using android::util::ProtoOutputStream;
38
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080039using aidl::android::os::IStatsCompanionService;
40using std::shared_ptr;
41using std::string;
42
Yangster-mac20877162017-12-22 17:19:39 -080043namespace android {
44namespace os {
45namespace statsd {
46
47// for DimensionsValue Proto
48const int DIMENSIONS_VALUE_FIELD = 1;
49const int DIMENSIONS_VALUE_VALUE_STR = 2;
50const int DIMENSIONS_VALUE_VALUE_INT = 3;
51const int DIMENSIONS_VALUE_VALUE_LONG = 4;
Yao Chen4c959cb2018-02-13 13:27:48 -080052// const int DIMENSIONS_VALUE_VALUE_BOOL = 5; // logd doesn't have bool data type.
Yangster-mac20877162017-12-22 17:19:39 -080053const int DIMENSIONS_VALUE_VALUE_FLOAT = 6;
54const int DIMENSIONS_VALUE_VALUE_TUPLE = 7;
Yangster-mac9def8e32018-04-17 13:55:51 -070055const int DIMENSIONS_VALUE_VALUE_STR_HASH = 8;
Yangster-mac20877162017-12-22 17:19:39 -080056
Yao Chen8a8d16c2018-02-08 14:50:40 -080057const int DIMENSIONS_VALUE_TUPLE_VALUE = 1;
58
tsaichristine69000e62019-10-18 17:34:52 -070059// for StateValue Proto
60const int STATE_VALUE_ATOM_ID = 1;
61const int STATE_VALUE_CONTENTS_GROUP_ID = 2;
62const int STATE_VALUE_CONTENTS_VALUE = 3;
63
Chenjie Yub038b702017-12-18 15:15:34 -080064// for PulledAtomStats proto
65const int FIELD_ID_PULLED_ATOM_STATS = 10;
66const int FIELD_ID_PULL_ATOM_ID = 1;
67const int FIELD_ID_TOTAL_PULL = 2;
68const int FIELD_ID_TOTAL_PULL_FROM_CACHE = 3;
69const int FIELD_ID_MIN_PULL_INTERVAL_SEC = 4;
Chenjie Yu48ed1cc2018-10-31 17:36:38 -070070const int FIELD_ID_AVERAGE_PULL_TIME_NANOS = 5;
71const int FIELD_ID_MAX_PULL_TIME_NANOS = 6;
72const int FIELD_ID_AVERAGE_PULL_DELAY_NANOS = 7;
73const int FIELD_ID_MAX_PULL_DELAY_NANOS = 8;
Chenjie Yuc715b9e2018-10-19 07:52:12 -070074const int FIELD_ID_DATA_ERROR = 9;
Chenjie Yu0bd73db2018-12-16 07:37:04 -080075const int FIELD_ID_PULL_TIMEOUT = 10;
76const int FIELD_ID_PULL_EXCEED_MAX_DELAY = 11;
Misha Wagner1eee2212019-01-22 11:47:11 +000077const int FIELD_ID_PULL_FAILED = 12;
78const int FIELD_ID_STATS_COMPANION_FAILED = 13;
79const int FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED = 14;
80const int FIELD_ID_EMPTY_DATA = 15;
Tej Singha0c89dd2019-01-25 16:39:18 -080081const int FIELD_ID_PULL_REGISTERED_COUNT = 16;
82const int FIELD_ID_PULL_UNREGISTERED_COUNT = 17;
Misha Wagner1eee2212019-01-22 11:47:11 +000083// for AtomMetricStats proto
84const int FIELD_ID_ATOM_METRIC_STATS = 17;
85const int FIELD_ID_METRIC_ID = 1;
86const int FIELD_ID_HARD_DIMENSION_LIMIT_REACHED = 2;
87const int FIELD_ID_LATE_LOG_EVENT_SKIPPED = 3;
88const int FIELD_ID_SKIPPED_FORWARD_BUCKETS = 4;
89const int FIELD_ID_BAD_VALUE_TYPE = 5;
90const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6;
Olivier Gaillard9a5d3592019-02-05 15:12:39 +000091const int FIELD_ID_INVALIDATED_BUCKET = 7;
Olivier Gaillard320952b2019-02-06 13:57:24 +000092const int FIELD_ID_BUCKET_DROPPED = 8;
Olivier Gaillard3ba2e932019-02-08 14:25:35 +000093const int FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS = 9;
94const int FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS = 10;
Olivier Gaillarde63d9e02019-02-12 14:43:59 +000095const int FIELD_ID_BUCKET_UNKNOWN_CONDITION = 11;
Olivier Gaillardf248c0d2019-02-21 15:56:58 +000096const int FIELD_ID_BUCKET_COUNT = 12;
Yangster-mac9def8e32018-04-17 13:55:51 -070097
Yao Chen8a8d16c2018-02-08 14:50:40 -080098namespace {
Chenjie Yub038b702017-12-18 15:15:34 -080099
Yao Chen8a8d16c2018-02-08 14:50:40 -0800100void writeDimensionToProtoHelper(const std::vector<FieldValue>& dims, size_t* index, int depth,
Yangster-mac9def8e32018-04-17 13:55:51 -0700101 int prefix, std::set<string> *str_set,
102 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800103 size_t count = dims.size();
104 while (*index < count) {
105 const auto& dim = dims[*index];
106 const int valueDepth = dim.mField.getDepth();
107 const int valuePrefix = dim.mField.getPrefix(depth);
108 const int fieldNum = dim.mField.getPosAtDepth(depth);
109 if (valueDepth > 2) {
110 ALOGE("Depth > 2 not supported");
111 return;
112 }
113
114 if (depth == valueDepth && valuePrefix == prefix) {
Yi Jin5ee07872018-03-05 18:18:27 -0800115 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
Yao Chen8a8d16c2018-02-08 14:50:40 -0800116 DIMENSIONS_VALUE_TUPLE_VALUE);
117 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
118 switch (dim.mValue.getType()) {
119 case INT:
120 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
121 dim.mValue.int_value);
122 break;
123 case LONG:
124 protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
125 (long long)dim.mValue.long_value);
126 break;
127 case FLOAT:
128 protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
129 dim.mValue.float_value);
130 break;
131 case STRING:
Yangster-mac9def8e32018-04-17 13:55:51 -0700132 if (str_set == nullptr) {
133 protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
134 dim.mValue.str_value);
135 } else {
136 str_set->insert(dim.mValue.str_value);
137 protoOutput->write(
138 FIELD_TYPE_UINT64 | DIMENSIONS_VALUE_VALUE_STR_HASH,
139 (long long)Hash64(dim.mValue.str_value));
140 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800141 break;
142 default:
143 break;
144 }
145 if (token != 0) {
146 protoOutput->end(token);
147 }
148 (*index)++;
149 } else if (valueDepth > depth && valuePrefix == prefix) {
150 // Writing the sub tree
Yi Jin5ee07872018-03-05 18:18:27 -0800151 uint64_t dimensionToken = protoOutput->start(
Yao Chen8a8d16c2018-02-08 14:50:40 -0800152 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | DIMENSIONS_VALUE_TUPLE_VALUE);
153 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
Yi Jin5ee07872018-03-05 18:18:27 -0800154 uint64_t tupleToken =
Yao Chen8a8d16c2018-02-08 14:50:40 -0800155 protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
156 writeDimensionToProtoHelper(dims, index, valueDepth, dim.mField.getPrefix(valueDepth),
Yangster-mac9def8e32018-04-17 13:55:51 -0700157 str_set, protoOutput);
158 protoOutput->end(tupleToken);
159 protoOutput->end(dimensionToken);
160 } else {
161 // Done with the prev sub tree
162 return;
163 }
164 }
165}
166
167void writeDimensionLeafToProtoHelper(const std::vector<FieldValue>& dims,
168 const int dimensionLeafField,
169 size_t* index, int depth,
170 int prefix, std::set<string> *str_set,
171 ProtoOutputStream* protoOutput) {
172 size_t count = dims.size();
173 while (*index < count) {
174 const auto& dim = dims[*index];
175 const int valueDepth = dim.mField.getDepth();
176 const int valuePrefix = dim.mField.getPrefix(depth);
177 if (valueDepth > 2) {
178 ALOGE("Depth > 2 not supported");
179 return;
180 }
181
182 if (depth == valueDepth && valuePrefix == prefix) {
183 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
184 dimensionLeafField);
185 switch (dim.mValue.getType()) {
186 case INT:
187 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_VALUE_INT,
188 dim.mValue.int_value);
189 break;
190 case LONG:
191 protoOutput->write(FIELD_TYPE_INT64 | DIMENSIONS_VALUE_VALUE_LONG,
192 (long long)dim.mValue.long_value);
193 break;
194 case FLOAT:
195 protoOutput->write(FIELD_TYPE_FLOAT | DIMENSIONS_VALUE_VALUE_FLOAT,
196 dim.mValue.float_value);
197 break;
198 case STRING:
199 if (str_set == nullptr) {
200 protoOutput->write(FIELD_TYPE_STRING | DIMENSIONS_VALUE_VALUE_STR,
201 dim.mValue.str_value);
202 } else {
203 str_set->insert(dim.mValue.str_value);
204 protoOutput->write(
205 FIELD_TYPE_UINT64 | DIMENSIONS_VALUE_VALUE_STR_HASH,
206 (long long)Hash64(dim.mValue.str_value));
207 }
208 break;
209 default:
210 break;
211 }
212 if (token != 0) {
213 protoOutput->end(token);
214 }
215 (*index)++;
216 } else if (valueDepth > depth && valuePrefix == prefix) {
217 writeDimensionLeafToProtoHelper(dims, dimensionLeafField,
218 index, valueDepth, dim.mField.getPrefix(valueDepth),
219 str_set, protoOutput);
220 } else {
221 // Done with the prev sub tree
222 return;
223 }
224 }
225}
226
227void writeDimensionPathToProtoHelper(const std::vector<Matcher>& fieldMatchers,
228 size_t* index, int depth, int prefix,
229 ProtoOutputStream* protoOutput) {
230 size_t count = fieldMatchers.size();
231 while (*index < count) {
232 const Field& field = fieldMatchers[*index].mMatcher;
233 const int valueDepth = field.getDepth();
234 const int valuePrefix = field.getPrefix(depth);
235 const int fieldNum = field.getPosAtDepth(depth);
236 if (valueDepth > 2) {
237 ALOGE("Depth > 2 not supported");
238 return;
239 }
240
241 if (depth == valueDepth && valuePrefix == prefix) {
242 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
243 DIMENSIONS_VALUE_TUPLE_VALUE);
244 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
245 if (token != 0) {
246 protoOutput->end(token);
247 }
248 (*index)++;
249 } else if (valueDepth > depth && valuePrefix == prefix) {
250 // Writing the sub tree
251 uint64_t dimensionToken = protoOutput->start(
252 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | DIMENSIONS_VALUE_TUPLE_VALUE);
253 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD, fieldNum);
254 uint64_t tupleToken =
255 protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
256 writeDimensionPathToProtoHelper(fieldMatchers, index, valueDepth,
257 field.getPrefix(valueDepth), protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800258 protoOutput->end(tupleToken);
259 protoOutput->end(dimensionToken);
260 } else {
261 // Done with the prev sub tree
262 return;
263 }
264 }
265}
266
267} // namespace
268
Yangster-mac9def8e32018-04-17 13:55:51 -0700269void writeDimensionToProto(const HashableDimensionKey& dimension, std::set<string> *str_set,
270 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800271 if (dimension.getValues().size() == 0) {
Yangster-mac93694462018-01-22 20:49:31 -0800272 return;
273 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800274 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD,
275 dimension.getValues()[0].mField.getTag());
Yi Jin5ee07872018-03-05 18:18:27 -0800276 uint64_t topToken = protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800277 size_t index = 0;
Yangster-mac9def8e32018-04-17 13:55:51 -0700278 writeDimensionToProtoHelper(dimension.getValues(), &index, 0, 0, str_set, protoOutput);
279 protoOutput->end(topToken);
280}
281
282void writeDimensionLeafNodesToProto(const HashableDimensionKey& dimension,
283 const int dimensionLeafFieldId,
284 std::set<string> *str_set,
285 ProtoOutputStream* protoOutput) {
286 if (dimension.getValues().size() == 0) {
287 return;
288 }
289 size_t index = 0;
290 writeDimensionLeafToProtoHelper(dimension.getValues(), dimensionLeafFieldId,
291 &index, 0, 0, str_set, protoOutput);
292}
293
294void writeDimensionPathToProto(const std::vector<Matcher>& fieldMatchers,
295 ProtoOutputStream* protoOutput) {
296 if (fieldMatchers.size() == 0) {
297 return;
298 }
299 protoOutput->write(FIELD_TYPE_INT32 | DIMENSIONS_VALUE_FIELD,
300 fieldMatchers[0].mMatcher.getTag());
301 uint64_t topToken = protoOutput->start(FIELD_TYPE_MESSAGE | DIMENSIONS_VALUE_VALUE_TUPLE);
302 size_t index = 0;
303 writeDimensionPathToProtoHelper(fieldMatchers, &index, 0, 0, protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800304 protoOutput->end(topToken);
Yangster-mac20877162017-12-22 17:19:39 -0800305}
306
Yao Chen8a8d16c2018-02-08 14:50:40 -0800307// Supported Atoms format
308// XYZ_Atom {
309// repeated SubMsg field_1 = 1;
310// SubMsg2 field_2 = 2;
311// int32/float/string/int63 field_3 = 3;
312// }
313// logd's msg format, doesn't allow us to distinguish between the 2 cases below
314// Case (1):
315// Atom {
316// SubMsg {
317// int i = 1;
318// int j = 2;
319// }
320// repeated SubMsg
321// }
322//
323// and case (2):
324// Atom {
325// SubMsg {
326// repeated int i = 1;
327// repeated int j = 2;
328// }
329// optional SubMsg = 1;
330// }
331//
332//
Yao Chenbbdd67d2018-10-24 12:15:56 -0700333void writeFieldValueTreeToStreamHelper(int tagId, const std::vector<FieldValue>& dims,
334 size_t* index, int depth, int prefix,
335 ProtoOutputStream* protoOutput) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800336 size_t count = dims.size();
337 while (*index < count) {
338 const auto& dim = dims[*index];
339 const int valueDepth = dim.mField.getDepth();
340 const int valuePrefix = dim.mField.getPrefix(depth);
341 const int fieldNum = dim.mField.getPosAtDepth(depth);
342 if (valueDepth > 2) {
343 ALOGE("Depth > 2 not supported");
344 return;
Yangster-mac20877162017-12-22 17:19:39 -0800345 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800346
347 if (depth == valueDepth && valuePrefix == prefix) {
348 switch (dim.mValue.getType()) {
349 case INT:
350 protoOutput->write(FIELD_TYPE_INT32 | fieldNum, dim.mValue.int_value);
351 break;
352 case LONG:
353 protoOutput->write(FIELD_TYPE_INT64 | fieldNum,
354 (long long)dim.mValue.long_value);
355 break;
356 case FLOAT:
357 protoOutput->write(FIELD_TYPE_FLOAT | fieldNum, dim.mValue.float_value);
358 break;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700359 case STRING: {
Muhammad Qureshif77913f2020-03-20 10:55:46 -0700360 protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800361 break;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700362 }
Chenjie Yu12e5e672018-09-14 15:54:59 -0700363 case STORAGE:
364 protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
365 (const char*)dim.mValue.storage_value.data(),
366 dim.mValue.storage_value.size());
367 break;
Yangster-macf5204922018-02-23 13:08:03 -0800368 default:
369 break;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800370 }
371 (*index)++;
372 } else if (valueDepth > depth && valuePrefix == prefix) {
373 // Writing the sub tree
Yi Jin5ee07872018-03-05 18:18:27 -0800374 uint64_t msg_token = 0ULL;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800375 if (valueDepth == depth + 2) {
376 msg_token =
377 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | fieldNum);
378 } else if (valueDepth == depth + 1) {
379 msg_token = protoOutput->start(FIELD_TYPE_MESSAGE | fieldNum);
380 }
381 // Directly jump to the leaf value because the repeated position field is implied
382 // by the position of the sub msg in the parent field.
Yao Chenbbdd67d2018-10-24 12:15:56 -0700383 writeFieldValueTreeToStreamHelper(tagId, dims, index, valueDepth,
Yao Chen8a8d16c2018-02-08 14:50:40 -0800384 dim.mField.getPrefix(valueDepth), protoOutput);
385 if (msg_token != 0) {
386 protoOutput->end(msg_token);
387 }
388 } else {
389 // Done with the prev sub tree
390 return;
391 }
Yangster-mac20877162017-12-22 17:19:39 -0800392 }
393}
394
Yao Chen8a8d16c2018-02-08 14:50:40 -0800395void writeFieldValueTreeToStream(int tagId, const std::vector<FieldValue>& values,
Yangster-mac20877162017-12-22 17:19:39 -0800396 util::ProtoOutputStream* protoOutput) {
Yi Jin5ee07872018-03-05 18:18:27 -0800397 uint64_t atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | tagId);
Yangster-mac20877162017-12-22 17:19:39 -0800398
Yao Chen8a8d16c2018-02-08 14:50:40 -0800399 size_t index = 0;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700400 writeFieldValueTreeToStreamHelper(tagId, values, &index, 0, 0, protoOutput);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800401 protoOutput->end(atomToken);
Yangster-macb8144812018-01-04 10:56:23 -0800402}
Yangster-mac20877162017-12-22 17:19:39 -0800403
tsaichristine69000e62019-10-18 17:34:52 -0700404void writeStateToProto(const FieldValue& state, util::ProtoOutputStream* protoOutput) {
405 protoOutput->write(FIELD_TYPE_INT32 | STATE_VALUE_ATOM_ID, state.mField.getTag());
406
407 switch (state.mValue.getType()) {
408 case INT:
409 protoOutput->write(FIELD_TYPE_INT32 | STATE_VALUE_CONTENTS_VALUE,
410 state.mValue.int_value);
411 break;
412 case LONG:
413 protoOutput->write(FIELD_TYPE_INT64 | STATE_VALUE_CONTENTS_GROUP_ID,
414 state.mValue.long_value);
415 break;
416 default:
417 break;
418 }
419}
420
yro59cc24d2018-02-13 20:17:32 -0800421int64_t TimeUnitToBucketSizeInMillisGuardrailed(int uid, TimeUnit unit) {
422 int64_t bucketSizeMillis = TimeUnitToBucketSizeInMillis(unit);
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700423 if (bucketSizeMillis > 1000 && bucketSizeMillis < 5 * 60 * 1000LL && uid != AID_SHELL &&
424 uid != AID_ROOT) {
yro59cc24d2018-02-13 20:17:32 -0800425 bucketSizeMillis = 5 * 60 * 1000LL;
426 }
427 return bucketSizeMillis;
428}
429
Yangster-macb8144812018-01-04 10:56:23 -0800430int64_t TimeUnitToBucketSizeInMillis(TimeUnit unit) {
431 switch (unit) {
432 case ONE_MINUTE:
433 return 60 * 1000LL;
434 case FIVE_MINUTES:
435 return 5 * 60 * 1000LL;
436 case TEN_MINUTES:
437 return 10 * 60 * 1000LL;
438 case THIRTY_MINUTES:
439 return 30 * 60 * 1000LL;
440 case ONE_HOUR:
441 return 60 * 60 * 1000LL;
442 case THREE_HOURS:
443 return 3 * 60 * 60 * 1000LL;
444 case SIX_HOURS:
445 return 6 * 60 * 60 * 1000LL;
446 case TWELVE_HOURS:
447 return 12 * 60 * 60 * 1000LL;
448 case ONE_DAY:
449 return 24 * 60 * 60 * 1000LL;
Ruchir Rastogi060fbfc2019-10-11 13:16:51 -0700450 case ONE_WEEK:
451 return 7 * 24 * 60 * 60 * 1000LL;
Yangster-macb8144812018-01-04 10:56:23 -0800452 case CTS:
453 return 1000;
454 case TIME_UNIT_UNSPECIFIED:
455 default:
456 return -1;
457 }
Yangster-mac20877162017-12-22 17:19:39 -0800458}
459
Chenjie Yub038b702017-12-18 15:15:34 -0800460void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
461 util::ProtoOutputStream* protoOutput) {
Yi Jin5ee07872018-03-05 18:18:27 -0800462 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_PULLED_ATOM_STATS |
Chenjie Yub038b702017-12-18 15:15:34 -0800463 FIELD_COUNT_REPEATED);
464 protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_PULL_ATOM_ID, (int32_t)pair.first);
465 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL, (long long)pair.second.totalPull);
466 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TOTAL_PULL_FROM_CACHE,
467 (long long)pair.second.totalPullFromCache);
468 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_PULL_INTERVAL_SEC,
469 (long long)pair.second.minPullIntervalSec);
Chenjie Yu48ed1cc2018-10-31 17:36:38 -0700470 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_AVERAGE_PULL_TIME_NANOS,
471 (long long)pair.second.avgPullTimeNs);
472 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_TIME_NANOS,
473 (long long)pair.second.maxPullTimeNs);
474 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_AVERAGE_PULL_DELAY_NANOS,
475 (long long)pair.second.avgPullDelayNs);
476 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_DELAY_NANOS,
477 (long long)pair.second.maxPullDelayNs);
Chenjie Yuc715b9e2018-10-19 07:52:12 -0700478 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DATA_ERROR, (long long)pair.second.dataError);
Chenjie Yu0bd73db2018-12-16 07:37:04 -0800479 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_TIMEOUT,
480 (long long)pair.second.pullTimeout);
481 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_EXCEED_MAX_DELAY,
482 (long long)pair.second.pullExceedMaxDelay);
Misha Wagner1eee2212019-01-22 11:47:11 +0000483 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_FAILED,
484 (long long)pair.second.pullFailed);
485 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_FAILED,
486 (long long)pair.second.statsCompanionPullFailed);
487 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED,
488 (long long)pair.second.statsCompanionPullBinderTransactionFailed);
489 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_EMPTY_DATA,
490 (long long)pair.second.emptyData);
Tej Singha0c89dd2019-01-25 16:39:18 -0800491 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_REGISTERED_COUNT,
492 (long long) pair.second.registeredCount);
493 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_UNREGISTERED_COUNT,
494 (long long) pair.second.unregisteredCount);
Misha Wagner1eee2212019-01-22 11:47:11 +0000495 protoOutput->end(token);
496}
497
Olivier Gaillardf48fb042019-02-13 11:03:20 +0000498void writeAtomMetricStatsToStream(const std::pair<int64_t, StatsdStats::AtomMetricStats> &pair,
Misha Wagner1eee2212019-01-22 11:47:11 +0000499 util::ProtoOutputStream *protoOutput) {
500 uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_METRIC_STATS |
501 FIELD_COUNT_REPEATED);
Olivier Gaillardf48fb042019-02-13 11:03:20 +0000502 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_ID, (long long)pair.first);
Misha Wagner1eee2212019-01-22 11:47:11 +0000503 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_HARD_DIMENSION_LIMIT_REACHED,
504 (long long)pair.second.hardDimensionLimitReached);
505 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_LATE_LOG_EVENT_SKIPPED,
506 (long long)pair.second.lateLogEventSkipped);
507 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_FORWARD_BUCKETS,
508 (long long)pair.second.skippedForwardBuckets);
509 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BAD_VALUE_TYPE,
510 (long long)pair.second.badValueType);
511 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET,
512 (long long)pair.second.conditionChangeInNextBucket);
Olivier Gaillard9a5d3592019-02-05 15:12:39 +0000513 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_INVALIDATED_BUCKET,
514 (long long)pair.second.invalidatedBucket);
Olivier Gaillard320952b2019-02-06 13:57:24 +0000515 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_DROPPED,
516 (long long)pair.second.bucketDropped);
Olivier Gaillard3ba2e932019-02-08 14:25:35 +0000517 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS,
518 (long long)pair.second.minBucketBoundaryDelayNs);
519 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS,
520 (long long)pair.second.maxBucketBoundaryDelayNs);
Olivier Gaillarde63d9e02019-02-12 14:43:59 +0000521 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_UNKNOWN_CONDITION,
522 (long long)pair.second.bucketUnknownCondition);
Olivier Gaillardf248c0d2019-02-21 15:56:58 +0000523 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_COUNT,
524 (long long)pair.second.bucketCount);
Chenjie Yub038b702017-12-18 15:15:34 -0800525 protoOutput->end(token);
526}
527
Yangster-mac330af582018-02-08 15:24:38 -0800528int64_t getElapsedRealtimeNs() {
529 return ::android::elapsedRealtimeNano();
530}
531
532int64_t getElapsedRealtimeSec() {
533 return ::android::elapsedRealtimeNano() / NS_PER_SEC;
534}
535
536int64_t getElapsedRealtimeMillis() {
537 return ::android::elapsedRealtime();
538}
539
540int64_t getWallClockNs() {
541 return time(nullptr) * NS_PER_SEC;
542}
543
544int64_t getWallClockSec() {
545 return time(nullptr);
546}
547
548int64_t getWallClockMillis() {
549 return time(nullptr) * MS_PER_SEC;
550}
551
Muhammad Qureshia7de0002020-04-15 11:34:35 -0700552int64_t truncateTimestampIfNecessary(const LogEvent& event) {
553 if (event.shouldTruncateTimestamp() ||
554 (event.GetTagId() >= StatsdStats::kTimestampTruncationStartTag &&
555 event.GetTagId() <= StatsdStats::kTimestampTruncationEndTag)) {
556 return event.GetElapsedTimestampNs() / NS_PER_SEC / (5 * 60) * NS_PER_SEC * (5 * 60);
Tej Singh29ac6012019-06-05 18:10:12 -0700557 } else {
Muhammad Qureshia7de0002020-04-15 11:34:35 -0700558 return event.GetElapsedTimestampNs();
Tej Singh29ac6012019-06-05 18:10:12 -0700559 }
Yangster-macd5c35622018-02-02 10:33:25 -0800560}
561
Yangster-mac9def8e32018-04-17 13:55:51 -0700562int64_t NanoToMillis(const int64_t nano) {
563 return nano / 1000000;
564}
565
566int64_t MillisToNano(const int64_t millis) {
567 return millis * 1000000;
568}
569
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800570bool checkPermissionForIds(const char* permission, pid_t pid, uid_t uid) {
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800571 shared_ptr<IStatsCompanionService> scs = getStatsCompanionService();
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800572 if (scs == nullptr) {
573 return false;
574 }
575
576 bool success;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800577 ::ndk::ScopedAStatus status = scs->checkPermission(string(permission), pid, uid, &success);
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800578 if (!status.isOk()) {
579 return false;
580 }
581
582 return success;
583}
584
Yangster-mac20877162017-12-22 17:19:39 -0800585} // namespace statsd
586} // namespace os
yro59cc24d2018-02-13 20:17:32 -0800587} // namespace android