blob: a230de46dcf32bc9d463cc0e64247bbfe6170358 [file] [log] [blame]
Yao Chend54f9dd2017-10-17 17:37:48 +00001/*
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
17#include "Collation.h"
18
19#include <stdio.h>
Muhammad Qureshia345af92020-03-24 17:05:14 -070020
Yao Chend54f9dd2017-10-17 17:37:48 +000021#include <map>
22
Muhammad Qureshia345af92020-03-24 17:05:14 -070023#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
24
Yao Chend54f9dd2017-10-17 17:37:48 +000025namespace android {
26namespace stats_log_api_gen {
27
Stefan Lafon9478f352017-10-30 21:20:20 -070028using google::protobuf::EnumDescriptor;
Yao Chend54f9dd2017-10-17 17:37:48 +000029using google::protobuf::FieldDescriptor;
30using google::protobuf::FileDescriptor;
31using google::protobuf::SourceLocation;
Muhammad Qureshib13a3212020-03-12 07:37:13 -070032using std::make_shared;
Yao Chend54f9dd2017-10-17 17:37:48 +000033using std::map;
34
Muhammad Qureshib13a3212020-03-12 07:37:13 -070035const bool dbg = false;
36
Yao Chend54f9dd2017-10-17 17:37:48 +000037//
38// AtomDecl class
39//
40
Muhammad Qureshia345af92020-03-24 17:05:14 -070041AtomDecl::AtomDecl() : code(0), name() {
Yao Chend54f9dd2017-10-17 17:37:48 +000042}
43
Muhammad Qureshia345af92020-03-24 17:05:14 -070044AtomDecl::AtomDecl(const AtomDecl& that)
45 : code(that.code),
46 name(that.name),
47 message(that.message),
48 fields(that.fields),
49 fieldNumberToAnnotations(that.fieldNumberToAnnotations),
50 primaryFields(that.primaryFields),
51 exclusiveField(that.exclusiveField),
52 defaultState(that.defaultState),
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -070053 triggerStateReset(that.triggerStateReset),
Muhammad Qureshia345af92020-03-24 17:05:14 -070054 nested(that.nested),
Muhammad Qureshi741d3182020-06-18 18:28:21 -070055 uidField(that.uidField) {
Yao Chend54f9dd2017-10-17 17:37:48 +000056}
57
Muhammad Qureshia345af92020-03-24 17:05:14 -070058AtomDecl::AtomDecl(int c, const string& n, const string& m) : code(c), name(n), message(m) {
Yao Chend54f9dd2017-10-17 17:37:48 +000059}
60
Muhammad Qureshia345af92020-03-24 17:05:14 -070061AtomDecl::~AtomDecl() {
62}
Yao Chend54f9dd2017-10-17 17:37:48 +000063
64/**
Muhammad Qureshia345af92020-03-24 17:05:14 -070065 * Print an error message for a FieldDescriptor, including the file name and
66 * line number.
Yao Chend54f9dd2017-10-17 17:37:48 +000067 */
Muhammad Qureshia345af92020-03-24 17:05:14 -070068static void print_error(const FieldDescriptor* field, const char* format, ...) {
Yao Chend54f9dd2017-10-17 17:37:48 +000069 const Descriptor* message = field->containing_type();
70 const FileDescriptor* file = message->file();
71
72 SourceLocation loc;
73 if (field->GetSourceLocation(&loc)) {
Muhammad Qureshia345af92020-03-24 17:05:14 -070074 // TODO: this will work if we can figure out how to pass
75 // --include_source_info to protoc
Yao Chend54f9dd2017-10-17 17:37:48 +000076 fprintf(stderr, "%s:%d: ", file->name().c_str(), loc.start_line);
77 } else {
78 fprintf(stderr, "%s: ", file->name().c_str());
79 }
80 va_list args;
81 va_start(args, format);
82 vfprintf(stderr, format, args);
Muhammad Qureshia345af92020-03-24 17:05:14 -070083 va_end(args);
Yao Chend54f9dd2017-10-17 17:37:48 +000084}
85
86/**
87 * Convert a protobuf type into a java type.
88 */
Muhammad Qureshia345af92020-03-24 17:05:14 -070089static java_type_t java_type(const FieldDescriptor* field) {
Yao Chend54f9dd2017-10-17 17:37:48 +000090 int protoType = field->type();
91 switch (protoType) {
92 case FieldDescriptor::TYPE_DOUBLE:
93 return JAVA_TYPE_DOUBLE;
94 case FieldDescriptor::TYPE_FLOAT:
95 return JAVA_TYPE_FLOAT;
96 case FieldDescriptor::TYPE_INT64:
97 return JAVA_TYPE_LONG;
98 case FieldDescriptor::TYPE_UINT64:
99 return JAVA_TYPE_LONG;
100 case FieldDescriptor::TYPE_INT32:
101 return JAVA_TYPE_INT;
102 case FieldDescriptor::TYPE_FIXED64:
103 return JAVA_TYPE_LONG;
104 case FieldDescriptor::TYPE_FIXED32:
105 return JAVA_TYPE_INT;
106 case FieldDescriptor::TYPE_BOOL:
107 return JAVA_TYPE_BOOLEAN;
108 case FieldDescriptor::TYPE_STRING:
109 return JAVA_TYPE_STRING;
110 case FieldDescriptor::TYPE_GROUP:
111 return JAVA_TYPE_UNKNOWN;
112 case FieldDescriptor::TYPE_MESSAGE:
113 // TODO: not the final package name
Muhammad Qureshia345af92020-03-24 17:05:14 -0700114 if (field->message_type()->full_name() == "android.os.statsd.AttributionNode") {
115 return JAVA_TYPE_ATTRIBUTION_CHAIN;
116 } else if (field->message_type()->full_name() == "android.os.statsd.KeyValuePair") {
117 return JAVA_TYPE_KEY_VALUE_PAIR;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700118 } else if (field->options().GetExtension(os::statsd::log_mode) ==
119 os::statsd::LogMode::MODE_BYTES) {
120 return JAVA_TYPE_BYTE_ARRAY;
Yao Chend54f9dd2017-10-17 17:37:48 +0000121 } else {
122 return JAVA_TYPE_OBJECT;
123 }
124 case FieldDescriptor::TYPE_BYTES:
125 return JAVA_TYPE_BYTE_ARRAY;
126 case FieldDescriptor::TYPE_UINT32:
127 return JAVA_TYPE_INT;
128 case FieldDescriptor::TYPE_ENUM:
Stefan Lafon9478f352017-10-30 21:20:20 -0700129 return JAVA_TYPE_ENUM;
Yao Chend54f9dd2017-10-17 17:37:48 +0000130 case FieldDescriptor::TYPE_SFIXED32:
131 return JAVA_TYPE_INT;
132 case FieldDescriptor::TYPE_SFIXED64:
133 return JAVA_TYPE_LONG;
134 case FieldDescriptor::TYPE_SINT32:
135 return JAVA_TYPE_INT;
136 case FieldDescriptor::TYPE_SINT64:
137 return JAVA_TYPE_LONG;
138 default:
139 return JAVA_TYPE_UNKNOWN;
140 }
141}
142
143/**
Yangster-macba5b9e42018-01-10 21:31:59 -0800144 * Gather the enums info.
145 */
Muhammad Qureshia345af92020-03-24 17:05:14 -0700146void collate_enums(const EnumDescriptor& enumDescriptor, AtomField* atomField) {
Yangster-macba5b9e42018-01-10 21:31:59 -0800147 for (int i = 0; i < enumDescriptor.value_count(); i++) {
148 atomField->enumValues[enumDescriptor.value(i)->number()] =
Muhammad Qureshia345af92020-03-24 17:05:14 -0700149 enumDescriptor.value(i)->name().c_str();
Yangster-macba5b9e42018-01-10 21:31:59 -0800150 }
151}
152
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700153static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber,
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700154 const AnnotationId annotationId,
155 const AnnotationType annotationType,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700156 const AnnotationValue annotationValue) {
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700157 if (dbg) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700158 printf(" Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(),
159 fieldNumber, annotationId, annotationType);
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700160 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700161 atomDecl->fieldNumberToAnnotations[fieldNumber].insert(
162 make_shared<Annotation>(annotationId, atomDecl->code, annotationType, annotationValue));
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700163}
164
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700165static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor* field,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700166 const int fieldNumber, const java_type_t& javaType) {
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700167 int errorCount = 0;
168
169 if (field->options().HasExtension(os::statsd::state_field_option)) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700170 const os::statsd::StateAtomFieldOption& stateFieldOption =
171 field->options().GetExtension(os::statsd::state_field_option);
172 const bool primaryField = stateFieldOption.primary_field();
173 const bool exclusiveState = stateFieldOption.exclusive_state();
174 const bool primaryFieldFirstUid = stateFieldOption.primary_field_first_uid();
175
176 // Check the field is only one of primaryField, exclusiveState, or primaryFieldFirstUid.
177 if (primaryField + primaryFieldFirstUid + exclusiveState > 1) {
178 print_error(field,
179 "Field can be max 1 of primary_field, exclusive_state, "
180 "or primary_field_first_uid: '%s'\n",
181 atomDecl->message.c_str());
182 errorCount++;
Muhammad Qureshia345af92020-03-24 17:05:14 -0700183 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700184
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700185 if (primaryField) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700186 if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
187 javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
188 print_error(field, "Invalid primary state field: '%s'\n",
189 atomDecl->message.c_str());
190 errorCount++;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700191 } else {
192 atomDecl->primaryFields.push_back(fieldNumber);
193 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_PRIMARY_FIELD,
194 ANNOTATION_TYPE_BOOL, AnnotationValue(true));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700195 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700196 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700197
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700198 if (primaryFieldFirstUid) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700199 if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
200 print_error(field,
201 "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: "
202 "'%s'\n",
203 atomDecl->message.c_str());
204 errorCount++;
205 } else {
206 atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700207 addAnnotationToAtomDecl(atomDecl, fieldNumber,
208 ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, ANNOTATION_TYPE_BOOL,
209 AnnotationValue(true));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700210 }
211 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700212
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700213 if (exclusiveState) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700214 if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
215 javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
216 print_error(field, "Invalid exclusive state field: '%s'\n",
217 atomDecl->message.c_str());
218 errorCount++;
219 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700220
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700221 if (atomDecl->exclusiveField != 0) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700222 print_error(field,
223 "Cannot have more than one exclusive state field in an "
224 "atom: '%s'\n",
225 atomDecl->message.c_str());
226 errorCount++;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700227 } else {
228 atomDecl->exclusiveField = fieldNumber;
229 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_EXCLUSIVE_STATE,
230 ANNOTATION_TYPE_BOOL, AnnotationValue(true));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700231 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700232
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700233 if (stateFieldOption.has_default_state_value()) {
234 const int defaultState = stateFieldOption.default_state_value();
Muhammad Qureshia345af92020-03-24 17:05:14 -0700235 atomDecl->defaultState = defaultState;
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700236
Muhammad Qureshia345af92020-03-24 17:05:14 -0700237 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
238 ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
239 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700240
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700241 if (stateFieldOption.has_trigger_state_reset_value()) {
242 const int triggerStateReset = stateFieldOption.trigger_state_reset_value();
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700243
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700244 atomDecl->triggerStateReset = triggerStateReset;
245 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_TRIGGER_STATE_RESET,
246 ANNOTATION_TYPE_INT, AnnotationValue(triggerStateReset));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700247 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700248
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700249 if (stateFieldOption.has_nested()) {
250 const bool nested = stateFieldOption.nested();
Muhammad Qureshia345af92020-03-24 17:05:14 -0700251 atomDecl->nested = nested;
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700252
Muhammad Qureshia345af92020-03-24 17:05:14 -0700253 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
254 ANNOTATION_TYPE_BOOL, AnnotationValue(nested));
255 }
256 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700257 }
258
259 if (field->options().GetExtension(os::statsd::is_uid) == true) {
260 if (javaType != JAVA_TYPE_INT) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700261 print_error(field, "is_uid annotation can only be applied to int32 fields: '%s'\n",
262 atomDecl->message.c_str());
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700263 errorCount++;
264 }
265
266 if (atomDecl->uidField == 0) {
267 atomDecl->uidField = fieldNumber;
268
269 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_IS_UID,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700270 ANNOTATION_TYPE_BOOL, AnnotationValue(true));
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700271 } else {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700272 print_error(field,
273 "Cannot have more than one field in an atom with is_uid "
274 "annotation: '%s'\n",
275 atomDecl->message.c_str());
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700276 errorCount++;
277 }
278 }
279
280 return errorCount;
281}
282
Yangster-macba5b9e42018-01-10 21:31:59 -0800283/**
Yangster-mac7604aea2017-12-11 22:55:49 -0800284 * Gather the info about an atom proto.
285 */
Muhammad Qureshia345af92020-03-24 17:05:14 -0700286int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature) {
287 int errorCount = 0;
Yangster-mac7604aea2017-12-11 22:55:49 -0800288
Yangster-macba5b9e42018-01-10 21:31:59 -0800289 // Build a sorted list of the fields. Descriptor has them in source file
290 // order.
Muhammad Qureshia345af92020-03-24 17:05:14 -0700291 map<int, const FieldDescriptor*> fields;
Yangster-macba5b9e42018-01-10 21:31:59 -0800292 for (int j = 0; j < atom->field_count(); j++) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700293 const FieldDescriptor* field = atom->field(j);
294 fields[field->number()] = field;
295 }
296
297 // Check that the parameters start at 1 and go up sequentially.
298 int expectedNumber = 1;
299 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
300 it++) {
301 const int number = it->first;
302 const FieldDescriptor* field = it->second;
303 if (number != expectedNumber) {
304 print_error(field,
305 "Fields must be numbered consecutively starting at 1:"
306 " '%s' is %d but should be %d\n",
307 field->name().c_str(), number, expectedNumber);
308 errorCount++;
309 expectedNumber = number;
310 continue;
311 }
312 expectedNumber++;
313 }
314
315 // Check that only allowed types are present. Remove any invalid ones.
316 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
317 it++) {
318 const FieldDescriptor* field = it->second;
319 bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
320 os::statsd::LogMode::MODE_BYTES;
321
322 java_type_t javaType = java_type(field);
323
324 if (javaType == JAVA_TYPE_UNKNOWN) {
325 print_error(field, "Unknown type for field: %s\n", field->name().c_str());
326 errorCount++;
327 continue;
328 } else if (javaType == JAVA_TYPE_OBJECT && atomDecl->code < PULL_ATOM_START_ID) {
329 // Allow attribution chain, but only at position 1.
330 print_error(field, "Message type not allowed for field in pushed atoms: %s\n",
331 field->name().c_str());
332 errorCount++;
333 continue;
334 } else if (javaType == JAVA_TYPE_BYTE_ARRAY && !isBinaryField) {
335 print_error(field, "Raw bytes type not allowed for field: %s\n", field->name().c_str());
336 errorCount++;
337 continue;
338 }
339
340 if (isBinaryField && javaType != JAVA_TYPE_BYTE_ARRAY) {
341 print_error(field, "Cannot mark field %s as bytes.\n", field->name().c_str());
342 errorCount++;
343 continue;
344 }
345
346 // Doubles are not supported yet.
347 if (javaType == JAVA_TYPE_DOUBLE) {
348 print_error(field,
349 "Doubles are not supported in atoms. Please change field %s "
350 "to float\n",
351 field->name().c_str());
352 errorCount++;
353 continue;
354 }
355
356 if (field->is_repeated() &&
357 !(javaType == JAVA_TYPE_ATTRIBUTION_CHAIN || javaType == JAVA_TYPE_KEY_VALUE_PAIR)) {
358 print_error(field,
359 "Repeated fields are not supported in atoms. Please make "
360 "field %s not "
361 "repeated.\n",
362 field->name().c_str());
363 errorCount++;
364 continue;
365 }
366 }
367
368 // Check that if there's an attribution chain, it's at position 1.
369 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
370 it++) {
371 int number = it->first;
372 if (number != 1) {
373 const FieldDescriptor* field = it->second;
374 java_type_t javaType = java_type(field);
375 if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
376 print_error(field,
377 "AttributionChain fields must have field id 1, in message: '%s'\n",
378 atom->name().c_str());
379 errorCount++;
380 }
381 }
382 }
383
384 // Build the type signature and the atom data.
385 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
386 it++) {
387 const FieldDescriptor* field = it->second;
388 java_type_t javaType = java_type(field);
389 bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
390 os::statsd::LogMode::MODE_BYTES;
391
392 AtomField atField(field->name(), javaType);
393
394 if (javaType == JAVA_TYPE_ENUM) {
395 // All enums are treated as ints when it comes to function signatures.
396 collate_enums(*field->enum_type(), &atField);
397 }
398
399 // Generate signature for pushed atoms
400 if (atomDecl->code < PULL_ATOM_START_ID) {
401 if (javaType == JAVA_TYPE_ENUM) {
402 // All enums are treated as ints when it comes to function signatures.
403 signature->push_back(JAVA_TYPE_INT);
404 } else if (javaType == JAVA_TYPE_OBJECT && isBinaryField) {
405 signature->push_back(JAVA_TYPE_BYTE_ARRAY);
406 } else {
407 signature->push_back(javaType);
408 }
409 }
410
411 atomDecl->fields.push_back(atField);
412
413 errorCount += collate_field_annotations(atomDecl, field, it->first, javaType);
414 }
415
416 return errorCount;
417}
418
419// This function flattens the fields of the AttributionNode proto in an Atom
420// proto and generates the corresponding atom decl and signature.
421bool get_non_chained_node(const Descriptor* atom, AtomDecl* atomDecl,
422 vector<java_type_t>* signature) {
423 // Build a sorted list of the fields. Descriptor has them in source file
424 // order.
425 map<int, const FieldDescriptor*> fields;
426 for (int j = 0; j < atom->field_count(); j++) {
427 const FieldDescriptor* field = atom->field(j);
Yangster-macba5b9e42018-01-10 21:31:59 -0800428 fields[field->number()] = field;
429 }
430
431 AtomDecl attributionDecl;
432 vector<java_type_t> attributionSignature;
Muhammad Qureshia345af92020-03-24 17:05:14 -0700433 collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl,
434 &attributionSignature);
Yangster-macba5b9e42018-01-10 21:31:59 -0800435
436 // Build the type signature and the atom data.
437 bool has_attribution_node = false;
Muhammad Qureshia345af92020-03-24 17:05:14 -0700438 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
439 it++) {
440 const FieldDescriptor* field = it->second;
Yangster-macba5b9e42018-01-10 21:31:59 -0800441 java_type_t javaType = java_type(field);
442 if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700443 atomDecl->fields.insert(atomDecl->fields.end(), attributionDecl.fields.begin(),
444 attributionDecl.fields.end());
445 signature->insert(signature->end(), attributionSignature.begin(),
446 attributionSignature.end());
Yangster-macba5b9e42018-01-10 21:31:59 -0800447 has_attribution_node = true;
448
449 } else {
450 AtomField atField(field->name(), javaType);
451 if (javaType == JAVA_TYPE_ENUM) {
452 // All enums are treated as ints when it comes to function signatures.
453 signature->push_back(JAVA_TYPE_INT);
454 collate_enums(*field->enum_type(), &atField);
455 } else {
456 signature->push_back(javaType);
457 }
458 atomDecl->fields.push_back(atField);
459 }
460 }
461 return has_attribution_node;
462}
463
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700464static void populateFieldNumberToAtomDeclSet(const shared_ptr<AtomDecl>& atomDecl,
465 FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet) {
466 for (FieldNumberToAnnotations::const_iterator it = atomDecl->fieldNumberToAnnotations.begin();
467 it != atomDecl->fieldNumberToAnnotations.end(); it++) {
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700468 const int fieldNumber = it->first;
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700469 (*fieldNumberToAtomDeclSet)[fieldNumber].insert(atomDecl);
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700470 }
471}
472
Yangster-mac7604aea2017-12-11 22:55:49 -0800473/**
Yao Chend54f9dd2017-10-17 17:37:48 +0000474 * Gather the info about the atoms.
475 */
Muhammad Qureshia345af92020-03-24 17:05:14 -0700476int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms) {
477 int errorCount = 0;
Yao Chend54f9dd2017-10-17 17:37:48 +0000478
Muhammad Qureshia345af92020-03-24 17:05:14 -0700479 for (int i = 0; i < descriptor->field_count(); i++) {
480 const FieldDescriptor* atomField = descriptor->field(i);
Yao Chend54f9dd2017-10-17 17:37:48 +0000481
Muhammad Qureshia345af92020-03-24 17:05:14 -0700482 if (moduleName != DEFAULT_MODULE_NAME) {
483 const int moduleCount = atomField->options().ExtensionSize(os::statsd::module);
484 int j;
485 for (j = 0; j < moduleCount; ++j) {
486 const string atomModuleName =
487 atomField->options().GetExtension(os::statsd::module, j);
488 if (atomModuleName == moduleName) {
489 break;
490 }
491 }
492
493 // This atom is not in the module we're interested in; skip it.
494 if (moduleCount == j) {
495 if (dbg) {
496 printf(" Skipping %s (%d)\n", atomField->name().c_str(), atomField->number());
497 }
498 continue;
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700499 }
500 }
501
Muhammad Qureshia345af92020-03-24 17:05:14 -0700502 if (dbg) {
503 printf(" %s (%d)\n", atomField->name().c_str(), atomField->number());
504 }
505
506 // StatsEvent only has one oneof, which contains only messages. Don't allow
507 // other types.
508 if (atomField->type() != FieldDescriptor::TYPE_MESSAGE) {
509 print_error(atomField,
510 "Bad type for atom. StatsEvent can only have message type "
511 "fields: %s\n",
512 atomField->name().c_str());
513 errorCount++;
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700514 continue;
515 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700516
517 const Descriptor* atom = atomField->message_type();
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700518 shared_ptr<AtomDecl> atomDecl =
519 make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
Muhammad Qureshia345af92020-03-24 17:05:14 -0700520
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700521 if (atomDecl->code < PULL_ATOM_START_ID &&
Muhammad Qureshia345af92020-03-24 17:05:14 -0700522 atomField->options().GetExtension(os::statsd::truncate_timestamp)) {
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700523 addAnnotationToAtomDecl(atomDecl.get(), ATOM_ID_FIELD_NUMBER,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700524 ANNOTATION_ID_TRUNCATE_TIMESTAMP, ANNOTATION_TYPE_BOOL,
525 AnnotationValue(true));
526 if (dbg) {
527 printf("%s can have timestamp truncated\n", atomField->name().c_str());
528 }
529 }
530
531 vector<java_type_t> signature;
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700532 errorCount += collate_atom(atom, atomDecl.get(), &signature);
533 if (atomDecl->primaryFields.size() != 0 && atomDecl->exclusiveField == 0) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700534 print_error(atomField, "Cannot have a primary field without an exclusive field: %s\n",
535 atomField->name().c_str());
536 errorCount++;
537 continue;
538 }
539
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700540 FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = atoms->signatureInfoMap[signature];
541 populateFieldNumberToAtomDeclSet(atomDecl, &fieldNumberToAtomDeclSet);
Muhammad Qureshia345af92020-03-24 17:05:14 -0700542
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700543 atoms->decls.insert(atomDecl);
544
545 shared_ptr<AtomDecl> nonChainedAtomDecl =
546 make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
Muhammad Qureshia345af92020-03-24 17:05:14 -0700547 vector<java_type_t> nonChainedSignature;
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700548 if (get_non_chained_node(atom, nonChainedAtomDecl.get(), &nonChainedSignature)) {
549 FieldNumberToAtomDeclSet& nonChainedFieldNumberToAtomDeclSet =
Muhammad Qureshia345af92020-03-24 17:05:14 -0700550 atoms->nonChainedSignatureInfoMap[nonChainedSignature];
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700551 populateFieldNumberToAtomDeclSet(nonChainedAtomDecl,
552 &nonChainedFieldNumberToAtomDeclSet);
553
554 atoms->non_chained_decls.insert(nonChainedAtomDecl);
Muhammad Qureshia345af92020-03-24 17:05:14 -0700555 }
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700556 }
557
Yao Chend54f9dd2017-10-17 17:37:48 +0000558 if (dbg) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700559 printf("signatures = [\n");
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700560 for (SignatureInfoMap::const_iterator it = atoms->signatureInfoMap.begin();
Muhammad Qureshia345af92020-03-24 17:05:14 -0700561 it != atoms->signatureInfoMap.end(); it++) {
562 printf(" ");
563 for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
564 jt++) {
565 printf(" %d", (int)*jt);
566 }
567 printf("\n");
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700568 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700569 printf("]\n");
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700570 }
571
Muhammad Qureshia345af92020-03-24 17:05:14 -0700572 return errorCount;
Yao Chend54f9dd2017-10-17 17:37:48 +0000573}
574
575} // namespace stats_log_api_gen
576} // namespace android