Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a903bdb authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Interface of writing key value pair atom to socket and parsing from statsd."

parents 31aa239b e124e425
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -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) {
@@ -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) {
@@ -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;
@@ -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]++;
@@ -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))));

@@ -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)));

+3 −0
Original line number Diff line number Diff line
@@ -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.
+84 −1
Original line number Diff line number Diff line
@@ -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);

@@ -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;
+0 −10
Original line number Diff line number Diff line
@@ -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++) {
+107 −4
Original line number Diff line number Diff line
@@ -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);
            }
@@ -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) {
@@ -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);
           }
@@ -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);
           }
@@ -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());
        }
@@ -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);
            }
@@ -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());
        }
@@ -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);
            }
@@ -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");
@@ -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:
@@ -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;
@@ -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);
        }
@@ -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)
@@ -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);
            }
@@ -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) {
@@ -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) {
@@ -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);
@@ -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");