1 /*
2 * Copyright (C) 2019, 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 "native_writer.h"
18
19 #include "utils.h"
20
21 namespace android {
22 namespace stats_log_api_gen {
23
write_native_annotation_constants(FILE * out)24 static void write_native_annotation_constants(FILE* out) {
25 fprintf(out, "// Annotation constants.\n");
26
27 const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
28 for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
29 fprintf(out, "const uint8_t %s = %hhu;\n", name.c_str(), id);
30 }
31 fprintf(out, "\n");
32 }
33
write_annotations(FILE * out,int argIndex,const FieldNumberToAtomDeclSet & fieldNumberToAtomDeclSet,const string & methodPrefix,const string & methodSuffix,const int minApiLevel)34 static void write_annotations(FILE* out, int argIndex,
35 const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
36 const string& methodPrefix, const string& methodSuffix,
37 const int minApiLevel) {
38 FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
39 fieldNumberToAtomDeclSet.find(argIndex);
40 if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) {
41 return;
42 }
43 const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
44 const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
45 const string constantPrefix = minApiLevel > API_R ? "ASTATSLOG_" : "";
46 for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
47 const string atomConstant = make_constant_name(atomDecl->name);
48 fprintf(out, " if (%s == code) {\n", atomConstant.c_str());
49 const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
50 int resetState = -1;
51 int defaultState = -1;
52 for (const shared_ptr<Annotation>& annotation : annotations) {
53 const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
54 switch (annotation->type) {
55 case ANNOTATION_TYPE_INT:
56 if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
57 resetState = annotation->value.intValue;
58 } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
59 defaultState = annotation->value.intValue;
60 } else {
61 fprintf(out, " %saddInt32Annotation(%s%s%s, %d);\n",
62 methodPrefix.c_str(), methodSuffix.c_str(),
63 constantPrefix.c_str(), annotationConstant.c_str(),
64 annotation->value.intValue);
65 }
66 break;
67 case ANNOTATION_TYPE_BOOL:
68 fprintf(out, " %saddBoolAnnotation(%s%s%s, %s);\n", methodPrefix.c_str(),
69 methodSuffix.c_str(), constantPrefix.c_str(),
70 annotationConstant.c_str(),
71 annotation->value.boolValue ? "true" : "false");
72 break;
73 default:
74 break;
75 }
76 }
77 if (defaultState != -1 && resetState != -1) {
78 const string& annotationConstant =
79 ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
80 fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
81 fprintf(out, " %saddInt32Annotation(%s%s%s, %d);\n", methodPrefix.c_str(),
82 methodSuffix.c_str(), constantPrefix.c_str(), annotationConstant.c_str(),
83 defaultState);
84 fprintf(out, " }\n");
85 }
86 fprintf(out, " }\n");
87 }
88 }
89
write_native_method_signature(FILE * out,const string & signaturePrefix,const vector<java_type_t> & signature,const AtomDecl & attributionDecl,const string & closer)90 static void write_native_method_signature(FILE* out, const string& signaturePrefix,
91 const vector<java_type_t>& signature,
92 const AtomDecl& attributionDecl, const string& closer) {
93 fprintf(out, "%sint32_t code", signaturePrefix.c_str());
94 int argIndex = 1;
95 for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
96 arg++) {
97 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
98 for (const auto& chainField : attributionDecl.fields) {
99 if (chainField.javaType == JAVA_TYPE_STRING) {
100 fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType),
101 chainField.name.c_str());
102 } else {
103 fprintf(out, ", const %s* %s, size_t %s_length",
104 cpp_type_name(chainField.javaType), chainField.name.c_str(),
105 chainField.name.c_str());
106 }
107 }
108 } else {
109 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
110
111 if (*arg == JAVA_TYPE_BOOLEAN_ARRAY) {
112 fprintf(out, ", size_t arg%d_length", argIndex);
113 }
114 }
115 argIndex++;
116 }
117 fprintf(out, ")%s\n", closer.c_str());
118 }
119
write_native_method_body(FILE * out,vector<java_type_t> & signature,const FieldNumberToAtomDeclSet & fieldNumberToAtomDeclSet,const AtomDecl & attributionDecl,const int minApiLevel)120 static int write_native_method_body(FILE* out, vector<java_type_t>& signature,
121 const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
122 const AtomDecl& attributionDecl, const int minApiLevel) {
123 int argIndex = 1;
124 fprintf(out, " AStatsEvent_setAtomId(event, code);\n");
125 write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "AStatsEvent_",
126 "event, ", minApiLevel);
127 for (vector<java_type_t>::const_iterator arg = signature.begin();
128 arg != signature.end(); arg++) {
129 if (minApiLevel < API_T && is_repeated_field(*arg)) {
130 fprintf(stderr, "Found repeated field type with min api level < T.");
131 return 1;
132 }
133 switch (*arg) {
134 case JAVA_TYPE_ATTRIBUTION_CHAIN: {
135 const char* uidName = attributionDecl.fields.front().name.c_str();
136 const char* tagName = attributionDecl.fields.back().name.c_str();
137 fprintf(out,
138 " AStatsEvent_writeAttributionChain(event, "
139 "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
140 "static_cast<uint8_t>(%s_length));\n",
141 uidName, tagName, uidName);
142 break;
143 }
144 case JAVA_TYPE_BYTE_ARRAY:
145 fprintf(out,
146 " AStatsEvent_writeByteArray(event, "
147 "reinterpret_cast<const uint8_t*>(arg%d.arg), "
148 "arg%d.arg_length);\n",
149 argIndex, argIndex);
150 break;
151 case JAVA_TYPE_BOOLEAN:
152 fprintf(out, " AStatsEvent_writeBool(event, arg%d);\n", argIndex);
153 break;
154 case JAVA_TYPE_INT:
155 [[fallthrough]];
156 case JAVA_TYPE_ENUM:
157 fprintf(out, " AStatsEvent_writeInt32(event, arg%d);\n", argIndex);
158 break;
159 case JAVA_TYPE_FLOAT:
160 fprintf(out, " AStatsEvent_writeFloat(event, arg%d);\n", argIndex);
161 break;
162 case JAVA_TYPE_LONG:
163 fprintf(out, " AStatsEvent_writeInt64(event, arg%d);\n", argIndex);
164 break;
165 case JAVA_TYPE_STRING:
166 fprintf(out, " AStatsEvent_writeString(event, arg%d);\n", argIndex);
167 break;
168 case JAVA_TYPE_BOOLEAN_ARRAY:
169 fprintf(out, " AStatsEvent_writeBoolArray(event, arg%d, arg%d_length);\n",
170 argIndex, argIndex);
171 break;
172 case JAVA_TYPE_INT_ARRAY:
173 [[fallthrough]];
174 case JAVA_TYPE_ENUM_ARRAY:
175 fprintf(out,
176 " AStatsEvent_writeInt32Array(event, arg%d.data(), arg%d.size());\n",
177 argIndex, argIndex);
178 break;
179 case JAVA_TYPE_FLOAT_ARRAY:
180 fprintf(out,
181 " AStatsEvent_writeFloatArray(event, arg%d.data(), arg%d.size());\n",
182 argIndex, argIndex);
183 break;
184 case JAVA_TYPE_LONG_ARRAY:
185 fprintf(out,
186 " AStatsEvent_writeInt64Array(event, arg%d.data(), arg%d.size());\n",
187 argIndex, argIndex);
188 break;
189 case JAVA_TYPE_STRING_ARRAY:
190 fprintf(out,
191 " AStatsEvent_writeStringArray(event, arg%d.data(), arg%d.size());\n",
192 argIndex, argIndex);
193 break;
194
195 default:
196 // Unsupported types: OBJECT, DOUBLE
197 fprintf(stderr, "Encountered unsupported type.\n");
198 return 1;
199 }
200 write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "AStatsEvent_",
201 "event, ", minApiLevel);
202 argIndex++;
203 }
204 return 0;
205 }
206
write_native_method_call(FILE * out,const string & methodName,const vector<java_type_t> & signature,const AtomDecl & attributionDecl,int argIndex)207 static void write_native_method_call(FILE* out, const string& methodName,
208 const vector<java_type_t>& signature,
209 const AtomDecl& attributionDecl, int argIndex) {
210 fprintf(out, "%s(code", methodName.c_str());
211 for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
212 arg++) {
213 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
214 for (const auto& chainField : attributionDecl.fields) {
215 if (chainField.javaType == JAVA_TYPE_STRING) {
216 fprintf(out, ", %s", chainField.name.c_str());
217 } else {
218 fprintf(out, ", %s, %s_length", chainField.name.c_str(),
219 chainField.name.c_str());
220 }
221 }
222 } else {
223 fprintf(out, ", arg%d", argIndex);
224
225 if (*arg == JAVA_TYPE_BOOLEAN_ARRAY) {
226 fprintf(out, ", arg%d_length", argIndex);
227 }
228 }
229 argIndex++;
230 }
231 fprintf(out, ");\n");
232 }
233
write_native_stats_write_methods(FILE * out,const SignatureInfoMap & signatureInfoMap,const AtomDecl & attributionDecl,const int minApiLevel,bool bootstrap)234 static int write_native_stats_write_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
235 const AtomDecl& attributionDecl, const int minApiLevel,
236 bool bootstrap) {
237 fprintf(out, "\n");
238 for (auto signatureInfoMapIt = signatureInfoMap.begin();
239 signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
240 vector<java_type_t> signature = signatureInfoMapIt->first;
241 const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
242 write_native_method_signature(out, "int stats_write(", signature, attributionDecl, " {");
243
244 // Write method body.
245 if (bootstrap) {
246 fprintf(out, " ::android::os::StatsBootstrapAtom atom;\n");
247 fprintf(out, " atom.atomId = code;\n");
248 FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
249 fieldNumberToAtomDeclSet.find(ATOM_ID_FIELD_NUMBER);
250 if (fieldNumberToAtomDeclSet.end() != fieldNumberToAtomDeclSetIt) {
251 fprintf(stderr, "Bootstrap atoms do not support annotations\n");
252 return 1;
253 }
254 int argIndex = 1;
255 const char* atomVal = "::android::os::StatsBootstrapAtomValue::";
256 for (vector<java_type_t>::const_iterator arg = signature.begin();
257 arg != signature.end(); arg++) {
258 switch (*arg) {
259 case JAVA_TYPE_BYTE_ARRAY:
260 fprintf(out,
261 " const uint8_t* arg%dbyte = reinterpret_cast<const "
262 "uint8_t*>(arg%d.arg);\n",
263 argIndex, argIndex);
264 fprintf(out,
265 " "
266 "atom.values.push_back(%smake<%sbytesValue>(std::vector(arg%dbyte, "
267 "arg%dbyte + arg%d.arg_length)));\n",
268 atomVal, atomVal, argIndex, argIndex, argIndex);
269 break;
270 case JAVA_TYPE_BOOLEAN:
271 fprintf(out, " atom.values.push_back(%smake<%sboolValue>(arg%d));\n",
272 atomVal, atomVal, argIndex);
273 break;
274 case JAVA_TYPE_INT: // Fall through.
275 case JAVA_TYPE_ENUM:
276 fprintf(out, " atom.values.push_back(%smake<%sintValue>(arg%d));\n",
277 atomVal, atomVal, argIndex);
278 break;
279 case JAVA_TYPE_FLOAT:
280 fprintf(out, " atom.values.push_back(%smake<%sfloatValue>(arg%d));\n",
281 atomVal, atomVal, argIndex);
282 break;
283 case JAVA_TYPE_LONG:
284 fprintf(out, " atom.values.push_back(%smake<%slongValue>(arg%d));\n",
285 atomVal, atomVal, argIndex);
286 break;
287 case JAVA_TYPE_STRING:
288 fprintf(out,
289 " atom.values.push_back(%smake<%sstringValue>("
290 "::android::String16(arg%d)));\n",
291 atomVal, atomVal, argIndex);
292 break;
293 default:
294 // Unsupported types: OBJECT, DOUBLE, ATTRIBUTION_CHAIN,
295 // and all repeated fields
296 fprintf(stderr, "Encountered unsupported type.\n");
297 return 1;
298 }
299 FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
300 fieldNumberToAtomDeclSet.find(argIndex);
301 if (fieldNumberToAtomDeclSet.end() != fieldNumberToAtomDeclSetIt) {
302 fprintf(stderr, "Bootstrap atoms do not support annotations\n");
303 return 1;
304 }
305 argIndex++;
306 }
307 fprintf(out,
308 " bool success = "
309 "::android::os::stats::StatsBootstrapAtomClient::reportBootstrapAtom(atom);\n");
310 fprintf(out, " return success? 0 : -1;\n");
311
312 } else if (minApiLevel == API_Q) {
313 int argIndex = 1;
314 fprintf(out, " StatsEventCompat event;\n");
315 fprintf(out, " event.setAtomId(code);\n");
316 write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "event.", "",
317 minApiLevel);
318 for (vector<java_type_t>::const_iterator arg = signature.begin();
319 arg != signature.end(); arg++) {
320 switch (*arg) {
321 case JAVA_TYPE_ATTRIBUTION_CHAIN: {
322 const char* uidName = attributionDecl.fields.front().name.c_str();
323 const char* tagName = attributionDecl.fields.back().name.c_str();
324 fprintf(out, " event.writeAttributionChain(%s, %s_length, %s);\n",
325 uidName, uidName, tagName);
326 break;
327 }
328 case JAVA_TYPE_BYTE_ARRAY:
329 fprintf(out, " event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
330 argIndex, argIndex);
331 break;
332 case JAVA_TYPE_BOOLEAN:
333 fprintf(out, " event.writeBool(arg%d);\n", argIndex);
334 break;
335 case JAVA_TYPE_INT: // Fall through.
336 case JAVA_TYPE_ENUM:
337 fprintf(out, " event.writeInt32(arg%d);\n", argIndex);
338 break;
339 case JAVA_TYPE_FLOAT:
340 fprintf(out, " event.writeFloat(arg%d);\n", argIndex);
341 break;
342 case JAVA_TYPE_LONG:
343 fprintf(out, " event.writeInt64(arg%d);\n", argIndex);
344 break;
345 case JAVA_TYPE_STRING:
346 fprintf(out, " event.writeString(arg%d);\n", argIndex);
347 break;
348 default:
349 // Unsupported types: OBJECT, DOUBLE, and all repeated
350 // fields.
351 fprintf(stderr, "Encountered unsupported type.\n");
352 return 1;
353 }
354 write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "event.", "",
355 minApiLevel);
356 argIndex++;
357 }
358 fprintf(out, " return event.writeToSocket();\n"); // end method body.
359 } else {
360 fprintf(out, " AStatsEvent* event = AStatsEvent_obtain();\n");
361 int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
362 attributionDecl, minApiLevel);
363 if (ret != 0) {
364 return ret;
365 }
366 fprintf(out, " const int ret = AStatsEvent_write(event);\n");
367 fprintf(out, " AStatsEvent_release(event);\n");
368 fprintf(out, " return ret;\n"); // end method body.
369 }
370 fprintf(out, "}\n\n"); // end method.
371 }
372 return 0;
373 }
374
write_native_stats_write_non_chained_methods(FILE * out,const SignatureInfoMap & signatureInfoMap,const AtomDecl & attributionDecl)375 static void write_native_stats_write_non_chained_methods(FILE* out,
376 const SignatureInfoMap& signatureInfoMap,
377 const AtomDecl& attributionDecl) {
378 fprintf(out, "\n");
379 for (auto signature_it = signatureInfoMap.begin();
380 signature_it != signatureInfoMap.end(); signature_it++) {
381 vector<java_type_t> signature = signature_it->first;
382
383 write_native_method_signature(out, "int stats_write_non_chained(", signature,
384 attributionDecl, " {");
385
386 vector<java_type_t> newSignature;
387
388 // First two args form the attribution node so size goes down by 1.
389 newSignature.reserve(signature.size() - 1);
390
391 // First arg is Attribution Chain.
392 newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
393
394 // Followed by the originial signature except the first 2 args.
395 newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
396
397 const char* uidName = attributionDecl.fields.front().name.c_str();
398 const char* tagName = attributionDecl.fields.back().name.c_str();
399 fprintf(out, " const int32_t* %s = &arg1;\n", uidName);
400 fprintf(out, " const size_t %s_length = 1;\n", uidName);
401 fprintf(out, " const std::vector<char const*> %s(1, arg2);\n", tagName);
402 fprintf(out, " return ");
403 write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
404
405 fprintf(out, "}\n\n");
406 }
407 }
408
write_native_build_stats_event_methods(FILE * out,const SignatureInfoMap & signatureInfoMap,const AtomDecl & attributionDecl,const int minApiLevel)409 static int write_native_build_stats_event_methods(FILE* out,
410 const SignatureInfoMap& signatureInfoMap,
411 const AtomDecl& attributionDecl,
412 const int minApiLevel) {
413 fprintf(out, "\n");
414 for (auto signatureInfoMapIt = signatureInfoMap.begin();
415 signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
416 vector<java_type_t> signature = signatureInfoMapIt->first;
417 const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
418 write_native_method_signature(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
419 signature, attributionDecl, " {");
420
421 fprintf(out, " AStatsEvent* event = AStatsEventList_addStatsEvent(pulled_data);\n");
422 int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
423 attributionDecl, minApiLevel);
424 if (ret != 0) {
425 return ret;
426 }
427 fprintf(out, " AStatsEvent_build(event);\n"); // end method body.
428
429 fprintf(out, "}\n\n"); // end method.
430 }
431 return 0;
432 }
433
write_native_method_header(FILE * out,const string & methodName,const SignatureInfoMap & signatureInfoMap,const AtomDecl & attributionDecl)434 static void write_native_method_header(FILE* out, const string& methodName,
435 const SignatureInfoMap& signatureInfoMap,
436 const AtomDecl& attributionDecl) {
437 for (auto signatureInfoMapIt = signatureInfoMap.begin();
438 signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
439 vector<java_type_t> signature = signatureInfoMapIt->first;
440
441 write_native_method_signature(out, methodName, signature, attributionDecl, ";");
442 }
443 }
444
write_stats_log_cpp(FILE * out,const Atoms & atoms,const AtomDecl & attributionDecl,const string & cppNamespace,const string & importHeader,const int minApiLevel,bool bootstrap)445 int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
446 const string& cppNamespace, const string& importHeader,
447 const int minApiLevel, bool bootstrap) {
448 // Print prelude
449 fprintf(out, "// This file is autogenerated\n");
450 fprintf(out, "\n");
451
452 fprintf(out, "#include <%s>\n", importHeader.c_str());
453 if (!bootstrap) {
454 if (minApiLevel == API_Q) {
455 fprintf(out, "#include <StatsEventCompat.h>\n");
456 } else {
457 fprintf(out, "#include <stats_event.h>\n");
458 }
459
460 if (minApiLevel > API_R) {
461 fprintf(out, "#include <stats_annotations.h>\n");
462 }
463
464 if (minApiLevel > API_Q && !atoms.pulledAtomsSignatureInfoMap.empty()) {
465 fprintf(out, "#include <stats_pull_atom_callback.h>\n");
466 }
467 } else {
468 fprintf(out, "#include <StatsBootstrapAtomClient.h>\n");
469 fprintf(out, "#include <android/os/StatsBootstrapAtom.h>\n");
470 fprintf(out, "#include <utils/String16.h>\n");
471 }
472
473 fprintf(out, "\n");
474 write_namespace(out, cppNamespace);
475
476 int ret = write_native_stats_write_methods(out, atoms.signatureInfoMap, attributionDecl,
477 minApiLevel, bootstrap);
478 if (ret != 0) {
479 return ret;
480 }
481 if (!bootstrap) {
482 write_native_stats_write_non_chained_methods(out, atoms.nonChainedSignatureInfoMap,
483 attributionDecl);
484 ret = write_native_build_stats_event_methods(out, atoms.pulledAtomsSignatureInfoMap,
485 attributionDecl, minApiLevel);
486 if (ret != 0) {
487 return ret;
488 }
489 }
490
491 // Print footer
492 fprintf(out, "\n");
493 write_closing_namespace(out, cppNamespace);
494
495 return 0;
496 }
497
write_stats_log_header(FILE * out,const Atoms & atoms,const AtomDecl & attributionDecl,const string & cppNamespace,const int minApiLevel,bool bootstrap)498 int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
499 const string& cppNamespace, const int minApiLevel, bool bootstrap) {
500 // Print prelude
501 fprintf(out, "// This file is autogenerated\n");
502 fprintf(out, "\n");
503 fprintf(out, "#pragma once\n");
504 fprintf(out, "\n");
505 fprintf(out, "#include <stdint.h>\n");
506 fprintf(out, "#include <vector>\n");
507 fprintf(out, "#include <map>\n");
508 fprintf(out, "#include <set>\n");
509 if (!atoms.pulledAtomsSignatureInfoMap.empty() && !bootstrap) {
510 fprintf(out, "#include <stats_pull_atom_callback.h>\n");
511 }
512 fprintf(out, "\n");
513
514 write_namespace(out, cppNamespace);
515 fprintf(out, "\n");
516 fprintf(out, "/*\n");
517 fprintf(out, " * API For logging statistics events.\n");
518 fprintf(out, " */\n");
519 fprintf(out, "\n");
520
521 write_native_atom_constants(out, atoms, attributionDecl);
522
523 // Print constants for the enum values.
524 fprintf(out, "//\n");
525 fprintf(out, "// Constants for enum values\n");
526 fprintf(out, "//\n\n");
527 for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
528 atomIt++) {
529 for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
530 field != (*atomIt)->fields.end(); field++) {
531 if (field->javaType == JAVA_TYPE_ENUM) {
532 fprintf(out, "// Values for %s.%s\n", (*atomIt)->message.c_str(),
533 field->name.c_str());
534 for (map<int, string>::const_iterator value = field->enumValues.begin();
535 value != field->enumValues.end(); value++) {
536 fprintf(out, "const int32_t %s__%s__%s = %d;\n",
537 make_constant_name((*atomIt)->message).c_str(),
538 make_constant_name(field->name).c_str(),
539 make_constant_name(value->second).c_str(), value->first);
540 }
541 fprintf(out, "\n");
542 }
543 }
544 }
545
546 if (minApiLevel <= API_R) {
547 write_native_annotation_constants(out);
548 }
549
550 fprintf(out, "struct BytesField {\n");
551 fprintf(out,
552 " BytesField(char const* array, size_t len) : arg(array), "
553 "arg_length(len) {}\n");
554 fprintf(out, " char const* arg;\n");
555 fprintf(out, " size_t arg_length;\n");
556 fprintf(out, "};\n");
557 fprintf(out, "\n");
558
559 // Print write methods
560 fprintf(out, "//\n");
561 fprintf(out, "// Write methods\n");
562 fprintf(out, "//\n");
563 write_native_method_header(out, "int stats_write(", atoms.signatureInfoMap, attributionDecl);
564 fprintf(out, "\n");
565
566 // Attribution chains and pulled atoms are not supported for bootstrap processes.
567 if (!bootstrap) {
568 fprintf(out, "//\n");
569 fprintf(out, "// Write flattened methods\n");
570 fprintf(out, "//\n");
571 write_native_method_header(out, "int stats_write_non_chained(",
572 atoms.nonChainedSignatureInfoMap, attributionDecl);
573 fprintf(out, "\n");
574
575 // Print pulled atoms methods.
576 fprintf(out, "//\n");
577 fprintf(out, "// Add AStatsEvent methods\n");
578 fprintf(out, "//\n");
579 write_native_method_header(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
580 atoms.pulledAtomsSignatureInfoMap, attributionDecl);
581 fprintf(out, "\n");
582 }
583
584 write_closing_namespace(out, cppNamespace);
585
586 return 0;
587 }
588
589 } // namespace stats_log_api_gen
590 } // namespace android
591