blob: 057772ffe0130767978219d78a638fe1f825c101 [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-macb8382a12018-04-04 10:39:12 -0700104 fprintf(out, "#include <chrono>\n");
105 fprintf(out, "#include <thread>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000106 fprintf(out, "#include <log/log_event_list.h>\n");
107 fprintf(out, "#include <log/log.h>\n");
108 fprintf(out, "#include <statslog.h>\n");
Yangster-mac330af582018-02-08 15:24:38 -0800109 fprintf(out, "#include <utils/SystemClock.h>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000110 fprintf(out, "\n");
111
112 fprintf(out, "namespace android {\n");
113 fprintf(out, "namespace util {\n");
Yao Chen80235402017-11-13 20:42:25 -0800114 fprintf(out, "// the single event tag id for all stats logs\n");
115 fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000116
Yao Chenc40a19d2018-03-15 16:48:25 -0700117 std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
118 "audio_state_changed",
119 "call_state_changed",
120 "phone_signal_strength_changed",
121 "mobile_bytes_transfer_by_fg_bg",
122 "mobile_bytes_transfer"};
123 fprintf(out,
124 "const std::set<int> "
125 "AtomsInfo::kNotTruncatingTimestampAtomWhiteList = {\n");
126 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
127 atom != atoms.decls.end(); atom++) {
128 if (kTruncatingAtomNames.find(atom->name) ==
129 kTruncatingAtomNames.end()) {
130 string constant = make_constant_name(atom->name);
131 fprintf(out, " %s,\n", constant.c_str());
132 }
133 }
134 fprintf(out, "};\n");
135 fprintf(out, "\n");
136
137 fprintf(out,
138 "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
139 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
140 atom != atoms.decls.end(); atom++) {
141 for (vector<AtomField>::const_iterator field = atom->fields.begin();
142 field != atom->fields.end(); field++) {
143 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
144 string constant = make_constant_name(atom->name);
145 fprintf(out, " %s,\n", constant.c_str());
146 break;
147 }
148 }
149 }
150 fprintf(out, "};\n");
151 fprintf(out, "\n");
152
153 fprintf(out,
154 "static std::map<int, int> "
155 "getAtomUidField() {\n");
156 fprintf(out, " std::map<int, int> uidField;\n");
157 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
158 atom != atoms.decls.end(); atom++) {
159 if (atom->uidField == 0) {
160 continue;
161 }
162 fprintf(out,
163 "\n // Adding uid field for atom "
164 "(%d)%s\n",
165 atom->code, atom->name.c_str());
166 fprintf(out, " uidField[static_cast<int>(%s)] = %d;\n",
167 make_constant_name(atom->name).c_str(), atom->uidField);
168 }
169
170 fprintf(out, " return uidField;\n");
171 fprintf(out, "};\n");
172
173 fprintf(out,
174 "const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
175 "getAtomUidField();\n");
176
177 fprintf(out,
178 "static std::map<int, StateAtomFieldOptions> "
179 "getStateAtomFieldOptions() {\n");
180 fprintf(out, " std::map<int, StateAtomFieldOptions> options;\n");
181 fprintf(out, " StateAtomFieldOptions opt;\n");
182 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
183 atom != atoms.decls.end(); atom++) {
184 if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
185 continue;
186 }
187 fprintf(out,
188 "\n // Adding primary and exclusive fields for atom "
189 "(%d)%s\n",
190 atom->code, atom->name.c_str());
191 fprintf(out, " opt.primaryFields.clear();\n");
192 for (const auto& field : atom->primaryFields) {
193 fprintf(out, " opt.primaryFields.push_back(%d);\n", field);
194 }
195
196 fprintf(out, " opt.exclusiveField = %d;\n", atom->exclusiveField);
197 fprintf(out, " options[static_cast<int>(%s)] = opt;\n",
198 make_constant_name(atom->name).c_str());
199 }
200
201 fprintf(out, " return options;\n");
202 fprintf(out, " }\n");
203
204 fprintf(out,
205 "const std::map<int, StateAtomFieldOptions> "
206 "AtomsInfo::kStateAtomsFieldOptions = "
207 "getStateAtomFieldOptions();\n");
208
Yao Chend54f9dd2017-10-17 17:37:48 +0000209 // Print write methods
210 fprintf(out, "\n");
211 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800212 signature != atoms.signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000213 int argIndex;
214
Yao Chen97e21ec2018-03-29 11:00:38 -0700215 fprintf(out, "int\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700216 fprintf(out, "try_stats_write(int32_t code");
Yao Chend54f9dd2017-10-17 17:37:48 +0000217 argIndex = 1;
218 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800219 arg != signature->end(); arg++) {
220 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
221 for (auto chainField : attributionDecl.fields) {
222 if (chainField.javaType == JAVA_TYPE_STRING) {
223 fprintf(out, ", const std::vector<%s>& %s",
224 cpp_type_name(chainField.javaType),
225 chainField.name.c_str());
226 } else {
227 fprintf(out, ", const %s* %s, size_t %s_length",
228 cpp_type_name(chainField.javaType),
229 chainField.name.c_str(), chainField.name.c_str());
230 }
231 }
232 } else {
233 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
234 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000235 argIndex++;
236 }
237 fprintf(out, ")\n");
238
239 fprintf(out, "{\n");
240 argIndex = 1;
Yao Chen80235402017-11-13 20:42:25 -0800241 fprintf(out, " android_log_event_list event(kStatsEventTag);\n");
Yangster-mac330af582018-02-08 15:24:38 -0800242 fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800243 fprintf(out, " event << code;\n\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000244 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800245 arg != signature->end(); arg++) {
246 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
247 for (const auto &chainField : attributionDecl.fields) {
248 if (chainField.javaType == JAVA_TYPE_STRING) {
249 fprintf(out, " if (%s_length != %s.size()) {\n",
250 attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
Yao Chen97e21ec2018-03-29 11:00:38 -0700251 fprintf(out, " return -EINVAL;\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800252 fprintf(out, " }\n");
253 }
254 }
255 fprintf(out, "\n event.begin();\n");
256 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
257 attributionDecl.fields.front().name.c_str());
258 fprintf(out, " event.begin();\n");
259 for (const auto &chainField : attributionDecl.fields) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800260 if (chainField.javaType == JAVA_TYPE_STRING) {
261 fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
262 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
263 fprintf(out, " } else {\n");
264 fprintf(out, " event << \"\";\n");
265 fprintf(out, " }\n");
266 } else {
267 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
268 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800269 }
270 fprintf(out, " event.end();\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000271 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800272 fprintf(out, " event.end();\n\n");
273 } else {
274 if (*arg == JAVA_TYPE_STRING) {
275 fprintf(out, " if (arg%d == NULL) {\n", argIndex);
276 fprintf(out, " arg%d = \"\";\n", argIndex);
277 fprintf(out, " }\n");
278 }
279 fprintf(out, " event << arg%d;\n", argIndex);
Yao Chend54f9dd2017-10-17 17:37:48 +0000280 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000281 argIndex++;
282 }
283
Yao Chen97e21ec2018-03-29 11:00:38 -0700284 fprintf(out, " return event.write(LOG_ID_STATS);\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000285 fprintf(out, "}\n");
286 fprintf(out, "\n");
287 }
288
Yangster-macb8382a12018-04-04 10:39:12 -0700289 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
290 signature != atoms.signatures.end(); signature++) {
291 int argIndex;
292
293 fprintf(out, "int \n");
294 fprintf(out, "stats_write(int32_t code");
295 argIndex = 1;
296 for (vector<java_type_t>::const_iterator arg = signature->begin();
297 arg != signature->end(); arg++) {
298 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
299 for (auto chainField : attributionDecl.fields) {
300 if (chainField.javaType == JAVA_TYPE_STRING) {
301 fprintf(out, ", const std::vector<%s>& %s",
302 cpp_type_name(chainField.javaType),
303 chainField.name.c_str());
304 } else {
305 fprintf(out, ", const %s* %s, size_t %s_length",
306 cpp_type_name(chainField.javaType),
307 chainField.name.c_str(), chainField.name.c_str());
308 }
309 }
310 } else {
311 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
312 }
313 argIndex++;
314 }
315 fprintf(out, ")\n");
316
317 fprintf(out, "{\n");
318 fprintf(out, " int ret = 0;\n");
319
320 fprintf(out, " for(int retry = 0; retry < 3; ++retry) {\n");
321 fprintf(out, " ret = try_stats_write(code");
322
323 argIndex = 1;
324 for (vector<java_type_t>::const_iterator arg = signature->begin();
325 arg != signature->end(); arg++) {
326 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
327 for (auto chainField : attributionDecl.fields) {
328 if (chainField.javaType == JAVA_TYPE_STRING) {
329 fprintf(out, ", %s",
330 chainField.name.c_str());
331 } else {
332 fprintf(out, ", %s, %s_length",
333 chainField.name.c_str(), chainField.name.c_str());
334 }
335 }
336 } else {
337 fprintf(out, ", arg%d", argIndex);
338 }
339 argIndex++;
340 }
341 fprintf(out, ");\n");
342 fprintf(out, " if (ret >= 0) { return retry; }\n");
343 fprintf(out,
344 " std::this_thread::sleep_for(std::chrono::milliseconds(10 + 10 * retry));\n");
345 fprintf(out, " }\n");
346 fprintf(out, " return ret;\n");
347 fprintf(out, "}\n");
348 fprintf(out, "\n");
349 }
350
Yangster-macba5b9e42018-01-10 21:31:59 -0800351 for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
352 signature != atoms.non_chained_signatures.end(); signature++) {
353 int argIndex;
354
Yao Chen97e21ec2018-03-29 11:00:38 -0700355 fprintf(out, "int\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700356 fprintf(out, "try_stats_write_non_chained(int32_t code");
Yangster-macba5b9e42018-01-10 21:31:59 -0800357 argIndex = 1;
358 for (vector<java_type_t>::const_iterator arg = signature->begin();
359 arg != signature->end(); arg++) {
360 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
361 argIndex++;
362 }
363 fprintf(out, ")\n");
364
365 fprintf(out, "{\n");
366 argIndex = 1;
367 fprintf(out, " android_log_event_list event(kStatsEventTag);\n");
Yangster-mac31ddcde2018-02-14 16:09:35 -0800368 fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800369 fprintf(out, " event << code;\n\n");
370 for (vector<java_type_t>::const_iterator arg = signature->begin();
371 arg != signature->end(); arg++) {
372 if (argIndex == 1) {
373 fprintf(out, " event.begin();\n\n");
374 fprintf(out, " event.begin();\n");
375 }
376 if (*arg == JAVA_TYPE_STRING) {
377 fprintf(out, " if (arg%d == NULL) {\n", argIndex);
378 fprintf(out, " arg%d = \"\";\n", argIndex);
379 fprintf(out, " }\n");
380 }
381 fprintf(out, " event << arg%d;\n", argIndex);
382 if (argIndex == 2) {
383 fprintf(out, " event.end();\n\n");
384 fprintf(out, " event.end();\n\n");
385 }
386 argIndex++;
387 }
388
Yao Chen97e21ec2018-03-29 11:00:38 -0700389 fprintf(out, " return event.write(LOG_ID_STATS);\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800390 fprintf(out, "}\n");
391 fprintf(out, "\n");
392 }
Yangster-macb8382a12018-04-04 10:39:12 -0700393
394 for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
395 signature != atoms.non_chained_signatures.end(); signature++) {
396 int argIndex;
397
398 fprintf(out, "int\n");
399 fprintf(out, "stats_write_non_chained(int32_t code");
400 argIndex = 1;
401 for (vector<java_type_t>::const_iterator arg = signature->begin();
402 arg != signature->end(); arg++) {
403 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
404 argIndex++;
405 }
406 fprintf(out, ")\n");
407
408 fprintf(out, "{\n");
409
410 fprintf(out, " int ret = 0;\n");
411 fprintf(out, " for(int retry = 0; retry < 3; ++retry) {\n");
412 fprintf(out, " ret = try_stats_write_non_chained(code");
413
414 argIndex = 1;
415 for (vector<java_type_t>::const_iterator arg = signature->begin();
416 arg != signature->end(); arg++) {
417 fprintf(out, ", arg%d", argIndex);
418 argIndex++;
419 }
420 fprintf(out, ");\n");
421 fprintf(out, " if (ret >= 0) { return retry; }\n");
422 fprintf(out,
423 " std::this_thread::sleep_for(std::chrono::milliseconds(10 + 10 * retry));\n");
424 fprintf(out, " }\n");
425 fprintf(out, " return ret;\n");
426 fprintf(out, "}\n");
427
428 fprintf(out, "\n");
429 }
430
431
Yao Chend54f9dd2017-10-17 17:37:48 +0000432 // Print footer
433 fprintf(out, "\n");
434 fprintf(out, "} // namespace util\n");
435 fprintf(out, "} // namespace android\n");
436
437 return 0;
438}
439
Yangster-macba5b9e42018-01-10 21:31:59 -0800440void build_non_chained_decl_map(const Atoms& atoms,
441 std::map<int, set<AtomDecl>::const_iterator>* decl_map){
442 for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin();
443 atom != atoms.non_chained_decls.end(); atom++) {
444 decl_map->insert(std::make_pair(atom->code, atom));
445 }
446}
447
448static void write_cpp_usage(
449 FILE* out, const string& method_name, const string& atom_code_name,
450 const AtomDecl& atom, const AtomDecl &attributionDecl) {
451 fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str());
452 for (vector<AtomField>::const_iterator field = atom.fields.begin();
453 field != atom.fields.end(); field++) {
454 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
455 for (auto chainField : attributionDecl.fields) {
456 if (chainField.javaType == JAVA_TYPE_STRING) {
457 fprintf(out, ", const std::vector<%s>& %s",
458 cpp_type_name(chainField.javaType),
459 chainField.name.c_str());
460 } else {
461 fprintf(out, ", const %s* %s, size_t %s_length",
462 cpp_type_name(chainField.javaType),
463 chainField.name.c_str(), chainField.name.c_str());
464 }
465 }
466 } else {
467 fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
468 }
469 }
470 fprintf(out, ");\n");
471}
472
473static void write_cpp_method_header(
474 FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures,
475 const AtomDecl &attributionDecl) {
476 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
477 signature != signatures.end(); signature++) {
Yao Chen97e21ec2018-03-29 11:00:38 -0700478 fprintf(out, "int %s(int32_t code ", method_name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800479 int argIndex = 1;
480 for (vector<java_type_t>::const_iterator arg = signature->begin();
481 arg != signature->end(); arg++) {
482 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
483 for (auto chainField : attributionDecl.fields) {
484 if (chainField.javaType == JAVA_TYPE_STRING) {
485 fprintf(out, ", const std::vector<%s>& %s",
486 cpp_type_name(chainField.javaType), chainField.name.c_str());
487 } else {
488 fprintf(out, ", const %s* %s, size_t %s_length",
489 cpp_type_name(chainField.javaType),
490 chainField.name.c_str(), chainField.name.c_str());
491 }
492 }
493 } else {
494 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
495 }
496 argIndex++;
497 }
498 fprintf(out, ");\n");
499
500 }
501}
Yao Chend54f9dd2017-10-17 17:37:48 +0000502
503static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800504write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000505{
Yao Chend54f9dd2017-10-17 17:37:48 +0000506 // Print prelude
507 fprintf(out, "// This file is autogenerated\n");
508 fprintf(out, "\n");
509 fprintf(out, "#pragma once\n");
510 fprintf(out, "\n");
511 fprintf(out, "#include <stdint.h>\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800512 fprintf(out, "#include <vector>\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800513 fprintf(out, "#include <map>\n");
Yangster-mac68985802018-01-21 10:05:09 -0800514 fprintf(out, "#include <set>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000515 fprintf(out, "\n");
516
517 fprintf(out, "namespace android {\n");
518 fprintf(out, "namespace util {\n");
519 fprintf(out, "\n");
520 fprintf(out, "/*\n");
521 fprintf(out, " * API For logging statistics events.\n");
522 fprintf(out, " */\n");
523 fprintf(out, "\n");
524 fprintf(out, "/**\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700525 fprintf(out, " * Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000526 fprintf(out, " */\n");
527 fprintf(out, "enum {\n");
528
Yangster-macba5b9e42018-01-10 21:31:59 -0800529 std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
530 build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
531
Yao Chend54f9dd2017-10-17 17:37:48 +0000532 size_t i = 0;
533 // Print constants
534 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800535 atom != atoms.decls.end(); atom++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000536 string constant = make_constant_name(atom->name);
537 fprintf(out, "\n");
538 fprintf(out, " /**\n");
539 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800540 write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl);
541
542 auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
543 if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
544 write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
545 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000546 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000547 fprintf(out, " */\n");
548 char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
549 fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
Yao Chenb3561512017-11-21 18:07:17 -0800550 if (atom->code < PULL_ATOM_START_ID && atom->code > maxPushedAtomId) {
551 maxPushedAtomId = atom->code;
552 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000553 i++;
554 }
555 fprintf(out, "\n");
556 fprintf(out, "};\n");
557 fprintf(out, "\n");
558
Yao Chen9c1debe2018-02-19 14:39:19 -0800559 fprintf(out, "struct StateAtomFieldOptions {\n");
560 fprintf(out, " std::vector<int> primaryFields;\n");
561 fprintf(out, " int exclusiveField;\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700562 fprintf(out, "};\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800563 fprintf(out, "\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700564
565 fprintf(out, "struct AtomsInfo {\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800566 fprintf(out,
Yao Chenc40a19d2018-03-15 16:48:25 -0700567 " const static std::set<int> "
568 "kNotTruncatingTimestampAtomWhiteList;\n");
569 fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
570 fprintf(out,
571 " const static std::set<int> kAtomsWithAttributionChain;\n");
572 fprintf(out,
573 " const static std::map<int, StateAtomFieldOptions> "
574 "kStateAtomsFieldOptions;\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800575 fprintf(out, "};\n");
576
Yao Chenc40a19d2018-03-15 16:48:25 -0700577 fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
578 maxPushedAtomId);
Yao Chen9c1debe2018-02-19 14:39:19 -0800579
Yao Chend54f9dd2017-10-17 17:37:48 +0000580 // Print write methods
581 fprintf(out, "//\n");
582 fprintf(out, "// Write methods\n");
583 fprintf(out, "//\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800584 write_cpp_method_header(out, "stats_write", atoms.signatures, attributionDecl);
585
586 fprintf(out, "//\n");
587 fprintf(out, "// Write flattened methods\n");
588 fprintf(out, "//\n");
589 write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures,
590 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000591
592 fprintf(out, "\n");
593 fprintf(out, "} // namespace util\n");
594 fprintf(out, "} // namespace android\n");
595
596 return 0;
597}
598
Yangster-macba5b9e42018-01-10 21:31:59 -0800599static void write_java_usage(
600 FILE* out, const string& method_name, const string& atom_code_name,
601 const AtomDecl& atom, const AtomDecl &attributionDecl) {
602 fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s",
603 method_name.c_str(), atom_code_name.c_str());
604 for (vector<AtomField>::const_iterator field = atom.fields.begin();
605 field != atom.fields.end(); field++) {
606 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
607 for (auto chainField : attributionDecl.fields) {
608 fprintf(out, ", %s[] %s",
609 java_type_name(chainField.javaType), chainField.name.c_str());
610 }
611 } else {
612 fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
613 }
614 }
615 fprintf(out, ");\n");
616}
617
618static void write_java_method(
619 FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures,
620 const AtomDecl &attributionDecl) {
621 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
622 signature != signatures.end(); signature++) {
Yao Chen97e21ec2018-03-29 11:00:38 -0700623 fprintf(out, " public static native int %s(int code", method_name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800624 int argIndex = 1;
625 for (vector<java_type_t>::const_iterator arg = signature->begin();
626 arg != signature->end(); arg++) {
627 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
628 for (auto chainField : attributionDecl.fields) {
629 fprintf(out, ", %s[] %s",
630 java_type_name(chainField.javaType), chainField.name.c_str());
631 }
632 } else {
633 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
634 }
635 argIndex++;
636 }
637 fprintf(out, ");\n");
638 }
639}
640
641
Yao Chend54f9dd2017-10-17 17:37:48 +0000642static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800643write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000644{
Yao Chend54f9dd2017-10-17 17:37:48 +0000645 // Print prelude
646 fprintf(out, "// This file is autogenerated\n");
647 fprintf(out, "\n");
648 fprintf(out, "package android.util;\n");
649 fprintf(out, "\n");
650 fprintf(out, "\n");
651 fprintf(out, "/**\n");
652 fprintf(out, " * API For logging statistics events.\n");
653 fprintf(out, " * @hide\n");
654 fprintf(out, " */\n");
David Chen0a368b22017-12-06 16:28:16 -0800655 fprintf(out, "public class StatsLogInternal {\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700656 fprintf(out, " // Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000657
Yangster-macba5b9e42018-01-10 21:31:59 -0800658 std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
659 build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
660
Stefan Lafon9478f352017-10-30 21:20:20 -0700661 // Print constants for the atom codes.
Yao Chend54f9dd2017-10-17 17:37:48 +0000662 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
663 atom != atoms.decls.end(); atom++) {
664 string constant = make_constant_name(atom->name);
665 fprintf(out, "\n");
666 fprintf(out, " /**\n");
667 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800668 write_java_usage(out, "write", constant, *atom, attributionDecl);
669 auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
670 if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
671 write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second,
672 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000673 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000674 fprintf(out, " */\n");
675 fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
676 }
677 fprintf(out, "\n");
678
Stefan Lafon9478f352017-10-30 21:20:20 -0700679 // Print constants for the enum values.
680 fprintf(out, " // Constants for enum values.\n\n");
681 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800682 atom != atoms.decls.end(); atom++) {
Stefan Lafon9478f352017-10-30 21:20:20 -0700683 for (vector<AtomField>::const_iterator field = atom->fields.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800684 field != atom->fields.end(); field++) {
685 if (field->javaType == JAVA_TYPE_ENUM) {
686 fprintf(out, " // Values for %s.%s\n", atom->message.c_str(),
687 field->name.c_str());
688 for (map<int, string>::const_iterator value = field->enumValues.begin();
689 value != field->enumValues.end(); value++) {
690 fprintf(out, " public static final int %s__%s__%s = %d;\n",
691 make_constant_name(atom->message).c_str(),
692 make_constant_name(field->name).c_str(),
693 make_constant_name(value->second).c_str(),
694 value->first);
695 }
696 fprintf(out, "\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700697 }
Stefan Lafon9478f352017-10-30 21:20:20 -0700698 }
699 }
700
Yao Chend54f9dd2017-10-17 17:37:48 +0000701 // Print write methods
702 fprintf(out, " // Write methods\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800703 write_java_method(out, "write", atoms.signatures, attributionDecl);
704 write_java_method(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000705
706 fprintf(out, "}\n");
707
708 return 0;
709}
710
711static const char*
712jni_type_name(java_type_t type)
713{
714 switch (type) {
715 case JAVA_TYPE_BOOLEAN:
716 return "jboolean";
717 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700718 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000719 return "jint";
720 case JAVA_TYPE_LONG:
721 return "jlong";
722 case JAVA_TYPE_FLOAT:
723 return "jfloat";
724 case JAVA_TYPE_DOUBLE:
725 return "jdouble";
726 case JAVA_TYPE_STRING:
727 return "jstring";
728 default:
729 return "UNKNOWN";
730 }
731}
732
Yangster-mac7604aea2017-12-11 22:55:49 -0800733static const char*
734jni_array_type_name(java_type_t type)
735{
736 switch (type) {
737 case JAVA_TYPE_INT:
738 return "jintArray";
739 case JAVA_TYPE_STRING:
740 return "jobjectArray";
741 default:
742 return "UNKNOWN";
743 }
744}
745
Yao Chend54f9dd2017-10-17 17:37:48 +0000746static string
Yangster-macba5b9e42018-01-10 21:31:59 -0800747jni_function_name(const string& method_name, const vector<java_type_t>& signature)
Yao Chend54f9dd2017-10-17 17:37:48 +0000748{
Yangster-macba5b9e42018-01-10 21:31:59 -0800749 string result("StatsLog_" + method_name);
Yao Chend54f9dd2017-10-17 17:37:48 +0000750 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800751 arg != signature.end(); arg++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000752 switch (*arg) {
753 case JAVA_TYPE_BOOLEAN:
754 result += "_boolean";
755 break;
756 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700757 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000758 result += "_int";
759 break;
760 case JAVA_TYPE_LONG:
761 result += "_long";
762 break;
763 case JAVA_TYPE_FLOAT:
764 result += "_float";
765 break;
766 case JAVA_TYPE_DOUBLE:
767 result += "_double";
768 break;
769 case JAVA_TYPE_STRING:
770 result += "_String";
771 break;
Yangster-mac7604aea2017-12-11 22:55:49 -0800772 case JAVA_TYPE_ATTRIBUTION_CHAIN:
773 result += "_AttributionChain";
774 break;
Yao Chend54f9dd2017-10-17 17:37:48 +0000775 default:
776 result += "_UNKNOWN";
777 break;
778 }
779 }
780 return result;
781}
782
783static const char*
784java_type_signature(java_type_t type)
785{
786 switch (type) {
787 case JAVA_TYPE_BOOLEAN:
788 return "Z";
789 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700790 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000791 return "I";
792 case JAVA_TYPE_LONG:
793 return "J";
794 case JAVA_TYPE_FLOAT:
795 return "F";
796 case JAVA_TYPE_DOUBLE:
797 return "D";
798 case JAVA_TYPE_STRING:
799 return "Ljava/lang/String;";
800 default:
801 return "UNKNOWN";
802 }
803}
804
805static string
Yangster-mac7604aea2017-12-11 22:55:49 -0800806jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000807{
808 string result("(I");
809 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800810 arg != signature.end(); arg++) {
811 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
812 for (auto chainField : attributionDecl.fields) {
813 result += "[";
814 result += java_type_signature(chainField.javaType);
815 }
816 } else {
817 result += java_type_signature(*arg);
818 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000819 }
Yao Chen97e21ec2018-03-29 11:00:38 -0700820 result += ")I";
Yao Chend54f9dd2017-10-17 17:37:48 +0000821 return result;
822}
823
824static int
Yangster-macba5b9e42018-01-10 21:31:59 -0800825write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp_method_name,
826 const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000827{
Yao Chend54f9dd2017-10-17 17:37:48 +0000828 // Print write methods
Yangster-macba5b9e42018-01-10 21:31:59 -0800829 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
830 signature != signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000831 int argIndex;
832
Yao Chen97e21ec2018-03-29 11:00:38 -0700833 fprintf(out, "static int\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000834 fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code",
Yangster-macba5b9e42018-01-10 21:31:59 -0800835 jni_function_name(java_method_name, *signature).c_str());
Yao Chend54f9dd2017-10-17 17:37:48 +0000836 argIndex = 1;
837 for (vector<java_type_t>::const_iterator arg = signature->begin();
838 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800839 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
840 for (auto chainField : attributionDecl.fields) {
841 fprintf(out, ", %s %s", jni_array_type_name(chainField.javaType),
842 chainField.name.c_str());
843 }
844 } else {
845 fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex);
846 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000847 argIndex++;
848 }
849 fprintf(out, ")\n");
850
851 fprintf(out, "{\n");
852
853 // Prepare strings
854 argIndex = 1;
Yangster-mac7604aea2017-12-11 22:55:49 -0800855 bool hadStringOrChain = false;
Yao Chend54f9dd2017-10-17 17:37:48 +0000856 for (vector<java_type_t>::const_iterator arg = signature->begin();
857 arg != signature->end(); arg++) {
858 if (*arg == JAVA_TYPE_STRING) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800859 hadStringOrChain = true;
Yao Chend54f9dd2017-10-17 17:37:48 +0000860 fprintf(out, " const char* str%d;\n", argIndex);
861 fprintf(out, " if (arg%d != NULL) {\n", argIndex);
862 fprintf(out, " str%d = env->GetStringUTFChars(arg%d, NULL);\n",
863 argIndex, argIndex);
864 fprintf(out, " } else {\n");
865 fprintf(out, " str%d = NULL;\n", argIndex);
866 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800867 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
868 hadStringOrChain = true;
869 for (auto chainField : attributionDecl.fields) {
870 fprintf(out, " size_t %s_length = env->GetArrayLength(%s);\n",
871 chainField.name.c_str(), chainField.name.c_str());
872 if (chainField.name != attributionDecl.fields.front().name) {
873 fprintf(out, " if (%s_length != %s_length) {\n",
874 chainField.name.c_str(),
875 attributionDecl.fields.front().name.c_str());
Yao Chen97e21ec2018-03-29 11:00:38 -0700876 fprintf(out, " return -EINVAL;\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800877 fprintf(out, " }\n");
878 }
879 if (chainField.javaType == JAVA_TYPE_INT) {
880 fprintf(out, " jint* %s_array = env->GetIntArrayElements(%s, NULL);\n",
881 chainField.name.c_str(), chainField.name.c_str());
882 } else if (chainField.javaType == JAVA_TYPE_STRING) {
883 fprintf(out, " std::vector<%s> %s_vec;\n",
884 cpp_type_name(chainField.javaType), chainField.name.c_str());
885 fprintf(out, " std::vector<ScopedUtfChars*> scoped_%s_vec;\n",
886 chainField.name.c_str());
887 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
888 chainField.name.c_str());
889 fprintf(out, " jstring jstr = "
890 "(jstring)env->GetObjectArrayElement(%s, i);\n",
891 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800892 fprintf(out, " if (jstr == NULL) {\n");
893 fprintf(out, " %s_vec.push_back(NULL);\n",
894 chainField.name.c_str());
895 fprintf(out, " } else {\n");
896 fprintf(out, " ScopedUtfChars* scoped_%s = "
Yangster-mac7604aea2017-12-11 22:55:49 -0800897 "new ScopedUtfChars(env, jstr);\n",
898 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800899 fprintf(out, " %s_vec.push_back(scoped_%s->c_str());\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800900 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800901 fprintf(out, " scoped_%s_vec.push_back(scoped_%s);\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800902 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800903 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800904 fprintf(out, " }\n");
905 }
906 fprintf(out, "\n");
907 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000908 }
909 argIndex++;
910 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800911 // Emit this to quiet the unused parameter warning if there were no strings or attribution
912 // chains.
913 if (!hadStringOrChain) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000914 fprintf(out, " (void)env;\n");
915 }
916
917 // stats_write call
918 argIndex = 1;
Yao Chen97e21ec2018-03-29 11:00:38 -0700919 fprintf(out, " int ret = android::util::%s(code", cpp_method_name.c_str());
Yao Chend54f9dd2017-10-17 17:37:48 +0000920 for (vector<java_type_t>::const_iterator arg = signature->begin();
921 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800922 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
923 for (auto chainField : attributionDecl.fields) {
924 if (chainField.javaType == JAVA_TYPE_INT) {
925 fprintf(out, ", (const %s*)%s_array, %s_length",
926 cpp_type_name(chainField.javaType),
927 chainField.name.c_str(), chainField.name.c_str());
928 } else if (chainField.javaType == JAVA_TYPE_STRING) {
929 fprintf(out, ", %s_vec", chainField.name.c_str());
930 }
931 }
932 } else {
933 const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
934 fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
935 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000936 argIndex++;
937 }
938 fprintf(out, ");\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800939 fprintf(out, "\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000940
941 // Clean up strings
942 argIndex = 1;
943 for (vector<java_type_t>::const_iterator arg = signature->begin();
944 arg != signature->end(); arg++) {
945 if (*arg == JAVA_TYPE_STRING) {
946 fprintf(out, " if (str%d != NULL) {\n", argIndex);
947 fprintf(out, " env->ReleaseStringUTFChars(arg%d, str%d);\n",
948 argIndex, argIndex);
949 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800950 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
951 for (auto chainField : attributionDecl.fields) {
952 if (chainField.javaType == JAVA_TYPE_INT) {
953 fprintf(out, " env->ReleaseIntArrayElements(%s, %s_array, 0);\n",
954 chainField.name.c_str(), chainField.name.c_str());
955 } else if (chainField.javaType == JAVA_TYPE_STRING) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800956 fprintf(out, " for (size_t i = 0; i < scoped_%s_vec.size(); ++i) {\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800957 chainField.name.c_str());
958 fprintf(out, " delete scoped_%s_vec[i];\n", chainField.name.c_str());
959 fprintf(out, " }\n");
960 }
961 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000962 }
963 argIndex++;
964 }
Yao Chen97e21ec2018-03-29 11:00:38 -0700965 fprintf(out, " return ret;\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000966
967 fprintf(out, "}\n");
968 fprintf(out, "\n");
969 }
970
Yangster-macba5b9e42018-01-10 21:31:59 -0800971
972 return 0;
973}
974
975void write_jni_registration(FILE* out, const string& java_method_name,
976 const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) {
977 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
978 signature != signatures.end(); signature++) {
979 fprintf(out, " { \"%s\", \"%s\", (void*)%s },\n",
980 java_method_name.c_str(),
981 jni_function_signature(*signature, attributionDecl).c_str(),
982 jni_function_name(java_method_name, *signature).c_str());
983 }
984}
985
986static int
987write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
988{
989 // Print prelude
990 fprintf(out, "// This file is autogenerated\n");
991 fprintf(out, "\n");
992
993 fprintf(out, "#include <statslog.h>\n");
994 fprintf(out, "\n");
995 fprintf(out, "#include <nativehelper/JNIHelp.h>\n");
996 fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n");
997 fprintf(out, "#include <utils/Vector.h>\n");
998 fprintf(out, "#include \"core_jni_helpers.h\"\n");
999 fprintf(out, "#include \"jni.h\"\n");
1000 fprintf(out, "\n");
1001 fprintf(out, "#define UNUSED __attribute__((__unused__))\n");
1002 fprintf(out, "\n");
1003
1004 fprintf(out, "namespace android {\n");
1005 fprintf(out, "\n");
1006
1007 write_stats_log_jni(out, "write", "stats_write", atoms.signatures, attributionDecl);
1008 write_stats_log_jni(out, "write_non_chained", "stats_write_non_chained",
1009 atoms.non_chained_signatures, attributionDecl);
1010
Yao Chend54f9dd2017-10-17 17:37:48 +00001011 // Print registration function table
1012 fprintf(out, "/*\n");
1013 fprintf(out, " * JNI registration.\n");
1014 fprintf(out, " */\n");
1015 fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n");
Yangster-macba5b9e42018-01-10 21:31:59 -08001016 write_jni_registration(out, "write", atoms.signatures, attributionDecl);
1017 write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001018 fprintf(out, "};\n");
1019 fprintf(out, "\n");
1020
1021 // Print registration function
1022 fprintf(out, "int register_android_util_StatsLog(JNIEnv* env) {\n");
1023 fprintf(out, " return RegisterMethodsOrDie(\n");
1024 fprintf(out, " env,\n");
1025 fprintf(out, " \"android/util/StatsLog\",\n");
1026 fprintf(out, " gRegisterMethods, NELEM(gRegisterMethods));\n");
1027 fprintf(out, "}\n");
1028
1029 fprintf(out, "\n");
1030 fprintf(out, "} // namespace android\n");
Yao Chend54f9dd2017-10-17 17:37:48 +00001031 return 0;
1032}
1033
Yao Chend54f9dd2017-10-17 17:37:48 +00001034static void
1035print_usage()
1036{
1037 fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
1038 fprintf(stderr, "\n");
1039 fprintf(stderr, "OPTIONS\n");
1040 fprintf(stderr, " --cpp FILENAME the header file to output\n");
1041 fprintf(stderr, " --header FILENAME the cpp file to output\n");
1042 fprintf(stderr, " --help this message\n");
1043 fprintf(stderr, " --java FILENAME the java file to output\n");
1044 fprintf(stderr, " --jni FILENAME the jni file to output\n");
1045}
1046
1047/**
1048 * Do the argument parsing and execute the tasks.
1049 */
1050static int
1051run(int argc, char const*const* argv)
1052{
1053 string cppFilename;
1054 string headerFilename;
1055 string javaFilename;
1056 string jniFilename;
1057
1058 int index = 1;
1059 while (index < argc) {
1060 if (0 == strcmp("--help", argv[index])) {
1061 print_usage();
1062 return 0;
1063 } else if (0 == strcmp("--cpp", argv[index])) {
1064 index++;
1065 if (index >= argc) {
1066 print_usage();
1067 return 1;
1068 }
1069 cppFilename = argv[index];
1070 } else if (0 == strcmp("--header", argv[index])) {
1071 index++;
1072 if (index >= argc) {
1073 print_usage();
1074 return 1;
1075 }
1076 headerFilename = argv[index];
1077 } else if (0 == strcmp("--java", argv[index])) {
1078 index++;
1079 if (index >= argc) {
1080 print_usage();
1081 return 1;
1082 }
1083 javaFilename = argv[index];
1084 } else if (0 == strcmp("--jni", argv[index])) {
1085 index++;
1086 if (index >= argc) {
1087 print_usage();
1088 return 1;
1089 }
1090 jniFilename = argv[index];
1091 }
1092 index++;
1093 }
1094
1095 if (cppFilename.size() == 0
1096 && headerFilename.size() == 0
1097 && javaFilename.size() == 0
1098 && jniFilename.size() == 0) {
1099 print_usage();
1100 return 1;
1101 }
1102
1103 // Collate the parameters
1104 Atoms atoms;
Stefan Lafonae2df012017-11-14 09:17:21 -08001105 int errorCount = collate_atoms(Atom::descriptor(), &atoms);
Yao Chend54f9dd2017-10-17 17:37:48 +00001106 if (errorCount != 0) {
1107 return 1;
1108 }
1109
Yangster-mac7604aea2017-12-11 22:55:49 -08001110 AtomDecl attributionDecl;
1111 vector<java_type_t> attributionSignature;
Yangster-mac20877162017-12-22 17:19:39 -08001112 collate_atom(android::os::statsd::AttributionNode::descriptor(),
Yangster-mac7604aea2017-12-11 22:55:49 -08001113 &attributionDecl, &attributionSignature);
1114
Yao Chend54f9dd2017-10-17 17:37:48 +00001115 // Write the .cpp file
1116 if (cppFilename.size() != 0) {
1117 FILE* out = fopen(cppFilename.c_str(), "w");
1118 if (out == NULL) {
1119 fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
1120 return 1;
1121 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001122 errorCount = android::stats_log_api_gen::write_stats_log_cpp(
1123 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001124 fclose(out);
1125 }
1126
1127 // Write the .h file
1128 if (headerFilename.size() != 0) {
1129 FILE* out = fopen(headerFilename.c_str(), "w");
1130 if (out == NULL) {
1131 fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
1132 return 1;
1133 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001134 errorCount = android::stats_log_api_gen::write_stats_log_header(
1135 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001136 fclose(out);
1137 }
1138
1139 // Write the .java file
1140 if (javaFilename.size() != 0) {
1141 FILE* out = fopen(javaFilename.c_str(), "w");
1142 if (out == NULL) {
1143 fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
1144 return 1;
1145 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001146 errorCount = android::stats_log_api_gen::write_stats_log_java(
1147 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001148 fclose(out);
1149 }
1150
1151 // Write the jni file
1152 if (jniFilename.size() != 0) {
1153 FILE* out = fopen(jniFilename.c_str(), "w");
1154 if (out == NULL) {
1155 fprintf(stderr, "Unable to open file for write: %s\n", jniFilename.c_str());
1156 return 1;
1157 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001158 errorCount = android::stats_log_api_gen::write_stats_log_jni(
1159 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001160 fclose(out);
1161 }
1162
1163 return 0;
1164}
1165
1166}
1167}
1168
1169/**
1170 * Main.
1171 */
1172int
1173main(int argc, char const*const* argv)
1174{
1175 GOOGLE_PROTOBUF_VERIFY_VERSION;
1176
1177 return android::stats_log_api_gen::run(argc, argv);
Yangster-mac7604aea2017-12-11 22:55:49 -08001178}