blob: 90dcae4197a2d53f80be0e8320711ab9ff3bd43d [file] [log] [blame]
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -08001/*
2 * Copyright (C) 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "native_writer.h"
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -080018#include "utils.h"
19
20namespace android {
21namespace stats_log_api_gen {
22
Muhammad Qureshia31a6222020-03-16 00:53:13 -070023static void write_annotations(
24 FILE* out, int argIndex,
25 const FieldNumberToAnnotations& fieldNumberToAnnotations,
26 const string& methodPrefix,
27 const string& methodSuffix) {
28 auto fieldNumberToAnnotationsIt = fieldNumberToAnnotations.find(argIndex);
29 if (fieldNumberToAnnotationsIt == fieldNumberToAnnotations.end()) {
30 return;
31 }
32 const set<shared_ptr<Annotation>>& annotations =
33 fieldNumberToAnnotationsIt->second;
34 for (const shared_ptr<Annotation>& annotation : annotations) {
35 // TODO(b/151744250): Group annotations for same atoms.
36 // TODO(b/151786433): Write atom constant name instead of atom id literal.
37 fprintf(out, " if (code == %d) {\n", annotation->atomId);
38 switch(annotation->type) {
39 // TODO(b/151776731): Check for reset state annotation and only include reset state
40 // when field value == default state annotation value.
41 case ANNOTATION_TYPE_INT:
42 // TODO(b/151786433): Write annotation constant name instead of
43 // annotation id literal.
44 fprintf(out, " %saddInt32Annotation(%s%d, %d);\n",
45 methodPrefix.c_str(),
46 methodSuffix.c_str(),
47 annotation->annotationId,
48 annotation->value.intValue);
49 break;
50 case ANNOTATION_TYPE_BOOL:
51 // TODO(b/151786433): Write annotation constant name instead of
52 // annotation id literal.
53 fprintf(out, " %saddBoolAnnotation(%s%d, %s);\n",
54 methodPrefix.c_str(),
55 methodSuffix.c_str(),
56 annotation->annotationId,
57 annotation->value.boolValue ? "true" : "false");
58 break;
59 default:
60 break;
61 }
62 fprintf(out, " }\n");
63 }
64
65}
66
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -080067static int write_native_stats_write_methods(FILE* out, const Atoms& atoms,
Muhammad Qureshib13a3212020-03-12 07:37:13 -070068 const AtomDecl& attributionDecl, const bool supportQ) {
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -080069 fprintf(out, "\n");
Muhammad Qureshib13a3212020-03-12 07:37:13 -070070 for (auto signatureInfoMapIt = atoms.signatureInfoMap.begin();
71 signatureInfoMapIt != atoms.signatureInfoMap.end(); signatureInfoMapIt++) {
72 vector<java_type_t> signature = signatureInfoMapIt->first;
Muhammad Qureshia31a6222020-03-16 00:53:13 -070073 const FieldNumberToAnnotations& fieldNumberToAnnotations = signatureInfoMapIt->second;
Tej Singhb26d0442020-01-31 16:18:21 -080074 // Key value pairs not supported in native.
75 if (find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != signature.end()) {
76 continue;
77 }
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -080078 write_native_method_signature(out, "int stats_write", signature,
79 attributionDecl, " {");
80
81 int argIndex = 1;
82 if (supportQ) {
83 fprintf(out, " StatsEventCompat event;\n");
84 fprintf(out, " event.setAtomId(code);\n");
85 for (vector<java_type_t>::const_iterator arg = signature.begin();
86 arg != signature.end(); arg++) {
87 switch (*arg) {
88 case JAVA_TYPE_ATTRIBUTION_CHAIN: {
89 const char* uidName = attributionDecl.fields.front().name.c_str();
90 const char* tagName = attributionDecl.fields.back().name.c_str();
91 fprintf(out, " event.writeAttributionChain(%s, %s_length, %s);\n",
92 uidName, uidName, tagName);
93 break;
94 }
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -080095 case JAVA_TYPE_BYTE_ARRAY:
96 fprintf(out, " event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
97 argIndex, argIndex);
98 break;
99 case JAVA_TYPE_BOOLEAN:
100 fprintf(out, " event.writeBool(arg%d);\n", argIndex);
101 break;
102 case JAVA_TYPE_INT: // Fall through.
103 case JAVA_TYPE_ENUM:
104 fprintf(out, " event.writeInt32(arg%d);\n", argIndex);
105 break;
106 case JAVA_TYPE_FLOAT:
107 fprintf(out, " event.writeFloat(arg%d);\n", argIndex);
108 break;
109 case JAVA_TYPE_LONG:
110 fprintf(out, " event.writeInt64(arg%d);\n", argIndex);
111 break;
112 case JAVA_TYPE_STRING:
113 fprintf(out, " event.writeString(arg%d);\n", argIndex);
114 break;
115 default:
Tej Singhb26d0442020-01-31 16:18:21 -0800116 // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS.
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800117 fprintf(stderr, "Encountered unsupported type.");
118 return 1;
119 }
Muhammad Qureshia31a6222020-03-16 00:53:13 -0700120 write_annotations(out, argIndex, fieldNumberToAnnotations, "event.", "");
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800121 argIndex++;
122 }
123 fprintf(out, " return event.writeToSocket();\n");
124 } else {
Tej Singhb26d0442020-01-31 16:18:21 -0800125 fprintf(out, " AStatsEvent* event = AStatsEvent_obtain();\n");
126 fprintf(out, " AStatsEvent_setAtomId(event, code);\n");
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800127 for (vector<java_type_t>::const_iterator arg = signature.begin();
128 arg != signature.end(); arg++) {
129 switch (*arg) {
130 case JAVA_TYPE_ATTRIBUTION_CHAIN: {
131 const char* uidName = attributionDecl.fields.front().name.c_str();
132 const char* tagName = attributionDecl.fields.back().name.c_str();
133 fprintf(out,
Tej Singhb26d0442020-01-31 16:18:21 -0800134 " AStatsEvent_writeAttributionChain(event, "
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800135 "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
136 "static_cast<uint8_t>(%s_length));\n",
137 uidName, tagName, uidName);
138 break;
139 }
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800140 case JAVA_TYPE_BYTE_ARRAY:
141 fprintf(out,
Tej Singhb26d0442020-01-31 16:18:21 -0800142 " AStatsEvent_writeByteArray(event, "
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800143 "reinterpret_cast<const uint8_t*>(arg%d.arg), arg%d.arg_length);\n",
144 argIndex, argIndex);
145 break;
146 case JAVA_TYPE_BOOLEAN:
Tej Singhb26d0442020-01-31 16:18:21 -0800147 fprintf(out, " AStatsEvent_writeBool(event, arg%d);\n", argIndex);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800148 break;
149 case JAVA_TYPE_INT: // Fall through.
150 case JAVA_TYPE_ENUM:
Tej Singhb26d0442020-01-31 16:18:21 -0800151 fprintf(out, " AStatsEvent_writeInt32(event, arg%d);\n", argIndex);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800152 break;
153 case JAVA_TYPE_FLOAT:
Tej Singhb26d0442020-01-31 16:18:21 -0800154 fprintf(out, " AStatsEvent_writeFloat(event, arg%d);\n", argIndex);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800155 break;
156 case JAVA_TYPE_LONG:
Tej Singhb26d0442020-01-31 16:18:21 -0800157 fprintf(out, " AStatsEvent_writeInt64(event, arg%d);\n", argIndex);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800158 break;
159 case JAVA_TYPE_STRING:
Tej Singhb26d0442020-01-31 16:18:21 -0800160 fprintf(out, " AStatsEvent_writeString(event, arg%d);\n", argIndex);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800161 break;
162 default:
Tej Singhb26d0442020-01-31 16:18:21 -0800163 // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800164 fprintf(stderr, "Encountered unsupported type.");
165 return 1;
166 }
Muhammad Qureshia31a6222020-03-16 00:53:13 -0700167 write_annotations(out, argIndex, fieldNumberToAnnotations, "AStatsEvent_",
168 "event, ");
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800169 argIndex++;
170 }
Tej Singhb26d0442020-01-31 16:18:21 -0800171 fprintf(out, " const int ret = AStatsEvent_write(event);\n");
172 fprintf(out, " AStatsEvent_release(event);\n");
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800173 fprintf(out, " return ret;\n");
174 }
175 fprintf(out, "}\n\n");
176 }
177 return 0;
178}
179
180static void write_native_stats_write_non_chained_methods(FILE* out, const Atoms& atoms,
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700181 const AtomDecl& attributionDecl) {
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800182 fprintf(out, "\n");
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700183 for (auto signature_it = atoms.nonChainedSignatureInfoMap.begin();
184 signature_it != atoms.nonChainedSignatureInfoMap.end(); signature_it++) {
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800185 vector<java_type_t> signature = signature_it->first;
Tej Singhb26d0442020-01-31 16:18:21 -0800186 // Key value pairs not supported in native.
187 if (find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != signature.end()) {
188 continue;
189 }
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800190
191 write_native_method_signature(out, "int stats_write_non_chained", signature,
192 attributionDecl, " {");
193
194 vector<java_type_t> newSignature;
195
196 // First two args form the attribution node so size goes down by 1.
197 newSignature.reserve(signature.size() - 1);
198
199 // First arg is Attribution Chain.
200 newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
201
202 // Followed by the originial signature except the first 2 args.
203 newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
204
205 const char* uidName = attributionDecl.fields.front().name.c_str();
206 const char* tagName = attributionDecl.fields.back().name.c_str();
207 fprintf(out, " const int32_t* %s = &arg1;\n", uidName);
208 fprintf(out, " const size_t %s_length = 1;\n", uidName);
209 fprintf(out, " const std::vector<char const*> %s(1, arg2);\n", tagName);
210 fprintf(out, " return ");
211 write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
212
213 fprintf(out, "}\n\n");
214 }
215
216}
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800217
218static void write_native_method_header(
219 FILE* out,
220 const string& methodName,
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700221 const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap,
222 const AtomDecl &attributionDecl) {
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800223
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700224 for (auto signatureInfoMapIt = signatureInfoMap.begin();
225 signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
226 vector<java_type_t> signature = signatureInfoMapIt->first;
Tej Singhb26d0442020-01-31 16:18:21 -0800227
Tej Singhb26d0442020-01-31 16:18:21 -0800228 // Key value pairs not supported in native.
229 if (find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != signature.end()) {
230 continue;
231 }
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800232 write_native_method_signature(out, methodName, signature, attributionDecl, ";");
233 }
234}
235
236int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700237 const string& cppNamespace,
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800238 const string& importHeader, const bool supportQ) {
239 // Print prelude
240 fprintf(out, "// This file is autogenerated\n");
241 fprintf(out, "\n");
242
243 fprintf(out, "#include <%s>\n", importHeader.c_str());
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800244 if (supportQ) {
245 fprintf(out, "#include <StatsEventCompat.h>\n");
246 } else {
247 fprintf(out, "#include <stats_event.h>\n");
248 }
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800249
250 fprintf(out, "\n");
251 write_namespace(out, cppNamespace);
252
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700253 write_native_stats_write_methods(out, atoms, attributionDecl, supportQ);
254 write_native_stats_write_non_chained_methods(out, atoms, attributionDecl);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800255
256 // Print footer
257 fprintf(out, "\n");
258 write_closing_namespace(out, cppNamespace);
259
260 return 0;
261}
262
263int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700264 const string& cppNamespace) {
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800265 // Print prelude
266 fprintf(out, "// This file is autogenerated\n");
267 fprintf(out, "\n");
268 fprintf(out, "#pragma once\n");
269 fprintf(out, "\n");
270 fprintf(out, "#include <stdint.h>\n");
271 fprintf(out, "#include <vector>\n");
272 fprintf(out, "#include <map>\n");
273 fprintf(out, "#include <set>\n");
274 fprintf(out, "\n");
275
276 write_namespace(out, cppNamespace);
277 fprintf(out, "\n");
278 fprintf(out, "/*\n");
279 fprintf(out, " * API For logging statistics events.\n");
280 fprintf(out, " */\n");
281 fprintf(out, "\n");
282
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700283 write_native_atom_constants(out, atoms, attributionDecl);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800284
285 // Print constants for the enum values.
286 fprintf(out, "//\n");
287 fprintf(out, "// Constants for enum values\n");
288 fprintf(out, "//\n\n");
289 for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
290 atom != atoms.decls.end(); atom++) {
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800291
292 for (vector<AtomField>::const_iterator field = atom->fields.begin();
293 field != atom->fields.end(); field++) {
294 if (field->javaType == JAVA_TYPE_ENUM) {
295 fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
296 field->name.c_str());
297 for (map<int, string>::const_iterator value = field->enumValues.begin();
298 value != field->enumValues.end(); value++) {
299 fprintf(out, "const int32_t %s__%s__%s = %d;\n",
300 make_constant_name(atom->message).c_str(),
301 make_constant_name(field->name).c_str(),
302 make_constant_name(value->second).c_str(),
303 value->first);
304 }
305 fprintf(out, "\n");
306 }
307 }
308 }
309
310 fprintf(out, "struct BytesField {\n");
311 fprintf(out,
312 " BytesField(char const* array, size_t len) : arg(array), "
313 "arg_length(len) {}\n");
314 fprintf(out, " char const* arg;\n");
315 fprintf(out, " size_t arg_length;\n");
316 fprintf(out, "};\n");
317 fprintf(out, "\n");
318
319 // Print write methods
320 fprintf(out, "//\n");
321 fprintf(out, "// Write methods\n");
322 fprintf(out, "//\n");
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700323 write_native_method_header(out, "int stats_write", atoms.signatureInfoMap, attributionDecl);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800324
325 fprintf(out, "//\n");
326 fprintf(out, "// Write flattened methods\n");
327 fprintf(out, "//\n");
328 write_native_method_header(out, "int stats_write_non_chained",
Muhammad Qureshib13a3212020-03-12 07:37:13 -0700329 atoms.nonChainedSignatureInfoMap, attributionDecl);
Muhammad Qureshi4fdc7fd2019-11-24 22:14:38 -0800330
331 fprintf(out, "\n");
332 write_closing_namespace(out, cppNamespace);
333
334 return 0;
335}
336
337} // namespace stats_log_api_gen
338} // namespace android