blob: 638549d395b398c91c6f7af19016509bfadc5235 [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-macca5c0862018-04-09 22:39:53 -0700104 fprintf(out, "#include <mutex>\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700105 fprintf(out, "#include <chrono>\n");
106 fprintf(out, "#include <thread>\n");
Yao Chenf7bc6ab2018-04-18 13:45:48 -0700107 fprintf(out, "#include <stats_event_list.h>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000108 fprintf(out, "#include <log/log.h>\n");
109 fprintf(out, "#include <statslog.h>\n");
Yangster-mac330af582018-02-08 15:24:38 -0800110 fprintf(out, "#include <utils/SystemClock.h>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000111 fprintf(out, "\n");
112
113 fprintf(out, "namespace android {\n");
114 fprintf(out, "namespace util {\n");
Yao Chen80235402017-11-13 20:42:25 -0800115 fprintf(out, "// the single event tag id for all stats logs\n");
116 fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000117
Yao Chenc40a19d2018-03-15 16:48:25 -0700118 std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
119 "audio_state_changed",
120 "call_state_changed",
121 "phone_signal_strength_changed",
122 "mobile_bytes_transfer_by_fg_bg",
123 "mobile_bytes_transfer"};
124 fprintf(out,
125 "const std::set<int> "
126 "AtomsInfo::kNotTruncatingTimestampAtomWhiteList = {\n");
127 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
128 atom != atoms.decls.end(); atom++) {
129 if (kTruncatingAtomNames.find(atom->name) ==
130 kTruncatingAtomNames.end()) {
131 string constant = make_constant_name(atom->name);
132 fprintf(out, " %s,\n", constant.c_str());
133 }
134 }
135 fprintf(out, "};\n");
136 fprintf(out, "\n");
137
138 fprintf(out,
139 "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
140 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
141 atom != atoms.decls.end(); atom++) {
142 for (vector<AtomField>::const_iterator field = atom->fields.begin();
143 field != atom->fields.end(); field++) {
144 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
145 string constant = make_constant_name(atom->name);
146 fprintf(out, " %s,\n", constant.c_str());
147 break;
148 }
149 }
150 }
151 fprintf(out, "};\n");
152 fprintf(out, "\n");
153
Yangster-macca5c0862018-04-09 22:39:53 -0700154 fprintf(out, "static std::map<int, int> getAtomUidField() {\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700155 fprintf(out, " std::map<int, int> uidField;\n");
156 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
157 atom != atoms.decls.end(); atom++) {
158 if (atom->uidField == 0) {
159 continue;
160 }
161 fprintf(out,
162 "\n // Adding uid field for atom "
163 "(%d)%s\n",
164 atom->code, atom->name.c_str());
165 fprintf(out, " uidField[static_cast<int>(%s)] = %d;\n",
166 make_constant_name(atom->name).c_str(), atom->uidField);
167 }
168
169 fprintf(out, " return uidField;\n");
170 fprintf(out, "};\n");
171
172 fprintf(out,
173 "const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
174 "getAtomUidField();\n");
175
176 fprintf(out,
177 "static std::map<int, StateAtomFieldOptions> "
178 "getStateAtomFieldOptions() {\n");
179 fprintf(out, " std::map<int, StateAtomFieldOptions> options;\n");
180 fprintf(out, " StateAtomFieldOptions opt;\n");
181 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
182 atom != atoms.decls.end(); atom++) {
183 if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
184 continue;
185 }
186 fprintf(out,
187 "\n // Adding primary and exclusive fields for atom "
188 "(%d)%s\n",
189 atom->code, atom->name.c_str());
190 fprintf(out, " opt.primaryFields.clear();\n");
191 for (const auto& field : atom->primaryFields) {
192 fprintf(out, " opt.primaryFields.push_back(%d);\n", field);
193 }
194
195 fprintf(out, " opt.exclusiveField = %d;\n", atom->exclusiveField);
196 fprintf(out, " options[static_cast<int>(%s)] = opt;\n",
197 make_constant_name(atom->name).c_str());
198 }
199
200 fprintf(out, " return options;\n");
201 fprintf(out, " }\n");
202
203 fprintf(out,
204 "const std::map<int, StateAtomFieldOptions> "
205 "AtomsInfo::kStateAtomsFieldOptions = "
206 "getStateAtomFieldOptions();\n");
207
Yangster-macca5c0862018-04-09 22:39:53 -0700208
209 fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
210 fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
211 fprintf(out, "static std::mutex mLogdRetryMutex;\n");
212
Yao Chend54f9dd2017-10-17 17:37:48 +0000213 // Print write methods
214 fprintf(out, "\n");
215 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800216 signature != atoms.signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000217 int argIndex;
218
Yao Chen97e21ec2018-03-29 11:00:38 -0700219 fprintf(out, "int\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700220 fprintf(out, "try_stats_write(int32_t code");
Yao Chend54f9dd2017-10-17 17:37:48 +0000221 argIndex = 1;
222 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800223 arg != signature->end(); arg++) {
224 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
225 for (auto chainField : attributionDecl.fields) {
226 if (chainField.javaType == JAVA_TYPE_STRING) {
227 fprintf(out, ", const std::vector<%s>& %s",
228 cpp_type_name(chainField.javaType),
229 chainField.name.c_str());
230 } else {
231 fprintf(out, ", const %s* %s, size_t %s_length",
232 cpp_type_name(chainField.javaType),
233 chainField.name.c_str(), chainField.name.c_str());
234 }
235 }
236 } else {
237 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
238 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000239 argIndex++;
240 }
241 fprintf(out, ")\n");
242
243 fprintf(out, "{\n");
244 argIndex = 1;
Yao Chenf7bc6ab2018-04-18 13:45:48 -0700245 fprintf(out, " stats_event_list event(kStatsEventTag);\n");
Yangster-mac330af582018-02-08 15:24:38 -0800246 fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800247 fprintf(out, " event << code;\n\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000248 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800249 arg != signature->end(); arg++) {
250 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
251 for (const auto &chainField : attributionDecl.fields) {
252 if (chainField.javaType == JAVA_TYPE_STRING) {
253 fprintf(out, " if (%s_length != %s.size()) {\n",
254 attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
Yao Chen97e21ec2018-03-29 11:00:38 -0700255 fprintf(out, " return -EINVAL;\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800256 fprintf(out, " }\n");
257 }
258 }
259 fprintf(out, "\n event.begin();\n");
260 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
261 attributionDecl.fields.front().name.c_str());
262 fprintf(out, " event.begin();\n");
263 for (const auto &chainField : attributionDecl.fields) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800264 if (chainField.javaType == JAVA_TYPE_STRING) {
265 fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
266 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
267 fprintf(out, " } else {\n");
268 fprintf(out, " event << \"\";\n");
269 fprintf(out, " }\n");
270 } else {
271 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
272 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800273 }
274 fprintf(out, " event.end();\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000275 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800276 fprintf(out, " event.end();\n\n");
277 } else {
278 if (*arg == JAVA_TYPE_STRING) {
279 fprintf(out, " if (arg%d == NULL) {\n", argIndex);
280 fprintf(out, " arg%d = \"\";\n", argIndex);
281 fprintf(out, " }\n");
282 }
283 fprintf(out, " event << arg%d;\n", argIndex);
Yao Chend54f9dd2017-10-17 17:37:48 +0000284 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000285 argIndex++;
286 }
287
Yao Chen97e21ec2018-03-29 11:00:38 -0700288 fprintf(out, " return event.write(LOG_ID_STATS);\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000289 fprintf(out, "}\n");
290 fprintf(out, "\n");
291 }
292
Yangster-macb8382a12018-04-04 10:39:12 -0700293 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
294 signature != atoms.signatures.end(); signature++) {
295 int argIndex;
296
297 fprintf(out, "int \n");
298 fprintf(out, "stats_write(int32_t code");
299 argIndex = 1;
300 for (vector<java_type_t>::const_iterator arg = signature->begin();
301 arg != signature->end(); arg++) {
302 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
303 for (auto chainField : attributionDecl.fields) {
304 if (chainField.javaType == JAVA_TYPE_STRING) {
305 fprintf(out, ", const std::vector<%s>& %s",
306 cpp_type_name(chainField.javaType),
307 chainField.name.c_str());
308 } else {
309 fprintf(out, ", const %s* %s, size_t %s_length",
310 cpp_type_name(chainField.javaType),
311 chainField.name.c_str(), chainField.name.c_str());
312 }
313 }
314 } else {
315 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
316 }
317 argIndex++;
318 }
319 fprintf(out, ")\n");
320
321 fprintf(out, "{\n");
322 fprintf(out, " int ret = 0;\n");
323
Yangster-macca5c0862018-04-09 22:39:53 -0700324 fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700325 fprintf(out, " ret = try_stats_write(code");
326
327 argIndex = 1;
328 for (vector<java_type_t>::const_iterator arg = signature->begin();
329 arg != signature->end(); arg++) {
330 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
331 for (auto chainField : attributionDecl.fields) {
332 if (chainField.javaType == JAVA_TYPE_STRING) {
333 fprintf(out, ", %s",
334 chainField.name.c_str());
335 } else {
336 fprintf(out, ", %s, %s_length",
337 chainField.name.c_str(), chainField.name.c_str());
338 }
339 }
340 } else {
341 fprintf(out, ", arg%d", argIndex);
342 }
343 argIndex++;
344 }
345 fprintf(out, ");\n");
346 fprintf(out, " if (ret >= 0) { return retry; }\n");
Yangster-macca5c0862018-04-09 22:39:53 -0700347
348
349 fprintf(out, " {\n");
350 fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
351 fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
352 "kMinRetryIntervalNs) break;\n");
353 fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
354 fprintf(out, " }\n");
355 fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700356 fprintf(out, " }\n");
357 fprintf(out, " return ret;\n");
358 fprintf(out, "}\n");
359 fprintf(out, "\n");
360 }
361
Yangster-macba5b9e42018-01-10 21:31:59 -0800362 for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
363 signature != atoms.non_chained_signatures.end(); signature++) {
364 int argIndex;
365
Yao Chen97e21ec2018-03-29 11:00:38 -0700366 fprintf(out, "int\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700367 fprintf(out, "try_stats_write_non_chained(int32_t code");
Yangster-macba5b9e42018-01-10 21:31:59 -0800368 argIndex = 1;
369 for (vector<java_type_t>::const_iterator arg = signature->begin();
370 arg != signature->end(); arg++) {
371 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
372 argIndex++;
373 }
374 fprintf(out, ")\n");
375
376 fprintf(out, "{\n");
377 argIndex = 1;
Yao Chenf7bc6ab2018-04-18 13:45:48 -0700378 fprintf(out, " stats_event_list event(kStatsEventTag);\n");
Yangster-mac31ddcde2018-02-14 16:09:35 -0800379 fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800380 fprintf(out, " event << code;\n\n");
381 for (vector<java_type_t>::const_iterator arg = signature->begin();
382 arg != signature->end(); arg++) {
383 if (argIndex == 1) {
384 fprintf(out, " event.begin();\n\n");
385 fprintf(out, " event.begin();\n");
386 }
387 if (*arg == JAVA_TYPE_STRING) {
388 fprintf(out, " if (arg%d == NULL) {\n", argIndex);
389 fprintf(out, " arg%d = \"\";\n", argIndex);
390 fprintf(out, " }\n");
391 }
392 fprintf(out, " event << arg%d;\n", argIndex);
393 if (argIndex == 2) {
394 fprintf(out, " event.end();\n\n");
395 fprintf(out, " event.end();\n\n");
396 }
397 argIndex++;
398 }
399
Yao Chen97e21ec2018-03-29 11:00:38 -0700400 fprintf(out, " return event.write(LOG_ID_STATS);\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800401 fprintf(out, "}\n");
402 fprintf(out, "\n");
403 }
Yangster-macb8382a12018-04-04 10:39:12 -0700404
405 for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
406 signature != atoms.non_chained_signatures.end(); signature++) {
407 int argIndex;
408
409 fprintf(out, "int\n");
410 fprintf(out, "stats_write_non_chained(int32_t code");
411 argIndex = 1;
412 for (vector<java_type_t>::const_iterator arg = signature->begin();
413 arg != signature->end(); arg++) {
414 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
415 argIndex++;
416 }
417 fprintf(out, ")\n");
418
419 fprintf(out, "{\n");
420
421 fprintf(out, " int ret = 0;\n");
Yangster-macca5c0862018-04-09 22:39:53 -0700422 fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700423 fprintf(out, " ret = try_stats_write_non_chained(code");
424
425 argIndex = 1;
426 for (vector<java_type_t>::const_iterator arg = signature->begin();
427 arg != signature->end(); arg++) {
428 fprintf(out, ", arg%d", argIndex);
429 argIndex++;
430 }
431 fprintf(out, ");\n");
432 fprintf(out, " if (ret >= 0) { return retry; }\n");
Yangster-macca5c0862018-04-09 22:39:53 -0700433
434 fprintf(out, " {\n");
435 fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
436 fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
437 "kMinRetryIntervalNs) break;\n");
438 fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
439 fprintf(out, " }\n");
440
441 fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700442 fprintf(out, " }\n");
443 fprintf(out, " return ret;\n");
444 fprintf(out, "}\n");
445
446 fprintf(out, "\n");
447 }
448
449
Yao Chend54f9dd2017-10-17 17:37:48 +0000450 // Print footer
451 fprintf(out, "\n");
452 fprintf(out, "} // namespace util\n");
453 fprintf(out, "} // namespace android\n");
454
455 return 0;
456}
457
Yangster-macba5b9e42018-01-10 21:31:59 -0800458void build_non_chained_decl_map(const Atoms& atoms,
459 std::map<int, set<AtomDecl>::const_iterator>* decl_map){
460 for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin();
461 atom != atoms.non_chained_decls.end(); atom++) {
462 decl_map->insert(std::make_pair(atom->code, atom));
463 }
464}
465
466static void write_cpp_usage(
467 FILE* out, const string& method_name, const string& atom_code_name,
468 const AtomDecl& atom, const AtomDecl &attributionDecl) {
469 fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str());
470 for (vector<AtomField>::const_iterator field = atom.fields.begin();
471 field != atom.fields.end(); field++) {
472 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
473 for (auto chainField : attributionDecl.fields) {
474 if (chainField.javaType == JAVA_TYPE_STRING) {
475 fprintf(out, ", const std::vector<%s>& %s",
476 cpp_type_name(chainField.javaType),
477 chainField.name.c_str());
478 } else {
479 fprintf(out, ", const %s* %s, size_t %s_length",
480 cpp_type_name(chainField.javaType),
481 chainField.name.c_str(), chainField.name.c_str());
482 }
483 }
484 } else {
485 fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
486 }
487 }
488 fprintf(out, ");\n");
489}
490
491static void write_cpp_method_header(
492 FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures,
493 const AtomDecl &attributionDecl) {
494 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
495 signature != signatures.end(); signature++) {
Yao Chen97e21ec2018-03-29 11:00:38 -0700496 fprintf(out, "int %s(int32_t code ", method_name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800497 int argIndex = 1;
498 for (vector<java_type_t>::const_iterator arg = signature->begin();
499 arg != signature->end(); arg++) {
500 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
501 for (auto chainField : attributionDecl.fields) {
502 if (chainField.javaType == JAVA_TYPE_STRING) {
503 fprintf(out, ", const std::vector<%s>& %s",
504 cpp_type_name(chainField.javaType), chainField.name.c_str());
505 } else {
506 fprintf(out, ", const %s* %s, size_t %s_length",
507 cpp_type_name(chainField.javaType),
508 chainField.name.c_str(), chainField.name.c_str());
509 }
510 }
511 } else {
512 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
513 }
514 argIndex++;
515 }
516 fprintf(out, ");\n");
517
518 }
519}
Yao Chend54f9dd2017-10-17 17:37:48 +0000520
521static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800522write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000523{
Yao Chend54f9dd2017-10-17 17:37:48 +0000524 // Print prelude
525 fprintf(out, "// This file is autogenerated\n");
526 fprintf(out, "\n");
527 fprintf(out, "#pragma once\n");
528 fprintf(out, "\n");
529 fprintf(out, "#include <stdint.h>\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800530 fprintf(out, "#include <vector>\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800531 fprintf(out, "#include <map>\n");
Yangster-mac68985802018-01-21 10:05:09 -0800532 fprintf(out, "#include <set>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000533 fprintf(out, "\n");
534
535 fprintf(out, "namespace android {\n");
536 fprintf(out, "namespace util {\n");
537 fprintf(out, "\n");
538 fprintf(out, "/*\n");
539 fprintf(out, " * API For logging statistics events.\n");
540 fprintf(out, " */\n");
541 fprintf(out, "\n");
542 fprintf(out, "/**\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700543 fprintf(out, " * Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000544 fprintf(out, " */\n");
545 fprintf(out, "enum {\n");
546
Yangster-macba5b9e42018-01-10 21:31:59 -0800547 std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
548 build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
549
Yao Chend54f9dd2017-10-17 17:37:48 +0000550 size_t i = 0;
551 // Print constants
552 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800553 atom != atoms.decls.end(); atom++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000554 string constant = make_constant_name(atom->name);
555 fprintf(out, "\n");
556 fprintf(out, " /**\n");
557 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800558 write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl);
559
560 auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
561 if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
562 write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
563 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000564 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000565 fprintf(out, " */\n");
566 char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
567 fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
Yao Chenb3561512017-11-21 18:07:17 -0800568 if (atom->code < PULL_ATOM_START_ID && atom->code > maxPushedAtomId) {
569 maxPushedAtomId = atom->code;
570 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000571 i++;
572 }
573 fprintf(out, "\n");
574 fprintf(out, "};\n");
575 fprintf(out, "\n");
576
Yao Chen9c1debe2018-02-19 14:39:19 -0800577 fprintf(out, "struct StateAtomFieldOptions {\n");
578 fprintf(out, " std::vector<int> primaryFields;\n");
579 fprintf(out, " int exclusiveField;\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700580 fprintf(out, "};\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800581 fprintf(out, "\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700582
583 fprintf(out, "struct AtomsInfo {\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800584 fprintf(out,
Yao Chenc40a19d2018-03-15 16:48:25 -0700585 " const static std::set<int> "
586 "kNotTruncatingTimestampAtomWhiteList;\n");
587 fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
588 fprintf(out,
589 " const static std::set<int> kAtomsWithAttributionChain;\n");
590 fprintf(out,
591 " const static std::map<int, StateAtomFieldOptions> "
592 "kStateAtomsFieldOptions;\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800593 fprintf(out, "};\n");
594
Yao Chenc40a19d2018-03-15 16:48:25 -0700595 fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
596 maxPushedAtomId);
Yao Chen9c1debe2018-02-19 14:39:19 -0800597
Yao Chend54f9dd2017-10-17 17:37:48 +0000598 // Print write methods
599 fprintf(out, "//\n");
600 fprintf(out, "// Write methods\n");
601 fprintf(out, "//\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800602 write_cpp_method_header(out, "stats_write", atoms.signatures, attributionDecl);
603
604 fprintf(out, "//\n");
605 fprintf(out, "// Write flattened methods\n");
606 fprintf(out, "//\n");
607 write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures,
608 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000609
610 fprintf(out, "\n");
611 fprintf(out, "} // namespace util\n");
612 fprintf(out, "} // namespace android\n");
613
614 return 0;
615}
616
Yangster-macba5b9e42018-01-10 21:31:59 -0800617static void write_java_usage(
618 FILE* out, const string& method_name, const string& atom_code_name,
619 const AtomDecl& atom, const AtomDecl &attributionDecl) {
620 fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s",
621 method_name.c_str(), atom_code_name.c_str());
622 for (vector<AtomField>::const_iterator field = atom.fields.begin();
623 field != atom.fields.end(); field++) {
624 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
625 for (auto chainField : attributionDecl.fields) {
626 fprintf(out, ", %s[] %s",
627 java_type_name(chainField.javaType), chainField.name.c_str());
628 }
629 } else {
630 fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
631 }
632 }
633 fprintf(out, ");\n");
634}
635
636static void write_java_method(
637 FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures,
638 const AtomDecl &attributionDecl) {
639 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
640 signature != signatures.end(); signature++) {
Yao Chen97e21ec2018-03-29 11:00:38 -0700641 fprintf(out, " public static native int %s(int code", method_name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800642 int argIndex = 1;
643 for (vector<java_type_t>::const_iterator arg = signature->begin();
644 arg != signature->end(); arg++) {
645 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
646 for (auto chainField : attributionDecl.fields) {
647 fprintf(out, ", %s[] %s",
648 java_type_name(chainField.javaType), chainField.name.c_str());
649 }
650 } else {
651 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
652 }
653 argIndex++;
654 }
655 fprintf(out, ");\n");
656 }
657}
658
659
Yao Chend54f9dd2017-10-17 17:37:48 +0000660static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800661write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000662{
Yao Chend54f9dd2017-10-17 17:37:48 +0000663 // Print prelude
664 fprintf(out, "// This file is autogenerated\n");
665 fprintf(out, "\n");
666 fprintf(out, "package android.util;\n");
667 fprintf(out, "\n");
668 fprintf(out, "\n");
669 fprintf(out, "/**\n");
670 fprintf(out, " * API For logging statistics events.\n");
671 fprintf(out, " * @hide\n");
672 fprintf(out, " */\n");
David Chen0a368b22017-12-06 16:28:16 -0800673 fprintf(out, "public class StatsLogInternal {\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700674 fprintf(out, " // Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000675
Yangster-macba5b9e42018-01-10 21:31:59 -0800676 std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
677 build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
678
Stefan Lafon9478f352017-10-30 21:20:20 -0700679 // Print constants for the atom codes.
Yao Chend54f9dd2017-10-17 17:37:48 +0000680 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
681 atom != atoms.decls.end(); atom++) {
682 string constant = make_constant_name(atom->name);
683 fprintf(out, "\n");
684 fprintf(out, " /**\n");
685 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800686 write_java_usage(out, "write", constant, *atom, attributionDecl);
687 auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
688 if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
689 write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second,
690 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000691 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000692 fprintf(out, " */\n");
693 fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
694 }
695 fprintf(out, "\n");
696
Stefan Lafon9478f352017-10-30 21:20:20 -0700697 // Print constants for the enum values.
698 fprintf(out, " // Constants for enum values.\n\n");
699 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800700 atom != atoms.decls.end(); atom++) {
Stefan Lafon9478f352017-10-30 21:20:20 -0700701 for (vector<AtomField>::const_iterator field = atom->fields.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800702 field != atom->fields.end(); field++) {
703 if (field->javaType == JAVA_TYPE_ENUM) {
704 fprintf(out, " // Values for %s.%s\n", atom->message.c_str(),
705 field->name.c_str());
706 for (map<int, string>::const_iterator value = field->enumValues.begin();
707 value != field->enumValues.end(); value++) {
708 fprintf(out, " public static final int %s__%s__%s = %d;\n",
709 make_constant_name(atom->message).c_str(),
710 make_constant_name(field->name).c_str(),
711 make_constant_name(value->second).c_str(),
712 value->first);
713 }
714 fprintf(out, "\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700715 }
Stefan Lafon9478f352017-10-30 21:20:20 -0700716 }
717 }
718
Yao Chend54f9dd2017-10-17 17:37:48 +0000719 // Print write methods
720 fprintf(out, " // Write methods\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800721 write_java_method(out, "write", atoms.signatures, attributionDecl);
722 write_java_method(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000723
724 fprintf(out, "}\n");
725
726 return 0;
727}
728
729static const char*
730jni_type_name(java_type_t type)
731{
732 switch (type) {
733 case JAVA_TYPE_BOOLEAN:
734 return "jboolean";
735 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700736 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000737 return "jint";
738 case JAVA_TYPE_LONG:
739 return "jlong";
740 case JAVA_TYPE_FLOAT:
741 return "jfloat";
742 case JAVA_TYPE_DOUBLE:
743 return "jdouble";
744 case JAVA_TYPE_STRING:
745 return "jstring";
746 default:
747 return "UNKNOWN";
748 }
749}
750
Yangster-mac7604aea2017-12-11 22:55:49 -0800751static const char*
752jni_array_type_name(java_type_t type)
753{
754 switch (type) {
755 case JAVA_TYPE_INT:
756 return "jintArray";
757 case JAVA_TYPE_STRING:
758 return "jobjectArray";
759 default:
760 return "UNKNOWN";
761 }
762}
763
Yao Chend54f9dd2017-10-17 17:37:48 +0000764static string
Yangster-macba5b9e42018-01-10 21:31:59 -0800765jni_function_name(const string& method_name, const vector<java_type_t>& signature)
Yao Chend54f9dd2017-10-17 17:37:48 +0000766{
Yangster-macba5b9e42018-01-10 21:31:59 -0800767 string result("StatsLog_" + method_name);
Yao Chend54f9dd2017-10-17 17:37:48 +0000768 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800769 arg != signature.end(); arg++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000770 switch (*arg) {
771 case JAVA_TYPE_BOOLEAN:
772 result += "_boolean";
773 break;
774 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700775 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000776 result += "_int";
777 break;
778 case JAVA_TYPE_LONG:
779 result += "_long";
780 break;
781 case JAVA_TYPE_FLOAT:
782 result += "_float";
783 break;
784 case JAVA_TYPE_DOUBLE:
785 result += "_double";
786 break;
787 case JAVA_TYPE_STRING:
788 result += "_String";
789 break;
Yangster-mac7604aea2017-12-11 22:55:49 -0800790 case JAVA_TYPE_ATTRIBUTION_CHAIN:
791 result += "_AttributionChain";
792 break;
Yao Chend54f9dd2017-10-17 17:37:48 +0000793 default:
794 result += "_UNKNOWN";
795 break;
796 }
797 }
798 return result;
799}
800
801static const char*
802java_type_signature(java_type_t type)
803{
804 switch (type) {
805 case JAVA_TYPE_BOOLEAN:
806 return "Z";
807 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700808 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000809 return "I";
810 case JAVA_TYPE_LONG:
811 return "J";
812 case JAVA_TYPE_FLOAT:
813 return "F";
814 case JAVA_TYPE_DOUBLE:
815 return "D";
816 case JAVA_TYPE_STRING:
817 return "Ljava/lang/String;";
818 default:
819 return "UNKNOWN";
820 }
821}
822
823static string
Yangster-mac7604aea2017-12-11 22:55:49 -0800824jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000825{
826 string result("(I");
827 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800828 arg != signature.end(); arg++) {
829 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
830 for (auto chainField : attributionDecl.fields) {
831 result += "[";
832 result += java_type_signature(chainField.javaType);
833 }
834 } else {
835 result += java_type_signature(*arg);
836 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000837 }
Yao Chen97e21ec2018-03-29 11:00:38 -0700838 result += ")I";
Yao Chend54f9dd2017-10-17 17:37:48 +0000839 return result;
840}
841
842static int
Yangster-macba5b9e42018-01-10 21:31:59 -0800843write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp_method_name,
844 const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000845{
Yao Chend54f9dd2017-10-17 17:37:48 +0000846 // Print write methods
Yangster-macba5b9e42018-01-10 21:31:59 -0800847 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
848 signature != signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000849 int argIndex;
850
Yao Chen97e21ec2018-03-29 11:00:38 -0700851 fprintf(out, "static int\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000852 fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code",
Yangster-macba5b9e42018-01-10 21:31:59 -0800853 jni_function_name(java_method_name, *signature).c_str());
Yao Chend54f9dd2017-10-17 17:37:48 +0000854 argIndex = 1;
855 for (vector<java_type_t>::const_iterator arg = signature->begin();
856 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800857 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
858 for (auto chainField : attributionDecl.fields) {
859 fprintf(out, ", %s %s", jni_array_type_name(chainField.javaType),
860 chainField.name.c_str());
861 }
862 } else {
863 fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex);
864 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000865 argIndex++;
866 }
867 fprintf(out, ")\n");
868
869 fprintf(out, "{\n");
870
871 // Prepare strings
872 argIndex = 1;
Yangster-mac7604aea2017-12-11 22:55:49 -0800873 bool hadStringOrChain = false;
Yao Chend54f9dd2017-10-17 17:37:48 +0000874 for (vector<java_type_t>::const_iterator arg = signature->begin();
875 arg != signature->end(); arg++) {
876 if (*arg == JAVA_TYPE_STRING) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800877 hadStringOrChain = true;
Yao Chend54f9dd2017-10-17 17:37:48 +0000878 fprintf(out, " const char* str%d;\n", argIndex);
879 fprintf(out, " if (arg%d != NULL) {\n", argIndex);
880 fprintf(out, " str%d = env->GetStringUTFChars(arg%d, NULL);\n",
881 argIndex, argIndex);
882 fprintf(out, " } else {\n");
883 fprintf(out, " str%d = NULL;\n", argIndex);
884 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800885 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
886 hadStringOrChain = true;
887 for (auto chainField : attributionDecl.fields) {
888 fprintf(out, " size_t %s_length = env->GetArrayLength(%s);\n",
889 chainField.name.c_str(), chainField.name.c_str());
890 if (chainField.name != attributionDecl.fields.front().name) {
891 fprintf(out, " if (%s_length != %s_length) {\n",
892 chainField.name.c_str(),
893 attributionDecl.fields.front().name.c_str());
Yao Chen97e21ec2018-03-29 11:00:38 -0700894 fprintf(out, " return -EINVAL;\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800895 fprintf(out, " }\n");
896 }
897 if (chainField.javaType == JAVA_TYPE_INT) {
898 fprintf(out, " jint* %s_array = env->GetIntArrayElements(%s, NULL);\n",
899 chainField.name.c_str(), chainField.name.c_str());
900 } else if (chainField.javaType == JAVA_TYPE_STRING) {
901 fprintf(out, " std::vector<%s> %s_vec;\n",
902 cpp_type_name(chainField.javaType), chainField.name.c_str());
903 fprintf(out, " std::vector<ScopedUtfChars*> scoped_%s_vec;\n",
904 chainField.name.c_str());
905 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
906 chainField.name.c_str());
907 fprintf(out, " jstring jstr = "
908 "(jstring)env->GetObjectArrayElement(%s, i);\n",
909 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800910 fprintf(out, " if (jstr == NULL) {\n");
911 fprintf(out, " %s_vec.push_back(NULL);\n",
912 chainField.name.c_str());
913 fprintf(out, " } else {\n");
914 fprintf(out, " ScopedUtfChars* scoped_%s = "
Yangster-mac7604aea2017-12-11 22:55:49 -0800915 "new ScopedUtfChars(env, jstr);\n",
916 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800917 fprintf(out, " %s_vec.push_back(scoped_%s->c_str());\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800918 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800919 fprintf(out, " scoped_%s_vec.push_back(scoped_%s);\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800920 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800921 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800922 fprintf(out, " }\n");
923 }
924 fprintf(out, "\n");
925 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000926 }
927 argIndex++;
928 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800929 // Emit this to quiet the unused parameter warning if there were no strings or attribution
930 // chains.
931 if (!hadStringOrChain) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000932 fprintf(out, " (void)env;\n");
933 }
934
935 // stats_write call
936 argIndex = 1;
Yao Chen97e21ec2018-03-29 11:00:38 -0700937 fprintf(out, " int ret = android::util::%s(code", cpp_method_name.c_str());
Yao Chend54f9dd2017-10-17 17:37:48 +0000938 for (vector<java_type_t>::const_iterator arg = signature->begin();
939 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800940 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
941 for (auto chainField : attributionDecl.fields) {
942 if (chainField.javaType == JAVA_TYPE_INT) {
943 fprintf(out, ", (const %s*)%s_array, %s_length",
944 cpp_type_name(chainField.javaType),
945 chainField.name.c_str(), chainField.name.c_str());
946 } else if (chainField.javaType == JAVA_TYPE_STRING) {
947 fprintf(out, ", %s_vec", chainField.name.c_str());
948 }
949 }
950 } else {
951 const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
952 fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
953 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000954 argIndex++;
955 }
956 fprintf(out, ");\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800957 fprintf(out, "\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000958
959 // Clean up strings
960 argIndex = 1;
961 for (vector<java_type_t>::const_iterator arg = signature->begin();
962 arg != signature->end(); arg++) {
963 if (*arg == JAVA_TYPE_STRING) {
964 fprintf(out, " if (str%d != NULL) {\n", argIndex);
965 fprintf(out, " env->ReleaseStringUTFChars(arg%d, str%d);\n",
966 argIndex, argIndex);
967 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800968 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
969 for (auto chainField : attributionDecl.fields) {
970 if (chainField.javaType == JAVA_TYPE_INT) {
971 fprintf(out, " env->ReleaseIntArrayElements(%s, %s_array, 0);\n",
972 chainField.name.c_str(), chainField.name.c_str());
973 } else if (chainField.javaType == JAVA_TYPE_STRING) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800974 fprintf(out, " for (size_t i = 0; i < scoped_%s_vec.size(); ++i) {\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800975 chainField.name.c_str());
976 fprintf(out, " delete scoped_%s_vec[i];\n", chainField.name.c_str());
977 fprintf(out, " }\n");
978 }
979 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000980 }
981 argIndex++;
982 }
Yao Chen97e21ec2018-03-29 11:00:38 -0700983 fprintf(out, " return ret;\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000984
985 fprintf(out, "}\n");
986 fprintf(out, "\n");
987 }
988
Yangster-macba5b9e42018-01-10 21:31:59 -0800989
990 return 0;
991}
992
993void write_jni_registration(FILE* out, const string& java_method_name,
994 const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) {
995 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
996 signature != signatures.end(); signature++) {
997 fprintf(out, " { \"%s\", \"%s\", (void*)%s },\n",
998 java_method_name.c_str(),
999 jni_function_signature(*signature, attributionDecl).c_str(),
1000 jni_function_name(java_method_name, *signature).c_str());
1001 }
1002}
1003
1004static int
1005write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
1006{
1007 // Print prelude
1008 fprintf(out, "// This file is autogenerated\n");
1009 fprintf(out, "\n");
1010
1011 fprintf(out, "#include <statslog.h>\n");
1012 fprintf(out, "\n");
1013 fprintf(out, "#include <nativehelper/JNIHelp.h>\n");
1014 fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n");
1015 fprintf(out, "#include <utils/Vector.h>\n");
1016 fprintf(out, "#include \"core_jni_helpers.h\"\n");
1017 fprintf(out, "#include \"jni.h\"\n");
1018 fprintf(out, "\n");
1019 fprintf(out, "#define UNUSED __attribute__((__unused__))\n");
1020 fprintf(out, "\n");
1021
1022 fprintf(out, "namespace android {\n");
1023 fprintf(out, "\n");
1024
1025 write_stats_log_jni(out, "write", "stats_write", atoms.signatures, attributionDecl);
1026 write_stats_log_jni(out, "write_non_chained", "stats_write_non_chained",
1027 atoms.non_chained_signatures, attributionDecl);
1028
Yao Chend54f9dd2017-10-17 17:37:48 +00001029 // Print registration function table
1030 fprintf(out, "/*\n");
1031 fprintf(out, " * JNI registration.\n");
1032 fprintf(out, " */\n");
1033 fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n");
Yangster-macba5b9e42018-01-10 21:31:59 -08001034 write_jni_registration(out, "write", atoms.signatures, attributionDecl);
1035 write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001036 fprintf(out, "};\n");
1037 fprintf(out, "\n");
1038
1039 // Print registration function
1040 fprintf(out, "int register_android_util_StatsLog(JNIEnv* env) {\n");
1041 fprintf(out, " return RegisterMethodsOrDie(\n");
1042 fprintf(out, " env,\n");
1043 fprintf(out, " \"android/util/StatsLog\",\n");
1044 fprintf(out, " gRegisterMethods, NELEM(gRegisterMethods));\n");
1045 fprintf(out, "}\n");
1046
1047 fprintf(out, "\n");
1048 fprintf(out, "} // namespace android\n");
Yao Chend54f9dd2017-10-17 17:37:48 +00001049 return 0;
1050}
1051
Yao Chend54f9dd2017-10-17 17:37:48 +00001052static void
1053print_usage()
1054{
1055 fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
1056 fprintf(stderr, "\n");
1057 fprintf(stderr, "OPTIONS\n");
1058 fprintf(stderr, " --cpp FILENAME the header file to output\n");
1059 fprintf(stderr, " --header FILENAME the cpp file to output\n");
1060 fprintf(stderr, " --help this message\n");
1061 fprintf(stderr, " --java FILENAME the java file to output\n");
1062 fprintf(stderr, " --jni FILENAME the jni file to output\n");
1063}
1064
1065/**
1066 * Do the argument parsing and execute the tasks.
1067 */
1068static int
1069run(int argc, char const*const* argv)
1070{
1071 string cppFilename;
1072 string headerFilename;
1073 string javaFilename;
1074 string jniFilename;
1075
1076 int index = 1;
1077 while (index < argc) {
1078 if (0 == strcmp("--help", argv[index])) {
1079 print_usage();
1080 return 0;
1081 } else if (0 == strcmp("--cpp", argv[index])) {
1082 index++;
1083 if (index >= argc) {
1084 print_usage();
1085 return 1;
1086 }
1087 cppFilename = argv[index];
1088 } else if (0 == strcmp("--header", argv[index])) {
1089 index++;
1090 if (index >= argc) {
1091 print_usage();
1092 return 1;
1093 }
1094 headerFilename = argv[index];
1095 } else if (0 == strcmp("--java", argv[index])) {
1096 index++;
1097 if (index >= argc) {
1098 print_usage();
1099 return 1;
1100 }
1101 javaFilename = argv[index];
1102 } else if (0 == strcmp("--jni", argv[index])) {
1103 index++;
1104 if (index >= argc) {
1105 print_usage();
1106 return 1;
1107 }
1108 jniFilename = argv[index];
1109 }
1110 index++;
1111 }
1112
1113 if (cppFilename.size() == 0
1114 && headerFilename.size() == 0
1115 && javaFilename.size() == 0
1116 && jniFilename.size() == 0) {
1117 print_usage();
1118 return 1;
1119 }
1120
1121 // Collate the parameters
1122 Atoms atoms;
Stefan Lafonae2df012017-11-14 09:17:21 -08001123 int errorCount = collate_atoms(Atom::descriptor(), &atoms);
Yao Chend54f9dd2017-10-17 17:37:48 +00001124 if (errorCount != 0) {
1125 return 1;
1126 }
1127
Yangster-mac7604aea2017-12-11 22:55:49 -08001128 AtomDecl attributionDecl;
1129 vector<java_type_t> attributionSignature;
Yangster-mac20877162017-12-22 17:19:39 -08001130 collate_atom(android::os::statsd::AttributionNode::descriptor(),
Yangster-mac7604aea2017-12-11 22:55:49 -08001131 &attributionDecl, &attributionSignature);
1132
Yao Chend54f9dd2017-10-17 17:37:48 +00001133 // Write the .cpp file
1134 if (cppFilename.size() != 0) {
1135 FILE* out = fopen(cppFilename.c_str(), "w");
1136 if (out == NULL) {
1137 fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
1138 return 1;
1139 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001140 errorCount = android::stats_log_api_gen::write_stats_log_cpp(
1141 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001142 fclose(out);
1143 }
1144
1145 // Write the .h file
1146 if (headerFilename.size() != 0) {
1147 FILE* out = fopen(headerFilename.c_str(), "w");
1148 if (out == NULL) {
1149 fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
1150 return 1;
1151 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001152 errorCount = android::stats_log_api_gen::write_stats_log_header(
1153 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001154 fclose(out);
1155 }
1156
1157 // Write the .java file
1158 if (javaFilename.size() != 0) {
1159 FILE* out = fopen(javaFilename.c_str(), "w");
1160 if (out == NULL) {
1161 fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
1162 return 1;
1163 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001164 errorCount = android::stats_log_api_gen::write_stats_log_java(
1165 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001166 fclose(out);
1167 }
1168
1169 // Write the jni file
1170 if (jniFilename.size() != 0) {
1171 FILE* out = fopen(jniFilename.c_str(), "w");
1172 if (out == NULL) {
1173 fprintf(stderr, "Unable to open file for write: %s\n", jniFilename.c_str());
1174 return 1;
1175 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001176 errorCount = android::stats_log_api_gen::write_stats_log_jni(
1177 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001178 fclose(out);
1179 }
1180
1181 return 0;
1182}
1183
1184}
1185}
1186
1187/**
1188 * Main.
1189 */
1190int
1191main(int argc, char const*const* argv)
1192{
1193 GOOGLE_PROTOBUF_VERIFY_VERSION;
1194
1195 return android::stats_log_api_gen::run(argc, argv);
Yangster-mac7604aea2017-12-11 22:55:49 -08001196}