gen_log: pass a struct to a logging callback
gen_log now uses a struct instead of Json object.
- no json deps
- simplify the build system
- smaller artifacts
- netd_aidl_interface-V5-cpp.so: 634692 -> 483484
Bug: 161439795
Bug: 172188290
Test: aidl_integration_test
Change-Id: I7de3e10b1221bf83ce46e6636c5aad1457515f21
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 2d69a4a..6ac1d30 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -32,6 +32,22 @@
namespace aidl {
namespace cpp {
+char kTransactionLogStruct[] = R"(struct TransactionLog {
+ double duration_ms;
+ std::string interface_name;
+ std::string method_name;
+ const void* proxy_address;
+ const void* stub_address;
+ std::vector<std::pair<std::string, std::string>> input_args;
+ std::vector<std::pair<std::string, std::string>> output_args;
+ std::string result;
+ std::string exception_message;
+ int32_t exception_code;
+ int32_t transaction_error;
+ int32_t service_specific_error_code;
+};
+)";
+
char kToStringHelper[] = R"(template <typename _T> class _has_toString {
template <typename _U> static std::true_type __has_toString(decltype(&_U::toString));
template <typename _U> static std::false_type __has_toString(...);
@@ -195,174 +211,26 @@
return ToStringRaw(type, expr);
}
-struct TypeInfo {
- // name of the type in C++ output
- std::string cpp_name;
-
- // function that writes an expression to convert a variable to a Json::Value
- // object
- std::function<void(CodeWriter& w, const AidlTypeSpecifier& type, const string& var_name,
- bool isNdk)>
- toJsonValueExpr;
-};
-
-const static std::unordered_map<std::string, TypeInfo> kTypeInfoMap = {
- {"void", {"void", nullptr}},
- {"boolean",
- {
- "bool",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool) {
- c << "Json::Value(" << var_name << "? \"true\" : \"false\")";
- },
- }},
- {"byte",
- {
- "int8_t",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool) {
- c << "Json::Value(" << var_name << ")";
- },
- }},
- {"char",
- {
- "char16_t",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool isNdk) {
- if (isNdk) {
- c << "Json::Value(" << var_name << ")";
- } else {
- c << "Json::Value(std::string(android::String8(&" << var_name << ", 1)))";
- }
- },
- }},
- {"int",
- {
- "int32_t",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool) {
- c << "Json::Value(" << var_name << ")";
- },
- }},
- {"long",
- {
- "int64_t",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool) {
- c << "Json::Value(static_cast<Json::Int64>(" << var_name << "))";
- },
- }},
- {"float",
- {
- "float",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool) {
- c << "Json::Value(" << var_name << ")";
- },
- }},
- {"double",
- {
- "double",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool) {
- c << "Json::Value(" << var_name << ")";
- },
- }},
- {"String",
- {
- "std::string",
- [](CodeWriter& c, const AidlTypeSpecifier&, const string& var_name, bool) {
- c << "Json::Value(" << var_name << ")";
- },
- }}
- // missing List, Map, ParcelFileDescriptor, IBinder
-};
-
-const static TypeInfo kTypeInfoForDefinedType{
- "<<parcelable>>", // pseudo-name for parcelable types
- [](CodeWriter& c, const AidlTypeSpecifier& type, const string& var_name, bool) {
- c << ToString(type, var_name);
- }};
-
-TypeInfo GetTypeInfo(const AidlTypeSpecifier& aidl) {
- AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
- const string& aidl_name = aidl.GetName();
-
- if (AidlTypenames::IsBuiltinTypename(aidl_name)) {
- auto it = kTypeInfoMap.find(aidl_name);
- if (it != kTypeInfoMap.end()) {
- return it->second;
- }
- return {};
- }
-
- const AidlDefinedType* defined_type = aidl.GetDefinedType();
- AIDL_FATAL_IF(defined_type == NULL, aidl) << aidl.ToString();
- if (defined_type->AsStructuredParcelable() || defined_type->AsEnumDeclaration() ||
- defined_type->AsUnionDeclaration()) {
- return kTypeInfoForDefinedType;
- }
-
- // skip interface types
- return {};
-}
-
-inline bool CanWriteLog(const TypeInfo& t) {
- return t.cpp_name != "";
-}
-
-bool CanWriteLog(const AidlTypeSpecifier& aidl) {
- return CanWriteLog(GetTypeInfo(aidl));
-}
-
-void WriteLogFor(CodeWriter& writer, const AidlTypeSpecifier& type, const std::string& name,
- bool isPointer, const std::string& log, bool isNdk) {
- const TypeInfo info = GetTypeInfo(type);
- if (!CanWriteLog(info)) {
- return;
- }
-
- const string var_object_expr = ((isPointer ? "*" : "")) + name;
- if (type.IsArray()) {
- const AidlTypeSpecifier& base_type = type.ArrayBase();
- writer << log << " = Json::Value(Json::arrayValue);\n";
- writer << "for (const auto& v: " << var_object_expr << ") " << log << ".append(";
- info.toJsonValueExpr(writer, base_type, "v", isNdk);
- writer << ");";
- } else {
- writer << log << " = ";
- info.toJsonValueExpr(writer, type, var_object_expr, isNdk);
- writer << ";";
- }
- writer << "\n";
-}
-
-void WriteLogForArguments(CodeWriterPtr& writer, const AidlArgument& a, bool isServer,
- string logVarName, bool isNdk) {
- if (!CanWriteLog(a.GetType())) {
- return;
- }
- string logElementVarName = "_log_arg_element";
- (*writer) << "{\n";
- (*writer).Indent();
- (*writer) << "Json::Value " << logElementVarName << "(Json::objectValue);\n";
- string varName = isServer || isNdk ? BuildVarName(a) : a.GetName();
- (*writer) << logElementVarName << "[\"name\"] = \"" << varName << "\";\n";
-
- bool isPointer = a.IsOut() && !isServer;
- WriteLogFor(*(writer.get()), a.GetType(), varName, isPointer, logElementVarName + "[\"value\"]",
- isNdk);
- (*writer) << logVarName << ".append(" << logElementVarName << ");\n";
- (*writer) << "}\n";
- (*writer).Dedent();
+void WriteLogForArgument(CodeWriter& w, const AidlArgument& a, bool is_server,
+ const string& log_var, bool is_ndk) {
+ const string var_name = is_server || is_ndk ? BuildVarName(a) : a.GetName();
+ const bool is_pointer = a.IsOut() && !is_server;
+ const string value_expr = (is_pointer ? "*" : "") + var_name;
+ w << log_var
+ << ".emplace_back(\"" + var_name + "\", " + ToString(a.GetType(), value_expr) + ");\n";
}
const string GenLogBeforeExecute(const string className, const AidlMethod& method, bool isServer,
bool isNdk) {
string code;
CodeWriterPtr writer = CodeWriter::ForString(&code);
- (*writer) << "Json::Value _log_input_args(Json::arrayValue);\n";
+ (*writer) << className << "::TransactionLog _transaction_log;\n";
(*writer) << "if (" << className << "::logFunc != nullptr) {\n";
(*writer).Indent();
- for (const auto& a : method.GetArguments()) {
- if (a->IsIn()) {
- WriteLogForArguments(writer, *a, isServer, "_log_input_args", isNdk);
- }
+ for (const auto& a : method.GetInArguments()) {
+ WriteLogForArgument(*writer, *a, isServer, "_transaction_log.input_args", isNdk);
}
(*writer).Dedent();
@@ -381,95 +249,45 @@
(*writer) << "if (" << className << "::logFunc != nullptr) {\n";
(*writer).Indent();
-
- // Write the log as a Json object. For example,
- //
- // Json log object for following interface description
- //
- // package foo.bar;
- // interface IFoo {
- // String TestMethod(int arg1, inout String[] arg2, out double arg3);
- // }
- //
- // would be:
- //
- // {
- // duration_ms: 100.42,
- // interface_name: "foo.bar.IFoo",
- // method_name: "TestMethod",
- // (proxy|stub)_address: "0x12345678",
- // input_args: [
- // {name: "arg1", value: 30,},
- // {name: "arg2", value: ["apple", "grape"],},
- // ],
- // output_args: [
- // {name: "arg2", value: ["mango", "banana"],},
- // {name: "arg3", value: "10.5",},
- // ],
- // _aidl_return: "ok",
- // binder_status: {
- // exception_code: -8,
- // exception_message: "Something wrong",
- // transaction_error: 0,
- // service_specific_error_code: -42,
- // },
- // }
+ const auto address = (isNdk && isServer) ? "_aidl_impl.get()" : "static_cast<const void*>(this)";
(*writer) << "auto _log_end = std::chrono::steady_clock::now();\n";
- (*writer) << "Json::Value _log_transaction(Json::objectValue);\n";
- (*writer) << "_log_transaction[\"duration_ms\"] = "
- << "std::chrono::duration<double, std::milli>(_log_end - "
- "_log_start).count();\n";
- (*writer) << "_log_transaction[\"interface_name\"] = "
- << "Json::Value(\"" << interface.GetCanonicalName() << "\");\n";
- (*writer) << "_log_transaction[\"method_name\"] = "
- << "Json::Value(\"" << method.GetName() << "\");\n";
+ (*writer) << "_transaction_log.duration_ms = std::chrono::duration<double, std::milli>(_log_end "
+ "- _log_start).count();\n";
+ (*writer) << "_transaction_log.interface_name = \"" << interface.GetCanonicalName() << "\";\n";
+ (*writer) << "_transaction_log.method_name = \"" << method.GetName() << "\";\n";
+ (*writer) << "_transaction_log.stub_address = " << (isServer ? address : "nullptr") << ";\n";
+ (*writer) << "_transaction_log.proxy_address = " << (isServer ? "nullptr" : address) << ";\n";
- (*writer) << "_log_transaction[\"" << (isServer ? "stub_address" : "proxy_address") << "\"] = ";
- (*writer) << "Json::Value("
- << "(std::ostringstream() << "
- << (isNdk && isServer ? "_aidl_impl" : "static_cast<const void*>(this)") << ").str()"
- << ");\n";
- (*writer) << "_log_transaction[\"input_args\"] = _log_input_args;\n";
- (*writer) << "Json::Value _log_output_args(Json::arrayValue);\n";
-
- (*writer) << "Json::Value _log_status(Json::objectValue);\n";
if (isNdk) {
- (*writer) << "_log_status[\"exception_code\"] = Json::Value(AStatus_getExceptionCode("
- << statusVarName << ".get()));\n";
- (*writer) << "_log_status[\"exception_message\"] = Json::Value(AStatus_getMessage("
- << statusVarName << ".get()));\n";
- (*writer) << "_log_status[\"transaction_error\"] = Json::Value(AStatus_getStatus("
- << statusVarName << ".get()));\n";
- (*writer) << "_log_status[\"service_specific_error_code\"] = "
- "Json::Value(AStatus_getServiceSpecificError("
- << statusVarName << ".get()));\n";
+ (*writer) << "_transaction_log.exception_code = AStatus_getExceptionCode(" << statusVarName
+ << ".get());\n";
+ (*writer) << "_transaction_log.exception_message = AStatus_getMessage(" << statusVarName
+ << ".get());\n";
+ (*writer) << "_transaction_log.transaction_error = AStatus_getStatus(" << statusVarName
+ << ".get());\n";
+ (*writer) << "_transaction_log.service_specific_error_code = AStatus_getServiceSpecificError("
+ << statusVarName << ".get());\n";
} else {
- (*writer) << "_log_status[\"exception_code\"] = Json::Value(" << statusVarName
- << ".exceptionCode());\n";
- (*writer) << "_log_status[\"exception_message\"] = Json::Value(" << statusVarName
- << ".exceptionMessage());\n";
- (*writer) << "_log_status[\"transaction_error\"] = Json::Value(" << statusVarName
- << ".transactionError());\n";
- (*writer) << "_log_status[\"service_specific_error_code\"] = Json::Value(" << statusVarName
- << ".serviceSpecificErrorCode());\n";
+ (*writer) << "_transaction_log.exception_code = " << statusVarName << ".exceptionCode();\n";
+ (*writer) << "_transaction_log.exception_message = " << statusVarName
+ << ".exceptionMessage();\n";
+ (*writer) << "_transaction_log.transaction_error = " << statusVarName
+ << ".transactionError();\n";
+ (*writer) << "_transaction_log.service_specific_error_code = " << statusVarName
+ << ".serviceSpecificErrorCode();\n";
}
- (*writer) << "_log_transaction[\"binder_status\"] = _log_status;\n";
-
for (const auto& a : method.GetOutArguments()) {
- WriteLogForArguments(writer, *a, isServer, "_log_output_args", isNdk);
+ WriteLogForArgument(*writer, *a, isServer, "_transaction_log.output_args", isNdk);
}
- (*writer) << "_log_transaction[\"output_args\"] = _log_output_args;\n";
-
if (method.GetType().GetName() != "void") {
- WriteLogFor(*(writer.get()), method.GetType(), returnVarName, !isServer,
- "_log_transaction[\"" + returnVarName + "\"]", isNdk);
+ const string expr = (isServer ? "" : "*") + returnVarName;
+ (*writer) << "_transaction_log.result = " << ToString(method.GetType(), expr) << ";\n";
}
- // call the user-provided function with the Json object for the entire
- // transaction
- (*writer) << className << "::logFunc(_log_transaction);\n";
+ // call the user-provided function with the transaction log object
+ (*writer) << className << "::logFunc(_transaction_log);\n";
(*writer).Dedent();
(*writer) << "}\n";