aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Huang <huangluke@google.com>2019-05-09 11:48:12 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-05-09 11:48:12 +0000
commit1844e2f3dc98ec3dc1fa46d4db594865891163e4 (patch)
treee8d4be599a6ae43f524387077a2057ed1304b3d6
parente308abd33006e46fc978ff7881bf43222afbca95 (diff)
parentba72499d84f4eec3bdc1ad725dc47179c4bf16f6 (diff)
downloadaidl-1844e2f3dc98ec3dc1fa46d4db594865891163e4.tar.gz
Merge changes from topic "b/126501406" into qt-dev
* changes: AIDL NDK logger bugfix Log supporting for binder ndk
-rw-r--r--Android.bp13
-rw-r--r--aidl_to_cpp.cpp113
-rw-r--r--aidl_to_cpp.h4
-rw-r--r--aidl_to_cpp_common.cpp270
-rw-r--r--aidl_to_cpp_common.h6
-rw-r--r--build/aidl_interface.go16
-rw-r--r--build/properties.go1
-rw-r--r--generate_cpp.cpp152
-rw-r--r--generate_ndk.cpp67
-rw-r--r--options.cpp4
-rw-r--r--tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl14
11 files changed, 381 insertions, 279 deletions
diff --git a/Android.bp b/Android.bp
index 268ece1d..e60468e4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -251,3 +251,16 @@ aidl_interface {
},
},
}
+
+aidl_interface {
+ name: "aidl_test_loggable_interface_ndk",
+ local_include_dir: "tests",
+ srcs: [
+ "tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl",
+ ],
+ backend: {
+ ndk: {
+ gen_log: true,
+ },
+ },
+} \ No newline at end of file
diff --git a/aidl_to_cpp.cpp b/aidl_to_cpp.cpp
index d5a9f025..61917e99 100644
--- a/aidl_to_cpp.cpp
+++ b/aidl_to_cpp.cpp
@@ -35,119 +35,6 @@ std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::str
return raw_value;
};
-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(const CodeGeneratorContext& c, const string& var_name)> toJsonValueExpr;
-};
-
-const static std::unordered_map<std::string, TypeInfo> kTypeInfoMap = {
- {"void", {"void", nullptr}},
- {"boolean",
- {
- "bool",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(" << var_name << "? \"true\" : \"false\")";
- },
- }},
- {"byte",
- {
- "int8_t",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(" << var_name << ")";
- },
- }},
- {"char",
- {
- "char16_t",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(std::string(android::String8(&" << var_name << ", 1)))";
- },
- }},
- {"int",
- {
- "int32_t",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(" << var_name << ")";
- },
- }},
- {"long",
- {
- "int64_t",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(static_cast<Json::Int64>(" << var_name << "))";
- },
- }},
- {"float",
- {
- "float",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(" << var_name << ")";
- },
- }},
- {"double",
- {
- "double",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(" << var_name << ")";
- },
- }},
- {"String",
- {
- "std::string",
- [](const CodeGeneratorContext& c, const string& var_name) {
- c.writer << "Json::Value(" << var_name << ")";
- },
- }}
- // missing List, Map, ParcelFileDescriptor, IBinder
-};
-
-TypeInfo GetTypeInfo(const AidlTypeSpecifier& aidl) {
- CHECK(aidl.IsResolved()) << aidl.ToString();
- const string& aidl_name = aidl.GetName();
-
- TypeInfo info;
- if (AidlTypenames::IsBuiltinTypename(aidl_name)) {
- auto it = kTypeInfoMap.find(aidl_name);
- if (it != kTypeInfoMap.end()) {
- info = it->second;
- }
- }
- // Missing interface and parcelable type
- return info;
-}
-
-inline bool CanWriteLog(const TypeInfo& t) {
- return t.cpp_name != "";
-}
-
-bool CanWriteLog(const AidlTypeSpecifier& aidl) {
- return CanWriteLog(GetTypeInfo(aidl));
-}
-
-void WriteLogFor(const CodeGeneratorContext& c) {
- const TypeInfo info = GetTypeInfo(c.type);
- if (!CanWriteLog(info)) {
- return;
- }
-
- const string var_object_expr = ((c.isPointer ? "*" : "")) + c.name;
- if (c.type.IsArray()) {
- c.writer << c.log << " = Json::Value(Json::arrayValue);\n";
- c.writer << "for (const auto& v: " << var_object_expr << ") " << c.log << ".append(";
- info.toJsonValueExpr(c, "v");
- c.writer << ");";
- } else {
- c.writer << c.log << " = ";
- info.toJsonValueExpr(c, var_object_expr);
- c.writer << ";";
- }
- c.writer << "\n";
-}
-
std::string GetTransactionIdFor(const AidlMethod& method) {
ostringstream output;
diff --git a/aidl_to_cpp.h b/aidl_to_cpp.h
index ca5a6cd0..5c936c9b 100644
--- a/aidl_to_cpp.h
+++ b/aidl_to_cpp.h
@@ -35,10 +35,6 @@ struct CodeGeneratorContext {
const string log; // name of the variable of type Json::Value to write the log into
};
-// Emits code that writes name and value of an argument or the return value to
-// the Json object
-void WriteLogFor(const CodeGeneratorContext& c);
-bool CanWriteLog(const AidlTypeSpecifier& aidl);
std::string GetTransactionIdFor(const AidlMethod& method);
} // namespace cpp
} // namespace aidl
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 9dbcadd0..89783110 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-#include "aidl_to_cpp_common.h"
+#include <unordered_map>
+#include "aidl_to_cpp_common.h"
+#include "logging.h"
#include "os.h"
namespace android {
@@ -84,6 +86,272 @@ string BuildVarName(const AidlArgument& a) {
return prefix + a.GetName();
}
+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 string& var_name, bool isNdk)> toJsonValueExpr;
+};
+
+const static std::unordered_map<std::string, TypeInfo> kTypeInfoMap = {
+ {"void", {"void", nullptr}},
+ {"boolean",
+ {
+ "bool",
+ [](CodeWriter& c, const string& var_name, bool) {
+ c << "Json::Value(" << var_name << "? \"true\" : \"false\")";
+ },
+ }},
+ {"byte",
+ {
+ "int8_t",
+ [](CodeWriter& c, const string& var_name, bool) {
+ c << "Json::Value(" << var_name << ")";
+ },
+ }},
+ {"char",
+ {
+ "char16_t",
+ [](CodeWriter& c, 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 string& var_name, bool) {
+ c << "Json::Value(" << var_name << ")";
+ },
+ }},
+ {"long",
+ {
+ "int64_t",
+ [](CodeWriter& c, const string& var_name, bool) {
+ c << "Json::Value(static_cast<Json::Int64>(" << var_name << "))";
+ },
+ }},
+ {"float",
+ {
+ "float",
+ [](CodeWriter& c, const string& var_name, bool) {
+ c << "Json::Value(" << var_name << ")";
+ },
+ }},
+ {"double",
+ {
+ "double",
+ [](CodeWriter& c, const string& var_name, bool) {
+ c << "Json::Value(" << var_name << ")";
+ },
+ }},
+ {"String",
+ {
+ "std::string",
+ [](CodeWriter& c, const string& var_name, bool) {
+ c << "Json::Value(" << var_name << ")";
+ },
+ }}
+ // missing List, Map, ParcelFileDescriptor, IBinder
+};
+
+TypeInfo GetTypeInfo(const AidlTypeSpecifier& aidl) {
+ CHECK(aidl.IsResolved()) << aidl.ToString();
+ const string& aidl_name = aidl.GetName();
+
+ TypeInfo info;
+ if (AidlTypenames::IsBuiltinTypename(aidl_name)) {
+ auto it = kTypeInfoMap.find(aidl_name);
+ if (it != kTypeInfoMap.end()) {
+ info = it->second;
+ }
+ }
+ // Missing interface and parcelable type
+ return info;
+}
+
+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()) {
+ writer << log << " = Json::Value(Json::arrayValue);\n";
+ writer << "for (const auto& v: " << var_object_expr << ") " << log << ".append(";
+ info.toJsonValueExpr(writer, "v", isNdk);
+ writer << ");";
+ } else {
+ writer << log << " = ";
+ info.toJsonValueExpr(writer, 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();
+}
+
+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) << "if (" << className << "::logFunc != nullptr) {\n";
+ (*writer).Indent();
+
+ for (const auto& a : method.GetArguments()) {
+ if (a->IsIn()) {
+ WriteLogForArguments(writer, *a, isServer, "_log_input_args", isNdk);
+ }
+ }
+
+ (*writer).Dedent();
+ (*writer) << "}\n";
+
+ (*writer) << "auto _log_start = std::chrono::steady_clock::now();\n";
+ writer->Close();
+ return code;
+}
+
+const string GenLogAfterExecute(const string className, const AidlInterface& interface,
+ const AidlMethod& method, const string& statusVarName,
+ const string& returnVarName, bool isServer, bool isNdk) {
+ string code;
+ CodeWriterPtr writer = CodeWriter::ForString(&code);
+
+ (*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,
+ // },
+ // }
+ (*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) << "_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";
+ } 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) << "_log_transaction[\"binder_status\"] = _log_status;\n";
+
+ for (const auto& a : method.GetOutArguments()) {
+ WriteLogForArguments(writer, *a, isServer, "_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);
+ }
+
+ // call the user-provided function with the Json object for the entire
+ // transaction
+ (*writer) << className << "::logFunc(_log_transaction);\n";
+
+ (*writer).Dedent();
+ (*writer) << "}\n";
+
+ writer->Close();
+ return code;
+}
+
} // namespace cpp
} // namespace aidl
} // namespace android
diff --git a/aidl_to_cpp_common.h b/aidl_to_cpp_common.h
index 3a6e2e60..381a8c96 100644
--- a/aidl_to_cpp_common.h
+++ b/aidl_to_cpp_common.h
@@ -49,7 +49,11 @@ void EnterNamespace(CodeWriter& out, const AidlDefinedType& defined_type);
void LeaveNamespace(CodeWriter& out, const AidlDefinedType& defined_type);
string BuildVarName(const AidlArgument& a);
-
+const string GenLogBeforeExecute(const string className, const AidlMethod& method, bool isServer,
+ bool isNdk);
+const string GenLogAfterExecute(const string className, const AidlInterface& interface,
+ const AidlMethod& method, const string& statusVarName,
+ const string& returnVarName, bool isServer, bool isNdk);
} // namespace cpp
} // namespace aidl
} // namespace android
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index 89594d23..dcda58f2 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -559,6 +559,10 @@ type aidlInterfaceProperties struct {
// Whether to generate C++ code using NDK binder APIs
// Default: true
Enabled *bool
+ // Whether to generate additional code for gathering information
+ // about the transactions
+ // Default: false
+ Gen_log *bool
}
}
}
@@ -751,6 +755,8 @@ func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version strin
genLog := false
if lang == langCpp {
genLog = proptools.Bool(i.properties.Backend.Cpp.Gen_log)
+ } else if lang == langNdk || lang == langNdkPlatform {
+ genLog = proptools.Bool(i.properties.Backend.Ndk.Gen_log)
}
mctx.CreateModule(android.ModuleFactoryAdaptor(aidlGenFactory), &nameProperties{
@@ -767,25 +773,30 @@ func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version strin
importExportDependencies := wrap("", i.properties.Imports, "-"+lang)
var libJSONCppDependency []string
+ var staticLibDependency []string
var sdkVersion *string
var stl *string
var cpp_std *string
-
if lang == langCpp {
importExportDependencies = append(importExportDependencies, "libbinder", "libutils")
if genLog {
libJSONCppDependency = []string{"libjsoncpp"}
- importExportDependencies = append(importExportDependencies, "libbase")
}
sdkVersion = nil
stl = nil
cpp_std = nil
} else if lang == langNdk {
importExportDependencies = append(importExportDependencies, "libbinder_ndk")
+ if genLog {
+ staticLibDependency = []string{"libjsoncpp_ndk"}
+ }
sdkVersion = proptools.StringPtr("current")
stl = proptools.StringPtr("c++_shared")
} else if lang == langNdkPlatform {
importExportDependencies = append(importExportDependencies, "libbinder_ndk")
+ if genLog {
+ libJSONCppDependency = []string{"libjsoncpp"}
+ }
} else {
panic("Unrecognized language: " + lang)
}
@@ -800,6 +811,7 @@ func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version strin
Export_generated_headers: []string{cppSourceGen},
Static: staticLib{Whole_static_libs: libJSONCppDependency},
Shared: sharedLib{Shared_libs: libJSONCppDependency, Export_shared_lib_headers: libJSONCppDependency},
+ Static_libs: staticLibDependency,
Shared_libs: importExportDependencies,
Export_shared_lib_headers: importExportDependencies,
Sdk_version: sdkVersion,
diff --git a/build/properties.go b/build/properties.go
index 13f1705a..f0256b88 100644
--- a/build/properties.go
+++ b/build/properties.go
@@ -34,6 +34,7 @@ type ccProperties struct {
Generated_headers []string
Shared sharedLib
Static staticLib
+ Static_libs []string
Shared_libs []string
Export_shared_lib_headers []string
Export_generated_headers []string
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 61552c1b..6d08eac7 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -225,140 +225,6 @@ string BuildHeaderGuard(const AidlDefinedType& defined_type, ClassNames header_t
return ret;
}
-void WriteLogForArguments(CodeWriterPtr& writer, const AidlArgument& a, const TypeNamespace& types,
- bool isServer, string logVarName) {
- if (!CanWriteLog(a.GetType())) {
- return;
- }
- string logElementVarName = "_log_arg_element";
- (*writer) << "{\n";
- (*writer).Indent();
- (*writer) << "Json::Value " << logElementVarName << "(Json::objectValue);\n";
- string varName = isServer ? BuildVarName(a) : a.GetName();
- (*writer) << logElementVarName << "[\"name\"] = \"" << varName << "\";\n";
-
- bool isPointer = a.IsOut() && !isServer;
- WriteLogFor({*(writer.get()), types.typenames_, a.GetType(), varName, isPointer,
- logElementVarName + "[\"value\"]"});
- (*writer) << logVarName << ".append(" << logElementVarName << ");\n";
- (*writer) << "}\n";
- (*writer).Dedent();
-}
-
-const string GenLogBeforeExecute(const string className, const AidlMethod& method,
- const TypeNamespace& types, bool isServer) {
- string code;
- CodeWriterPtr writer = CodeWriter::ForString(&code);
- (*writer) << "Json::Value _log_input_args(Json::arrayValue);\n";
-
- (*writer) << "if (" << className << "::logFunc != nullptr) {\n";
- (*writer).Indent();
-
- for (const auto& a : method.GetArguments()) {
- if (a->IsIn()) {
- WriteLogForArguments(writer, *a, types, isServer, "_log_input_args");
- }
- }
-
- (*writer).Dedent();
- (*writer) << "}\n";
-
- (*writer) << "auto _log_start = std::chrono::steady_clock::now();\n";
- writer->Close();
- return code;
-}
-
-const string GenLogAfterExecute(const string className, const AidlInterface& interface,
- const AidlMethod& method, const TypeNamespace& types,
- const string& statusVarName, const string& returnVarName,
- bool isServer) {
- string code;
- CodeWriterPtr writer = CodeWriter::ForString(&code);
-
- (*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,
- // },
- // }
- (*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) << "_log_transaction[\"" << (isServer ? "stub_address" : "proxy_address") << "\"] = "
- << "Json::Value(android::base::StringPrintf(\"0x%%p\", this));\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";
- (*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) << "_log_transaction[\"binder_status\"] = _log_status;\n";
-
- for (const auto& a : method.GetOutArguments()) {
- WriteLogForArguments(writer, *a, types, isServer, "_log_output_args");
- }
-
- (*writer) << "_log_transaction[\"output_args\"] = _log_output_args;\n";
-
- if (method.GetType().GetName() != "void") {
- WriteLogFor({*(writer.get()), types.typenames_, method.GetType(), returnVarName, !isServer,
- "_log_transaction[\"" + returnVarName + "\"]"});
- }
-
- // call the user-provided function with the Json object for the entire
- // transaction
- (*writer) << className << "::logFunc(_log_transaction);\n";
-
- (*writer).Dedent();
- (*writer) << "}\n";
-
- writer->Close();
- return code;
-}
-
unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
const AidlInterface& interface,
const AidlMethod& method, const Options& options) {
@@ -388,7 +254,8 @@ unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
}
if (options.GenLog()) {
- b->AddLiteral(GenLogBeforeExecute(bp_name, method, types, false), false /* no semicolon */);
+ b->AddLiteral(GenLogBeforeExecute(bp_name, method, false /* isServer */, false /* isNdk */),
+ false /* no semicolon */);
}
// Add the name of the interface we're hoping to call.
@@ -517,8 +384,8 @@ unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
kAndroidStatusVarName));
if (options.GenLog()) {
- b->AddLiteral(GenLogAfterExecute(bp_name, interface, method, types, kStatusVarName,
- kReturnVarName, false),
+ b->AddLiteral(GenLogAfterExecute(bp_name, interface, method, kStatusVarName, kReturnVarName,
+ false /* isServer */, false /* isNdk */),
false /* no semicolon */);
}
@@ -571,7 +438,6 @@ unique_ptr<Document> BuildClientSource(const TypeNamespace& types, const AidlInt
include_list.emplace_back("chrono");
include_list.emplace_back("functional");
include_list.emplace_back("json/value.h");
- include_list.emplace_back("android-base/stringprintf.h");
}
vector<unique_ptr<Declaration>> file_decls;
@@ -675,7 +541,8 @@ bool HandleServerTransaction(const TypeNamespace& types, const AidlInterface& in
}
const string bn_name = ClassName(interface, ClassNames::SERVER);
if (options.GenLog()) {
- b->AddLiteral(GenLogBeforeExecute(bn_name, method, types, true), false);
+ b->AddLiteral(GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */),
+ false);
}
// Call the actual method. This is implemented by the subclass.
vector<unique_ptr<AstNode>> status_args;
@@ -692,9 +559,9 @@ bool HandleServerTransaction(const TypeNamespace& types, const AidlInterface& in
}
if (options.GenLog()) {
- b->AddLiteral(
- GenLogAfterExecute(bn_name, interface, method, types, kStatusVarName, kReturnVarName, true),
- false);
+ b->AddLiteral(GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
+ true /* isServer */, false /* isNdk */),
+ false);
}
// Write exceptions during transaction handling to parcel.
@@ -766,7 +633,6 @@ unique_ptr<Document> BuildServerSource(const TypeNamespace& types, const AidlInt
include_list.emplace_back("chrono");
include_list.emplace_back("functional");
include_list.emplace_back("json/value.h");
- include_list.emplace_back("android-base/stringprintf.h");
}
unique_ptr<MethodImpl> on_transact{new MethodImpl{
kAndroidStatusLiteral, bn_name, "onTransact",
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index cafd794d..f0445f7a 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -233,9 +233,11 @@ static std::string MethodId(const AidlMethod& m) {
return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
}
-static void GenerateClientMethodDefinition(
- CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
- const AidlMethod& method, const std::optional<std::string> return_value_cached_to) {
+static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
+ const AidlInterface& defined_type,
+ const AidlMethod& method,
+ const std::optional<std::string> return_value_cached_to,
+ const Options& options) {
const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
out << NdkMethodDecl(types, method, clazz) << " {\n";
@@ -256,6 +258,11 @@ static void GenerateClientMethodDefinition(
out << "::ndk::ScopedAParcel _aidl_out;\n";
out << "\n";
+ if (options.GenLog()) {
+ out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
+ false /* isServer */, true /* isNdk */);
+ }
+
out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
StatusCheckGoto(out);
@@ -320,14 +327,19 @@ static void GenerateClientMethodDefinition(
out << "_aidl_error:\n";
out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
+ if (options.GenLog()) {
+ out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
+ method, "_aidl_status", "_aidl_return", false /* isServer */,
+ true /* isNdk */);
+ }
out << "return _aidl_status;\n";
out.Dedent();
out << "}\n";
}
static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
- const AidlInterface& /*defined_type*/,
- const AidlMethod& method) {
+ const AidlInterface& defined_type,
+ const AidlMethod& method, const Options& options) {
out << "case " << MethodId(method) << ": {\n";
out.Indent();
for (const auto& arg : method.GetArguments()) {
@@ -351,10 +363,18 @@ static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& t
out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
}
}
-
+ if (options.GenLog()) {
+ out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::SERVER), method,
+ true /* isServer */, true /* isNdk */);
+ }
out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
<< NdkArgList(types, method, FormatArgForCall) << ");\n";
+ if (options.GenLog()) {
+ out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::SERVER), defined_type,
+ method, "_aidl_status", "_aidl_return", true /* isServer */,
+ true /* isNdk */);
+ }
if (method.IsOneway()) {
// For a oneway transaction, the kernel will have already returned a result. This is for the
// in-process case when a oneway transaction is parceled/unparceled in the same process.
@@ -378,14 +398,13 @@ static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& t
StatusCheckBreak(out);
}
}
-
out << "break;\n";
out.Dedent();
out << "}\n";
}
void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
- const AidlInterface& defined_type, const Options& /*options*/) {
+ const AidlInterface& defined_type, const Options& options) {
const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
@@ -405,7 +424,7 @@ void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
out << "switch (_aidl_code) {\n";
out.Indent();
for (const auto& method : defined_type.GetMethods()) {
- GenerateServerCaseDefinition(out, types, defined_type, *method);
+ GenerateServerCaseDefinition(out, types, defined_type, *method, options);
}
out.Dedent();
out << "}\n";
@@ -426,6 +445,9 @@ void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
out << clazz << "::~" << clazz << "() {}\n";
+ if (options.GenLog()) {
+ out << "std::function<void(const Json::Value&)> " << clazz << "::logFunc;\n";
+ }
out << "\n";
for (const auto& method : defined_type.GetMethods()) {
// Only getInterfaceVersion can use cache.
@@ -433,7 +455,8 @@ void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
options.Version() > 0;
const auto return_value_cached_to =
cacheable ? std::make_optional<std::string>(kCacheVariable) : std::nullopt;
- GenerateClientMethodDefinition(out, types, defined_type, *method, return_value_cached_to);
+ GenerateClientMethodDefinition(out, types, defined_type, *method, return_value_cached_to,
+ options);
}
}
void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
@@ -444,7 +467,9 @@ void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
out << "// Source for " << clazz << "\n";
out << clazz << "::" << clazz << "() {}\n";
out << clazz << "::~" << clazz << "() {}\n";
-
+ if (options.GenLog()) {
+ out << "std::function<void(const Json::Value&)> " << clazz << "::logFunc;\n";
+ }
out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
out.Indent();
out << "AIBinder* binder = AIBinder_new(" << kClazz << ", static_cast<void*>(this));\n";
@@ -585,6 +610,12 @@ void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
<< "\"\n";
out << "\n";
out << "#include <android/binder_ibinder.h>\n";
+ if (options.GenLog()) {
+ out << "#include <json/value.h>\n";
+ out << "#include <functional>\n";
+ out << "#include <chrono>\n";
+ out << "#include <sstream>\n";
+ }
out << "\n";
EnterNdkNamespace(out, defined_type);
out << "class " << clazz << " : public ::ndk::BpCInterface<"
@@ -601,7 +632,9 @@ void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
if (options.Version() > 0) {
out << "int32_t " << kCacheVariable << " = -1;\n";
}
-
+ if (options.GenLog()) {
+ out << "static std::function<void(const Json::Value&)> logFunc;\n";
+ }
out.Dedent();
out << "};\n";
LeaveNdkNamespace(out, defined_type);
@@ -635,7 +668,9 @@ void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
}
}
-
+ if (options.GenLog()) {
+ out << "static std::function<void(const Json::Value&)> logFunc;\n";
+ }
out.Dedent();
out << "protected:\n";
out.Indent();
@@ -653,6 +688,12 @@ void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
out << "#pragma once\n\n";
out << "#include <android/binder_interface_utils.h>\n";
+ if (options.GenLog()) {
+ out << "#include <json/value.h>\n";
+ out << "#include <functional>\n";
+ out << "#include <chrono>\n";
+ out << "#include <sstream>\n";
+ }
out << "\n";
GenerateHeaderIncludes(out, types, defined_type);
diff --git a/options.cpp b/options.cpp
index 166e8ac1..351b4f6a 100644
--- a/options.cpp
+++ b/options.cpp
@@ -408,8 +408,8 @@ Options::Options(int argc, const char* const argv[], Options::Language default_l
<< "file." << endl;
return;
}
- if (gen_log_ && language_ != Options::Language::CPP) {
- error_message_ << "--log is currently supported only for --lang=cpp" << endl;
+ if (gen_log_ && (language_ != Options::Language::CPP && language_ != Options::Language::NDK)) {
+ error_message_ << "--log is currently supported for either --lang=cpp or --lang=ndk" << endl;
return;
}
}
diff --git a/tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl b/tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl
new file mode 100644
index 00000000..b3d2de69
--- /dev/null
+++ b/tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl
@@ -0,0 +1,14 @@
+package android.aidl.loggable;
+
+interface ILoggableInterfaceNdk {
+ String[] LogThis(boolean boolValue, inout boolean[] boolArray,
+ byte byteValue, inout byte[] byteArray,
+ char charValue, inout char[] charArray,
+ int intValue, inout int[] intArray,
+ long longValue, inout long[] longArray,
+ float floatValue, inout float[] floatArray,
+ double doubleValue, inout double[] doubleArray,
+ String stringValue, inout String[] stringArray,
+ IBinder binderValue,
+ inout ParcelFileDescriptor pfdValue);
+}