Merge "Mainline logging to statsd: native static libs"
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 2a3eee2..16c936c 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -84,4 +84,6 @@
optional LogMode log_mode = 50002 [default = MODE_AUTOMATIC];
optional bool allow_from_any_uid = 50003 [default = false];
+
+ optional string log_from_module = 50004;
}
\ No newline at end of file
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 5725f0c..4ce4406 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -31,6 +31,7 @@
shared_libs: [
"libstats_proto_host",
"libprotobuf-cpp-full",
+ "libbase",
],
proto: {
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index a8d970e..e66ead7 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -49,7 +49,9 @@
exclusiveField(that.exclusiveField),
uidField(that.uidField),
whitelisted(that.whitelisted),
- binaryFields(that.binaryFields) {}
+ binaryFields(that.binaryFields),
+ hasModule(that.hasModule),
+ moduleName(that.moduleName) {}
AtomDecl::AtomDecl(int c, const string& n, const string& m)
:code(c),
@@ -391,7 +393,12 @@
AtomDecl atomDecl(atomField->number(), atomField->name(), atom->name());
if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) {
- atomDecl.whitelisted = true;
+ atomDecl.whitelisted = true;
+ }
+
+ if (atomField->options().HasExtension(os::statsd::log_from_module)) {
+ atomDecl.hasModule = true;
+ atomDecl.moduleName = atomField->options().GetExtension(os::statsd::log_from_module);
}
vector<java_type_t> signature;
@@ -399,25 +406,49 @@
if (atomDecl.primaryFields.size() != 0 && atomDecl.exclusiveField == 0) {
errorCount++;
}
- atoms->signatures.insert(signature);
+
+ // Add the signature if does not already exist.
+ auto signature_to_modules_it = atoms->signatures_to_modules.find(signature);
+ if (signature_to_modules_it == atoms->signatures_to_modules.end()) {
+ set<string> modules;
+ if (atomDecl.hasModule) {
+ modules.insert(atomDecl.moduleName);
+ }
+ atoms->signatures_to_modules[signature] = modules;
+ } else {
+ if (atomDecl.hasModule) {
+ signature_to_modules_it->second.insert(atomDecl.moduleName);
+ }
+ }
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);
+ auto it = atoms->non_chained_signatures_to_modules.find(signature);
+ if (it == atoms->non_chained_signatures_to_modules.end()) {
+ set<string> modules_non_chained;
+ if (atomDecl.hasModule) {
+ modules_non_chained.insert(atomDecl.moduleName);
+ }
+ atoms->non_chained_signatures_to_modules[nonChainedSignature] = modules_non_chained;
+ } else {
+ if (atomDecl.hasModule) {
+ it->second.insert(atomDecl.moduleName);
+ }
+ }
atoms->non_chained_decls.insert(nonChainedAtomDecl);
}
}
if (dbg) {
printf("signatures = [\n");
- for (set<vector<java_type_t>>::const_iterator it =
- atoms->signatures.begin();
- it != atoms->signatures.end(); it++) {
+ for (map<vector<java_type_t>, set<string>>::const_iterator it =
+ atoms->signatures_to_modules.begin();
+ it != atoms->signatures_to_modules.end(); it++) {
printf(" ");
- for (vector<java_type_t>::const_iterator jt = it->begin();
- jt != it->end(); jt++) {
+ for (vector<java_type_t>::const_iterator jt = it->first.begin();
+ jt != it->first.end(); jt++) {
printf(" %d", (int)*jt);
}
printf("\n");
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index 6b86b862..44746c9 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -93,6 +93,9 @@
vector<int> binaryFields;
+ bool hasModule = false;
+ string moduleName;
+
AtomDecl();
AtomDecl(const AtomDecl& that);
AtomDecl(int code, const string& name, const string& message);
@@ -104,10 +107,10 @@
};
struct Atoms {
- set<vector<java_type_t>> signatures;
+ map<vector<java_type_t>, set<string>> signatures_to_modules;
set<AtomDecl> decls;
set<AtomDecl> non_chained_decls;
- set<vector<java_type_t>> non_chained_signatures;
+ map<vector<java_type_t>, set<string>> non_chained_signatures_to_modules;
};
/**
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 0216920..daee6d6 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -12,6 +12,8 @@
#include <stdlib.h>
#include <string.h>
+#include "android-base/strings.h"
+
using namespace google::protobuf;
using namespace std;
@@ -20,6 +22,10 @@
int maxPushedAtomId = 2;
+const string DEFAULT_MODULE_NAME = "DEFAULT";
+const string DEFAULT_CPP_NAMESPACE = "android,util";
+const string DEFAULT_CPP_HEADER_IMPORT = "statslog.h";
+
using android::os::statsd::Atom;
/**
@@ -97,40 +103,27 @@
}
}
-static int write_stats_log_cpp(FILE *out, const Atoms &atoms,
- const AtomDecl &attributionDecl) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
+static bool atom_needed_for_module(const AtomDecl& atomDecl, const string& moduleName) {
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ return true;
+ }
+ return atomDecl.hasModule && (moduleName == atomDecl.moduleName);
+}
- fprintf(out, "#include <mutex>\n");
- fprintf(out, "#include <chrono>\n");
- fprintf(out, "#include <thread>\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "#include <cutils/properties.h>\n");
- fprintf(out, "#endif\n");
- fprintf(out, "#include <stats_event_list.h>\n");
- fprintf(out, "#include <log/log.h>\n");
- fprintf(out, "#include <statslog.h>\n");
- fprintf(out, "#include <utils/SystemClock.h>\n");
- fprintf(out, "\n");
+static bool signature_needed_for_module(const set<string>& modules, const string& moduleName) {
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ return true;
+ }
+ return modules.find(moduleName) != modules.end();
+}
- fprintf(out, "namespace android {\n");
- fprintf(out, "namespace util {\n");
- fprintf(out, "// the single event tag id for all stats logs\n");
- fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
- fprintf(out, "#else\n");
- fprintf(out, "const static bool kStatsdEnabled = false;\n");
- fprintf(out, "#endif\n");
-
+static void write_atoms_info_cpp(FILE *out, const Atoms &atoms) {
std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
- "audio_state_changed",
- "call_state_changed",
- "phone_signal_strength_changed",
- "mobile_bytes_transfer_by_fg_bg",
- "mobile_bytes_transfer"};
+ "audio_state_changed",
+ "call_state_changed",
+ "phone_signal_strength_changed",
+ "mobile_bytes_transfer_by_fg_bg",
+ "mobile_bytes_transfer"};
fprintf(out,
"const std::set<int> "
"AtomsInfo::kNotTruncatingTimestampAtomWhiteList = {\n");
@@ -256,6 +249,56 @@
"const std::map<int, std::vector<int>> "
"AtomsInfo::kBytesFieldAtoms = "
"getBinaryFieldAtoms();\n");
+}
+
+// Writes namespaces for the cpp and header files, returning the number of namespaces written.
+void write_namespace(FILE* out, const string& cppNamespaces) {
+ vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
+ for (string cppNamespace : cppNamespaceVec) {
+ fprintf(out, "namespace %s {\n", cppNamespace.c_str());
+ }
+}
+
+// Writes namespace closing brackets for cpp and header files.
+void write_closing_namespace(FILE* out, const string& cppNamespaces) {
+ vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
+ for (auto it = cppNamespaceVec.rbegin(); it != cppNamespaceVec.rend(); ++it) {
+ fprintf(out, "} // namespace %s\n", it->c_str());
+ }
+}
+
+static int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace,
+ const string& importHeader) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+
+ fprintf(out, "#include <mutex>\n");
+ fprintf(out, "#include <chrono>\n");
+ fprintf(out, "#include <thread>\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out, "#include <cutils/properties.h>\n");
+ fprintf(out, "#endif\n");
+ fprintf(out, "#include <stats_event_list.h>\n");
+ fprintf(out, "#include <log/log.h>\n");
+ fprintf(out, "#include <%s>\n", importHeader.c_str());
+ fprintf(out, "#include <utils/SystemClock.h>\n");
+ fprintf(out, "\n");
+
+ write_namespace(out, cppNamespace);
+ fprintf(out, "// the single event tag id for all stats logs\n");
+ fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
+ fprintf(out, "#else\n");
+ fprintf(out, "const static bool kStatsdEnabled = false;\n");
+ fprintf(out, "#endif\n");
+
+ // AtomsInfo is only used by statsd internally and is not needed for other modules.
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ write_atoms_info_cpp(out, atoms);
+ }
fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
@@ -263,15 +306,19 @@
// Print write methods
fprintf(out, "\n");
- for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
- signature != atoms.signatures.end(); signature++) {
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
int argIndex;
fprintf(out, "int\n");
fprintf(out, "try_stats_write(int32_t code");
argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ 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) {
@@ -303,8 +350,8 @@
fprintf(out, " stats_event_list event(kStatsEventTag);\n");
fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
for (const auto &chainField : attributionDecl.fields) {
if (chainField.javaType == JAVA_TYPE_STRING) {
@@ -387,15 +434,19 @@
fprintf(out, "\n");
}
- for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
- signature != atoms.signatures.end(); signature++) {
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
int argIndex;
fprintf(out, "int\n");
fprintf(out, "stats_write(int32_t code");
argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ 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) {
@@ -429,8 +480,8 @@
fprintf(out, " ret = try_stats_write(code");
argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ 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) {
@@ -468,15 +519,19 @@
fprintf(out, "\n");
}
- for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
- signature != atoms.non_chained_signatures.end(); signature++) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
int argIndex;
fprintf(out, "int\n");
fprintf(out, "try_stats_write_non_chained(int32_t code");
argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ 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++;
}
@@ -488,8 +543,8 @@
fprintf(out, " stats_event_list event(kStatsEventTag);\n");
fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ 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");
@@ -522,15 +577,19 @@
fprintf(out, "\n");
}
- for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
- signature != atoms.non_chained_signatures.end(); signature++) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
int argIndex;
fprintf(out, "int\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++) {
+ 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++;
}
@@ -543,8 +602,8 @@
fprintf(out, " ret = try_stats_write_non_chained(code");
argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
fprintf(out, ", arg%d", argIndex);
argIndex++;
}
@@ -572,8 +631,7 @@
// Print footer
fprintf(out, "\n");
- fprintf(out, "} // namespace util\n");
- fprintf(out, "} // namespace android\n");
+ write_closing_namespace(out, cppNamespace);
return 0;
}
@@ -623,14 +681,23 @@
}
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++) {
+ FILE* out,
+ const string& method_name,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl, const string& moduleName) {
+
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+
+ vector<java_type_t> signature = signature_to_modules_it->first;
fprintf(out, "int %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++) {
+ 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) {
@@ -659,7 +726,8 @@
}
static int
-write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
+write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace)
{
// Print prelude
fprintf(out, "// This file is autogenerated\n");
@@ -672,8 +740,7 @@
fprintf(out, "#include <set>\n");
fprintf(out, "\n");
- fprintf(out, "namespace android {\n");
- fprintf(out, "namespace util {\n");
+ write_namespace(out, cppNamespace);
fprintf(out, "\n");
fprintf(out, "/*\n");
fprintf(out, " * API For logging statistics events.\n");
@@ -691,6 +758,10 @@
// Print atom constants
for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
string constant = make_constant_name(atom->name);
fprintf(out, "\n");
fprintf(out, " /**\n");
@@ -720,6 +791,11 @@
fprintf(out, "//\n\n");
for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
+
for (vector<AtomField>::const_iterator field = atom->fields.begin();
field != atom->fields.end(); field++) {
if (field->javaType == JAVA_TYPE_ENUM) {
@@ -747,47 +823,51 @@
fprintf(out, "};\n");
fprintf(out, "\n");
- fprintf(out, "struct StateAtomFieldOptions {\n");
- fprintf(out, " std::vector<int> primaryFields;\n");
- fprintf(out, " int exclusiveField;\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
+ // This metadata is only used by statsd, which uses the default libstatslog.
+ if (moduleName == DEFAULT_MODULE_NAME) {
- fprintf(out, "struct AtomsInfo {\n");
- fprintf(out,
- " const static std::set<int> "
- "kNotTruncatingTimestampAtomWhiteList;\n");
- fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
- fprintf(out,
- " const static std::set<int> kAtomsWithAttributionChain;\n");
- fprintf(out,
- " const static std::map<int, StateAtomFieldOptions> "
- "kStateAtomsFieldOptions;\n");
- fprintf(out,
- " const static std::map<int, std::vector<int>> "
- "kBytesFieldAtoms;");
- fprintf(out,
- " const static std::set<int> kWhitelistedAtoms;\n");
- fprintf(out, "};\n");
+ fprintf(out, "struct StateAtomFieldOptions {\n");
+ fprintf(out, " std::vector<int> primaryFields;\n");
+ fprintf(out, " int exclusiveField;\n");
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
- fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
- maxPushedAtomId);
+ fprintf(out, "struct AtomsInfo {\n");
+ fprintf(out,
+ " const static std::set<int> "
+ "kNotTruncatingTimestampAtomWhiteList;\n");
+ fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
+ fprintf(out,
+ " const static std::set<int> kAtomsWithAttributionChain;\n");
+ fprintf(out,
+ " const static std::map<int, StateAtomFieldOptions> "
+ "kStateAtomsFieldOptions;\n");
+ fprintf(out,
+ " const static std::map<int, std::vector<int>> "
+ "kBytesFieldAtoms;");
+ fprintf(out,
+ " const static std::set<int> kWhitelistedAtoms;\n");
+ fprintf(out, "};\n");
+
+ fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
+ maxPushedAtomId);
+ }
// Print write methods
fprintf(out, "//\n");
fprintf(out, "// Write methods\n");
fprintf(out, "//\n");
- write_cpp_method_header(out, "stats_write", atoms.signatures, attributionDecl);
+ write_cpp_method_header(out, "stats_write", atoms.signatures_to_modules, attributionDecl,
+ moduleName);
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);
+ write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures_to_modules,
+ attributionDecl, moduleName);
fprintf(out, "\n");
- fprintf(out, "} // namespace util\n");
- fprintf(out, "} // namespace android\n");
+ write_closing_namespace(out, cppNamespace);
return 0;
}
@@ -812,15 +892,19 @@
}
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++) {
+ FILE* out,
+ const string& method_name,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl) {
+
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ vector<java_type_t> signature = signature_to_modules_it->first;
fprintf(out, " /** @hide */\n");
fprintf(out, " public static native int %s(int code", method_name.c_str());
int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ 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",
@@ -837,15 +921,17 @@
}
}
-static void write_java_work_source_method(FILE* out, const set<vector<java_type_t>>& signatures) {
+static void write_java_work_source_method(FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules) {
fprintf(out, "\n // WorkSource methods.\n");
- for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
- signature != signatures.end(); signature++) {
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ vector<java_type_t> signature = signature_to_modules_it->first;
// Determine if there is Attribution in this signature.
int attributionArg = -1;
int argIndexMax = 0;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
argIndexMax++;
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
if (attributionArg > -1) {
@@ -865,8 +951,8 @@
fprintf(out, " /** @hide */\n");
fprintf(out, " public static void write(int code");
int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
fprintf(out, ", WorkSource ws");
} else {
@@ -974,9 +1060,10 @@
// Print write methods
fprintf(out, " // Write methods\n");
- write_java_method(out, "write", atoms.signatures, attributionDecl);
- write_java_method(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
- write_java_work_source_method(out, atoms.signatures);
+ write_java_method(out, "write", atoms.signatures_to_modules, attributionDecl);
+ write_java_method(out, "write_non_chained", atoms.non_chained_signatures_to_modules,
+ attributionDecl);
+ write_java_work_source_method(out, atoms.signatures_to_modules);
fprintf(out, "}\n");
@@ -1154,19 +1241,20 @@
static int
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)
-{
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl) {
// Print write methods
- for (set<vector<java_type_t>>::const_iterator signature = signatures.begin();
- signature != signatures.end(); signature++) {
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ vector<java_type_t> signature = signature_to_modules_it->first;
int argIndex;
fprintf(out, "static int\n");
fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code",
- jni_function_name(java_method_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++) {
+ 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", jni_array_type_name(chainField.javaType),
@@ -1187,8 +1275,8 @@
argIndex = 1;
bool hadStringOrChain = false;
bool isKeyValuePairAtom = false;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
if (*arg == JAVA_TYPE_STRING) {
hadStringOrChain = true;
fprintf(out, " const char* str%d;\n", argIndex);
@@ -1288,8 +1376,8 @@
argIndex = 1;
fprintf(out, "\n int ret = android::util::%s(code",
cpp_method_name.c_str());
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ 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_INT) {
@@ -1316,8 +1404,8 @@
// Clean up strings
argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature->begin();
- arg != signature->end(); arg++) {
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
if (*arg == JAVA_TYPE_STRING) {
fprintf(out, " if (str%d != NULL) {\n", argIndex);
fprintf(out, " env->ReleaseStringUTFChars(arg%d, str%d);\n",
@@ -1357,13 +1445,15 @@
}
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++) {
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl) {
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ vector<java_type_t> signature = signature_to_modules_it->first;
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());
+ jni_function_signature(signature, attributionDecl).c_str(),
+ jni_function_name(java_method_name, signature).c_str());
}
}
@@ -1388,17 +1478,18 @@
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", "stats_write", atoms.signatures_to_modules, attributionDecl);
write_stats_log_jni(out, "write_non_chained", "stats_write_non_chained",
- atoms.non_chained_signatures, attributionDecl);
+ atoms.non_chained_signatures_to_modules, attributionDecl);
// Print registration function table
fprintf(out, "/*\n");
fprintf(out, " * JNI registration.\n");
fprintf(out, " */\n");
fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n");
- write_jni_registration(out, "write", atoms.signatures, attributionDecl);
- write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures, attributionDecl);
+ write_jni_registration(out, "write", atoms.signatures_to_modules, attributionDecl);
+ write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures_to_modules,
+ attributionDecl);
fprintf(out, "};\n");
fprintf(out, "\n");
@@ -1426,6 +1517,10 @@
fprintf(stderr, " --help this message\n");
fprintf(stderr, " --java FILENAME the java file to output\n");
fprintf(stderr, " --jni FILENAME the jni file to output\n");
+ fprintf(stderr, " --module NAME optional, module name to generate outputs for\n");
+ fprintf(stderr, " --namespace COMMA,SEP,NAMESPACE required for cpp/header with module\n");
+ fprintf(stderr, " comma separated namespace of the files\n");
+ fprintf(stderr, " --importHeader NAME required for cpp/jni to say which header to import\n");
}
/**
@@ -1439,6 +1534,10 @@
string javaFilename;
string jniFilename;
+ string moduleName = DEFAULT_MODULE_NAME;
+ string cppNamespace = DEFAULT_CPP_NAMESPACE;
+ string cppHeaderImport = DEFAULT_CPP_HEADER_IMPORT;
+
int index = 1;
while (index < argc) {
if (0 == strcmp("--help", argv[index])) {
@@ -1472,6 +1571,27 @@
return 1;
}
jniFilename = argv[index];
+ } else if (0 == strcmp("--module", argv[index])) {
+ index++;
+ if (index >= argc) {
+ print_usage();
+ return 1;
+ }
+ moduleName = argv[index];
+ } else if (0 == strcmp("--namespace", argv[index])) {
+ index++;
+ if (index >= argc) {
+ print_usage();
+ return 1;
+ }
+ cppNamespace = argv[index];
+ } else if (0 == strcmp("--importHeader", argv[index])) {
+ index++;
+ if (index >= argc) {
+ print_usage();
+ return 1;
+ }
+ cppHeaderImport = argv[index];
}
index++;
}
@@ -1503,8 +1623,18 @@
fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
return 1;
}
+ // If this is for a specific module, the namespace must also be provided.
+ if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) {
+ fprintf(stderr, "Must supply --namespace if supplying a specific module\n");
+ return 1;
+ }
+ // If this is for a specific module, the header file to import must also be provided.
+ if (moduleName != DEFAULT_MODULE_NAME && cppHeaderImport == DEFAULT_CPP_HEADER_IMPORT) {
+ fprintf(stderr, "Must supply --headerImport if supplying a specific module\n");
+ return 1;
+ }
errorCount = android::stats_log_api_gen::write_stats_log_cpp(
- out, atoms, attributionDecl);
+ out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport);
fclose(out);
}
@@ -1515,8 +1645,12 @@
fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
return 1;
}
+ // If this is for a specific module, the namespace must also be provided.
+ if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) {
+ fprintf(stderr, "Must supply --namespace if supplying a specific module\n");
+ }
errorCount = android::stats_log_api_gen::write_stats_log_header(
- out, atoms, attributionDecl);
+ out, atoms, attributionDecl, moduleName, cppNamespace);
fclose(out);
}
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index 24ebf4d..c3e70382 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -213,4 +213,24 @@
// by whitelisted sources
NonWhitelistedAtom non_whitelisted_atom = 2;
}
+}
+
+message ModuleOneAtom {
+ optional int32 field = 1;
+}
+
+message ModuleTwoAtom {
+ optional int32 field = 1;
+}
+
+message NoModuleAtom {
+ optional string field = 1;
+}
+
+message ModuleAtoms {
+ oneof event {
+ ModuleOneAtom module_one_atom = 1 [(android.os.statsd.log_from_module) = "module1"];
+ ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.log_from_module) = "module2"];
+ NoModuleAtom no_module_atom = 3;
+ }
}
\ No newline at end of file
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
index dc585c1..bcf18ae 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -32,7 +32,7 @@
* Return whether the set contains a vector of the elements provided.
*/
static bool
-set_contains_vector(const set<vector<java_type_t>>& s, int count, ...)
+set_contains_vector(const map<vector<java_type_t>, set<string>>& s, int count, ...)
{
va_list args;
vector<java_type_t> v;
@@ -86,17 +86,17 @@
int errorCount = collate_atoms(Event::descriptor(), &atoms);
EXPECT_EQ(0, errorCount);
- EXPECT_EQ(3ul, atoms.signatures.size());
+ EXPECT_EQ(3ul, atoms.signatures_to_modules.size());
// IntAtom, AnotherIntAtom
- EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures, JAVA_TYPE_INT);
+ EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_INT);
// OutOfOrderAtom
- EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures, JAVA_TYPE_INT, JAVA_TYPE_INT);
+ EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_INT, JAVA_TYPE_INT);
// AllTypesAtom
EXPECT_SET_CONTAINS_SIGNATURE(
- atoms.signatures,
+ atoms.signatures_to_modules,
JAVA_TYPE_ATTRIBUTION_CHAIN, // AttributionChain
JAVA_TYPE_DOUBLE, // double
JAVA_TYPE_FLOAT, // float
@@ -228,8 +228,7 @@
TEST(CollationTest, PassOnWhitelistedAtom) {
Atoms atoms;
- int errorCount =
- collate_atoms(ListedAtoms::descriptor(), &atoms);
+ int errorCount = collate_atoms(ListedAtoms::descriptor(), &atoms);
EXPECT_EQ(errorCount, 0);
EXPECT_EQ(atoms.decls.size(), 2ul);
}
@@ -246,5 +245,46 @@
}
}
+TEST(CollationTest, PassOnLogFromModuleAtom) {
+ Atoms atoms;
+ int errorCount = collate_atoms(ModuleAtoms::descriptor(), &atoms);
+ EXPECT_EQ(errorCount, 0);
+ EXPECT_EQ(atoms.decls.size(), 3ul);
+}
+
+TEST(CollationTest, RecognizeModuleAtom) {
+ Atoms atoms;
+ int errorCount = collate_atoms(ModuleAtoms::descriptor(), &atoms);
+ EXPECT_EQ(errorCount, 0);
+ EXPECT_EQ(atoms.decls.size(), 3ul);
+ for (const auto& atomDecl: atoms.decls) {
+ if (atomDecl.code == 1) {
+ EXPECT_TRUE(atomDecl.hasModule);
+ EXPECT_EQ(atomDecl.moduleName, "module1");
+ } else if (atomDecl.code == 2) {
+ EXPECT_TRUE(atomDecl.hasModule);
+ EXPECT_EQ(atomDecl.moduleName, "module2");
+ } else {
+ EXPECT_FALSE(atomDecl.hasModule);
+ }
+ }
+
+ EXPECT_EQ(atoms.signatures_to_modules.size(), 2u);
+ EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_INT);
+ EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures_to_modules, JAVA_TYPE_STRING);
+ for (auto signature_to_modules_it : atoms.signatures_to_modules) {
+ vector<java_type_t> signature = signature_to_modules_it.first;
+ if (signature[0] == JAVA_TYPE_STRING) {
+ EXPECT_EQ(signature_to_modules_it.second.size(), 0u);
+ } else if (signature[0] == JAVA_TYPE_INT) {
+ set<string> modules = signature_to_modules_it.second;
+ EXPECT_EQ(modules.size(), 2u);
+ // Assert that the set contains "module1" and "module2".
+ EXPECT_NE(modules.find("module1"), modules.end());
+ EXPECT_NE(modules.find("module2"), modules.end());
+ }
+ }
+}
+
} // namespace stats_log_api_gen
} // namespace android
\ No newline at end of file