blob: 140653a490e1b177f581d8bd07a4858cd264fc77 [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 Chencf3829a2018-06-05 14:20:35 -0700107 fprintf(out, "#include <cutils/properties.h>\n");
Yao Chenf7bc6ab2018-04-18 13:45:48 -0700108 fprintf(out, "#include <stats_event_list.h>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000109 fprintf(out, "#include <log/log.h>\n");
110 fprintf(out, "#include <statslog.h>\n");
Yangster-mac330af582018-02-08 15:24:38 -0800111 fprintf(out, "#include <utils/SystemClock.h>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000112 fprintf(out, "\n");
113
114 fprintf(out, "namespace android {\n");
115 fprintf(out, "namespace util {\n");
Yao Chen80235402017-11-13 20:42:25 -0800116 fprintf(out, "// the single event tag id for all stats logs\n");
117 fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
Yao Chencf3829a2018-06-05 14:20:35 -0700118 fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000119
Yao Chenc40a19d2018-03-15 16:48:25 -0700120 std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
121 "audio_state_changed",
122 "call_state_changed",
123 "phone_signal_strength_changed",
124 "mobile_bytes_transfer_by_fg_bg",
125 "mobile_bytes_transfer"};
126 fprintf(out,
127 "const std::set<int> "
128 "AtomsInfo::kNotTruncatingTimestampAtomWhiteList = {\n");
129 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
130 atom != atoms.decls.end(); atom++) {
131 if (kTruncatingAtomNames.find(atom->name) ==
132 kTruncatingAtomNames.end()) {
133 string constant = make_constant_name(atom->name);
134 fprintf(out, " %s,\n", constant.c_str());
135 }
136 }
137 fprintf(out, "};\n");
138 fprintf(out, "\n");
139
140 fprintf(out,
141 "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
142 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
143 atom != atoms.decls.end(); atom++) {
144 for (vector<AtomField>::const_iterator field = atom->fields.begin();
145 field != atom->fields.end(); field++) {
146 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
147 string constant = make_constant_name(atom->name);
148 fprintf(out, " %s,\n", constant.c_str());
149 break;
150 }
151 }
152 }
153 fprintf(out, "};\n");
154 fprintf(out, "\n");
155
Yangster-macca5c0862018-04-09 22:39:53 -0700156 fprintf(out, "static std::map<int, int> getAtomUidField() {\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700157 fprintf(out, " std::map<int, int> uidField;\n");
158 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
159 atom != atoms.decls.end(); atom++) {
160 if (atom->uidField == 0) {
161 continue;
162 }
163 fprintf(out,
164 "\n // Adding uid field for atom "
165 "(%d)%s\n",
166 atom->code, atom->name.c_str());
167 fprintf(out, " uidField[static_cast<int>(%s)] = %d;\n",
168 make_constant_name(atom->name).c_str(), atom->uidField);
169 }
170
171 fprintf(out, " return uidField;\n");
172 fprintf(out, "};\n");
173
174 fprintf(out,
175 "const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
176 "getAtomUidField();\n");
177
178 fprintf(out,
179 "static std::map<int, StateAtomFieldOptions> "
180 "getStateAtomFieldOptions() {\n");
181 fprintf(out, " std::map<int, StateAtomFieldOptions> options;\n");
182 fprintf(out, " StateAtomFieldOptions opt;\n");
183 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
184 atom != atoms.decls.end(); atom++) {
185 if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
186 continue;
187 }
188 fprintf(out,
189 "\n // Adding primary and exclusive fields for atom "
190 "(%d)%s\n",
191 atom->code, atom->name.c_str());
192 fprintf(out, " opt.primaryFields.clear();\n");
193 for (const auto& field : atom->primaryFields) {
194 fprintf(out, " opt.primaryFields.push_back(%d);\n", field);
195 }
196
197 fprintf(out, " opt.exclusiveField = %d;\n", atom->exclusiveField);
198 fprintf(out, " options[static_cast<int>(%s)] = opt;\n",
199 make_constant_name(atom->name).c_str());
200 }
201
202 fprintf(out, " return options;\n");
203 fprintf(out, " }\n");
204
205 fprintf(out,
206 "const std::map<int, StateAtomFieldOptions> "
207 "AtomsInfo::kStateAtomsFieldOptions = "
208 "getStateAtomFieldOptions();\n");
209
Yangster-macca5c0862018-04-09 22:39:53 -0700210
211 fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
212 fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
213 fprintf(out, "static std::mutex mLogdRetryMutex;\n");
214
Yao Chend54f9dd2017-10-17 17:37:48 +0000215 // Print write methods
216 fprintf(out, "\n");
217 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800218 signature != atoms.signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000219 int argIndex;
220
Yao Chen97e21ec2018-03-29 11:00:38 -0700221 fprintf(out, "int\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700222 fprintf(out, "try_stats_write(int32_t code");
Yao Chend54f9dd2017-10-17 17:37:48 +0000223 argIndex = 1;
224 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800225 arg != signature->end(); arg++) {
226 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
227 for (auto chainField : attributionDecl.fields) {
228 if (chainField.javaType == JAVA_TYPE_STRING) {
229 fprintf(out, ", const std::vector<%s>& %s",
230 cpp_type_name(chainField.javaType),
231 chainField.name.c_str());
232 } else {
233 fprintf(out, ", const %s* %s, size_t %s_length",
234 cpp_type_name(chainField.javaType),
235 chainField.name.c_str(), chainField.name.c_str());
236 }
237 }
238 } else {
239 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
240 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000241 argIndex++;
242 }
243 fprintf(out, ")\n");
244
245 fprintf(out, "{\n");
246 argIndex = 1;
Yao Chencf3829a2018-06-05 14:20:35 -0700247 fprintf(out, " if (kStatsdEnabled) {\n");
Yao Chenf7bc6ab2018-04-18 13:45:48 -0700248 fprintf(out, " stats_event_list event(kStatsEventTag);\n");
Yangster-mac330af582018-02-08 15:24:38 -0800249 fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800250 fprintf(out, " event << code;\n\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000251 for (vector<java_type_t>::const_iterator arg = signature->begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800252 arg != signature->end(); arg++) {
253 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
254 for (const auto &chainField : attributionDecl.fields) {
255 if (chainField.javaType == JAVA_TYPE_STRING) {
256 fprintf(out, " if (%s_length != %s.size()) {\n",
257 attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
Yao Chen97e21ec2018-03-29 11:00:38 -0700258 fprintf(out, " return -EINVAL;\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800259 fprintf(out, " }\n");
260 }
261 }
262 fprintf(out, "\n event.begin();\n");
263 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
264 attributionDecl.fields.front().name.c_str());
265 fprintf(out, " event.begin();\n");
266 for (const auto &chainField : attributionDecl.fields) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800267 if (chainField.javaType == JAVA_TYPE_STRING) {
268 fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
269 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
270 fprintf(out, " } else {\n");
271 fprintf(out, " event << \"\";\n");
272 fprintf(out, " }\n");
273 } else {
274 fprintf(out, " event << %s[i];\n", chainField.name.c_str());
275 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800276 }
277 fprintf(out, " event.end();\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000278 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800279 fprintf(out, " event.end();\n\n");
280 } else {
281 if (*arg == JAVA_TYPE_STRING) {
282 fprintf(out, " if (arg%d == NULL) {\n", argIndex);
283 fprintf(out, " arg%d = \"\";\n", argIndex);
284 fprintf(out, " }\n");
285 }
286 fprintf(out, " event << arg%d;\n", argIndex);
Yao Chend54f9dd2017-10-17 17:37:48 +0000287 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000288 argIndex++;
289 }
290
Yao Chen97e21ec2018-03-29 11:00:38 -0700291 fprintf(out, " return event.write(LOG_ID_STATS);\n");
Yao Chencf3829a2018-06-05 14:20:35 -0700292 fprintf(out, " } else {\n");
293 fprintf(out, " return 1;\n");
294 fprintf(out, " }\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000295 fprintf(out, "}\n");
296 fprintf(out, "\n");
297 }
298
Yangster-macb8382a12018-04-04 10:39:12 -0700299 for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
300 signature != atoms.signatures.end(); signature++) {
301 int argIndex;
302
303 fprintf(out, "int \n");
304 fprintf(out, "stats_write(int32_t code");
305 argIndex = 1;
306 for (vector<java_type_t>::const_iterator arg = signature->begin();
307 arg != signature->end(); arg++) {
308 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
309 for (auto chainField : attributionDecl.fields) {
310 if (chainField.javaType == JAVA_TYPE_STRING) {
311 fprintf(out, ", const std::vector<%s>& %s",
312 cpp_type_name(chainField.javaType),
313 chainField.name.c_str());
314 } else {
315 fprintf(out, ", const %s* %s, size_t %s_length",
316 cpp_type_name(chainField.javaType),
317 chainField.name.c_str(), chainField.name.c_str());
318 }
319 }
320 } else {
321 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
322 }
323 argIndex++;
324 }
325 fprintf(out, ")\n");
326
327 fprintf(out, "{\n");
328 fprintf(out, " int ret = 0;\n");
329
Yangster-macca5c0862018-04-09 22:39:53 -0700330 fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700331 fprintf(out, " ret = try_stats_write(code");
332
333 argIndex = 1;
334 for (vector<java_type_t>::const_iterator arg = signature->begin();
335 arg != signature->end(); arg++) {
336 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
337 for (auto chainField : attributionDecl.fields) {
338 if (chainField.javaType == JAVA_TYPE_STRING) {
339 fprintf(out, ", %s",
340 chainField.name.c_str());
341 } else {
342 fprintf(out, ", %s, %s_length",
343 chainField.name.c_str(), chainField.name.c_str());
344 }
345 }
346 } else {
347 fprintf(out, ", arg%d", argIndex);
348 }
349 argIndex++;
350 }
351 fprintf(out, ");\n");
352 fprintf(out, " if (ret >= 0) { return retry; }\n");
Yangster-macca5c0862018-04-09 22:39:53 -0700353
354
355 fprintf(out, " {\n");
356 fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
357 fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
358 "kMinRetryIntervalNs) break;\n");
359 fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
360 fprintf(out, " }\n");
361 fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700362 fprintf(out, " }\n");
363 fprintf(out, " return ret;\n");
364 fprintf(out, "}\n");
365 fprintf(out, "\n");
366 }
367
Yangster-macba5b9e42018-01-10 21:31:59 -0800368 for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
369 signature != atoms.non_chained_signatures.end(); signature++) {
370 int argIndex;
371
Yao Chen97e21ec2018-03-29 11:00:38 -0700372 fprintf(out, "int\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700373 fprintf(out, "try_stats_write_non_chained(int32_t code");
Yangster-macba5b9e42018-01-10 21:31:59 -0800374 argIndex = 1;
375 for (vector<java_type_t>::const_iterator arg = signature->begin();
376 arg != signature->end(); arg++) {
377 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
378 argIndex++;
379 }
380 fprintf(out, ")\n");
381
382 fprintf(out, "{\n");
383 argIndex = 1;
Yao Chencf3829a2018-06-05 14:20:35 -0700384 fprintf(out, " if (kStatsdEnabled) {\n");
Yao Chenf7bc6ab2018-04-18 13:45:48 -0700385 fprintf(out, " stats_event_list event(kStatsEventTag);\n");
Yangster-mac31ddcde2018-02-14 16:09:35 -0800386 fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800387 fprintf(out, " event << code;\n\n");
388 for (vector<java_type_t>::const_iterator arg = signature->begin();
389 arg != signature->end(); arg++) {
390 if (argIndex == 1) {
391 fprintf(out, " event.begin();\n\n");
392 fprintf(out, " event.begin();\n");
393 }
394 if (*arg == JAVA_TYPE_STRING) {
395 fprintf(out, " if (arg%d == NULL) {\n", argIndex);
396 fprintf(out, " arg%d = \"\";\n", argIndex);
397 fprintf(out, " }\n");
398 }
399 fprintf(out, " event << arg%d;\n", argIndex);
400 if (argIndex == 2) {
401 fprintf(out, " event.end();\n\n");
402 fprintf(out, " event.end();\n\n");
403 }
404 argIndex++;
405 }
406
Yao Chen97e21ec2018-03-29 11:00:38 -0700407 fprintf(out, " return event.write(LOG_ID_STATS);\n");
Yao Chencf3829a2018-06-05 14:20:35 -0700408 fprintf(out, " } else {\n");
409 fprintf(out, " return 1;\n");
410 fprintf(out, " }\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800411 fprintf(out, "}\n");
412 fprintf(out, "\n");
413 }
Yangster-macb8382a12018-04-04 10:39:12 -0700414
415 for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
416 signature != atoms.non_chained_signatures.end(); signature++) {
417 int argIndex;
418
419 fprintf(out, "int\n");
420 fprintf(out, "stats_write_non_chained(int32_t code");
421 argIndex = 1;
422 for (vector<java_type_t>::const_iterator arg = signature->begin();
423 arg != signature->end(); arg++) {
424 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
425 argIndex++;
426 }
427 fprintf(out, ")\n");
428
429 fprintf(out, "{\n");
430
431 fprintf(out, " int ret = 0;\n");
Yangster-macca5c0862018-04-09 22:39:53 -0700432 fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700433 fprintf(out, " ret = try_stats_write_non_chained(code");
434
435 argIndex = 1;
436 for (vector<java_type_t>::const_iterator arg = signature->begin();
437 arg != signature->end(); arg++) {
438 fprintf(out, ", arg%d", argIndex);
439 argIndex++;
440 }
441 fprintf(out, ");\n");
442 fprintf(out, " if (ret >= 0) { return retry; }\n");
Yangster-macca5c0862018-04-09 22:39:53 -0700443
444 fprintf(out, " {\n");
445 fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
446 fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
447 "kMinRetryIntervalNs) break;\n");
448 fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
449 fprintf(out, " }\n");
450
451 fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
Yangster-macb8382a12018-04-04 10:39:12 -0700452 fprintf(out, " }\n");
453 fprintf(out, " return ret;\n");
454 fprintf(out, "}\n");
455
456 fprintf(out, "\n");
457 }
458
459
Yao Chend54f9dd2017-10-17 17:37:48 +0000460 // Print footer
461 fprintf(out, "\n");
462 fprintf(out, "} // namespace util\n");
463 fprintf(out, "} // namespace android\n");
464
465 return 0;
466}
467
Yangster-macba5b9e42018-01-10 21:31:59 -0800468void build_non_chained_decl_map(const Atoms& atoms,
469 std::map<int, set<AtomDecl>::const_iterator>* decl_map){
470 for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin();
471 atom != atoms.non_chained_decls.end(); atom++) {
472 decl_map->insert(std::make_pair(atom->code, atom));
473 }
474}
475
476static void write_cpp_usage(
477 FILE* out, const string& method_name, const string& atom_code_name,
478 const AtomDecl& atom, const AtomDecl &attributionDecl) {
479 fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str());
480 for (vector<AtomField>::const_iterator field = atom.fields.begin();
481 field != atom.fields.end(); field++) {
482 if (field->javaType == 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),
487 chainField.name.c_str());
488 } else {
489 fprintf(out, ", const %s* %s, size_t %s_length",
490 cpp_type_name(chainField.javaType),
491 chainField.name.c_str(), chainField.name.c_str());
492 }
493 }
494 } else {
495 fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
496 }
497 }
498 fprintf(out, ");\n");
499}
500
501static void write_cpp_method_header(
502 FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures,
503 const AtomDecl &attributionDecl) {
504 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
505 signature != signatures.end(); signature++) {
Yao Chen97e21ec2018-03-29 11:00:38 -0700506 fprintf(out, "int %s(int32_t code ", method_name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800507 int argIndex = 1;
508 for (vector<java_type_t>::const_iterator arg = signature->begin();
509 arg != signature->end(); arg++) {
510 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
511 for (auto chainField : attributionDecl.fields) {
512 if (chainField.javaType == JAVA_TYPE_STRING) {
513 fprintf(out, ", const std::vector<%s>& %s",
514 cpp_type_name(chainField.javaType), chainField.name.c_str());
515 } else {
516 fprintf(out, ", const %s* %s, size_t %s_length",
517 cpp_type_name(chainField.javaType),
518 chainField.name.c_str(), chainField.name.c_str());
519 }
520 }
521 } else {
522 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
523 }
524 argIndex++;
525 }
526 fprintf(out, ");\n");
527
528 }
529}
Yao Chend54f9dd2017-10-17 17:37:48 +0000530
531static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800532write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000533{
Yao Chend54f9dd2017-10-17 17:37:48 +0000534 // Print prelude
535 fprintf(out, "// This file is autogenerated\n");
536 fprintf(out, "\n");
537 fprintf(out, "#pragma once\n");
538 fprintf(out, "\n");
539 fprintf(out, "#include <stdint.h>\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800540 fprintf(out, "#include <vector>\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800541 fprintf(out, "#include <map>\n");
Yangster-mac68985802018-01-21 10:05:09 -0800542 fprintf(out, "#include <set>\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000543 fprintf(out, "\n");
544
545 fprintf(out, "namespace android {\n");
546 fprintf(out, "namespace util {\n");
547 fprintf(out, "\n");
548 fprintf(out, "/*\n");
549 fprintf(out, " * API For logging statistics events.\n");
550 fprintf(out, " */\n");
551 fprintf(out, "\n");
552 fprintf(out, "/**\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700553 fprintf(out, " * Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000554 fprintf(out, " */\n");
555 fprintf(out, "enum {\n");
556
Yangster-macba5b9e42018-01-10 21:31:59 -0800557 std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
558 build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
559
Yao Chend54f9dd2017-10-17 17:37:48 +0000560 size_t i = 0;
561 // Print constants
562 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800563 atom != atoms.decls.end(); atom++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000564 string constant = make_constant_name(atom->name);
565 fprintf(out, "\n");
566 fprintf(out, " /**\n");
567 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800568 write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl);
569
570 auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
571 if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
572 write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
573 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000574 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000575 fprintf(out, " */\n");
576 char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
577 fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
Yao Chenb3561512017-11-21 18:07:17 -0800578 if (atom->code < PULL_ATOM_START_ID && atom->code > maxPushedAtomId) {
579 maxPushedAtomId = atom->code;
580 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000581 i++;
582 }
583 fprintf(out, "\n");
584 fprintf(out, "};\n");
585 fprintf(out, "\n");
586
Yao Chen9c1debe2018-02-19 14:39:19 -0800587 fprintf(out, "struct StateAtomFieldOptions {\n");
588 fprintf(out, " std::vector<int> primaryFields;\n");
589 fprintf(out, " int exclusiveField;\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700590 fprintf(out, "};\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800591 fprintf(out, "\n");
Yao Chenc40a19d2018-03-15 16:48:25 -0700592
593 fprintf(out, "struct AtomsInfo {\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800594 fprintf(out,
Yao Chenc40a19d2018-03-15 16:48:25 -0700595 " const static std::set<int> "
596 "kNotTruncatingTimestampAtomWhiteList;\n");
597 fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
598 fprintf(out,
599 " const static std::set<int> kAtomsWithAttributionChain;\n");
600 fprintf(out,
601 " const static std::map<int, StateAtomFieldOptions> "
602 "kStateAtomsFieldOptions;\n");
Yao Chen9c1debe2018-02-19 14:39:19 -0800603 fprintf(out, "};\n");
604
Yao Chenc40a19d2018-03-15 16:48:25 -0700605 fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
606 maxPushedAtomId);
Yao Chen9c1debe2018-02-19 14:39:19 -0800607
Yao Chend54f9dd2017-10-17 17:37:48 +0000608 // Print write methods
609 fprintf(out, "//\n");
610 fprintf(out, "// Write methods\n");
611 fprintf(out, "//\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800612 write_cpp_method_header(out, "stats_write", atoms.signatures, attributionDecl);
613
614 fprintf(out, "//\n");
615 fprintf(out, "// Write flattened methods\n");
616 fprintf(out, "//\n");
617 write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures,
618 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000619
620 fprintf(out, "\n");
621 fprintf(out, "} // namespace util\n");
622 fprintf(out, "} // namespace android\n");
623
624 return 0;
625}
626
Yangster-macba5b9e42018-01-10 21:31:59 -0800627static void write_java_usage(
628 FILE* out, const string& method_name, const string& atom_code_name,
629 const AtomDecl& atom, const AtomDecl &attributionDecl) {
630 fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s",
631 method_name.c_str(), atom_code_name.c_str());
632 for (vector<AtomField>::const_iterator field = atom.fields.begin();
633 field != atom.fields.end(); field++) {
634 if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
635 for (auto chainField : attributionDecl.fields) {
636 fprintf(out, ", %s[] %s",
637 java_type_name(chainField.javaType), chainField.name.c_str());
638 }
639 } else {
640 fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
641 }
642 }
643 fprintf(out, ");\n");
644}
645
646static void write_java_method(
647 FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures,
648 const AtomDecl &attributionDecl) {
649 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
650 signature != signatures.end(); signature++) {
Yao Chen97e21ec2018-03-29 11:00:38 -0700651 fprintf(out, " public static native int %s(int code", method_name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800652 int argIndex = 1;
653 for (vector<java_type_t>::const_iterator arg = signature->begin();
654 arg != signature->end(); arg++) {
655 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
656 for (auto chainField : attributionDecl.fields) {
657 fprintf(out, ", %s[] %s",
658 java_type_name(chainField.javaType), chainField.name.c_str());
659 }
660 } else {
661 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
662 }
663 argIndex++;
664 }
665 fprintf(out, ");\n");
666 }
667}
668
669
Yao Chend54f9dd2017-10-17 17:37:48 +0000670static int
Yangster-mac7604aea2017-12-11 22:55:49 -0800671write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000672{
Yao Chend54f9dd2017-10-17 17:37:48 +0000673 // Print prelude
674 fprintf(out, "// This file is autogenerated\n");
675 fprintf(out, "\n");
676 fprintf(out, "package android.util;\n");
677 fprintf(out, "\n");
678 fprintf(out, "\n");
679 fprintf(out, "/**\n");
680 fprintf(out, " * API For logging statistics events.\n");
681 fprintf(out, " * @hide\n");
682 fprintf(out, " */\n");
David Chen0a368b22017-12-06 16:28:16 -0800683 fprintf(out, "public class StatsLogInternal {\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700684 fprintf(out, " // Constants for atom codes.\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000685
Yangster-macba5b9e42018-01-10 21:31:59 -0800686 std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
687 build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
688
Stefan Lafon9478f352017-10-30 21:20:20 -0700689 // Print constants for the atom codes.
Yao Chend54f9dd2017-10-17 17:37:48 +0000690 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
691 atom != atoms.decls.end(); atom++) {
692 string constant = make_constant_name(atom->name);
693 fprintf(out, "\n");
694 fprintf(out, " /**\n");
695 fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
Yangster-macba5b9e42018-01-10 21:31:59 -0800696 write_java_usage(out, "write", constant, *atom, attributionDecl);
697 auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
698 if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
699 write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second,
700 attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000701 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000702 fprintf(out, " */\n");
703 fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
704 }
705 fprintf(out, "\n");
706
Stefan Lafon9478f352017-10-30 21:20:20 -0700707 // Print constants for the enum values.
708 fprintf(out, " // Constants for enum values.\n\n");
709 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800710 atom != atoms.decls.end(); atom++) {
Stefan Lafon9478f352017-10-30 21:20:20 -0700711 for (vector<AtomField>::const_iterator field = atom->fields.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800712 field != atom->fields.end(); field++) {
713 if (field->javaType == JAVA_TYPE_ENUM) {
714 fprintf(out, " // Values for %s.%s\n", atom->message.c_str(),
715 field->name.c_str());
716 for (map<int, string>::const_iterator value = field->enumValues.begin();
717 value != field->enumValues.end(); value++) {
718 fprintf(out, " public static final int %s__%s__%s = %d;\n",
719 make_constant_name(atom->message).c_str(),
720 make_constant_name(field->name).c_str(),
721 make_constant_name(value->second).c_str(),
722 value->first);
723 }
724 fprintf(out, "\n");
Stefan Lafon9478f352017-10-30 21:20:20 -0700725 }
Stefan Lafon9478f352017-10-30 21:20:20 -0700726 }
727 }
728
Yao Chend54f9dd2017-10-17 17:37:48 +0000729 // Print write methods
730 fprintf(out, " // Write methods\n");
Yangster-macba5b9e42018-01-10 21:31:59 -0800731 write_java_method(out, "write", atoms.signatures, attributionDecl);
732 write_java_method(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +0000733
734 fprintf(out, "}\n");
735
736 return 0;
737}
738
739static const char*
740jni_type_name(java_type_t type)
741{
742 switch (type) {
743 case JAVA_TYPE_BOOLEAN:
744 return "jboolean";
745 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700746 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000747 return "jint";
748 case JAVA_TYPE_LONG:
749 return "jlong";
750 case JAVA_TYPE_FLOAT:
751 return "jfloat";
752 case JAVA_TYPE_DOUBLE:
753 return "jdouble";
754 case JAVA_TYPE_STRING:
755 return "jstring";
756 default:
757 return "UNKNOWN";
758 }
759}
760
Yangster-mac7604aea2017-12-11 22:55:49 -0800761static const char*
762jni_array_type_name(java_type_t type)
763{
764 switch (type) {
765 case JAVA_TYPE_INT:
766 return "jintArray";
767 case JAVA_TYPE_STRING:
768 return "jobjectArray";
769 default:
770 return "UNKNOWN";
771 }
772}
773
Yao Chend54f9dd2017-10-17 17:37:48 +0000774static string
Yangster-macba5b9e42018-01-10 21:31:59 -0800775jni_function_name(const string& method_name, const vector<java_type_t>& signature)
Yao Chend54f9dd2017-10-17 17:37:48 +0000776{
Yangster-macba5b9e42018-01-10 21:31:59 -0800777 string result("StatsLog_" + method_name);
Yao Chend54f9dd2017-10-17 17:37:48 +0000778 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800779 arg != signature.end(); arg++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000780 switch (*arg) {
781 case JAVA_TYPE_BOOLEAN:
782 result += "_boolean";
783 break;
784 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700785 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000786 result += "_int";
787 break;
788 case JAVA_TYPE_LONG:
789 result += "_long";
790 break;
791 case JAVA_TYPE_FLOAT:
792 result += "_float";
793 break;
794 case JAVA_TYPE_DOUBLE:
795 result += "_double";
796 break;
797 case JAVA_TYPE_STRING:
798 result += "_String";
799 break;
Yangster-mac7604aea2017-12-11 22:55:49 -0800800 case JAVA_TYPE_ATTRIBUTION_CHAIN:
801 result += "_AttributionChain";
802 break;
Yao Chend54f9dd2017-10-17 17:37:48 +0000803 default:
804 result += "_UNKNOWN";
805 break;
806 }
807 }
808 return result;
809}
810
811static const char*
812java_type_signature(java_type_t type)
813{
814 switch (type) {
815 case JAVA_TYPE_BOOLEAN:
816 return "Z";
817 case JAVA_TYPE_INT:
Stefan Lafon9478f352017-10-30 21:20:20 -0700818 case JAVA_TYPE_ENUM:
Yao Chend54f9dd2017-10-17 17:37:48 +0000819 return "I";
820 case JAVA_TYPE_LONG:
821 return "J";
822 case JAVA_TYPE_FLOAT:
823 return "F";
824 case JAVA_TYPE_DOUBLE:
825 return "D";
826 case JAVA_TYPE_STRING:
827 return "Ljava/lang/String;";
828 default:
829 return "UNKNOWN";
830 }
831}
832
833static string
Yangster-mac7604aea2017-12-11 22:55:49 -0800834jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000835{
836 string result("(I");
837 for (vector<java_type_t>::const_iterator arg = signature.begin();
Yangster-mac7604aea2017-12-11 22:55:49 -0800838 arg != signature.end(); arg++) {
839 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
840 for (auto chainField : attributionDecl.fields) {
841 result += "[";
842 result += java_type_signature(chainField.javaType);
843 }
844 } else {
845 result += java_type_signature(*arg);
846 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000847 }
Yao Chen97e21ec2018-03-29 11:00:38 -0700848 result += ")I";
Yao Chend54f9dd2017-10-17 17:37:48 +0000849 return result;
850}
851
852static int
Yangster-macba5b9e42018-01-10 21:31:59 -0800853write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp_method_name,
854 const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl)
Yao Chend54f9dd2017-10-17 17:37:48 +0000855{
Yao Chend54f9dd2017-10-17 17:37:48 +0000856 // Print write methods
Yangster-macba5b9e42018-01-10 21:31:59 -0800857 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
858 signature != signatures.end(); signature++) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000859 int argIndex;
860
Yao Chen97e21ec2018-03-29 11:00:38 -0700861 fprintf(out, "static int\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000862 fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code",
Yangster-macba5b9e42018-01-10 21:31:59 -0800863 jni_function_name(java_method_name, *signature).c_str());
Yao Chend54f9dd2017-10-17 17:37:48 +0000864 argIndex = 1;
865 for (vector<java_type_t>::const_iterator arg = signature->begin();
866 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800867 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
868 for (auto chainField : attributionDecl.fields) {
869 fprintf(out, ", %s %s", jni_array_type_name(chainField.javaType),
870 chainField.name.c_str());
871 }
872 } else {
873 fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex);
874 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000875 argIndex++;
876 }
877 fprintf(out, ")\n");
878
879 fprintf(out, "{\n");
880
881 // Prepare strings
882 argIndex = 1;
Yangster-mac7604aea2017-12-11 22:55:49 -0800883 bool hadStringOrChain = false;
Yao Chend54f9dd2017-10-17 17:37:48 +0000884 for (vector<java_type_t>::const_iterator arg = signature->begin();
885 arg != signature->end(); arg++) {
886 if (*arg == JAVA_TYPE_STRING) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800887 hadStringOrChain = true;
Yao Chend54f9dd2017-10-17 17:37:48 +0000888 fprintf(out, " const char* str%d;\n", argIndex);
889 fprintf(out, " if (arg%d != NULL) {\n", argIndex);
890 fprintf(out, " str%d = env->GetStringUTFChars(arg%d, NULL);\n",
891 argIndex, argIndex);
892 fprintf(out, " } else {\n");
893 fprintf(out, " str%d = NULL;\n", argIndex);
894 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800895 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
896 hadStringOrChain = true;
897 for (auto chainField : attributionDecl.fields) {
898 fprintf(out, " size_t %s_length = env->GetArrayLength(%s);\n",
899 chainField.name.c_str(), chainField.name.c_str());
900 if (chainField.name != attributionDecl.fields.front().name) {
901 fprintf(out, " if (%s_length != %s_length) {\n",
902 chainField.name.c_str(),
903 attributionDecl.fields.front().name.c_str());
Yao Chen97e21ec2018-03-29 11:00:38 -0700904 fprintf(out, " return -EINVAL;\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800905 fprintf(out, " }\n");
906 }
907 if (chainField.javaType == JAVA_TYPE_INT) {
908 fprintf(out, " jint* %s_array = env->GetIntArrayElements(%s, NULL);\n",
909 chainField.name.c_str(), chainField.name.c_str());
910 } else if (chainField.javaType == JAVA_TYPE_STRING) {
911 fprintf(out, " std::vector<%s> %s_vec;\n",
912 cpp_type_name(chainField.javaType), chainField.name.c_str());
913 fprintf(out, " std::vector<ScopedUtfChars*> scoped_%s_vec;\n",
914 chainField.name.c_str());
915 fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
916 chainField.name.c_str());
917 fprintf(out, " jstring jstr = "
918 "(jstring)env->GetObjectArrayElement(%s, i);\n",
919 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800920 fprintf(out, " if (jstr == NULL) {\n");
921 fprintf(out, " %s_vec.push_back(NULL);\n",
922 chainField.name.c_str());
923 fprintf(out, " } else {\n");
924 fprintf(out, " ScopedUtfChars* scoped_%s = "
Yangster-mac7604aea2017-12-11 22:55:49 -0800925 "new ScopedUtfChars(env, jstr);\n",
926 chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800927 fprintf(out, " %s_vec.push_back(scoped_%s->c_str());\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800928 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800929 fprintf(out, " scoped_%s_vec.push_back(scoped_%s);\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800930 chainField.name.c_str(), chainField.name.c_str());
Yangster-mac20ac9442018-01-08 14:54:48 -0800931 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800932 fprintf(out, " }\n");
933 }
934 fprintf(out, "\n");
935 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000936 }
937 argIndex++;
938 }
Yangster-mac7604aea2017-12-11 22:55:49 -0800939 // Emit this to quiet the unused parameter warning if there were no strings or attribution
940 // chains.
941 if (!hadStringOrChain) {
Yao Chend54f9dd2017-10-17 17:37:48 +0000942 fprintf(out, " (void)env;\n");
943 }
944
945 // stats_write call
946 argIndex = 1;
Yao Chen97e21ec2018-03-29 11:00:38 -0700947 fprintf(out, " int ret = android::util::%s(code", cpp_method_name.c_str());
Yao Chend54f9dd2017-10-17 17:37:48 +0000948 for (vector<java_type_t>::const_iterator arg = signature->begin();
949 arg != signature->end(); arg++) {
Yangster-mac7604aea2017-12-11 22:55:49 -0800950 if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
951 for (auto chainField : attributionDecl.fields) {
952 if (chainField.javaType == JAVA_TYPE_INT) {
953 fprintf(out, ", (const %s*)%s_array, %s_length",
954 cpp_type_name(chainField.javaType),
955 chainField.name.c_str(), chainField.name.c_str());
956 } else if (chainField.javaType == JAVA_TYPE_STRING) {
957 fprintf(out, ", %s_vec", chainField.name.c_str());
958 }
959 }
960 } else {
961 const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
962 fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
963 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000964 argIndex++;
965 }
966 fprintf(out, ");\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800967 fprintf(out, "\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000968
969 // Clean up strings
970 argIndex = 1;
971 for (vector<java_type_t>::const_iterator arg = signature->begin();
972 arg != signature->end(); arg++) {
973 if (*arg == JAVA_TYPE_STRING) {
974 fprintf(out, " if (str%d != NULL) {\n", argIndex);
975 fprintf(out, " env->ReleaseStringUTFChars(arg%d, str%d);\n",
976 argIndex, argIndex);
977 fprintf(out, " }\n");
Yangster-mac7604aea2017-12-11 22:55:49 -0800978 } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
979 for (auto chainField : attributionDecl.fields) {
980 if (chainField.javaType == JAVA_TYPE_INT) {
981 fprintf(out, " env->ReleaseIntArrayElements(%s, %s_array, 0);\n",
982 chainField.name.c_str(), chainField.name.c_str());
983 } else if (chainField.javaType == JAVA_TYPE_STRING) {
Yangster-mac20ac9442018-01-08 14:54:48 -0800984 fprintf(out, " for (size_t i = 0; i < scoped_%s_vec.size(); ++i) {\n",
Yangster-mac7604aea2017-12-11 22:55:49 -0800985 chainField.name.c_str());
986 fprintf(out, " delete scoped_%s_vec[i];\n", chainField.name.c_str());
987 fprintf(out, " }\n");
988 }
989 }
Yao Chend54f9dd2017-10-17 17:37:48 +0000990 }
991 argIndex++;
992 }
Yao Chen97e21ec2018-03-29 11:00:38 -0700993 fprintf(out, " return ret;\n");
Yao Chend54f9dd2017-10-17 17:37:48 +0000994
995 fprintf(out, "}\n");
996 fprintf(out, "\n");
997 }
998
Yangster-macba5b9e42018-01-10 21:31:59 -0800999
1000 return 0;
1001}
1002
1003void write_jni_registration(FILE* out, const string& java_method_name,
1004 const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) {
1005 for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
1006 signature != signatures.end(); signature++) {
1007 fprintf(out, " { \"%s\", \"%s\", (void*)%s },\n",
1008 java_method_name.c_str(),
1009 jni_function_signature(*signature, attributionDecl).c_str(),
1010 jni_function_name(java_method_name, *signature).c_str());
1011 }
1012}
1013
1014static int
1015write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
1016{
1017 // Print prelude
1018 fprintf(out, "// This file is autogenerated\n");
1019 fprintf(out, "\n");
1020
1021 fprintf(out, "#include <statslog.h>\n");
1022 fprintf(out, "\n");
1023 fprintf(out, "#include <nativehelper/JNIHelp.h>\n");
1024 fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n");
1025 fprintf(out, "#include <utils/Vector.h>\n");
1026 fprintf(out, "#include \"core_jni_helpers.h\"\n");
1027 fprintf(out, "#include \"jni.h\"\n");
1028 fprintf(out, "\n");
1029 fprintf(out, "#define UNUSED __attribute__((__unused__))\n");
1030 fprintf(out, "\n");
1031
1032 fprintf(out, "namespace android {\n");
1033 fprintf(out, "\n");
1034
1035 write_stats_log_jni(out, "write", "stats_write", atoms.signatures, attributionDecl);
1036 write_stats_log_jni(out, "write_non_chained", "stats_write_non_chained",
1037 atoms.non_chained_signatures, attributionDecl);
1038
Yao Chend54f9dd2017-10-17 17:37:48 +00001039 // Print registration function table
1040 fprintf(out, "/*\n");
1041 fprintf(out, " * JNI registration.\n");
1042 fprintf(out, " */\n");
1043 fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n");
Yangster-macba5b9e42018-01-10 21:31:59 -08001044 write_jni_registration(out, "write", atoms.signatures, attributionDecl);
1045 write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001046 fprintf(out, "};\n");
1047 fprintf(out, "\n");
1048
1049 // Print registration function
1050 fprintf(out, "int register_android_util_StatsLog(JNIEnv* env) {\n");
1051 fprintf(out, " return RegisterMethodsOrDie(\n");
1052 fprintf(out, " env,\n");
1053 fprintf(out, " \"android/util/StatsLog\",\n");
1054 fprintf(out, " gRegisterMethods, NELEM(gRegisterMethods));\n");
1055 fprintf(out, "}\n");
1056
1057 fprintf(out, "\n");
1058 fprintf(out, "} // namespace android\n");
Yao Chend54f9dd2017-10-17 17:37:48 +00001059 return 0;
1060}
1061
Yao Chend54f9dd2017-10-17 17:37:48 +00001062static void
1063print_usage()
1064{
1065 fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
1066 fprintf(stderr, "\n");
1067 fprintf(stderr, "OPTIONS\n");
1068 fprintf(stderr, " --cpp FILENAME the header file to output\n");
1069 fprintf(stderr, " --header FILENAME the cpp file to output\n");
1070 fprintf(stderr, " --help this message\n");
1071 fprintf(stderr, " --java FILENAME the java file to output\n");
1072 fprintf(stderr, " --jni FILENAME the jni file to output\n");
1073}
1074
1075/**
1076 * Do the argument parsing and execute the tasks.
1077 */
1078static int
1079run(int argc, char const*const* argv)
1080{
1081 string cppFilename;
1082 string headerFilename;
1083 string javaFilename;
1084 string jniFilename;
1085
1086 int index = 1;
1087 while (index < argc) {
1088 if (0 == strcmp("--help", argv[index])) {
1089 print_usage();
1090 return 0;
1091 } else if (0 == strcmp("--cpp", argv[index])) {
1092 index++;
1093 if (index >= argc) {
1094 print_usage();
1095 return 1;
1096 }
1097 cppFilename = argv[index];
1098 } else if (0 == strcmp("--header", argv[index])) {
1099 index++;
1100 if (index >= argc) {
1101 print_usage();
1102 return 1;
1103 }
1104 headerFilename = argv[index];
1105 } else if (0 == strcmp("--java", argv[index])) {
1106 index++;
1107 if (index >= argc) {
1108 print_usage();
1109 return 1;
1110 }
1111 javaFilename = argv[index];
1112 } else if (0 == strcmp("--jni", argv[index])) {
1113 index++;
1114 if (index >= argc) {
1115 print_usage();
1116 return 1;
1117 }
1118 jniFilename = argv[index];
1119 }
1120 index++;
1121 }
1122
1123 if (cppFilename.size() == 0
1124 && headerFilename.size() == 0
1125 && javaFilename.size() == 0
1126 && jniFilename.size() == 0) {
1127 print_usage();
1128 return 1;
1129 }
1130
1131 // Collate the parameters
1132 Atoms atoms;
Stefan Lafonae2df012017-11-14 09:17:21 -08001133 int errorCount = collate_atoms(Atom::descriptor(), &atoms);
Yao Chend54f9dd2017-10-17 17:37:48 +00001134 if (errorCount != 0) {
1135 return 1;
1136 }
1137
Yangster-mac7604aea2017-12-11 22:55:49 -08001138 AtomDecl attributionDecl;
1139 vector<java_type_t> attributionSignature;
Yangster-mac20877162017-12-22 17:19:39 -08001140 collate_atom(android::os::statsd::AttributionNode::descriptor(),
Yangster-mac7604aea2017-12-11 22:55:49 -08001141 &attributionDecl, &attributionSignature);
1142
Yao Chend54f9dd2017-10-17 17:37:48 +00001143 // Write the .cpp file
1144 if (cppFilename.size() != 0) {
1145 FILE* out = fopen(cppFilename.c_str(), "w");
1146 if (out == NULL) {
1147 fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
1148 return 1;
1149 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001150 errorCount = android::stats_log_api_gen::write_stats_log_cpp(
1151 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001152 fclose(out);
1153 }
1154
1155 // Write the .h file
1156 if (headerFilename.size() != 0) {
1157 FILE* out = fopen(headerFilename.c_str(), "w");
1158 if (out == NULL) {
1159 fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
1160 return 1;
1161 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001162 errorCount = android::stats_log_api_gen::write_stats_log_header(
1163 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001164 fclose(out);
1165 }
1166
1167 // Write the .java file
1168 if (javaFilename.size() != 0) {
1169 FILE* out = fopen(javaFilename.c_str(), "w");
1170 if (out == NULL) {
1171 fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
1172 return 1;
1173 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001174 errorCount = android::stats_log_api_gen::write_stats_log_java(
1175 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001176 fclose(out);
1177 }
1178
1179 // Write the jni file
1180 if (jniFilename.size() != 0) {
1181 FILE* out = fopen(jniFilename.c_str(), "w");
1182 if (out == NULL) {
1183 fprintf(stderr, "Unable to open file for write: %s\n", jniFilename.c_str());
1184 return 1;
1185 }
Yangster-mac7604aea2017-12-11 22:55:49 -08001186 errorCount = android::stats_log_api_gen::write_stats_log_jni(
1187 out, atoms, attributionDecl);
Yao Chend54f9dd2017-10-17 17:37:48 +00001188 fclose(out);
1189 }
1190
1191 return 0;
1192}
1193
1194}
1195}
1196
1197/**
1198 * Main.
1199 */
1200int
1201main(int argc, char const*const* argv)
1202{
1203 GOOGLE_PROTOBUF_VERIFY_VERSION;
1204
1205 return android::stats_log_api_gen::run(argc, argv);
Yao Chencf3829a2018-06-05 14:20:35 -07001206}