diff options
| -rw-r--r-- | tools/stats_log_api_gen/Collation.cpp | 71 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/Collation.h | 6 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/main.cpp | 316 |
3 files changed, 286 insertions, 107 deletions
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp index 80853b13a7cc..0e57f7ff0ed2 100644 --- a/tools/stats_log_api_gen/Collation.cpp +++ b/tools/stats_log_api_gen/Collation.cpp @@ -15,6 +15,7 @@ */ #include "Collation.h" +#include "frameworks/base/cmds/statsd/src/atoms.pb.h" #include <stdio.h> #include <map> @@ -137,6 +138,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. */ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, @@ -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); } @@ -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. */ @@ -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) { diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h index cd0625c3a61d..0455eca62da8 100644 --- a/tools/stats_log_api_gen/Collation.h +++ b/tools/stats_log_api_gen/Collation.h @@ -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. @@ -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 diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index bbe6d63073c1..e0e6b5883e32 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -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"); @@ -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) @@ -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(); @@ -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); @@ -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) { @@ -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++) { @@ -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()); - } - } else { - fprintf(out, ", %s %s", java_type_name(field->javaType), field->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); } - fprintf(out, ");\n"); fprintf(out, " */\n"); fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code); } @@ -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"); @@ -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) { @@ -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++) { @@ -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) { @@ -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"); @@ -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() { |