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

Commit b2a92d14 authored by Muhammad Qureshi's avatar Muhammad Qureshi Committed by android-build-merger
Browse files

Merge "Use StatsEvent in Java autogenerated code"

am: 94e980f8

Change-Id: I2a6b36c74055ec55a1f2dcca082b6c343e352095
parents fca0df02 94e980f8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -21,9 +21,13 @@ cc_binary_host {
    name: "stats-log-api-gen",
    srcs: [
        "Collation.cpp",
        "java_writer.cpp",
        "java_writer_q.cpp",
        "main.cpp",
        "utils.cpp",
    ],
    cflags: [
        "-DSTATS_SCHEMA_LEGACY",
        "-Wall",
        "-Werror",
    ],
+286 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "java_writer.h"
#include "java_writer_q.h"
#include "utils.h"

namespace android {
namespace stats_log_api_gen {

static int write_java_q_logger_class(
        FILE* out,
        const map<vector<java_type_t>, set<string>>& signatures_to_modules,
        const AtomDecl &attributionDecl,
        const string& moduleName
        ) {
    fprintf(out, "\n");
    fprintf(out, "    // Write logging helper methods for statsd in Q and earlier.\n");
    fprintf(out, "    private static class QLogger {\n");

    write_java_q_logging_constants(out, "        ");

    // Print Q write methods.
    fprintf(out, "\n");
    fprintf(out, "        // Write methods.\n");
    write_java_methods_q_schema(
            out, signatures_to_modules, attributionDecl, moduleName, "        ");

    fprintf(out, "    }\n");
    return 0;
}


static int write_java_methods(
        FILE* out,
        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;
        }

        // Print method signature.
        if (DEFAULT_MODULE_NAME == moduleName) {
            fprintf(out, "    /** @hide */\n");
        }
        fprintf(out, "    public static void write(int code");
        vector<java_type_t> signature = signature_to_modules_it->first;
        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 if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
                fprintf(out, ", SparseArray<Object> valueMap");
            } else {
                fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
            }
            argIndex++;
        }
        fprintf(out, ") {\n");

        // Print method body.
        string indent("");
        if (DEFAULT_MODULE_NAME != moduleName) {
            fprintf(out, "        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n");
            indent = "    ";
        }

        // Start StatsEvent.Builder.
        fprintf(out, "%s        final StatsEvent.Builder builder = StatsEvent.newBuilder();\n",
                indent.c_str());

        // Write atom code.
        fprintf(out, "%s        builder.setAtomId(code);\n", indent.c_str());

        // Write the args.
        argIndex = 1;
        for (vector<java_type_t>::const_iterator arg = signature.begin();
                arg != signature.end(); arg++) {
            switch (*arg) {
            case JAVA_TYPE_BOOLEAN:
                fprintf(out, "%s        builder.writeBoolean(arg%d);\n", indent.c_str(), argIndex);
                break;
            case JAVA_TYPE_INT:
            case JAVA_TYPE_ENUM:
                fprintf(out, "%s        builder.writeInt(arg%d);\n", indent.c_str(), argIndex);
                break;
            case JAVA_TYPE_FLOAT:
                fprintf(out, "%s        builder.writeFloat(arg%d);\n", indent.c_str(), argIndex);
                break;
            case JAVA_TYPE_LONG:
                fprintf(out, "%s        builder.writeLong(arg%d);\n", indent.c_str(), argIndex);
                break;
            case JAVA_TYPE_STRING:
                fprintf(out, "%s        builder.writeString(arg%d);\n", indent.c_str(), argIndex);
                break;
            case JAVA_TYPE_BYTE_ARRAY:
                fprintf(out, "%s        builder.writeByteArray(arg%d);\n",
                        indent.c_str(), argIndex);
                break;
            case JAVA_TYPE_ATTRIBUTION_CHAIN:
            {
                const char* uidName = attributionDecl.fields.front().name.c_str();
                const char* tagName = attributionDecl.fields.back().name.c_str();

                fprintf(out, "%s        builder.writeAttributionChain(%s, %s);\n",
                        indent.c_str(), uidName, tagName);
                break;
            }
            case JAVA_TYPE_KEY_VALUE_PAIR:
                fprintf(out, "\n");
                fprintf(out,
                        "%s        // Write KeyValuePairs.\n", indent.c_str());
                fprintf(out,
                        "%s        final int count = valueMap.size();\n", indent.c_str());
                fprintf(out,
                        "%s        final SparseIntArray intMap = new SparseIntArray();\n",
                        indent.c_str());
                fprintf(out,
                        "%s        final SparseLongArray longMap = new SparseLongArray();\n",
                        indent.c_str());
                fprintf(out,
                        "%s        final SparseArray<String> stringMap = new SparseArray<>();\n",
                        indent.c_str());
                fprintf(out,
                        "%s        final SparseArray<Float> floatMap = new SparseArray<>();\n",
                        indent.c_str());
                fprintf(out,
                        "%s        for (int i = 0; i < count; i++) {\n", indent.c_str());
                fprintf(out,
                        "%s            final int key = valueMap.keyAt(i);\n", indent.c_str());
                fprintf(out,
                        "%s            final Object value = valueMap.valueAt(i);\n",
                        indent.c_str());
                fprintf(out,
                        "%s            if (value instanceof Integer) {\n", indent.c_str());
                fprintf(out,
                        "%s                intMap.put(key, (Integer) value);\n", indent.c_str());
                fprintf(out,
                        "%s            } else if (value instanceof Long) {\n", indent.c_str());
                fprintf(out,
                        "%s                longMap.put(key, (Long) value);\n", indent.c_str());
                fprintf(out,
                        "%s            } else if (value instanceof String) {\n", indent.c_str());
                fprintf(out,
                        "%s                stringMap.put(key, (String) value);\n", indent.c_str());
                fprintf(out,
                        "%s            } else if (value instanceof Float) {\n", indent.c_str());
                fprintf(out,
                        "%s                floatMap.put(key, (Float) value);\n", indent.c_str());
                fprintf(out,
                        "%s            }\n", indent.c_str());
                fprintf(out,
                        "%s        }\n", indent.c_str());
                fprintf(out,
                        "%s        builder.writeKeyValuePairs("
                        "intMap, longMap, stringMap, floatMap);\n", indent.c_str());
                break;
            default:
                // Unsupported types: OBJECT, DOUBLE.
                fprintf(stderr, "Encountered unsupported type.");
                return 1;
            }
            argIndex++;
        }

        fprintf(out, "\n");
        fprintf(out, "%s        StatsLog.write(builder.build());\n", indent.c_str());

        // Add support for writing using Q schema if this is not the default module.
        if (DEFAULT_MODULE_NAME != moduleName) {
            fprintf(out, "        } else {\n");
            fprintf(out, "            QLogger.write(code");
            argIndex = 1;
            for (vector<java_type_t>::const_iterator arg = signature.begin();
                arg != signature.end(); arg++) {
                if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
                    const char* uidName = attributionDecl.fields.front().name.c_str();
                    const char* tagName = attributionDecl.fields.back().name.c_str();
                    fprintf(out, ", %s, %s", uidName, tagName);
                } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
                    // Module logging does not yet support key value pair.
                    fprintf(stderr, "Module logging does not yet support key value pair.\n");
                    return 1;
                } else {
                    fprintf(out, ", arg%d", argIndex);
                }
                argIndex++;
            }
            fprintf(out, ");\n");
            fprintf(out, "        }\n"); // if
        }

        fprintf(out, "    }\n"); // method
        fprintf(out, "\n");
    }
    return 0;

}

