Loading cmds/statsd/src/logd/LogEvent.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,56 @@ bool LogEvent::write(float value) { return false; } bool LogEvent::writeKeyValuePairs(const std::map<int32_t, int64_t>& int_map, const std::map<int32_t, std::string>& string_map, const std::map<int32_t, float>& float_map) { if (mContext) { if (android_log_write_list_begin(mContext) < 0) { return false; } for (const auto& itr : int_map) { if (android_log_write_list_begin(mContext) < 0) { return false; } write(itr.first); write(itr.second); if (android_log_write_list_end(mContext) < 0) { return false; } } for (const auto& itr : string_map) { if (android_log_write_list_begin(mContext) < 0) { return false; } write(itr.first); write(itr.second.c_str()); if (android_log_write_list_end(mContext) < 0) { return false; } } for (const auto& itr : float_map) { if (android_log_write_list_begin(mContext) < 0) { return false; } write(itr.first); write(itr.second); if (android_log_write_list_end(mContext) < 0) { return false; } } if (android_log_write_list_end(mContext) < 0) { return false; } return true; } return false; } bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) { if (mContext) { if (android_log_write_list_begin(mContext) < 0) { Loading Loading @@ -225,6 +275,7 @@ void LogEvent::init(android_log_context context) { int i = 0; int depth = -1; int pos[] = {1, 1, 1}; bool isKeyValuePairAtom = false; do { elem = android_log_read_next(context); switch ((int)elem.type) { Loading @@ -232,6 +283,7 @@ void LogEvent::init(android_log_context context) { // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id. if (i == 2) { mTagId = elem.data.int32; isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM); } else { if (depth < 0 || depth > 2) { return; Loading @@ -249,6 +301,11 @@ void LogEvent::init(android_log_context context) { return; } // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { pos[depth] = 4; } mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32))); pos[depth]++; Loading @@ -260,6 +317,10 @@ void LogEvent::init(android_log_context context) { return; } // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { pos[depth] = 3; } mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(string(elem.data.string, elem.len)))); Loading @@ -274,6 +335,10 @@ void LogEvent::init(android_log_context context) { ALOGE("Depth > 2. Not supported!"); return; } // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { pos[depth] = 2; } mValues.push_back( FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64))); Loading cmds/statsd/src/logd/LogEvent.h +3 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,9 @@ public: bool write(float value); bool write(const std::vector<AttributionNodeInternal>& nodes); bool write(const AttributionNodeInternal& node); bool writeKeyValuePairs(const std::map<int32_t, int64_t>& int_map, const std::map<int32_t, std::string>& string_map, const std::map<int32_t, float>& float_map); /** * Return a string representation of this event. Loading cmds/statsd/tests/LogEvent_test.cpp +84 −1 Original line number Diff line number Diff line Loading @@ -89,6 +89,89 @@ TEST(LogEventTest, TestLogParsing) { EXPECT_EQ((float)1.1, item7.mValue.float_value); } TEST(LogEventTest, TestKeyValuePairsAtomParsing) { LogEvent event1(83, 2000); std::map<int32_t, int64_t> int_map; std::map<int32_t, std::string> string_map; std::map<int32_t, float> float_map; int_map[11] = 123L; int_map[22] = 345L; string_map[1] = "test2"; string_map[2] = "test1"; float_map[111] = 2.2f; float_map[222] = 1.1f; EXPECT_TRUE(event1.writeKeyValuePairs(int_map, string_map, float_map)); event1.init(); EXPECT_EQ(83, event1.GetTagId()); const auto& items = event1.getValues(); EXPECT_EQ((size_t)12, items.size()); const FieldValue& item0 = event1.getValues()[0]; EXPECT_EQ(0x2010101, item0.mField.getField()); EXPECT_EQ(Type::INT, item0.mValue.getType()); EXPECT_EQ(11, item0.mValue.int_value); const FieldValue& item1 = event1.getValues()[1]; EXPECT_EQ(0x2010182, item1.mField.getField()); EXPECT_EQ(Type::LONG, item1.mValue.getType()); EXPECT_EQ(123L, item1.mValue.long_value); const FieldValue& item2 = event1.getValues()[2]; EXPECT_EQ(0x2010201, item2.mField.getField()); EXPECT_EQ(Type::INT, item2.mValue.getType()); EXPECT_EQ(22, item2.mValue.int_value); const FieldValue& item3 = event1.getValues()[3]; EXPECT_EQ(0x2010282, item3.mField.getField()); EXPECT_EQ(Type::LONG, item3.mValue.getType()); EXPECT_EQ(345L, item3.mValue.long_value); const FieldValue& item4 = event1.getValues()[4]; EXPECT_EQ(0x2010301, item4.mField.getField()); EXPECT_EQ(Type::INT, item4.mValue.getType()); EXPECT_EQ(1, item4.mValue.int_value); const FieldValue& item5 = event1.getValues()[5]; EXPECT_EQ(0x2010383, item5.mField.getField()); EXPECT_EQ(Type::STRING, item5.mValue.getType()); EXPECT_EQ("test2", item5.mValue.str_value); const FieldValue& item6 = event1.getValues()[6]; EXPECT_EQ(0x2010401, item6.mField.getField()); EXPECT_EQ(Type::INT, item6.mValue.getType()); EXPECT_EQ(2, item6.mValue.int_value); const FieldValue& item7 = event1.getValues()[7]; EXPECT_EQ(0x2010483, item7.mField.getField()); EXPECT_EQ(Type::STRING, item7.mValue.getType()); EXPECT_EQ("test1", item7.mValue.str_value); const FieldValue& item8 = event1.getValues()[8]; EXPECT_EQ(0x2010501, item8.mField.getField()); EXPECT_EQ(Type::INT, item8.mValue.getType()); EXPECT_EQ(111, item8.mValue.int_value); const FieldValue& item9 = event1.getValues()[9]; EXPECT_EQ(0x2010584, item9.mField.getField()); EXPECT_EQ(Type::FLOAT, item9.mValue.getType()); EXPECT_EQ(2.2f, item9.mValue.float_value); const FieldValue& item10 = event1.getValues()[10]; EXPECT_EQ(0x2018601, item10.mField.getField()); EXPECT_EQ(Type::INT, item10.mValue.getType()); EXPECT_EQ(222, item10.mValue.int_value); const FieldValue& item11 = event1.getValues()[11]; EXPECT_EQ(0x2018684, item11.mField.getField()); EXPECT_EQ(Type::FLOAT, item11.mValue.getType()); EXPECT_EQ(1.1f, item11.mValue.float_value); } TEST(LogEventTest, TestLogParsing2) { LogEvent event1(1, 2000); Loading Loading @@ -158,7 +241,7 @@ TEST(LogEventTest, TestLogParsing2) { EXPECT_EQ((float)1.1, item7.mValue.float_value); } TEST(LogEventTest, TestKeyValuePairsAtomParsing) { TEST(LogEventTest, TestKeyValuePairsEvent) { std::map<int32_t, int64_t> int_map; std::map<int32_t, std::string> string_map; std::map<int32_t, float> float_map; Loading tools/stats_log_api_gen/Collation.cpp +0 −10 Original line number Diff line number Diff line Loading @@ -184,16 +184,6 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, expectedNumber++; } // Skips the key value pair atom. 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_KEY_VALUE_PAIR) { return 0; } } // Check that only allowed types are present. Remove any invalid ones. for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin(); it != fields.end(); it++) { Loading tools/stats_log_api_gen/main.cpp +107 −4 Original line number Diff line number Diff line Loading @@ -235,6 +235,10 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& arg%d_1, " "const std::map<int, char const*>& arg%d_2, " "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } Loading Loading @@ -276,6 +280,30 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, } fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " event.end();\n\n"); } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, " event.begin();\n\n"); fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex); fprintf(out, " event.begin();\n"); fprintf(out, " event << it.first;\n"); fprintf(out, " event << it.second;\n"); fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex); fprintf(out, " event.begin();\n"); fprintf(out, " event << it.first;\n"); fprintf(out, " event << it.second;\n"); fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex); fprintf(out, " event.begin();\n"); fprintf(out, " event << it.first;\n"); fprintf(out, " event << it.second;\n"); fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " event.end();\n\n"); } else { if (*arg == JAVA_TYPE_STRING) { Loading Loading @@ -317,6 +345,10 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& arg%d_1, " "const std::map<int, char const*>& arg%d_2, " "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } Loading @@ -343,6 +375,8 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", arg%d_1, arg%d_2, arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", arg%d", argIndex); } Loading Loading @@ -496,6 +530,11 @@ static void write_cpp_usage( chainField.name.c_str(), chainField.name.c_str()); } } } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& %s_int" ", const std::map<int, char const*>& %s_str" ", const std::map<int, float>& %s_float", field->name.c_str(), field->name.c_str(), field->name.c_str()); } else { fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str()); } Loading Loading @@ -523,6 +562,10 @@ static void write_cpp_method_header( chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& arg%d_1, " "const std::map<int, char const*>& arg%d_2, " "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } Loading Loading @@ -637,6 +680,8 @@ static void write_java_usage(FILE* out, const string& method_name, const string& field != atom.fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { fprintf(out, ", android.os.WorkSource workSource"); } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", SparseArray<Object> value_map"); } else { fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str()); } Loading @@ -658,6 +703,8 @@ static void write_java_method( fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", SparseArray<Object> value_map"); } else { fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); } Loading Loading @@ -746,6 +793,7 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD fprintf(out, "package android.util;\n"); fprintf(out, "\n"); fprintf(out, "import android.os.WorkSource;\n"); fprintf(out, "import android.util.SparseArray;\n"); fprintf(out, "import java.util.ArrayList;\n"); fprintf(out, "\n"); fprintf(out, "\n"); Loading Loading @@ -837,6 +885,8 @@ jni_array_type_name(java_type_t type) switch (type) { case JAVA_TYPE_INT: return "jintArray"; case JAVA_TYPE_FLOAT: return "jfloatArray"; case JAVA_TYPE_STRING: return "jobjectArray"; default: Loading Loading @@ -873,6 +923,9 @@ jni_function_name(const string& method_name, const vector<java_type_t>& signatur case JAVA_TYPE_ATTRIBUTION_CHAIN: result += "_AttributionChain"; break; case JAVA_TYPE_KEY_VALUE_PAIR: result += "_KeyValuePairs"; break; default: result += "_UNKNOWN"; break; Loading Loading @@ -914,6 +967,8 @@ jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &att result += "["; result += java_type_signature(chainField.javaType); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { result += "Landroid/util/SparseArray;"; } else { result += java_type_signature(*arg); } Loading @@ -922,6 +977,43 @@ jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &att return result; } static void write_key_value_map_jni(FILE* out) { fprintf(out, " std::map<int, int64_t> int64_t_map;\n"); fprintf(out, " std::map<int, float> float_map;\n"); fprintf(out, " std::map<int, char const*> string_map;\n\n"); fprintf(out, " jclass jmap_class = env->FindClass(\"android/util/SparseArray\");\n"); fprintf(out, " jmethodID jget_size_method = env->GetMethodID(jmap_class, \"size\", \"()I\");\n"); fprintf(out, " jmethodID jget_key_method = env->GetMethodID(jmap_class, \"keyAt\", \"(I)I\");\n"); fprintf(out, " jmethodID jget_value_method = env->GetMethodID(jmap_class, \"valueAt\", \"(I)Ljava/lang/Object;\");\n\n"); fprintf(out, " std::vector<std::unique_ptr<ScopedUtfChars>> scoped_ufs;\n\n"); fprintf(out, " jclass jlong_class = env->FindClass(\"java/lang/Long\");\n"); fprintf(out, " jclass jfloat_class = env->FindClass(\"java/lang/Float\");\n"); fprintf(out, " jclass jstring_class = env->FindClass(\"java/lang/String\");\n"); fprintf(out, " jmethodID jget_long_method = env->GetMethodID(jlong_class, \"longValue\", \"()J\");\n"); fprintf(out, " jmethodID jget_float_method = env->GetMethodID(jfloat_class, \"floatValue\", \"()F\");\n\n"); fprintf(out, " jint jsize = env->CallIntMethod(value_map, jget_size_method);\n"); fprintf(out, " for(int i = 0; i < jsize; i++) {\n"); fprintf(out, " jint key = env->CallIntMethod(value_map, jget_key_method, i);\n"); fprintf(out, " jobject jvalue_obj = env->CallObjectMethod(value_map, jget_value_method, i);\n"); fprintf(out, " if (jvalue_obj == NULL) { continue; }\n"); fprintf(out, " if (env->IsInstanceOf(jvalue_obj, jlong_class)) {\n"); fprintf(out, " int64_t_map[key] = env->CallLongMethod(jvalue_obj, jget_long_method);\n"); fprintf(out, " } else if (env->IsInstanceOf(jvalue_obj, jfloat_class)) {\n"); fprintf(out, " float_map[key] = env->CallFloatMethod(jvalue_obj, jget_float_method);\n"); fprintf(out, " } else if (env->IsInstanceOf(jvalue_obj, jstring_class)) {\n"); fprintf(out, " std::unique_ptr<ScopedUtfChars> utf(new ScopedUtfChars(env, (jstring)jvalue_obj));\n"); fprintf(out, " if (utf->c_str() != NULL) { string_map[key] = utf->c_str(); }\n"); fprintf(out, " scoped_ufs.push_back(std::move(utf));\n"); fprintf(out, " }\n"); fprintf(out, " }\n"); } 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) Loading @@ -942,6 +1034,8 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp fprintf(out, ", %s %s", jni_array_type_name(chainField.javaType), chainField.name.c_str()); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", jobject value_map"); } else { fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex); } Loading @@ -954,6 +1048,7 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp // Prepare strings argIndex = 1; bool hadStringOrChain = false; bool isKeyValuePairAtom = false; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_STRING) { Loading Loading @@ -1006,18 +1101,23 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp } fprintf(out, "\n"); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { isKeyValuePairAtom = true; } argIndex++; } // Emit this to quiet the unused parameter warning if there were no strings or attribution // chains. if (!hadStringOrChain) { if (!hadStringOrChain && !isKeyValuePairAtom) { fprintf(out, " (void)env;\n"); } if (isKeyValuePairAtom) { write_key_value_map_jni(out); } // stats_write call argIndex = 1; fprintf(out, " int ret = android::util::%s(code", cpp_method_name.c_str()); 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++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { Loading @@ -1030,6 +1130,8 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp fprintf(out, ", %s_vec", chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", int64_t_map, string_map, float_map"); } else { const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg"; fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex); Loading Loading @@ -1063,6 +1165,7 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp } argIndex++; } fprintf(out, " return ret;\n"); fprintf(out, "}\n"); Loading Loading
cmds/statsd/src/logd/LogEvent.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,56 @@ bool LogEvent::write(float value) { return false; } bool LogEvent::writeKeyValuePairs(const std::map<int32_t, int64_t>& int_map, const std::map<int32_t, std::string>& string_map, const std::map<int32_t, float>& float_map) { if (mContext) { if (android_log_write_list_begin(mContext) < 0) { return false; } for (const auto& itr : int_map) { if (android_log_write_list_begin(mContext) < 0) { return false; } write(itr.first); write(itr.second); if (android_log_write_list_end(mContext) < 0) { return false; } } for (const auto& itr : string_map) { if (android_log_write_list_begin(mContext) < 0) { return false; } write(itr.first); write(itr.second.c_str()); if (android_log_write_list_end(mContext) < 0) { return false; } } for (const auto& itr : float_map) { if (android_log_write_list_begin(mContext) < 0) { return false; } write(itr.first); write(itr.second); if (android_log_write_list_end(mContext) < 0) { return false; } } if (android_log_write_list_end(mContext) < 0) { return false; } return true; } return false; } bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) { if (mContext) { if (android_log_write_list_begin(mContext) < 0) { Loading Loading @@ -225,6 +275,7 @@ void LogEvent::init(android_log_context context) { int i = 0; int depth = -1; int pos[] = {1, 1, 1}; bool isKeyValuePairAtom = false; do { elem = android_log_read_next(context); switch ((int)elem.type) { Loading @@ -232,6 +283,7 @@ void LogEvent::init(android_log_context context) { // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id. if (i == 2) { mTagId = elem.data.int32; isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM); } else { if (depth < 0 || depth > 2) { return; Loading @@ -249,6 +301,11 @@ void LogEvent::init(android_log_context context) { return; } // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { pos[depth] = 4; } mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32))); pos[depth]++; Loading @@ -260,6 +317,10 @@ void LogEvent::init(android_log_context context) { return; } // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { pos[depth] = 3; } mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(string(elem.data.string, elem.len)))); Loading @@ -274,6 +335,10 @@ void LogEvent::init(android_log_context context) { ALOGE("Depth > 2. Not supported!"); return; } // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { pos[depth] = 2; } mValues.push_back( FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64))); Loading
cmds/statsd/src/logd/LogEvent.h +3 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,9 @@ public: bool write(float value); bool write(const std::vector<AttributionNodeInternal>& nodes); bool write(const AttributionNodeInternal& node); bool writeKeyValuePairs(const std::map<int32_t, int64_t>& int_map, const std::map<int32_t, std::string>& string_map, const std::map<int32_t, float>& float_map); /** * Return a string representation of this event. Loading
cmds/statsd/tests/LogEvent_test.cpp +84 −1 Original line number Diff line number Diff line Loading @@ -89,6 +89,89 @@ TEST(LogEventTest, TestLogParsing) { EXPECT_EQ((float)1.1, item7.mValue.float_value); } TEST(LogEventTest, TestKeyValuePairsAtomParsing) { LogEvent event1(83, 2000); std::map<int32_t, int64_t> int_map; std::map<int32_t, std::string> string_map; std::map<int32_t, float> float_map; int_map[11] = 123L; int_map[22] = 345L; string_map[1] = "test2"; string_map[2] = "test1"; float_map[111] = 2.2f; float_map[222] = 1.1f; EXPECT_TRUE(event1.writeKeyValuePairs(int_map, string_map, float_map)); event1.init(); EXPECT_EQ(83, event1.GetTagId()); const auto& items = event1.getValues(); EXPECT_EQ((size_t)12, items.size()); const FieldValue& item0 = event1.getValues()[0]; EXPECT_EQ(0x2010101, item0.mField.getField()); EXPECT_EQ(Type::INT, item0.mValue.getType()); EXPECT_EQ(11, item0.mValue.int_value); const FieldValue& item1 = event1.getValues()[1]; EXPECT_EQ(0x2010182, item1.mField.getField()); EXPECT_EQ(Type::LONG, item1.mValue.getType()); EXPECT_EQ(123L, item1.mValue.long_value); const FieldValue& item2 = event1.getValues()[2]; EXPECT_EQ(0x2010201, item2.mField.getField()); EXPECT_EQ(Type::INT, item2.mValue.getType()); EXPECT_EQ(22, item2.mValue.int_value); const FieldValue& item3 = event1.getValues()[3]; EXPECT_EQ(0x2010282, item3.mField.getField()); EXPECT_EQ(Type::LONG, item3.mValue.getType()); EXPECT_EQ(345L, item3.mValue.long_value); const FieldValue& item4 = event1.getValues()[4]; EXPECT_EQ(0x2010301, item4.mField.getField()); EXPECT_EQ(Type::INT, item4.mValue.getType()); EXPECT_EQ(1, item4.mValue.int_value); const FieldValue& item5 = event1.getValues()[5]; EXPECT_EQ(0x2010383, item5.mField.getField()); EXPECT_EQ(Type::STRING, item5.mValue.getType()); EXPECT_EQ("test2", item5.mValue.str_value); const FieldValue& item6 = event1.getValues()[6]; EXPECT_EQ(0x2010401, item6.mField.getField()); EXPECT_EQ(Type::INT, item6.mValue.getType()); EXPECT_EQ(2, item6.mValue.int_value); const FieldValue& item7 = event1.getValues()[7]; EXPECT_EQ(0x2010483, item7.mField.getField()); EXPECT_EQ(Type::STRING, item7.mValue.getType()); EXPECT_EQ("test1", item7.mValue.str_value); const FieldValue& item8 = event1.getValues()[8]; EXPECT_EQ(0x2010501, item8.mField.getField()); EXPECT_EQ(Type::INT, item8.mValue.getType()); EXPECT_EQ(111, item8.mValue.int_value); const FieldValue& item9 = event1.getValues()[9]; EXPECT_EQ(0x2010584, item9.mField.getField()); EXPECT_EQ(Type::FLOAT, item9.mValue.getType()); EXPECT_EQ(2.2f, item9.mValue.float_value); const FieldValue& item10 = event1.getValues()[10]; EXPECT_EQ(0x2018601, item10.mField.getField()); EXPECT_EQ(Type::INT, item10.mValue.getType()); EXPECT_EQ(222, item10.mValue.int_value); const FieldValue& item11 = event1.getValues()[11]; EXPECT_EQ(0x2018684, item11.mField.getField()); EXPECT_EQ(Type::FLOAT, item11.mValue.getType()); EXPECT_EQ(1.1f, item11.mValue.float_value); } TEST(LogEventTest, TestLogParsing2) { LogEvent event1(1, 2000); Loading Loading @@ -158,7 +241,7 @@ TEST(LogEventTest, TestLogParsing2) { EXPECT_EQ((float)1.1, item7.mValue.float_value); } TEST(LogEventTest, TestKeyValuePairsAtomParsing) { TEST(LogEventTest, TestKeyValuePairsEvent) { std::map<int32_t, int64_t> int_map; std::map<int32_t, std::string> string_map; std::map<int32_t, float> float_map; Loading
tools/stats_log_api_gen/Collation.cpp +0 −10 Original line number Diff line number Diff line Loading @@ -184,16 +184,6 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, expectedNumber++; } // Skips the key value pair atom. 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_KEY_VALUE_PAIR) { return 0; } } // Check that only allowed types are present. Remove any invalid ones. for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin(); it != fields.end(); it++) { Loading
tools/stats_log_api_gen/main.cpp +107 −4 Original line number Diff line number Diff line Loading @@ -235,6 +235,10 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& arg%d_1, " "const std::map<int, char const*>& arg%d_2, " "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } Loading Loading @@ -276,6 +280,30 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, } fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " event.end();\n\n"); } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, " event.begin();\n\n"); fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex); fprintf(out, " event.begin();\n"); fprintf(out, " event << it.first;\n"); fprintf(out, " event << it.second;\n"); fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex); fprintf(out, " event.begin();\n"); fprintf(out, " event << it.first;\n"); fprintf(out, " event << it.second;\n"); fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex); fprintf(out, " event.begin();\n"); fprintf(out, " event << it.first;\n"); fprintf(out, " event << it.second;\n"); fprintf(out, " event.end();\n"); fprintf(out, " }\n"); fprintf(out, " event.end();\n\n"); } else { if (*arg == JAVA_TYPE_STRING) { Loading Loading @@ -317,6 +345,10 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& arg%d_1, " "const std::map<int, char const*>& arg%d_2, " "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } Loading @@ -343,6 +375,8 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms, chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", arg%d_1, arg%d_2, arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", arg%d", argIndex); } Loading Loading @@ -496,6 +530,11 @@ static void write_cpp_usage( chainField.name.c_str(), chainField.name.c_str()); } } } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& %s_int" ", const std::map<int, char const*>& %s_str" ", const std::map<int, float>& %s_float", field->name.c_str(), field->name.c_str(), field->name.c_str()); } else { fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str()); } Loading Loading @@ -523,6 +562,10 @@ static void write_cpp_method_header( chainField.name.c_str(), chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", const std::map<int, int64_t>& arg%d_1, " "const std::map<int, char const*>& arg%d_2, " "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex); } else { fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); } Loading Loading @@ -637,6 +680,8 @@ static void write_java_usage(FILE* out, const string& method_name, const string& field != atom.fields.end(); field++) { if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { fprintf(out, ", android.os.WorkSource workSource"); } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", SparseArray<Object> value_map"); } else { fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str()); } Loading @@ -658,6 +703,8 @@ static void write_java_method( fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", SparseArray<Object> value_map"); } else { fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); } Loading Loading @@ -746,6 +793,7 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD fprintf(out, "package android.util;\n"); fprintf(out, "\n"); fprintf(out, "import android.os.WorkSource;\n"); fprintf(out, "import android.util.SparseArray;\n"); fprintf(out, "import java.util.ArrayList;\n"); fprintf(out, "\n"); fprintf(out, "\n"); Loading Loading @@ -837,6 +885,8 @@ jni_array_type_name(java_type_t type) switch (type) { case JAVA_TYPE_INT: return "jintArray"; case JAVA_TYPE_FLOAT: return "jfloatArray"; case JAVA_TYPE_STRING: return "jobjectArray"; default: Loading Loading @@ -873,6 +923,9 @@ jni_function_name(const string& method_name, const vector<java_type_t>& signatur case JAVA_TYPE_ATTRIBUTION_CHAIN: result += "_AttributionChain"; break; case JAVA_TYPE_KEY_VALUE_PAIR: result += "_KeyValuePairs"; break; default: result += "_UNKNOWN"; break; Loading Loading @@ -914,6 +967,8 @@ jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &att result += "["; result += java_type_signature(chainField.javaType); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { result += "Landroid/util/SparseArray;"; } else { result += java_type_signature(*arg); } Loading @@ -922,6 +977,43 @@ jni_function_signature(const vector<java_type_t>& signature, const AtomDecl &att return result; } static void write_key_value_map_jni(FILE* out) { fprintf(out, " std::map<int, int64_t> int64_t_map;\n"); fprintf(out, " std::map<int, float> float_map;\n"); fprintf(out, " std::map<int, char const*> string_map;\n\n"); fprintf(out, " jclass jmap_class = env->FindClass(\"android/util/SparseArray\");\n"); fprintf(out, " jmethodID jget_size_method = env->GetMethodID(jmap_class, \"size\", \"()I\");\n"); fprintf(out, " jmethodID jget_key_method = env->GetMethodID(jmap_class, \"keyAt\", \"(I)I\");\n"); fprintf(out, " jmethodID jget_value_method = env->GetMethodID(jmap_class, \"valueAt\", \"(I)Ljava/lang/Object;\");\n\n"); fprintf(out, " std::vector<std::unique_ptr<ScopedUtfChars>> scoped_ufs;\n\n"); fprintf(out, " jclass jlong_class = env->FindClass(\"java/lang/Long\");\n"); fprintf(out, " jclass jfloat_class = env->FindClass(\"java/lang/Float\");\n"); fprintf(out, " jclass jstring_class = env->FindClass(\"java/lang/String\");\n"); fprintf(out, " jmethodID jget_long_method = env->GetMethodID(jlong_class, \"longValue\", \"()J\");\n"); fprintf(out, " jmethodID jget_float_method = env->GetMethodID(jfloat_class, \"floatValue\", \"()F\");\n\n"); fprintf(out, " jint jsize = env->CallIntMethod(value_map, jget_size_method);\n"); fprintf(out, " for(int i = 0; i < jsize; i++) {\n"); fprintf(out, " jint key = env->CallIntMethod(value_map, jget_key_method, i);\n"); fprintf(out, " jobject jvalue_obj = env->CallObjectMethod(value_map, jget_value_method, i);\n"); fprintf(out, " if (jvalue_obj == NULL) { continue; }\n"); fprintf(out, " if (env->IsInstanceOf(jvalue_obj, jlong_class)) {\n"); fprintf(out, " int64_t_map[key] = env->CallLongMethod(jvalue_obj, jget_long_method);\n"); fprintf(out, " } else if (env->IsInstanceOf(jvalue_obj, jfloat_class)) {\n"); fprintf(out, " float_map[key] = env->CallFloatMethod(jvalue_obj, jget_float_method);\n"); fprintf(out, " } else if (env->IsInstanceOf(jvalue_obj, jstring_class)) {\n"); fprintf(out, " std::unique_ptr<ScopedUtfChars> utf(new ScopedUtfChars(env, (jstring)jvalue_obj));\n"); fprintf(out, " if (utf->c_str() != NULL) { string_map[key] = utf->c_str(); }\n"); fprintf(out, " scoped_ufs.push_back(std::move(utf));\n"); fprintf(out, " }\n"); fprintf(out, " }\n"); } 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) Loading @@ -942,6 +1034,8 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp fprintf(out, ", %s %s", jni_array_type_name(chainField.javaType), chainField.name.c_str()); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", jobject value_map"); } else { fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex); } Loading @@ -954,6 +1048,7 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp // Prepare strings argIndex = 1; bool hadStringOrChain = false; bool isKeyValuePairAtom = false; for (vector<java_type_t>::const_iterator arg = signature->begin(); arg != signature->end(); arg++) { if (*arg == JAVA_TYPE_STRING) { Loading Loading @@ -1006,18 +1101,23 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp } fprintf(out, "\n"); } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { isKeyValuePairAtom = true; } argIndex++; } // Emit this to quiet the unused parameter warning if there were no strings or attribution // chains. if (!hadStringOrChain) { if (!hadStringOrChain && !isKeyValuePairAtom) { fprintf(out, " (void)env;\n"); } if (isKeyValuePairAtom) { write_key_value_map_jni(out); } // stats_write call argIndex = 1; fprintf(out, " int ret = android::util::%s(code", cpp_method_name.c_str()); 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++) { if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { Loading @@ -1030,6 +1130,8 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp fprintf(out, ", %s_vec", chainField.name.c_str()); } } } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { fprintf(out, ", int64_t_map, string_map, float_map"); } else { const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg"; fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex); Loading Loading @@ -1063,6 +1165,7 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp } argIndex++; } fprintf(out, " return ret;\n"); fprintf(out, "}\n"); Loading