blob: 958e94efcf9c3d0ca6e0286cd1108af6c0c4f0c7 [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),
55 uidField(that.uidField),
56 whitelisted(that.whitelisted),
57 truncateTimestamp(that.truncateTimestamp) {
Yao Chend54f9dd2017-10-17 17:37:48 +000058}
59
Muhammad Qureshia345af92020-03-24 17:05:14 -070060AtomDecl::AtomDecl(int c, const string& n, const string& m) : code(c), name(n), message(m) {
Yao Chend54f9dd2017-10-17 17:37:48 +000061}
62
Muhammad Qureshia345af92020-03-24 17:05:14 -070063AtomDecl::~AtomDecl() {
64}
Yao Chend54f9dd2017-10-17 17:37:48 +000065
66/**
Muhammad Qureshia345af92020-03-24 17:05:14 -070067 * Print an error message for a FieldDescriptor, including the file name and
68 * line number.
Yao Chend54f9dd2017-10-17 17:37:48 +000069 */
Muhammad Qureshia345af92020-03-24 17:05:14 -070070static void print_error(const FieldDescriptor* field, const char* format, ...) {
Yao Chend54f9dd2017-10-17 17:37:48 +000071 const Descriptor* message = field->containing_type();
72 const FileDescriptor* file = message->file();
73
74 SourceLocation loc;
75 if (field->GetSourceLocation(&loc)) {
Muhammad Qureshia345af92020-03-24 17:05:14 -070076 // TODO: this will work if we can figure out how to pass
77 // --include_source_info to protoc
Yao Chend54f9dd2017-10-17 17:37:48 +000078 fprintf(stderr, "%s:%d: ", file->name().c_str(), loc.start_line);
79 } else {
80 fprintf(stderr, "%s: ", file->name().c_str());
81 }
82 va_list args;
83 va_start(args, format);
84 vfprintf(stderr, format, args);
Muhammad Qureshia345af92020-03-24 17:05:14 -070085 va_end(args);
Yao Chend54f9dd2017-10-17 17:37:48 +000086}
87
88/**
89 * Convert a protobuf type into a java type.
90 */
Muhammad Qureshia345af92020-03-24 17:05:14 -070091static java_type_t java_type(const FieldDescriptor* field) {
Yao Chend54f9dd2017-10-17 17:37:48 +000092 int protoType = field->type();
93 switch (protoType) {
94 case FieldDescriptor::TYPE_DOUBLE:
95 return JAVA_TYPE_DOUBLE;
96 case FieldDescriptor::TYPE_FLOAT:
97 return JAVA_TYPE_FLOAT;
98 case FieldDescriptor::TYPE_INT64:
99 return JAVA_TYPE_LONG;
100 case FieldDescriptor::TYPE_UINT64:
101 return JAVA_TYPE_LONG;
102 case FieldDescriptor::TYPE_INT32:
103 return JAVA_TYPE_INT;
104 case FieldDescriptor::TYPE_FIXED64:
105 return JAVA_TYPE_LONG;
106 case FieldDescriptor::TYPE_FIXED32:
107 return JAVA_TYPE_INT;
108 case FieldDescriptor::TYPE_BOOL:
109 return JAVA_TYPE_BOOLEAN;
110 case FieldDescriptor::TYPE_STRING:
111 return JAVA_TYPE_STRING;
112 case FieldDescriptor::TYPE_GROUP:
113 return JAVA_TYPE_UNKNOWN;
114 case FieldDescriptor::TYPE_MESSAGE:
115 // TODO: not the final package name
Muhammad Qureshia345af92020-03-24 17:05:14 -0700116 if (field->message_type()->full_name() == "android.os.statsd.AttributionNode") {
117 return JAVA_TYPE_ATTRIBUTION_CHAIN;
118 } else if (field->message_type()->full_name() == "android.os.statsd.KeyValuePair") {
119 return JAVA_TYPE_KEY_VALUE_PAIR;
Yao Chenbbdd67d2018-10-24 12:15:56 -0700120 } else if (field->options().GetExtension(os::statsd::log_mode) ==
121 os::statsd::LogMode::MODE_BYTES) {
122 return JAVA_TYPE_BYTE_ARRAY;
Yao Chend54f9dd2017-10-17 17:37:48 +0000123 } else {
124 return JAVA_TYPE_OBJECT;
125 }
126 case FieldDescriptor::TYPE_BYTES:
127 return JAVA_TYPE_BYTE_ARRAY;
128 case FieldDescriptor::TYPE_UINT32:
129 return JAVA_TYPE_INT;
130 case FieldDescriptor::TYPE_ENUM:
Stefan Lafon9478f352017-10-30 21:20:20 -0700131 return JAVA_TYPE_ENUM;
Yao Chend54f9dd2017-10-17 17:37:48 +0000132 case FieldDescriptor::TYPE_SFIXED32:
133 return JAVA_TYPE_INT;
134 case FieldDescriptor::TYPE_SFIXED64:
135 return JAVA_TYPE_LONG;
136 case FieldDescriptor::TYPE_SINT32:
137 return JAVA_TYPE_INT;
138 case FieldDescriptor::TYPE_SINT64:
139 return JAVA_TYPE_LONG;
140 default:
141 return JAVA_TYPE_UNKNOWN;
142 }
143}
144
145/**
Yangster-macba5b9e42018-01-10 21:31:59 -0800146 * Gather the enums info.
147 */
Muhammad Qureshia345af92020-03-24 17:05:14 -0700148void collate_enums(const EnumDescriptor& enumDescriptor, AtomField* atomField) {
Yangster-macba5b9e42018-01-10 21:31:59 -0800149 for (int i = 0; i < enumDescriptor.value_count(); i++) {
150 atomField->enumValues[enumDescriptor.value(i)->number()] =
Muhammad Qureshia345af92020-03-24 17:05:14 -0700151 enumDescriptor.value(i)->name().c_str();
Yangster-macba5b9e42018-01-10 21:31:59 -0800152 }
153}
154
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700155static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber,
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700156 const AnnotationId annotationId,
157 const AnnotationType annotationType,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700158 const AnnotationValue annotationValue) {
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700159 if (dbg) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700160 printf(" Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(),
161 fieldNumber, annotationId, annotationType);
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700162 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700163 atomDecl->fieldNumberToAnnotations[fieldNumber].insert(
164 make_shared<Annotation>(annotationId, atomDecl->code, annotationType, annotationValue));
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700165}
166
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700167static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor* field,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700168 const int fieldNumber, const java_type_t& javaType) {
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700169 int errorCount = 0;
170
171 if (field->options().HasExtension(os::statsd::state_field_option)) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700172 const os::statsd::StateAtomFieldOption& stateFieldOption =
173 field->options().GetExtension(os::statsd::state_field_option);
174 const bool primaryField = stateFieldOption.primary_field();
175 const bool exclusiveState = stateFieldOption.exclusive_state();
176 const bool primaryFieldFirstUid = stateFieldOption.primary_field_first_uid();
177
178 // Check the field is only one of primaryField, exclusiveState, or primaryFieldFirstUid.
179 if (primaryField + primaryFieldFirstUid + exclusiveState > 1) {
180 print_error(field,
181 "Field can be max 1 of primary_field, exclusive_state, "
182 "or primary_field_first_uid: '%s'\n",
183 atomDecl->message.c_str());
184 errorCount++;
Muhammad Qureshia345af92020-03-24 17:05:14 -0700185 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700186
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700187 if (primaryField) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700188 if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
189 javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
190 print_error(field, "Invalid primary state field: '%s'\n",
191 atomDecl->message.c_str());
192 errorCount++;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700193 } else {
194 atomDecl->primaryFields.push_back(fieldNumber);
195 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_PRIMARY_FIELD,
196 ANNOTATION_TYPE_BOOL, AnnotationValue(true));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700197 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700198 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700199
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700200 if (primaryFieldFirstUid) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700201 if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
202 print_error(field,
203 "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: "
204 "'%s'\n",
205 atomDecl->message.c_str());
206 errorCount++;
207 } else {
208 atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700209 addAnnotationToAtomDecl(atomDecl, fieldNumber,
210 ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, ANNOTATION_TYPE_BOOL,
211 AnnotationValue(true));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700212 }
213 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700214
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700215 if (exclusiveState) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700216 if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
217 javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
218 print_error(field, "Invalid exclusive state field: '%s'\n",
219 atomDecl->message.c_str());
220 errorCount++;
221 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700222
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700223 if (atomDecl->exclusiveField != 0) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700224 print_error(field,
225 "Cannot have more than one exclusive state field in an "
226 "atom: '%s'\n",
227 atomDecl->message.c_str());
228 errorCount++;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700229 } else {
230 atomDecl->exclusiveField = fieldNumber;
231 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_EXCLUSIVE_STATE,
232 ANNOTATION_TYPE_BOOL, AnnotationValue(true));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700233 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700234
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700235 if (stateFieldOption.has_default_state_value()) {
236 const int defaultState = stateFieldOption.default_state_value();
Muhammad Qureshia345af92020-03-24 17:05:14 -0700237 atomDecl->defaultState = defaultState;
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700238
Muhammad Qureshia345af92020-03-24 17:05:14 -0700239 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
240 ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
241 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700242
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700243 if (stateFieldOption.has_trigger_state_reset_value()) {
244 const int triggerStateReset = stateFieldOption.trigger_state_reset_value();
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700245
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700246 atomDecl->triggerStateReset = triggerStateReset;
247 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_TRIGGER_STATE_RESET,
248 ANNOTATION_TYPE_INT, AnnotationValue(triggerStateReset));
Muhammad Qureshia345af92020-03-24 17:05:14 -0700249 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700250
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700251 if (stateFieldOption.has_nested()) {
252 const bool nested = stateFieldOption.nested();
Muhammad Qureshia345af92020-03-24 17:05:14 -0700253 atomDecl->nested = nested;
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700254
Muhammad Qureshia345af92020-03-24 17:05:14 -0700255 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
256 ANNOTATION_TYPE_BOOL, AnnotationValue(nested));
257 }
258 }
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700259 }
260
261 if (field->options().GetExtension(os::statsd::is_uid) == true) {
262 if (javaType != JAVA_TYPE_INT) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700263 print_error(field, "is_uid annotation can only be applied to int32 fields: '%s'\n",
264 atomDecl->message.c_str());
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700265 errorCount++;
266 }
267
268 if (atomDecl->uidField == 0) {
269 atomDecl->uidField = fieldNumber;
270
271 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_IS_UID,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700272 ANNOTATION_TYPE_BOOL, AnnotationValue(true));
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700273 } else {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700274 print_error(field,
275 "Cannot have more than one field in an atom with is_uid "
276 "annotation: '%s'\n",
277 atomDecl->message.c_str());
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700278 errorCount++;
279 }
280 }
281
282 return errorCount;
283}
284
Yangster-macba5b9e42018-01-10 21:31:59 -0800285/**
Yangster-mac7604aea2017-12-11 22:55:49 -0800286 * Gather the info about an atom proto.
287 */
Muhammad Qureshia345af92020-03-24 17:05:14 -0700288int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature) {
289 int errorCount = 0;
Yangster-mac7604aea2017-12-11 22:55:49 -0800290
Yangster-macba5b9e42018-01-10 21:31:59 -0800291 // Build a sorted list of the fields. Descriptor has them in source file
292 // order.
Muhammad Qureshia345af92020-03-24 17:05:14 -0700293 map<int, const FieldDescriptor*> fields;
Yangster-macba5b9e42018-01-10 21:31:59 -0800294 for (int j = 0; j < atom->field_count(); j++) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700295 const FieldDescriptor* field = atom->field(j);
296 fields[field->number()] = field;
297 }
298
299 // Check that the parameters start at 1 and go up sequentially.
300 int expectedNumber = 1;
301 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
302 it++) {
303 const int number = it->first;
304 const FieldDescriptor* field = it->second;
305 if (number != expectedNumber) {
306 print_error(field,
307 "Fields must be numbered consecutively starting at 1:"
308 " '%s' is %d but should be %d\n",
309 field->name().c_str(), number, expectedNumber);
310 errorCount++;
311 expectedNumber = number;
312 continue;
313 }
314 expectedNumber++;
315 }
316
317 // Check that only allowed types are present. Remove any invalid ones.
318 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
319 it++) {
320 const FieldDescriptor* field = it->second;
321 bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
322 os::statsd::LogMode::MODE_BYTES;
323
324 java_type_t javaType = java_type(field);
325
326 if (javaType == JAVA_TYPE_UNKNOWN) {
327 print_error(field, "Unknown type for field: %s\n", field->name().c_str());
328 errorCount++;
329 continue;
330 } else if (javaType == JAVA_TYPE_OBJECT && atomDecl->code < PULL_ATOM_START_ID) {
331 // Allow attribution chain, but only at position 1.
332 print_error(field, "Message type not allowed for field in pushed atoms: %s\n",
333 field->name().c_str());
334 errorCount++;
335 continue;
336 } else if (javaType == JAVA_TYPE_BYTE_ARRAY && !isBinaryField) {
337 print_error(field, "Raw bytes type not allowed for field: %s\n", field->name().c_str());
338 errorCount++;
339 continue;
340 }
341
342 if (isBinaryField && javaType != JAVA_TYPE_BYTE_ARRAY) {
343 print_error(field, "Cannot mark field %s as bytes.\n", field->name().c_str());
344 errorCount++;
345 continue;
346 }
347
348 // Doubles are not supported yet.
349 if (javaType == JAVA_TYPE_DOUBLE) {
350 print_error(field,
351 "Doubles are not supported in atoms. Please change field %s "
352 "to float\n",
353 field->name().c_str());
354 errorCount++;
355 continue;
356 }
357
358 if (field->is_repeated() &&
359 !(javaType == JAVA_TYPE_ATTRIBUTION_CHAIN || javaType == JAVA_TYPE_KEY_VALUE_PAIR)) {
360 print_error(field,
361 "Repeated fields are not supported in atoms. Please make "
362 "field %s not "
363 "repeated.\n",
364 field->name().c_str());
365 errorCount++;
366 continue;
367 }
368 }
369
370 // Check that if there's an attribution chain, it's at position 1.
371 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
372 it++) {
373 int number = it->first;
374 if (number != 1) {
375 const FieldDescriptor* field = it->second;
376 java_type_t javaType = java_type(field);
377 if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
378 print_error(field,
379 "AttributionChain fields must have field id 1, in message: '%s'\n",
380 atom->name().c_str());
381 errorCount++;
382 }
383 }
384 }
385
386 // Build the type signature and the atom data.
387 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
388 it++) {
389 const FieldDescriptor* field = it->second;
390 java_type_t javaType = java_type(field);
391 bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
392 os::statsd::LogMode::MODE_BYTES;
393
394 AtomField atField(field->name(), javaType);
395
396 if (javaType == JAVA_TYPE_ENUM) {
397 // All enums are treated as ints when it comes to function signatures.
398 collate_enums(*field->enum_type(), &atField);
399 }
400
401 // Generate signature for pushed atoms
402 if (atomDecl->code < PULL_ATOM_START_ID) {
403 if (javaType == JAVA_TYPE_ENUM) {
404 // All enums are treated as ints when it comes to function signatures.
405 signature->push_back(JAVA_TYPE_INT);
406 } else if (javaType == JAVA_TYPE_OBJECT && isBinaryField) {
407 signature->push_back(JAVA_TYPE_BYTE_ARRAY);
408 } else {
409 signature->push_back(javaType);
410 }
411 }
412
413 atomDecl->fields.push_back(atField);
414
415 errorCount += collate_field_annotations(atomDecl, field, it->first, javaType);
416 }
417
418 return errorCount;
419}
420
421// This function flattens the fields of the AttributionNode proto in an Atom
422// proto and generates the corresponding atom decl and signature.
423bool get_non_chained_node(const Descriptor* atom, AtomDecl* atomDecl,
424 vector<java_type_t>* signature) {
425 // Build a sorted list of the fields. Descriptor has them in source file
426 // order.
427 map<int, const FieldDescriptor*> fields;
428 for (int j = 0; j < atom->field_count(); j++) {
429 const FieldDescriptor* field = atom->field(j);
Yangster-macba5b9e42018-01-10 21:31:59 -0800430 fields[field->number()] = field;
431 }
432
433 AtomDecl attributionDecl;
434 vector<java_type_t> attributionSignature;
Muhammad Qureshia345af92020-03-24 17:05:14 -0700435 collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl,
436 &attributionSignature);
Yangster-macba5b9e42018-01-10 21:31:59 -0800437
438 // Build the type signature and the atom data.
439 bool has_attribution_node = false;
Muhammad Qureshia345af92020-03-24 17:05:14 -0700440 for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
441 it++) {
442 const FieldDescriptor* field = it->second;
Yangster-macba5b9e42018-01-10 21:31:59 -0800443 java_type_t javaType = java_type(field);
444 if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700445 atomDecl->fields.insert(atomDecl->fields.end(), attributionDecl.fields.begin(),
446 attributionDecl.fields.end());
447 signature->insert(signature->end(), attributionSignature.begin(),
448 attributionSignature.end());
Yangster-macba5b9e42018-01-10 21:31:59 -0800449 has_attribution_node = true;
450
451 } else {
452 AtomField atField(field->name(), javaType);
453 if (javaType == JAVA_TYPE_ENUM) {
454 // All enums are treated as ints when it comes to function signatures.
455 signature->push_back(JAVA_TYPE_INT);
456 collate_enums(*field->enum_type(), &atField);
457 } else {
458 signature->push_back(javaType);
459 }
460 atomDecl->fields.push_back(atField);
461 }
462 }
463 return has_attribution_node;
464}
465
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700466static void populateFieldNumberToAtomDeclSet(const shared_ptr<AtomDecl>& atomDecl,
467 FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet) {
468 for (FieldNumberToAnnotations::const_iterator it = atomDecl->fieldNumberToAnnotations.begin();
469 it != atomDecl->fieldNumberToAnnotations.end(); it++) {
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700470 const int fieldNumber = it->first;
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700471 (*fieldNumberToAtomDeclSet)[fieldNumber].insert(atomDecl);
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700472 }
473}
474
Yangster-mac7604aea2017-12-11 22:55:49 -0800475/**
Yao Chend54f9dd2017-10-17 17:37:48 +0000476 * Gather the info about the atoms.
477 */
Muhammad Qureshia345af92020-03-24 17:05:14 -0700478int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms) {
479 int errorCount = 0;
Yao Chend54f9dd2017-10-17 17:37:48 +0000480
Muhammad Qureshia345af92020-03-24 17:05:14 -0700481 for (int i = 0; i < descriptor->field_count(); i++) {
482 const FieldDescriptor* atomField = descriptor->field(i);
Yao Chend54f9dd2017-10-17 17:37:48 +0000483
Muhammad Qureshia345af92020-03-24 17:05:14 -0700484 if (moduleName != DEFAULT_MODULE_NAME) {
485 const int moduleCount = atomField->options().ExtensionSize(os::statsd::module);
486 int j;
487 for (j = 0; j < moduleCount; ++j) {
488 const string atomModuleName =
489 atomField->options().GetExtension(os::statsd::module, j);
490 if (atomModuleName == moduleName) {
491 break;
492 }
493 }
494
495 // This atom is not in the module we're interested in; skip it.
496 if (moduleCount == j) {
497 if (dbg) {
498 printf(" Skipping %s (%d)\n", atomField->name().c_str(), atomField->number());
499 }
500 continue;
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700501 }
502 }
503
Muhammad Qureshia345af92020-03-24 17:05:14 -0700504 if (dbg) {
505 printf(" %s (%d)\n", atomField->name().c_str(), atomField->number());
506 }
507
508 // StatsEvent only has one oneof, which contains only messages. Don't allow
509 // other types.
510 if (atomField->type() != FieldDescriptor::TYPE_MESSAGE) {
511 print_error(atomField,
512 "Bad type for atom. StatsEvent can only have message type "
513 "fields: %s\n",
514 atomField->name().c_str());
515 errorCount++;
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700516 continue;
517 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700518
519 const Descriptor* atom = atomField->message_type();
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700520 shared_ptr<AtomDecl> atomDecl =
521 make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
Muhammad Qureshia345af92020-03-24 17:05:14 -0700522
523 if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) {
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700524 atomDecl->whitelisted = true;
Muhammad Qureshia345af92020-03-24 17:05:14 -0700525 if (dbg) {
526 printf("%s is whitelisted\n", atomField->name().c_str());
527 }
528 }
529
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700530 if (atomDecl->code < PULL_ATOM_START_ID &&
Muhammad Qureshia345af92020-03-24 17:05:14 -0700531 atomField->options().GetExtension(os::statsd::truncate_timestamp)) {
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700532 addAnnotationToAtomDecl(atomDecl.get(), ATOM_ID_FIELD_NUMBER,
Muhammad Qureshia345af92020-03-24 17:05:14 -0700533 ANNOTATION_ID_TRUNCATE_TIMESTAMP, ANNOTATION_TYPE_BOOL,
534 AnnotationValue(true));
535 if (dbg) {
536 printf("%s can have timestamp truncated\n", atomField->name().c_str());
537 }
538 }
539
540 vector<java_type_t> signature;
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700541 errorCount += collate_atom(atom, atomDecl.get(), &signature);
542 if (atomDecl->primaryFields.size() != 0 && atomDecl->exclusiveField == 0) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700543 print_error(atomField, "Cannot have a primary field without an exclusive field: %s\n",
544 atomField->name().c_str());
545 errorCount++;
546 continue;
547 }
548
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700549 FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = atoms->signatureInfoMap[signature];
550 populateFieldNumberToAtomDeclSet(atomDecl, &fieldNumberToAtomDeclSet);
Muhammad Qureshia345af92020-03-24 17:05:14 -0700551
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700552 atoms->decls.insert(atomDecl);
553
554 shared_ptr<AtomDecl> nonChainedAtomDecl =
555 make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
Muhammad Qureshia345af92020-03-24 17:05:14 -0700556 vector<java_type_t> nonChainedSignature;
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700557 if (get_non_chained_node(atom, nonChainedAtomDecl.get(), &nonChainedSignature)) {
558 FieldNumberToAtomDeclSet& nonChainedFieldNumberToAtomDeclSet =
Muhammad Qureshia345af92020-03-24 17:05:14 -0700559 atoms->nonChainedSignatureInfoMap[nonChainedSignature];
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700560 populateFieldNumberToAtomDeclSet(nonChainedAtomDecl,
561 &nonChainedFieldNumberToAtomDeclSet);
562
563 atoms->non_chained_decls.insert(nonChainedAtomDecl);
Muhammad Qureshia345af92020-03-24 17:05:14 -0700564 }
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700565 }
566
Yao Chend54f9dd2017-10-17 17:37:48 +0000567 if (dbg) {
Muhammad Qureshia345af92020-03-24 17:05:14 -0700568 printf("signatures = [\n");
Muhammad Qureshic6c38632020-03-25 17:45:01 -0700569 for (SignatureInfoMap::const_iterator it = atoms->signatureInfoMap.begin();
Muhammad Qureshia345af92020-03-24 17:05:14 -0700570 it != atoms->signatureInfoMap.end(); it++) {
571 printf(" ");
572 for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
573 jt++) {
574 printf(" %d", (int)*jt);
575 }
576 printf("\n");
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700577 }
Muhammad Qureshia345af92020-03-24 17:05:14 -0700578 printf("]\n");
Muhammad Qureshi9b995802020-03-20 13:55:51 -0700579 }
580
Muhammad Qureshia345af92020-03-24 17:05:14 -0700581 return errorCount;
Yao Chend54f9dd2017-10-17 17:37:48 +0000582}
583
584} // namespace stats_log_api_gen
585} // namespace android