1 /*
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 "atoms_info_writer.h"
18 #include "utils.h"
19 
20 #include <map>
21 #include <set>
22 #include <vector>
23 
24 namespace android {
25 namespace stats_log_api_gen {
26 
write_atoms_info_header_body(FILE * out,const Atoms & atoms)27 static void write_atoms_info_header_body(FILE* out, const Atoms& atoms) {
28     fprintf(out, "struct StateAtomFieldOptions {\n");
29     fprintf(out, "  std::vector<int> primaryFields;\n");
30     fprintf(out, "  int exclusiveField;\n");
31     fprintf(out, "};\n");
32     fprintf(out, "\n");
33 
34     fprintf(out, "struct AtomsInfo {\n");
35     fprintf(out,
36             "  const static std::set<int> "
37             "kTruncatingTimestampAtomBlackList;\n");
38     fprintf(out, "  const static std::map<int, int> kAtomsWithUidField;\n");
39     fprintf(out,
40             "  const static std::set<int> kAtomsWithAttributionChain;\n");
41     fprintf(out,
42             "  const static std::map<int, StateAtomFieldOptions> "
43             "kStateAtomsFieldOptions;\n");
44     fprintf(out,
45             "  const static std::map<int, std::vector<int>> "
46             "kBytesFieldAtoms;\n");
47     fprintf(out,
48             "  const static std::set<int> kWhitelistedAtoms;\n");
49     fprintf(out, "};\n");
50     fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", atoms.maxPushedAtomId);
51 
52 }
53 
write_atoms_info_cpp_body(FILE * out,const Atoms & atoms)54 static void write_atoms_info_cpp_body(FILE* out, const Atoms& atoms) {
55     std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
56                                                  "audio_state_changed",
57                                                  "call_state_changed",
58                                                  "phone_signal_strength_changed",
59                                                  "mobile_bytes_transfer_by_fg_bg",
60                                                  "mobile_bytes_transfer"};
61     fprintf(out,
62             "const std::set<int> "
63             "AtomsInfo::kTruncatingTimestampAtomBlackList = {\n");
64     for (set<string>::const_iterator blacklistedAtom = kTruncatingAtomNames.begin();
65          blacklistedAtom != kTruncatingAtomNames.end(); blacklistedAtom++) {
66             fprintf(out, " %s,\n", make_constant_name(*blacklistedAtom).c_str());
67     }
68     fprintf(out, "};\n");
69     fprintf(out, "\n");
70 
71     fprintf(out,
72             "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
73     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
74          atom != atoms.decls.end(); atom++) {
75         for (vector<AtomField>::const_iterator field = atom->fields.begin();
76              field != atom->fields.end(); field++) {
77             if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
78                 string constant = make_constant_name(atom->name);
79                 fprintf(out, " %s,\n", constant.c_str());
80                 break;
81             }
82         }
83     }
84 
85     fprintf(out, "};\n");
86     fprintf(out, "\n");
87 
88     fprintf(out,
89             "const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n");
90     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
91          atom != atoms.decls.end(); atom++) {
92         if (atom->whitelisted) {
93             string constant = make_constant_name(atom->name);
94             fprintf(out, " %s,\n", constant.c_str());
95         }
96     }
97 
98     fprintf(out, "};\n");
99     fprintf(out, "\n");
100 
101     fprintf(out, "static std::map<int, int> getAtomUidField() {\n");
102     fprintf(out, "  std::map<int, int> uidField;\n");
103     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
104          atom != atoms.decls.end(); atom++) {
105         if (atom->uidField == 0) {
106             continue;
107         }
108         fprintf(out,
109                 "\n    // Adding uid field for atom "
110                 "(%d)%s\n",
111                 atom->code, atom->name.c_str());
112         fprintf(out, "    uidField[static_cast<int>(%s)] = %d;\n",
113                 make_constant_name(atom->name).c_str(), atom->uidField);
114     }
115 
116     fprintf(out, "    return uidField;\n");
117     fprintf(out, "};\n");
118 
119     fprintf(out,
120             "const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
121             "getAtomUidField();\n");
122 
123     fprintf(out,
124             "static std::map<int, StateAtomFieldOptions> "
125             "getStateAtomFieldOptions() {\n");
126     fprintf(out, "    std::map<int, StateAtomFieldOptions> options;\n");
127     fprintf(out, "    StateAtomFieldOptions opt;\n");
128     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
129          atom != atoms.decls.end(); atom++) {
130         if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
131             continue;
132         }
133         fprintf(out,
134                 "\n    // Adding primary and exclusive fields for atom "
135                 "(%d)%s\n",
136                 atom->code, atom->name.c_str());
137         fprintf(out, "    opt.primaryFields.clear();\n");
138         for (const auto& field : atom->primaryFields) {
139             fprintf(out, "    opt.primaryFields.push_back(%d);\n", field);
140         }
141 
142         fprintf(out, "    opt.exclusiveField = %d;\n", atom->exclusiveField);
143         fprintf(out, "    options[static_cast<int>(%s)] = opt;\n",
144                 make_constant_name(atom->name).c_str());
145     }
146 
147     fprintf(out, "    return options;\n");
148     fprintf(out, "}\n");
149 
150     fprintf(out,
151             "const std::map<int, StateAtomFieldOptions> "
152             "AtomsInfo::kStateAtomsFieldOptions = "
153             "getStateAtomFieldOptions();\n");
154 
155     fprintf(out,
156             "static std::map<int, std::vector<int>> "
157             "getBinaryFieldAtoms() {\n");
158     fprintf(out, "    std::map<int, std::vector<int>> options;\n");
159     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
160          atom != atoms.decls.end(); atom++) {
161         if (atom->binaryFields.size() == 0) {
162             continue;
163         }
164         fprintf(out,
165                 "\n    // Adding binary fields for atom "
166                 "(%d)%s\n",
167                 atom->code, atom->name.c_str());
168 
169         for (const auto& field : atom->binaryFields) {
170             fprintf(out, "    options[static_cast<int>(%s)].push_back(%d);\n",
171                     make_constant_name(atom->name).c_str(), field);
172         }
173     }
174 
175     fprintf(out, "    return options;\n");
176     fprintf(out, "}\n");
177 
178     fprintf(out,
179             "const std::map<int, std::vector<int>> "
180             "AtomsInfo::kBytesFieldAtoms = "
181             "getBinaryFieldAtoms();\n");
182 
183 }
184 
write_atoms_info_header(FILE * out,const Atoms & atoms,const string & namespaceStr)185 int write_atoms_info_header(FILE* out, const Atoms &atoms, const string& namespaceStr) {
186     // Print prelude
187     fprintf(out, "// This file is autogenerated\n");
188     fprintf(out, "\n");
189     fprintf(out, "#pragma once\n");
190     fprintf(out, "\n");
191     fprintf(out, "#include <vector>\n");
192     fprintf(out, "#include <map>\n");
193     fprintf(out, "#include <set>\n");
194     fprintf(out, "\n");
195 
196     write_namespace(out, namespaceStr);
197 
198     write_atoms_info_header_body(out, atoms);
199 
200     fprintf(out, "\n");
201     write_closing_namespace(out, namespaceStr);
202 
203     return 0;
204 }
205 
write_atoms_info_cpp(FILE * out,const Atoms & atoms,const string & namespaceStr,const string & importHeader,const string & statslogHeader)206 int write_atoms_info_cpp(FILE *out, const Atoms &atoms, const string& namespaceStr,
207         const string& importHeader, const string& statslogHeader) {
208     // Print prelude
209     fprintf(out, "// This file is autogenerated\n");
210     fprintf(out, "\n");
211     fprintf(out, "#include <%s>\n", importHeader.c_str());
212     fprintf(out, "#include <%s>\n", statslogHeader.c_str());
213     fprintf(out, "\n");
214 
215     write_namespace(out, namespaceStr);
216 
217     write_atoms_info_cpp_body(out, atoms);
218 
219     // Print footer
220     fprintf(out, "\n");
221     write_closing_namespace(out, namespaceStr);
222 
223     return 0;
224 }
225 
226 }  // namespace stats_log_api_gen
227 }  // namespace android
228