int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
                                    const string& moduleName, const string& javaClass,
                                    const string& javaPackage) {
    // Print prelude
    fprintf(out, "// This file is autogenerated\n");
    fprintf(out, "\n");
    fprintf(out, "package %s;\n", javaPackage.c_str());
    fprintf(out, "\n");
    fprintf(out, "\n");
    fprintf(out, "import android.os.Build;\n");
    fprintf(out, "import android.os.SystemClock;\n");

    if (DEFAULT_MODULE_NAME == moduleName) {
        // Mainline modules don't use WorkSource logging.
        fprintf(out, "import android.os.WorkSource;\n");

        // SparseArray is used for writing KeyValuePairs; not supported for Mainline modules.
        fprintf(out, "import android.util.SparseArray;\n");
        fprintf(out, "import android.util.SparseIntArray;\n");
        fprintf(out, "import android.util.SparseLongArray;\n");
    }

    fprintf(out, "import android.util.StatsEvent;\n");
    fprintf(out, "import android.util.StatsLog;\n");

    if (DEFAULT_MODULE_NAME == moduleName) {
        // List is used for WorkSource writing. Only needed for default module.
        fprintf(out, "\n");
        fprintf(out, "import java.util.ArrayList;\n");
    }

    fprintf(out, "\n");
    fprintf(out, "\n");
    fprintf(out, "/**\n");
    fprintf(out, " * Utility class for logging statistics events.\n");
    if (DEFAULT_MODULE_NAME == moduleName) {
        fprintf(out, " * @hide\n");
    }
    fprintf(out, " */\n");
    fprintf(out, "public class %s {\n", javaClass.c_str());

    write_java_atom_codes(out, atoms, moduleName);
    write_java_enum_values(out, atoms, moduleName);

    int errors = 0;

    // Print write methods.
    fprintf(out, "    // Write methods\n");
    errors += write_java_methods(out, atoms.signatures_to_modules, attributionDecl, moduleName);
    errors += write_java_non_chained_methods(
            out, atoms.non_chained_signatures_to_modules, moduleName);
    if (DEFAULT_MODULE_NAME == moduleName) {
        errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName);
    } else {
        errors += write_java_q_logger_class(
                out, atoms.signatures_to_modules, attributionDecl, moduleName);
    }

    fprintf(out, "}\n");

    return errors;
}

}  // namespace stats_log_api_gen
}  // namespace android
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "Collation.h"

#include <map>
#include <set>
#include <vector>

#include <stdio.h>
#include <string.h>

namespace android {
namespace stats_log_api_gen {

using namespace std;

int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
                                    const string& moduleName, const string& javaClass,
                                    const string& javaPackage
);

}  // namespace stats_log_api_gen
}  // namespace android
+470 −0

File added.

Preview size limit exceeded, changes collapsed.

+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "Collation.h"

#include <map>
#include <set>
#include <vector>

#include <stdio.h>
#include <string.h>

namespace android {
namespace stats_log_api_gen {

using namespace std;

void write_java_q_logging_constants(FILE* out, const string& indent);

int write_java_methods_q_schema(
        FILE* out,
        const map<vector<java_type_t>, set<string>>& signatures_to_modules,
        const AtomDecl &attributionDecl,
        const string& moduleName,
        const string& indent
);

void write_java_helpers_for_q_schema_methods(
        FILE * out,
        const AtomDecl &attributionDecl,
        const int requiredHelpers,
        const string& indent
);

#if defined(STATS_SCHEMA_LEGACY)
int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl);

int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
                                    const string& moduleName, const string& javaClass,
                                    const string& javaPackage);
#endif
}  // namespace stats_log_api_gen
}  // namespace android
Loading