blob: bbe6d63073c1c028113b7e835051a5e4eb4cefe4 [file] [log] [blame]
Yao Chend54f9dd2017-10-17 17:37:48 +00001
2
3#include "Collation.h"
4
Stefan Lafonae2df012017-11-14 09:17:21 -08005#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
Yao Chend54f9dd2017-10-17 17:37:48 +00006
7#include <set>
8#include <vector>
9
10#include <getopt.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15using namespace google::protobuf;
16using namespace std;
17
18namespace android {
19namespace stats_log_api_gen {
20
Yao Chenb3561512017-11-21 18:07:17 -080021const int PULL_ATOM_START_ID = 1000;
22
23int maxPushedAtomId = 2;
24
Stefan Lafonae2df012017-11-14 09:17:21 -080025using android::os::statsd::Atom;
Yao Chend54f9dd2017-10-17 17:37:48 +000026
Yao Chend54f9dd2017-10-17 17:37:48 +000027/**
28 * Turn lower and camel case into upper case with underscores.
29 */
30static string
31make_constant_name(const string& str)
32{
33 string result;
34 const int N = str.size();
35 bool underscore_next = false;
36 for (int i=0; i<N; i++) {
37 char c = str[i];
38 if (c >= 'A' && c <= 'Z') {
39 if (underscore_next) {
40 result += '_';
41 underscore_next = false;
42 }
43 } else if (c >= 'a' && c <= 'z') {
44 c = 'A' + c - 'a';
45 underscore_next = true;
46 } else if (c == '_') {
47 underscore_next = false;
48 }
49 result += c;
50 }
51 return result;
52}
53
54static const char*
55cpp_type_name(java_type_t type)
56{
57 switch (type) {
58 case JAVA_TYPE_BOOLEAN:
59 return "bool";
60 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -070061 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +000062 return "int32_t";
63 case JAVA_TYPE_LONG:
64 return "int64_t";
65 case JAVA_TYPE_FLOAT:
66 return "float";
67 case JAVA_TYPE_DOUBLE:
68 return "double";
69 case JAVA_TYPE_STRING:
70 return "char const*";
71 default:
72 return "UNKNOWN";
73 }
74}
75
76static const char*
77java_type_name(java_type_t type)
78{
79 switch (type) {
80 case JAVA_TYPE_BOOLEAN:
81 return "boolean";
82 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -070083 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +000084 return "int";
85 case JAVA_TYPE_LONG:
86 return "long";
87 case JAVA_TYPE_FLOAT:
88 return "float";
89 case JAVA_TYPE_DOUBLE:
90 return "double";
91 case JAVA_TYPE_STRING:
92 return "java.lang.String";
93 default:
94 return "UNKNOWN";
95 }
96}
97
Yangster-mac7604aea2017-12-11 22:55:49 -080098static int write_stats_log_cpp(FILE *out, const Atoms &atoms,
99 const AtomDecl &attributionDecl) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000100 // Print prelude
101 fprintf(out, "// This file is autogenerated\n");
102 fprintf(out, "\n");
103
Yangster-mac7604aea2017-12-11 22:55:49 -0800104 fprintf(out, "#include <exception>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000105 fprintf(out, "#include <log/log_event_list.h>\n");
106 fprintf(out, "#include <log/log.h>\n");
107 fprintf(out, "#include <statslog.h>\n");
108 fprintf(out, "\n");
109
110 fprintf(out, "namespace android {\n");
111 fprintf(out, "namespace util {\n");
Yao Chen80235402017-11-13 20:42:25 -0800112 fprintf(out, "// the single event tag id for all stats logs\n");
113 fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000114
115 // Print write methods
116 fprintf(out, "\n");
117 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800118 signature != atoms.signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000119 int argIndex;
120
121 fprintf(out, "void\n");
Yao Chen80235402017-11-13 20:42:25 -0800122 fprintf(out, "stats_write(int32_t code");
Yao Chend54f9dd2017-10-17 17:37:48 +0000123 argIndex = 1;
124 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800125 arg != signature->end(); arg++) {
126 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
127 for (auto chainField : attributionDecl.fields) {
128 if (chainField.javaType == JAVA_TYPE_STRING) {
129 fprintf(out, ", const std::vector<%s>& %s",
130 cpp_type_name(chainField.javaType),
131 chainField.name.c_str());
132 } else {
133 fprintf(out, ", const %s* %s, size_t %s_length",
134 cpp_type_name(chainField.javaType),
135 chainField.name.c_str(), chainField.name.c_str());
136 }
137 }
138 } else {
139 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
140 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000141 argIndex++;
142 }
143 fprintf(out, ")\n");
144
145 fprintf(out, "{\n");
146 argIndex = 1;
Yao Chen80235402017-11-13 20:42:25 -0800147 fprintf(out, " android_log_event_list event(kStatsEventTag);\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800148 fprintf(out, " event << code;\n\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000149 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800150 arg != signature->end(); arg++) {
151 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
152 for (const auto &chainField : attributionDecl.fields) {
153 if (chainField.javaType == JAVA_TYPE_STRING) {
154 fprintf(out, " if (%s_length != %s.size()) {\n",
155 attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
156 fprintf(out, " throw std::invalid_argument(\"attribution fields with"
157 " diff length: %s vs %s\");\n",
158 attributionDecl.fields.front().name.c_str(),
159 chainField.name.c_str());
160 fprintf(out, " return;\n");
161 fprintf(out, " }\n");
162 }
163 }
164 fprintf(out, "\n event.begin();\n");
165 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
166 attributionDecl.fields.front().name.c_str());
167 fprintf(out, " event.begin();\n");
168 for (const auto &chainField : attributionDecl.fields) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800169 if (chainField.javaType == JAVA_TYPE_STRING) {
170 fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
171 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
172 fprintf(out, " } else {\n");
173 fprintf(out, " event << \"\";\n");
174 fprintf(out, " }\n");
175 } else {
176 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
177 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800178 }
179 fprintf(out, " event.end();\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000180 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800181 fprintf(out, " event.end();\n\n");
182 } else {
183 if (*arg == JAVA_TYPE_STRING) {
184 fprintf(out, " if (arg%d == NULL) {\n", argIndex);
185 fprintf(out, " arg%d = \"\";\n", argIndex);
186 fprintf(out, " }\n");
187 }
188 fprintf(out, " event << arg%d;\n", argIndex);
Yao Chend54f9dd2017-10-17 17:37:48 +0000189 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000190 argIndex++;
191 }
192
193 fprintf(out, " event.write(LOG_ID_STATS);\n");
194 fprintf(out, "}\n");
195 fprintf(out, "\n");
196 }
197
198 // Print footer
199 fprintf(out, "\n");
200 fprintf(out, "} // namespace util\n");
201 fprintf(out, "} // namespace android\n");
202
203 return 0;
204}
205
206
207static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800208write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000209{
Yao Chend54f9dd2017-10-17 17:37:48 +0000210 // Print prelude
211 fprintf(out, "// This file is autogenerated\n");
212 fprintf(out, "\n");
213 fprintf(out, "#pragma once\n");
214 fprintf(out, "\n");
215 fprintf(out, "#include <stdint.h>\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800216 fprintf(out, "#include <vector>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000217 fprintf(out, "\n");
218
219 fprintf(out, "namespace android {\n");
220 fprintf(out, "namespace util {\n");
221 fprintf(out, "\n");
222 fprintf(out, "/*\n");
223 fprintf(out, " * API For logging statistics events.\n");
224 fprintf(out, " */\n");
225 fprintf(out, "\n");
226 fprintf(out, "/**\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700227 fprintf(out, " * Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000228 fprintf(out, " */\n");
229 fprintf(out, "enum {\n");
230
231 size_t i = 0;
232 // Print constants
233 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800234 atom != atoms.decls.end(); atom++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000235 string constant = make_constant_name(atom->name);
236 fprintf(out, "\n");
237 fprintf(out, " /**\n");
238 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
239 fprintf(out, " * Usage: stats_write(StatsLog.%s", constant.c_str());
240 for (vector<AtomField>::const_iterator field = atom->fields.begin();
241 field != atom->fields.end(); field++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800242 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
243 for (auto chainField : attributionDecl.fields) {
244 if (chainField.javaType == JAVA_TYPE_STRING) {
245 fprintf(out, ", const std::vector<%s>& %s",
246 cpp_type_name(chainField.javaType),
247 chainField.name.c_str());
248 } else {
249 fprintf(out, ", const %s* %s, size_t %s_length",
250 cpp_type_name(chainField.javaType),
251 chainField.name.c_str(), chainField.name.c_str());
252 }
253 }
254 } else {
255 fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
256 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000257 }
258 fprintf(out, ");\n");
259 fprintf(out, " */\n");
260 char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
261 fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
Yao Chenb3561512017-11-21 18:07:17 -0800262 if (atom->code < PULL_ATOM_START_ID && atom->code > maxPushedAtomId) {
263 maxPushedAtomId = atom->code;
264 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000265 i++;
266 }
267 fprintf(out, "\n");
268 fprintf(out, "};\n");
269 fprintf(out, "\n");
270
Yangster-mac7604aea2017-12-11 22:55:49 -0800271 fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", maxPushedAtomId);
Yao Chenb3561512017-11-21 18:07:17 -0800272
Yao Chend54f9dd2017-10-17 17:37:48 +0000273 // Print write methods
274 fprintf(out, "//\n");
275 fprintf(out, "// Write methods\n");
276 fprintf(out, "//\n");
277 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
278 signature != atoms.signatures.end(); signature++) {
Yao Chen80235402017-11-13 20:42:25 -0800279 fprintf(out, "void stats_write(int32_t code ");
Yao Chend54f9dd2017-10-17 17:37:48 +0000280 int argIndex = 1;
281 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800282 arg != signature->end(); arg++) {
283 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
284 for (auto chainField : attributionDecl.fields) {
285 if (chainField.javaType == JAVA_TYPE_STRING) {
286 fprintf(out, ", const std::vector<%s>& %s",
287 cpp_type_name(chainField.javaType), chainField.name.c_str());
288 } else {
289 fprintf(out, ", const %s* %s, size_t %s_length",
290 cpp_type_name(chainField.javaType),
291 chainField.name.c_str(), chainField.name.c_str());
292 }
293 }
294 } else {
295 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
296 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000297 argIndex++;
298 }
299 fprintf(out, ");\n");
300 }
301
302 fprintf(out, "\n");
303 fprintf(out, "} // namespace util\n");
304 fprintf(out, "} // namespace android\n");
305
306 return 0;
307}
308
309static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800310write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000311{
Yao Chend54f9dd2017-10-17 17:37:48 +0000312 // Print prelude
313 fprintf(out, "// This file is autogenerated\n");
314 fprintf(out, "\n");
315 fprintf(out, "package android.util;\n");
316 fprintf(out, "\n");
317 fprintf(out, "\n");
318 fprintf(out, "/**\n");
319 fprintf(out, " * API For logging statistics events.\n");
320 fprintf(out, " * @hide\n");
321 fprintf(out, " */\n");
David Chen0a368b22017-12-06 16:28:16 -0800322 fprintf(out, "public class StatsLogInternal {\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700323 fprintf(out, " // Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000324
Stefan Lafon9478f352017-10-30 21:20:20 -0700325 // Print constants for the atom codes.
Yao Chend54f9dd2017-10-17 17:37:48 +0000326 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
327 atom != atoms.decls.end(); atom++) {
328 string constant = make_constant_name(atom->name);
329 fprintf(out, "\n");
330 fprintf(out, " /**\n");
331 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
332 fprintf(out, " * Usage: StatsLog.write(StatsLog.%s", constant.c_str());
333 for (vector<AtomField>::const_iterator field = atom->fields.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800334 field != atom->fields.end(); field++) {
335 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
336 for (auto chainField : attributionDecl.fields) {
337 fprintf(out, ", %s[] %s",
338 java_type_name(chainField.javaType), chainField.name.c_str());
339 }
340 } else {
341 fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
342 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000343 }
344 fprintf(out, ");\n");
345 fprintf(out, " */\n");
346 fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
347 }
348 fprintf(out, "\n");
349
Stefan Lafon9478f352017-10-30 21:20:20 -0700350 // Print constants for the enum values.
351 fprintf(out, " // Constants for enum values.\n\n");
352 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800353 atom != atoms.decls.end(); atom++) {
Stefan Lafon9478f352017-10-30 21:20:20 -0700354 for (vector<AtomField>::const_iterator field = atom->fields.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800355 field != atom->fields.end(); field++) {
356 if (field->javaType == JAVA_TYPE_ENUM) {
357 fprintf(out, " // Values for %s.%s\n", atom->message.c_str(),
358 field->name.c_str());
359 for (map<int, string>::const_iterator value = field->enumValues.begin();
360 value != field->enumValues.end(); value++) {
361 fprintf(out, " public static final int %s__%s__%s = %d;\n",
362 make_constant_name(atom->message).c_str(),
363 make_constant_name(field->name).c_str(),
364 make_constant_name(value->second).c_str(),
365 value->first);
366 }
367 fprintf(out, "\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700368 }
Stefan Lafon9478f352017-10-30 21:20:20 -0700369 }
370 }
371
Yao Chend54f9dd2017-10-17 17:37:48 +0000372 // Print write methods
373 fprintf(out, " // Write methods\n");
374 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800375 signature != atoms.signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000376 fprintf(out, " public static native void write(int code");
377 int argIndex = 1;
378 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800379 arg != signature->end(); arg++) {
380 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
381 for (auto chainField : attributionDecl.fields) {
382 fprintf(out, ", %s[] %s",
383 java_type_name(chainField.javaType), chainField.name.c_str());
384 }
385 } else {
386 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
387 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000388 argIndex++;
389 }
390 fprintf(out, ");\n");
391 }
392
393 fprintf(out, "}\n");
394
395 return 0;
396}
397
398static const char*
399jni_type_name(java_type_t type)
400{
401 switch (type) {
402 case JAVA_TYPE_BOOLEAN:
403 return "jboolean";
404 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700405 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000406 return "jint";
407 case JAVA_TYPE_LONG:
408 return "jlong";
409 case JAVA_TYPE_FLOAT:
410 return "jfloat";
411 case JAVA_TYPE_DOUBLE:
412 return "jdouble";
413 case JAVA_TYPE_STRING:
414 return "jstring";
415 default:
416 return "UNKNOWN";
417 }
418}
419
Yangster-mac7604aea2017-12-11 22:55:49 -0800420static const char*
421jni_array_type_name(java_type_t type)
422{
423 switch (type) {
424 case JAVA_TYPE_INT:
425 return "jintArray";
426 case JAVA_TYPE_STRING:
427 return "jobjectArray";
428 default:
429 return "UNKNOWN";
430 }
431}
432
Yao Chend54f9dd2017-10-17 17:37:48 +0000433static string
434jni_function_name(const vector<java_type_t>& signature)
435{
436 string result("StatsLog_write");
437 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800438 arg != signature.end(); arg++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000439 switch (*arg) {
440 case JAVA_TYPE_BOOLEAN:
441 result += "_boolean";
442 break;
443 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700444 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000445 result += "_int";
446 break;
447 case JAVA_TYPE_LONG:
448 result += "_long";
449 break;
450 case JAVA_TYPE_FLOAT:
451 result += "_float";
452 break;
453 case JAVA_TYPE_DOUBLE:
454 result += "_double";
455 break;
456 case JAVA_TYPE_STRING:
457 result += "_String";
458 break;
Yangster-mac7604aea2017-12-11 22:55:49 -0800459 case JAVA_TYPE_ATTRIBUTION_CHAIN:
460 result += "_AttributionChain";
461 break;
Yao Chend54f9dd2017-10-17 17:37:48 +0000462 default:
463 result += "_UNKNOWN";
464 break;
465 }
466 }
467 return result;
468}
469
470static const char*
471java_type_signature(java_type_t type)
472{
473 switch (type) {
474 case JAVA_TYPE_BOOLEAN:
475 return "Z";
476 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700477 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000478 return "I";
479 case JAVA_TYPE_LONG:
480 return "J";
481 case JAVA_TYPE_FLOAT:
482 return "F";
483 case JAVA_TYPE_DOUBLE:
484 return "D";
485 case JAVA_TYPE_STRING:
486 return "Ljava/lang/String;";
487 default:
488 return "UNKNOWN";
489 }
490}
491
492static string
Yangster-mac7604aea2017-12-11 22:55:49 -0800493jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000494{
495 string result("(I");
496 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800497 arg != signature.end(); arg++) {
498 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
499 for (auto chainField : attributionDecl.fields) {
500 result += "[";
501 result += java_type_signature(chainField.javaType);
502 }
503 } else {
504 result += java_type_signature(*arg);
505 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000506 }
507 result += ")V";
508 return result;
509}
510
511static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800512write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000513{
Yao Chend54f9dd2017-10-17 17:37:48 +0000514 // Print prelude
515 fprintf(out, "// This file is autogenerated\n");
516 fprintf(out, "\n");
517
518 fprintf(out, "#include <statslog.h>\n");
519 fprintf(out, "\n");
520 fprintf(out, "#include <nativehelper/JNIHelp.h>\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800521 fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n");
522 fprintf(out, "#include <utils/Vector.h>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000523 fprintf(out, "#include \"core_jni_helpers.h\"\n");
524 fprintf(out, "#include \"jni.h\"\n");
525 fprintf(out, "\n");
526 fprintf(out, "#define UNUSED __attribute__((__unused__))\n");
527 fprintf(out, "\n");
528
529 fprintf(out, "namespace android {\n");
530 fprintf(out, "\n");
531
532 // Print write methods
533 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800534 signature != atoms.signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000535 int argIndex;
536
537 fprintf(out, "static void\n");
538 fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code",
539 jni_function_name(*signature).c_str());
540 argIndex = 1;
541 for (vector<java_type_t>::const_iterator arg = signature->begin();
542 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800543 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
544 for (auto chainField : attributionDecl.fields) {
545 fprintf(out, ", %s %s", jni_array_type_name(chainField.javaType),
546 chainField.name.c_str());
547 }
548 } else {
549 fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex);
550 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000551 argIndex++;
552 }
553 fprintf(out, ")\n");
554
555 fprintf(out, "{\n");
556
557 // Prepare strings
558 argIndex = 1;
Yangster-mac7604aea2017-12-11 22:55:49 -0800559 bool hadStringOrChain = false;
Yao Chend54f9dd2017-10-17 17:37:48 +0000560 for (vector<java_type_t>::const_iterator arg = signature->begin();
561 arg != signature->end(); arg++) {
562 if (*arg == JAVA_TYPE_STRING) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800563 hadStringOrChain = true;
Yao Chend54f9dd2017-10-17 17:37:48 +0000564 fprintf(out, " const char* str%d;\n", argIndex);
565 fprintf(out, " if (arg%d != NULL) {\n", argIndex);
566 fprintf(out, " str%d = env->GetStringUTFChars(arg%d, NULL);\n",
567 argIndex, argIndex);
568 fprintf(out, " } else {\n");
569 fprintf(out, " str%d = NULL;\n", argIndex);
570 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800571 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
572 hadStringOrChain = true;
573 for (auto chainField : attributionDecl.fields) {
574 fprintf(out, " size_t %s_length = env->GetArrayLength(%s);\n",
575 chainField.name.c_str(), chainField.name.c_str());
576 if (chainField.name != attributionDecl.fields.front().name) {
577 fprintf(out, " if (%s_length != %s_length) {\n",
578 chainField.name.c_str(),
579 attributionDecl.fields.front().name.c_str());
580 fprintf(out, " jniThrowException(env, "
581 "\"java/lang/IllegalArgumentException\", "
582 "\"invalid attribution field(%s) length.\");\n",
583 chainField.name.c_str());
584 fprintf(out, " return;\n");
585 fprintf(out, " }\n");
586 }
587 if (chainField.javaType == JAVA_TYPE_INT) {
588 fprintf(out, " jint* %s_array = env->GetIntArrayElements(%s, NULL);\n",
589 chainField.name.c_str(), chainField.name.c_str());
590 } else if (chainField.javaType == JAVA_TYPE_STRING) {
591 fprintf(out, " std::vector<%s> %s_vec;\n",
592 cpp_type_name(chainField.javaType), chainField.name.c_str());
593 fprintf(out, " std::vector<ScopedUtfChars*> scoped_%s_vec;\n",
594 chainField.name.c_str());
595 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
596 chainField.name.c_str());
597 fprintf(out, " jstring jstr = "
598 "(jstring)env->GetObjectArrayElement(%s, i);\n",
599 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800600 fprintf(out, " if (jstr == NULL) {\n");
601 fprintf(out, " %s_vec.push_back(NULL);\n",
602 chainField.name.c_str());
603 fprintf(out, " } else {\n");
604 fprintf(out, " ScopedUtfChars* scoped_%s = "
Yangster-mac7604aea2017-12-11 22:55:49 -0800605 "new ScopedUtfChars(env, jstr);\n",
606 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800607 fprintf(out, " %s_vec.push_back(scoped_%s->c_str());\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800608 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800609 fprintf(out, " scoped_%s_vec.push_back(scoped_%s);\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800610 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800611 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800612 fprintf(out, " }\n");
613 }
614 fprintf(out, "\n");
615 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000616 }
617 argIndex++;
618 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800619 // Emit this to quiet the unused parameter warning if there were no strings or attribution
620 // chains.
621 if (!hadStringOrChain) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000622 fprintf(out, " (void)env;\n");
623 }
624
625 // stats_write call
626 argIndex = 1;
627 fprintf(out, " android::util::stats_write(code");
628 for (vector<java_type_t>::const_iterator arg = signature->begin();
629 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800630 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
631 for (auto chainField : attributionDecl.fields) {
632 if (chainField.javaType == JAVA_TYPE_INT) {
633 fprintf(out, ", (const %s*)%s_array, %s_length",
634 cpp_type_name(chainField.javaType),
635 chainField.name.c_str(), chainField.name.c_str());
636 } else if (chainField.javaType == JAVA_TYPE_STRING) {
637 fprintf(out, ", %s_vec", chainField.name.c_str());
638 }
639 }
640 } else {
641 const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
642 fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
643 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000644 argIndex++;
645 }
646 fprintf(out, ");\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800647 fprintf(out, "\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000648
649 // Clean up strings
650 argIndex = 1;
651 for (vector<java_type_t>::const_iterator arg = signature->begin();
652 arg != signature->end(); arg++) {
653 if (*arg == JAVA_TYPE_STRING) {
654 fprintf(out, " if (str%d != NULL) {\n", argIndex);
655 fprintf(out, " env->ReleaseStringUTFChars(arg%d, str%d);\n",
656 argIndex, argIndex);
657 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800658 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
659 for (auto chainField : attributionDecl.fields) {
660 if (chainField.javaType == JAVA_TYPE_INT) {
661 fprintf(out, " env->ReleaseIntArrayElements(%s, %s_array, 0);\n",
662 chainField.name.c_str(), chainField.name.c_str());
663 } else if (chainField.javaType == JAVA_TYPE_STRING) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800664 fprintf(out, " for (size_t i = 0; i < scoped_%s_vec.size(); ++i) {\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800665 chainField.name.c_str());
666 fprintf(out, " delete scoped_%s_vec[i];\n", chainField.name.c_str());
667 fprintf(out, " }\n");
668 }
669 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000670 }
671 argIndex++;
672 }
673
674 fprintf(out, "}\n");
675 fprintf(out, "\n");
676 }
677
678 // Print registration function table
679 fprintf(out, "/*\n");
680 fprintf(out, " * JNI registration.\n");
681 fprintf(out, " */\n");
682 fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n");
683 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
684 signature != atoms.signatures.end(); signature++) {
685 fprintf(out, " { \"write\", \"%s\", (void*)%s },\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800686 jni_function_signature(*signature, attributionDecl).c_str(),
687 jni_function_name(*signature).c_str());
Yao Chend54f9dd2017-10-17 17:37:48 +0000688 }
689 fprintf(out, "};\n");
690 fprintf(out, "\n");
691
692 // Print registration function
693 fprintf(out, "int register_android_util_StatsLog(JNIEnv* env) {\n");
694 fprintf(out, " return RegisterMethodsOrDie(\n");
695 fprintf(out, " env,\n");
696 fprintf(out, " \"android/util/StatsLog\",\n");
697 fprintf(out, " gRegisterMethods, NELEM(gRegisterMethods));\n");
698 fprintf(out, "}\n");
699
700 fprintf(out, "\n");
701 fprintf(out, "} // namespace android\n");
702
703 return 0;
704}
705
706
707static void
708print_usage()
709{
710 fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
711 fprintf(stderr, "\n");
712 fprintf(stderr, "OPTIONS\n");
713 fprintf(stderr, " --cpp FILENAME the header file to output\n");
714 fprintf(stderr, " --header FILENAME the cpp file to output\n");
715 fprintf(stderr, " --help this message\n");
716 fprintf(stderr, " --java FILENAME the java file to output\n");
717 fprintf(stderr, " --jni FILENAME the jni file to output\n");
718}
719
720/**
721 * Do the argument parsing and execute the tasks.
722 */
723static int
724run(int argc, char const*const* argv)
725{
726 string cppFilename;
727 string headerFilename;
728 string javaFilename;
729 string jniFilename;
730
731 int index = 1;
732 while (index < argc) {
733 if (0 == strcmp("--help", argv[index])) {
734 print_usage();
735 return 0;
736 } else if (0 == strcmp("--cpp", argv[index])) {
737 index++;
738 if (index >= argc) {
739 print_usage();
740 return 1;
741 }
742 cppFilename = argv[index];
743 } else if (0 == strcmp("--header", argv[index])) {
744 index++;
745 if (index >= argc) {
746 print_usage();
747 return 1;
748 }
749 headerFilename = argv[index];
750 } else if (0 == strcmp("--java", argv[index])) {
751 index++;
752 if (index >= argc) {
753 print_usage();
754 return 1;
755 }
756 javaFilename = argv[index];
757 } else if (0 == strcmp("--jni", argv[index])) {
758 index++;
759 if (index >= argc) {
760 print_usage();
761 return 1;
762 }
763 jniFilename = argv[index];
764 }
765 index++;
766 }
767
768 if (cppFilename.size() == 0
769 && headerFilename.size() == 0
770 && javaFilename.size() == 0
771 && jniFilename.size() == 0) {
772 print_usage();
773 return 1;
774 }
775
776 // Collate the parameters
777 Atoms atoms;
Stefan Lafonae2df012017-11-14 09:17:21 -0800778 int errorCount = collate_atoms(Atom::descriptor(), &atoms);
Yao Chend54f9dd2017-10-17 17:37:48 +0000779 if (errorCount != 0) {
780 return 1;
781 }
782
Yangster-mac7604aea2017-12-11 22:55:49 -0800783 AtomDecl attributionDecl;
784 vector<java_type_t> attributionSignature;
Yangster-mac20877162017-12-22 17:19:39 -0800785 collate_atom(android::os::statsd::AttributionNode::descriptor(),
Yangster-mac7604aea2017-12-11 22:55:49 -0800786 &attributionDecl, &attributionSignature);
787
Yao Chend54f9dd2017-10-17 17:37:48 +0000788 // Write the .cpp file
789 if (cppFilename.size() != 0) {
790 FILE* out = fopen(cppFilename.c_str(), "w");
791 if (out == NULL) {
792 fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
793 return 1;
794 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800795 errorCount = android::stats_log_api_gen::write_stats_log_cpp(
796 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000797 fclose(out);
798 }
799
800 // Write the .h file
801 if (headerFilename.size() != 0) {
802 FILE* out = fopen(headerFilename.c_str(), "w");
803 if (out == NULL) {
804 fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
805 return 1;
806 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800807 errorCount = android::stats_log_api_gen::write_stats_log_header(
808 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000809 fclose(out);
810 }
811
812 // Write the .java file
813 if (javaFilename.size() != 0) {
814 FILE* out = fopen(javaFilename.c_str(), "w");
815 if (out == NULL) {
816 fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
817 return 1;
818 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800819 errorCount = android::stats_log_api_gen::write_stats_log_java(
820 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000821 fclose(out);
822 }
823
824 // Write the jni file
825 if (jniFilename.size() != 0) {
826 FILE* out = fopen(jniFilename.c_str(), "w");
827 if (out == NULL) {
828 fprintf(stderr, "Unable to open file for write: %s\n", jniFilename.c_str());
829 return 1;
830 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800831 errorCount = android::stats_log_api_gen::write_stats_log_jni(
832 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000833 fclose(out);
834 }
835
836 return 0;
837}
838
839}
840}
841
842/**
843 * Main.
844 */
845int
846main(int argc, char const*const* argv)
847{
848 GOOGLE_PROTOBUF_VERIFY_VERSION;
849
850 return android::stats_log_api_gen::run(argc, argv);
Yangster-mac7604aea2017-12-11 22:55:49 -0800851}