Loading tools/stats_log_api_gen/Collation.cpp +66 −5 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "Collation.h" #include "frameworks/base/cmds/statsd/src/atoms.pb.h" #include <stdio.h> #include <map> Loading Loading @@ -136,6 +137,16 @@ java_type(const FieldDescriptor* field) } } /** * Gather the enums info. */ void collate_enums(const EnumDescriptor &enumDescriptor, AtomField *atomField) { for (int i = 0; i < enumDescriptor.value_count(); i++) { atomField->enumValues[enumDescriptor.value(i)->number()] = enumDescriptor.value(i)->name().c_str(); } } /** * Gather the info about an atom proto. */ Loading Loading @@ -221,11 +232,7 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, if (javaType == JAVA_TYPE_ENUM) { // All enums are treated as ints when it comes to function signatures. signature->push_back(JAVA_TYPE_INT); const EnumDescriptor *enumDescriptor = field->enum_type(); for (int i = 0; i < enumDescriptor->value_count(); i++) { atField.enumValues[enumDescriptor->value(i)->number()] = enumDescriptor->value(i)->name().c_str(); } collate_enums(*field->enum_type(), &atField); } else { signature->push_back(javaType); } Loading @@ -235,6 +242,53 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, return errorCount; } // This function flattens the fields of the AttributionNode proto in an Atom proto and generates // the corresponding atom decl and signature. bool get_non_chained_node(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature) { // Build a sorted list of the fields. Descriptor has them in source file // order. map<int, const FieldDescriptor *> fields; for (int j = 0; j < atom->field_count(); j++) { const FieldDescriptor *field = atom->field(j); fields[field->number()] = field; } AtomDecl attributionDecl; vector<java_type_t> attributionSignature; collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl, &attributionSignature); // Build the type signature and the atom data. bool has_attribution_node = false; for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin(); it != fields.end(); it++) { const FieldDescriptor *field = it->second; java_type_t javaType = java_type(field); if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { atomDecl->fields.insert( atomDecl->fields.end(), attributionDecl.fields.begin(), attributionDecl.fields.end()); signature->insert( signature->end(), attributionSignature.begin(), attributionSignature.end()); has_attribution_node = true; } else { AtomField atField(field->name(), javaType); if (javaType == JAVA_TYPE_ENUM) { // All enums are treated as ints when it comes to function signatures. signature->push_back(JAVA_TYPE_INT); collate_enums(*field->enum_type(), &atField); } else { signature->push_back(javaType); } atomDecl->fields.push_back(atField); } } return has_attribution_node; } /** * Gather the info about the atoms. */ Loading Loading @@ -266,6 +320,13 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) { errorCount += collate_atom(atom, &atomDecl, &signature); atoms->signatures.insert(signature); atoms->decls.insert(atomDecl); AtomDecl nonChainedAtomDecl(atomField->number(), atomField->name(), atom->name()); vector<java_type_t> nonChainedSignature; if (get_non_chained_node(atom, &nonChainedAtomDecl, &nonChainedSignature)) { atoms->non_chained_signatures.insert(nonChainedSignature); atoms->non_chained_decls.insert(nonChainedAtomDecl); } } if (dbg) { Loading tools/stats_log_api_gen/Collation.h +4 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ using std::set; using std::string; using std::vector; using google::protobuf::Descriptor; using google::protobuf::FieldDescriptor; /** * The types for atom parameters. Loading Loading @@ -93,14 +94,15 @@ struct AtomDecl { struct Atoms { set<vector<java_type_t>> signatures; set<AtomDecl> decls; set<AtomDecl> non_chained_decls; set<vector<java_type_t>> non_chained_signatures; }; /** * Gather the information about the atoms. Returns the number of errors. */ int collate_atoms(const Descriptor* descriptor, Atoms* atoms); int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature); int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature); } // namespace stats_log_api_gen } // namespace android Loading tools/stats_log_api_gen/main.cpp +216 −100 Original line number Diff line number Diff line Loading @@ -195,6 +195,47 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, fprintf(out, "\n"); } for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin(); signature != atoms.non_chained_signatures.end(); signature++) { int argIndex; fprintf(out, "void\n"); fprintf(out, "stats_write_non_chained(int32_t code"); argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); argIndex++; } fprintf(out, ")\n"); fprintf(out, "{\n"); argIndex = 1; fprintf(out, " android_log_event_list event(kStatsEventTag);\n"); fprintf(out, " event << code;\n\n"); for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (argIndex == 1) { fprintf(out, " event.begin();\n\n"); fprintf(out, " event.begin();\n"); } if (*arg == JAVA_TYPE_STRING) { fprintf(out, " if (arg%d == NULL) {\n", argIndex); fprintf(out, " arg%d = \"\";\n", argIndex); fprintf(out, " }\n"); } fprintf(out, " event << arg%d;\n", argIndex); if (argIndex == 2) { fprintf(out, " event.end();\n\n"); fprintf(out, " event.end();\n\n"); } argIndex++; } fprintf(out, " event.write(LOG_ID_STATS);\n"); fprintf(out, "}\n"); fprintf(out, "\n"); } // Print footer fprintf(out, "\n"); fprintf(out, "} // namespace util\n"); Loading @@ -203,6 +244,68 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, return 0; } void build_non_chained_decl_map(const Atoms& atoms, std::map<int, set<AtomDecl>::const_iterator>* decl_map){ for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin(); atom != atoms.non_chained_decls.end(); atom++) { decl_map->insert(std::make_pair(atom->code, atom)); } } static void write_cpp_usage( FILE* out, const string& method_name, const string& atom_code_name, const AtomDecl& atom, const AtomDecl &attributionDecl) { fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str()); for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } } } else { fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str()); } } fprintf(out, ");\n"); } static void write_cpp_method_header( FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { fprintf(out, "void %s(int32_t code ", method_name.c_str()); int argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } } } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } argIndex++; } fprintf(out, ");\n"); } } static int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) Loading @@ -228,6 +331,9 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, " */\n"); fprintf(out, "enum {\n"); std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map; build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map); size_t i = 0; // Print constants for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); Loading @@ -236,26 +342,13 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, "\n"); fprintf(out, " /**\n"); fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str()); fprintf(out, " * Usage: stats_write(StatsLog.%s", constant.c_str()); for (vector<AtomField>::const_iterator field = atom->fields.begin(); field != atom->fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } } } else { fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str()); } write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl); auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code); if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) { write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second, attributionDecl); } fprintf(out, ");\n"); fprintf(out, " */\n"); char const* const comma = (i == atoms.decls.size() - 1) ? "" : ","; fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma); Loading @@ -274,38 +367,64 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, "//\n"); fprintf(out, "// Write methods\n"); fprintf(out, "//\n"); for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { fprintf(out, "void stats_write(int32_t code "); write_cpp_method_header(out, "stats_write", atoms.signatures, attributionDecl); fprintf(out, "//\n"); fprintf(out, "// Write flattened methods\n"); fprintf(out, "//\n"); write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures, attributionDecl); fprintf(out, "\n"); fprintf(out, "} // namespace util\n"); fprintf(out, "} // namespace android\n"); return 0; } static void write_java_usage( FILE* out, const string& method_name, const string& atom_code_name, const AtomDecl& atom, const AtomDecl &attributionDecl) { fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str()); for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else { fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str()); } } fprintf(out, ");\n"); } static void write_java_method( FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { fprintf(out, " public static native void %s(int code", method_name.c_str()); int argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); } argIndex++; } fprintf(out, ");\n"); } fprintf(out, "\n"); fprintf(out, "} // namespace util\n"); fprintf(out, "} // namespace android\n"); return 0; } static int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) { Loading @@ -322,6 +441,9 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD fprintf(out, "public class StatsLogInternal {\n"); fprintf(out, " // Constants for atom codes.\n"); std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map; build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map); // Print constants for the atom codes. for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end(); atom++) { Loading @@ -329,19 +451,12 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD fprintf(out, "\n"); fprintf(out, " /**\n"); fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str()); fprintf(out, " * Usage: StatsLog.write(StatsLog.%s", constant.c_str()); for (vector<AtomField>::const_iterator field = atom->fields.begin(); field != atom->fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); write_java_usage(out, "write", constant, *atom, attributionDecl); auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code); if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) { write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second, attributionDecl); } } else { fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str()); } } fprintf(out, ");\n"); fprintf(out, " */\n"); fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code); } Loading Loading @@ -371,24 +486,8 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD // Print write methods fprintf(out, " // Write methods\n"); for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { fprintf(out, " public static native void write(int code"); int argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else { fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); } argIndex++; } fprintf(out, ");\n"); } write_java_method(out, "write", atoms.signatures, attributionDecl); write_java_method(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl); fprintf(out, "}\n"); Loading Loading @@ -431,9 +530,9 @@ jni_array_type_name(java_type_t type) } static string jni_function_name(const vector<java_type_t>& signature) jni_function_name(const string& method_name, const vector<java_type_t>& signature) { string result("StatsLog_write"); string result("StatsLog_" + method_name); for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); arg++) { switch (*arg) { Loading Loading @@ -509,34 +608,17 @@ jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &att } static int write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp_method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { // Print prelude fprintf(out, "// This file is autogenerated\n"); fprintf(out, "\n"); fprintf(out, "#include <statslog.h>\n"); fprintf(out, "\n"); fprintf(out, "#include <nativehelper/JNIHelp.h>\n"); fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n"); fprintf(out, "#include <utils/Vector.h>\n"); fprintf(out, "#include \"core_jni_helpers.h\"\n"); fprintf(out, "#include \"jni.h\"\n"); fprintf(out, "\n"); fprintf(out, "#define UNUSED __attribute__((__unused__))\n"); fprintf(out, "\n"); fprintf(out, "namespace android {\n"); fprintf(out, "\n"); // Print write methods for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { int argIndex; fprintf(out, "static void\n"); fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code", jni_function_name(*signature).c_str()); jni_function_name(java_method_name, *signature).c_str()); argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { Loading Loading @@ -624,7 +706,7 @@ write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDe // stats_write call argIndex = 1; fprintf(out, " android::util::stats_write(code"); fprintf(out, " android::util::%s(code", cpp_method_name.c_str()); for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { Loading Loading @@ -675,17 +757,53 @@ write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDe fprintf(out, "\n"); } return 0; } void write_jni_registration(FILE* out, const string& java_method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { fprintf(out, " { \"%s\", \"%s\", (void*)%s },\n", java_method_name.c_str(), jni_function_signature(*signature, attributionDecl).c_str(), jni_function_name(java_method_name, *signature).c_str()); } } static int write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) { // Print prelude fprintf(out, "// This file is autogenerated\n"); fprintf(out, "\n"); fprintf(out, "#include <statslog.h>\n"); fprintf(out, "\n"); fprintf(out, "#include <nativehelper/JNIHelp.h>\n"); fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n"); fprintf(out, "#include <utils/Vector.h>\n"); fprintf(out, "#include \"core_jni_helpers.h\"\n"); fprintf(out, "#include \"jni.h\"\n"); fprintf(out, "\n"); fprintf(out, "#define UNUSED __attribute__((__unused__))\n"); fprintf(out, "\n"); fprintf(out, "namespace android {\n"); fprintf(out, "\n"); write_stats_log_jni(out, "write", "stats_write", atoms.signatures, attributionDecl); write_stats_log_jni(out, "write_non_chained", "stats_write_non_chained", atoms.non_chained_signatures, attributionDecl); // Print registration function table fprintf(out, "/*\n"); fprintf(out, " * JNI registration.\n"); fprintf(out, " */\n"); fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n"); for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { fprintf(out, " { \"write\", \"%s\", (void*)%s },\n", jni_function_signature(*signature, attributionDecl).c_str(), jni_function_name(*signature).c_str()); } write_jni_registration(out, "write", atoms.signatures, attributionDecl); write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl); fprintf(out, "};\n"); fprintf(out, "\n"); Loading @@ -699,11 +817,9 @@ write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDe fprintf(out, "\n"); fprintf(out, "} // namespace android\n"); return 0; } static void print_usage() { Loading Loading
tools/stats_log_api_gen/Collation.cpp +66 −5 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "Collation.h" #include "frameworks/base/cmds/statsd/src/atoms.pb.h" #include <stdio.h> #include <map> Loading Loading @@ -136,6 +137,16 @@ java_type(const FieldDescriptor* field) } } /** * Gather the enums info. */ void collate_enums(const EnumDescriptor &enumDescriptor, AtomField *atomField) { for (int i = 0; i < enumDescriptor.value_count(); i++) { atomField->enumValues[enumDescriptor.value(i)->number()] = enumDescriptor.value(i)->name().c_str(); } } /** * Gather the info about an atom proto. */ Loading Loading @@ -221,11 +232,7 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, if (javaType == JAVA_TYPE_ENUM) { // All enums are treated as ints when it comes to function signatures. signature->push_back(JAVA_TYPE_INT); const EnumDescriptor *enumDescriptor = field->enum_type(); for (int i = 0; i < enumDescriptor->value_count(); i++) { atField.enumValues[enumDescriptor->value(i)->number()] = enumDescriptor->value(i)->name().c_str(); } collate_enums(*field->enum_type(), &atField); } else { signature->push_back(javaType); } Loading @@ -235,6 +242,53 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, return errorCount; } // This function flattens the fields of the AttributionNode proto in an Atom proto and generates // the corresponding atom decl and signature. bool get_non_chained_node(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature) { // Build a sorted list of the fields. Descriptor has them in source file // order. map<int, const FieldDescriptor *> fields; for (int j = 0; j < atom->field_count(); j++) { const FieldDescriptor *field = atom->field(j); fields[field->number()] = field; } AtomDecl attributionDecl; vector<java_type_t> attributionSignature; collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl, &attributionSignature); // Build the type signature and the atom data. bool has_attribution_node = false; for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin(); it != fields.end(); it++) { const FieldDescriptor *field = it->second; java_type_t javaType = java_type(field); if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { atomDecl->fields.insert( atomDecl->fields.end(), attributionDecl.fields.begin(), attributionDecl.fields.end()); signature->insert( signature->end(), attributionSignature.begin(), attributionSignature.end()); has_attribution_node = true; } else { AtomField atField(field->name(), javaType); if (javaType == JAVA_TYPE_ENUM) { // All enums are treated as ints when it comes to function signatures. signature->push_back(JAVA_TYPE_INT); collate_enums(*field->enum_type(), &atField); } else { signature->push_back(javaType); } atomDecl->fields.push_back(atField); } } return has_attribution_node; } /** * Gather the info about the atoms. */ Loading Loading @@ -266,6 +320,13 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) { errorCount += collate_atom(atom, &atomDecl, &signature); atoms->signatures.insert(signature); atoms->decls.insert(atomDecl); AtomDecl nonChainedAtomDecl(atomField->number(), atomField->name(), atom->name()); vector<java_type_t> nonChainedSignature; if (get_non_chained_node(atom, &nonChainedAtomDecl, &nonChainedSignature)) { atoms->non_chained_signatures.insert(nonChainedSignature); atoms->non_chained_decls.insert(nonChainedAtomDecl); } } if (dbg) { Loading
tools/stats_log_api_gen/Collation.h +4 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ using std::set; using std::string; using std::vector; using google::protobuf::Descriptor; using google::protobuf::FieldDescriptor; /** * The types for atom parameters. Loading Loading @@ -93,14 +94,15 @@ struct AtomDecl { struct Atoms { set<vector<java_type_t>> signatures; set<AtomDecl> decls; set<AtomDecl> non_chained_decls; set<vector<java_type_t>> non_chained_signatures; }; /** * Gather the information about the atoms. Returns the number of errors. */ int collate_atoms(const Descriptor* descriptor, Atoms* atoms); int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature); int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> *signature); } // namespace stats_log_api_gen } // namespace android Loading
tools/stats_log_api_gen/main.cpp +216 −100 Original line number Diff line number Diff line Loading @@ -195,6 +195,47 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, fprintf(out, "\n"); } for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin(); signature != atoms.non_chained_signatures.end(); signature++) { int argIndex; fprintf(out, "void\n"); fprintf(out, "stats_write_non_chained(int32_t code"); argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); argIndex++; } fprintf(out, ")\n"); fprintf(out, "{\n"); argIndex = 1; fprintf(out, " android_log_event_list event(kStatsEventTag);\n"); fprintf(out, " event << code;\n\n"); for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (argIndex == 1) { fprintf(out, " event.begin();\n\n"); fprintf(out, " event.begin();\n"); } if (*arg == JAVA_TYPE_STRING) { fprintf(out, " if (arg%d == NULL) {\n", argIndex); fprintf(out, " arg%d = \"\";\n", argIndex); fprintf(out, " }\n"); } fprintf(out, " event << arg%d;\n", argIndex); if (argIndex == 2) { fprintf(out, " event.end();\n\n"); fprintf(out, " event.end();\n\n"); } argIndex++; } fprintf(out, " event.write(LOG_ID_STATS);\n"); fprintf(out, "}\n"); fprintf(out, "\n"); } // Print footer fprintf(out, "\n"); fprintf(out, "} // namespace util\n"); Loading @@ -203,6 +244,68 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, return 0; } void build_non_chained_decl_map(const Atoms& atoms, std::map<int, set<AtomDecl>::const_iterator>* decl_map){ for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin(); atom != atoms.non_chained_decls.end(); atom++) { decl_map->insert(std::make_pair(atom->code, atom)); } } static void write_cpp_usage( FILE* out, const string& method_name, const string& atom_code_name, const AtomDecl& atom, const AtomDecl &attributionDecl) { fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str()); for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } } } else { fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str()); } } fprintf(out, ");\n"); } static void write_cpp_method_header( FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { fprintf(out, "void %s(int32_t code ", method_name.c_str()); int argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } } } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } argIndex++; } fprintf(out, ");\n"); } } static int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) Loading @@ -228,6 +331,9 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, " */\n"); fprintf(out, "enum {\n"); std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map; build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map); size_t i = 0; // Print constants for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); Loading @@ -236,26 +342,13 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, "\n"); fprintf(out, " /**\n"); fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str()); fprintf(out, " * Usage: stats_write(StatsLog.%s", constant.c_str()); for (vector<AtomField>::const_iterator field = atom->fields.begin(); field != atom->fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } } } else { fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str()); } write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl); auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code); if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) { write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second, attributionDecl); } fprintf(out, ");\n"); fprintf(out, " */\n"); char const* const comma = (i == atoms.decls.size() - 1) ? "" : ","; fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma); Loading @@ -274,38 +367,64 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio fprintf(out, "//\n"); fprintf(out, "// Write methods\n"); fprintf(out, "//\n"); for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { fprintf(out, "void stats_write(int32_t code "); write_cpp_method_header(out, "stats_write", atoms.signatures, attributionDecl); fprintf(out, "//\n"); fprintf(out, "// Write flattened methods\n"); fprintf(out, "//\n"); write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures, attributionDecl); fprintf(out, "\n"); fprintf(out, "} // namespace util\n"); fprintf(out, "} // namespace android\n"); return 0; } static void write_java_usage( FILE* out, const string& method_name, const string& atom_code_name, const AtomDecl& atom, const AtomDecl &attributionDecl) { fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str()); for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else { fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str()); } } fprintf(out, ");\n"); } static void write_java_method( FILE* out, const string& method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { fprintf(out, " public static native void %s(int code", method_name.c_str()); int argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { if (chainField.javaType == JAVA_TYPE_STRING) { fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), chainField.name.c_str()); } else { fprintf(out, ", const %s* %s, size_t %s_length", cpp_type_name(chainField.javaType), chainField.name.c_str(), chainField.name.c_str()); } fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); } argIndex++; } fprintf(out, ");\n"); } fprintf(out, "\n"); fprintf(out, "} // namespace util\n"); fprintf(out, "} // namespace android\n"); return 0; } static int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) { Loading @@ -322,6 +441,9 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD fprintf(out, "public class StatsLogInternal {\n"); fprintf(out, " // Constants for atom codes.\n"); std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map; build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map); // Print constants for the atom codes. for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end(); atom++) { Loading @@ -329,19 +451,12 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD fprintf(out, "\n"); fprintf(out, " /**\n"); fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str()); fprintf(out, " * Usage: StatsLog.write(StatsLog.%s", constant.c_str()); for (vector<AtomField>::const_iterator field = atom->fields.begin(); field != atom->fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); write_java_usage(out, "write", constant, *atom, attributionDecl); auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code); if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) { write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second, attributionDecl); } } else { fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str()); } } fprintf(out, ");\n"); fprintf(out, " */\n"); fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code); } Loading Loading @@ -371,24 +486,8 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD // Print write methods fprintf(out, " // Write methods\n"); for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { fprintf(out, " public static native void write(int code"); int argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { for (auto chainField : attributionDecl.fields) { fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else { fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); } argIndex++; } fprintf(out, ");\n"); } write_java_method(out, "write", atoms.signatures, attributionDecl); write_java_method(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl); fprintf(out, "}\n"); Loading Loading @@ -431,9 +530,9 @@ jni_array_type_name(java_type_t type) } static string jni_function_name(const vector<java_type_t>& signature) jni_function_name(const string& method_name, const vector<java_type_t>& signature) { string result("StatsLog_write"); string result("StatsLog_" + method_name); for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); arg++) { switch (*arg) { Loading Loading @@ -509,34 +608,17 @@ jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &att } static int write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp_method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { // Print prelude fprintf(out, "// This file is autogenerated\n"); fprintf(out, "\n"); fprintf(out, "#include <statslog.h>\n"); fprintf(out, "\n"); fprintf(out, "#include <nativehelper/JNIHelp.h>\n"); fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n"); fprintf(out, "#include <utils/Vector.h>\n"); fprintf(out, "#include \"core_jni_helpers.h\"\n"); fprintf(out, "#include \"jni.h\"\n"); fprintf(out, "\n"); fprintf(out, "#define UNUSED __attribute__((__unused__))\n"); fprintf(out, "\n"); fprintf(out, "namespace android {\n"); fprintf(out, "\n"); // Print write methods for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { int argIndex; fprintf(out, "static void\n"); fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code", jni_function_name(*signature).c_str()); jni_function_name(java_method_name, *signature).c_str()); argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { Loading Loading @@ -624,7 +706,7 @@ write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDe // stats_write call argIndex = 1; fprintf(out, " android::util::stats_write(code"); fprintf(out, " android::util::%s(code", cpp_method_name.c_str()); for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { Loading Loading @@ -675,17 +757,53 @@ write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDe fprintf(out, "\n"); } return 0; } void write_jni_registration(FILE* out, const string& java_method_name, const set<vector<java_type_t>>& signatures, const AtomDecl &attributionDecl) { for (set<vector<java_type_t>>::const_iterator signature = signatures.begin(); signature != signatures.end(); signature++) { fprintf(out, " { \"%s\", \"%s\", (void*)%s },\n", java_method_name.c_str(), jni_function_signature(*signature, attributionDecl).c_str(), jni_function_name(java_method_name, *signature).c_str()); } } static int write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) { // Print prelude fprintf(out, "// This file is autogenerated\n"); fprintf(out, "\n"); fprintf(out, "#include <statslog.h>\n"); fprintf(out, "\n"); fprintf(out, "#include <nativehelper/JNIHelp.h>\n"); fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n"); fprintf(out, "#include <utils/Vector.h>\n"); fprintf(out, "#include \"core_jni_helpers.h\"\n"); fprintf(out, "#include \"jni.h\"\n"); fprintf(out, "\n"); fprintf(out, "#define UNUSED __attribute__((__unused__))\n"); fprintf(out, "\n"); fprintf(out, "namespace android {\n"); fprintf(out, "\n"); write_stats_log_jni(out, "write", "stats_write", atoms.signatures, attributionDecl); write_stats_log_jni(out, "write_non_chained", "stats_write_non_chained", atoms.non_chained_signatures, attributionDecl); // Print registration function table fprintf(out, "/*\n"); fprintf(out, " * JNI registration.\n"); fprintf(out, " */\n"); fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n"); for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin(); signature != atoms.signatures.end(); signature++) { fprintf(out, " { \"write\", \"%s\", (void*)%s },\n", jni_function_signature(*signature, attributionDecl).c_str(), jni_function_name(*signature).c_str()); } write_jni_registration(out, "write", atoms.signatures, attributionDecl); write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl); fprintf(out, "};\n"); fprintf(out, "\n"); Loading @@ -699,11 +817,9 @@ write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDe fprintf(out, "\n"); fprintf(out, "} // namespace android\n"); return 0; } static void print_usage() { Loading