aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartijn Coenen <maco@google.com>2018-02-21 21:06:23 +0100
committerMartijn Coenen <maco@google.com>2018-03-23 11:42:48 +0100
commitb06c82923869f50e9641f7dac56df0aebe637845 (patch)
treeaf1e6202837e0644f9c1fd19fc468e25af6fd37a
parent0805f17188b640d2078d1b381b78ca377c44ad08 (diff)
downloadaidl-pie-qpr1-s3-release.tar.gz
This allows generating AIDL code that traces to the newly introduced ATRACE_TAG_AIDL, for both c++ and Java targets. The "::client" traces wrap the complete call, from entering the proxy right until returning the result. As such, this tag can be used to measure the complete duration of the IPC call. The "::server" traces wrap the actual execution of the method on the server side, so it can be used to determine the actual time the server took to complete the work. Subtracting the "::server" slice from the corresponding "::client" slice allows determining the overhead binder itself introduced. This is similar to how HIDL calls are traced. Bug: 74416314 Test: aidl_unittest passed (incl new tests), verified atrace outpout Change-Id: Id9a0207d53ebbdb6a21d8d96f56b8eee116bd477
-rw-r--r--aidl.cpp5
-rw-r--r--aidl.h1
-rw-r--r--aidl_language.h9
-rw-r--r--aidl_unittest.cpp1
-rw-r--r--generate_cpp.cpp30
-rw-r--r--generate_cpp_unittest.cpp578
-rw-r--r--generate_java_binder.cpp79
-rw-r--r--options.cpp10
-rw-r--r--options.h4
-rw-r--r--tests/end_to_end_tests.cpp23
-rw-r--r--tests/test_data.h1
-rw-r--r--tests/test_data_example_interface.cpp452
12 files changed, 1180 insertions, 13 deletions
diff --git a/aidl.cpp b/aidl.cpp
index e0eef0d2..88a42f8b 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -548,6 +548,7 @@ AidlError load_and_validate_aidl(
const std::vector<std::string>& preprocessed_files,
const std::vector<std::string>& import_paths,
const std::string& input_file_name,
+ const bool generate_traces,
const IoDelegate& io_delegate,
TypeNamespace* types,
std::unique_ptr<AidlInterface>* returned_interface,
@@ -633,6 +634,8 @@ AidlError load_and_validate_aidl(
interface->SetLanguageType(types->GetInterfaceType(*interface));
+ interface->SetGenerateTraces(generate_traces);
+
for (const auto& import : p.GetImports()) {
// If we skipped an unresolved import above (see comment there) we'll have
// an empty bucket here.
@@ -685,6 +688,7 @@ int compile_aidl_to_cpp(const CppOptions& options,
std::vector<std::string>{}, // no preprocessed files
options.ImportPaths(),
options.InputFileName(),
+ options.ShouldGenTraces(),
io_delegate,
types.get(),
&interface,
@@ -710,6 +714,7 @@ int compile_aidl_to_java(const JavaOptions& options,
options.preprocessed_files_,
options.import_paths_,
options.input_file_name_,
+ options.gen_traces_,
io_delegate,
types.get(),
&interface,
diff --git a/aidl.h b/aidl.h
index 2e5b0ee3..eb260c02 100644
--- a/aidl.h
+++ b/aidl.h
@@ -58,6 +58,7 @@ AidlError load_and_validate_aidl(
const std::vector<std::string>& preprocessed_files,
const std::vector<std::string>& import_paths,
const std::string& input_file_name,
+ const bool generate_traces,
const IoDelegate& io_delegate,
TypeNamespace* types,
std::unique_ptr<AidlInterface>* returned_interface,
diff --git a/aidl_language.h b/aidl_language.h
index 7982e761..41196286 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -345,6 +345,14 @@ class AidlInterface : public AidlAnnotatable {
return reinterpret_cast<const T*>(language_type_);
}
+ void SetGenerateTraces(bool generate_traces) {
+ generate_traces_ = generate_traces;
+ }
+
+ bool ShouldGenerateTraces() const {
+ return generate_traces_;
+ }
+
private:
std::string name_;
std::string comments_;
@@ -356,6 +364,7 @@ class AidlInterface : public AidlAnnotatable {
std::vector<std::string> package_;
const android::aidl::ValidatableType* language_type_ = nullptr;
+ bool generate_traces_ = false;
DISALLOW_COPY_AND_ASSIGN(AidlInterface);
};
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 570ecc74..597a766d 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -80,6 +80,7 @@ class AidlTest : public ::testing::Test {
preprocessed_files_,
import_paths_,
path,
+ false, /* generate_traces */
io_delegate_,
types,
&ret,
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 41e9fb40..7e8892b1 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -52,6 +52,7 @@ const char kImplVarName[] = "_aidl_impl";
const char kReplyVarName[] = "_aidl_reply";
const char kReturnVarName[] = "_aidl_return";
const char kStatusVarName[] = "_aidl_status";
+const char kTraceVarName[] = "_aidl_trace";
const char kAndroidParcelLiteral[] = "::android::Parcel";
const char kAndroidStatusLiteral[] = "::android::status_t";
const char kAndroidStatusOk[] = "::android::OK";
@@ -61,6 +62,7 @@ const char kIInterfaceHeader[] = "binder/IInterface.h";
const char kParcelHeader[] = "binder/Parcel.h";
const char kStatusHeader[] = "binder/Status.h";
const char kString16Header[] = "utils/String16.h";
+const char kTraceHeader[] = "utils/Trace.h";
const char kStrongPointerHeader[] = "utils/StrongPointer.h";
unique_ptr<AstNode> BreakOnStatusNotOk() {
@@ -271,6 +273,12 @@ unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
// We unconditionally return a Status object.
b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
+ if (interface.ShouldGenerateTraces()) {
+ b->AddLiteral(
+ StringPrintf("ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
+ kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
+ }
+
// Add the name of the interface we're hoping to call.
b->AddStatement(new Assignment(
kAndroidStatusVarName,
@@ -378,6 +386,7 @@ unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
b->AddLiteral(
StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
kAndroidStatusVarName));
+
b->AddLiteral(StringPrintf("return %s", kStatusVarName));
return unique_ptr<Declaration>(ret.release());
@@ -417,6 +426,7 @@ unique_ptr<Document> BuildClientSource(const TypeNamespace& types,
namespace {
bool HandleServerTransaction(const TypeNamespace& types,
+ const AidlInterface& interface,
const AidlMethod& method,
StatementBlock* b) {
// Declare all the parameters now. In the common case, we expect no errors
@@ -469,6 +479,14 @@ bool HandleServerTransaction(const TypeNamespace& types,
}
}
+ if (interface.ShouldGenerateTraces()) {
+ b->AddStatement(new Statement(new MethodCall("atrace_begin",
+ ArgList{{"ATRACE_TAG_AIDL",
+ StringPrintf("\"%s::%s::cppServer\"",
+ interface.GetName().c_str(),
+ method.GetName().c_str())}})));
+ }
+
// Call the actual method. This is implemented by the subclass.
vector<unique_ptr<AstNode>> status_args;
status_args.emplace_back(new MethodCall(
@@ -478,6 +496,11 @@ bool HandleServerTransaction(const TypeNamespace& types,
StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
ArgList(std::move(status_args)))));
+ if (interface.ShouldGenerateTraces()) {
+ b->AddStatement(new Statement(new MethodCall("atrace_end",
+ "ATRACE_TAG_AIDL")));
+ }
+
// Write exceptions during transaction handling to parcel.
if (!method.IsOneway()) {
b->AddStatement(new Assignment(
@@ -551,7 +574,7 @@ unique_ptr<Document> BuildServerSource(const TypeNamespace& types,
StatementBlock* b = s->AddCase("Call::" + UpperCase(method->GetName()));
if (!b) { return nullptr; }
- if (!HandleServerTransaction(types, *method, b)) { return nullptr; }
+ if (!HandleServerTransaction(types, interface, *method, b)) { return nullptr; }
}
// The switch statement has a default case which defers to the super class.
@@ -727,6 +750,11 @@ unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
if (!interface.GetStringConstants().empty()) {
includes.insert(kString16Header);
}
+
+ if (interface.ShouldGenerateTraces()) {
+ includes.insert(kTraceHeader);
+ }
+
for (const auto& constant : interface.GetStringConstants()) {
unique_ptr<MethodDecl> getter(new MethodDecl(
"const ::android::String16&", constant->GetName(),
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index 50bfd9c9..32e93624 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -378,6 +378,304 @@ return _aidl_status;
} // namespace android
)";
+const char kExpectedComplexTypeClientWithTraceSourceOutput[] =
+R"(#include <android/os/BpComplexTypeInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+namespace os {
+
+BpComplexTypeInterface::BpComplexTypeInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
+ : BpInterface<IComplexTypeInterface>(_aidl_impl){
+}
+
+::android::binder::Status BpComplexTypeInterface::Send(const ::std::unique_ptr<::std::vector<int32_t>>& goes_in, ::std::vector<double>* goes_in_and_out, ::std::vector<bool>* goes_out, ::std::vector<int32_t>* _aidl_return) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::Send::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeInt32Vector(goes_in);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeDoubleVector(*goes_in_and_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeVectorSize(*goes_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::SEND, _aidl_data, &_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
+}
+_aidl_ret_status = _aidl_reply.readInt32Vector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_reply.readDoubleVector(goes_in_and_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_reply.readBoolVector(goes_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+::android::binder::Status BpComplexTypeInterface::Piff(int32_t times) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::Piff::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeInt32(times);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::PIFF, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_ONEWAY);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+::android::binder::Status BpComplexTypeInterface::TakesABinder(const ::android::sp<::foo::IFooType>& f, ::android::sp<::foo::IFooType>* _aidl_return) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesABinder::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeStrongBinder(::foo::IFooType::asBinder(f));
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::TAKESABINDER, _aidl_data, &_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
+}
+_aidl_ret_status = _aidl_reply.readStrongBinder(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+::android::binder::Status BpComplexTypeInterface::NullableBinder(::android::sp<::foo::IFooType>* _aidl_return) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::NullableBinder::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::NULLABLEBINDER, _aidl_data, &_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
+}
+_aidl_ret_status = _aidl_reply.readNullableStrongBinder(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+::android::binder::Status BpComplexTypeInterface::StringListMethod(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* output, ::std::vector<::android::String16>* _aidl_return) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::StringListMethod::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeString16Vector(input);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::STRINGLISTMETHOD, _aidl_data, &_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
+}
+_aidl_ret_status = _aidl_reply.readString16Vector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_reply.readString16Vector(output);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+::android::binder::Status BpComplexTypeInterface::BinderListMethod(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* output, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::BinderListMethod::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeStrongBinderVector(input);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::BINDERLISTMETHOD, _aidl_data, &_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
+}
+_aidl_ret_status = _aidl_reply.readStrongBinderVector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_reply.readStrongBinderVector(output);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+::android::binder::Status BpComplexTypeInterface::TakesAFileDescriptor(const ::android::base::unique_fd& f, ::android::base::unique_fd* _aidl_return) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptor::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeUniqueFileDescriptor(f);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::TAKESAFILEDESCRIPTOR, _aidl_data, &_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
+}
+_aidl_ret_status = _aidl_reply.readUniqueFileDescriptor(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+::android::binder::Status BpComplexTypeInterface::TakesAFileDescriptorArray(const ::std::vector<::android::base::unique_fd>& f, ::std::vector<::android::base::unique_fd>* _aidl_return) {
+::android::Parcel _aidl_data;
+::android::Parcel _aidl_reply;
+::android::status_t _aidl_ret_status = ::android::OK;
+::android::binder::Status _aidl_status;
+ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptorArray::cppClient");
+_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_data.writeUniqueFileDescriptorVector(f);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = remote()->transact(IComplexTypeInterface::TAKESAFILEDESCRIPTORARRAY, _aidl_data, &_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
+}
+_aidl_ret_status = _aidl_reply.readUniqueFileDescriptorVector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
+_aidl_error:
+_aidl_status.setFromStatusT(_aidl_ret_status);
+return _aidl_status;
+}
+
+} // namespace os
+
+} // namespace android
+)";
+
const char kExpectedComplexTypeServerHeaderOutput[] =
R"(#ifndef AIDL_GENERATED_ANDROID_OS_BN_COMPLEX_TYPE_INTERFACE_H_
#define AIDL_GENERATED_ANDROID_OS_BN_COMPLEX_TYPE_INTERFACE_H_
@@ -648,6 +946,269 @@ return _aidl_ret_status;
} // namespace android
)";
+const char kExpectedComplexTypeServerWithTraceSourceOutput[] =
+R"(#include <android/os/BnComplexTypeInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+namespace os {
+
+::android::status_t BnComplexTypeInterface::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
+::android::status_t _aidl_ret_status = ::android::OK;
+switch (_aidl_code) {
+case Call::SEND:
+{
+::std::unique_ptr<::std::vector<int32_t>> in_goes_in;
+::std::vector<double> in_goes_in_and_out;
+::std::vector<bool> out_goes_out;
+::std::vector<int32_t> _aidl_return;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+_aidl_ret_status = _aidl_data.readInt32Vector(&in_goes_in);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+_aidl_ret_status = _aidl_data.readDoubleVector(&in_goes_in_and_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+_aidl_ret_status = _aidl_data.resizeOutVector(&out_goes_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::Send::cppServer");
+::android::binder::Status _aidl_status(Send(in_goes_in, &in_goes_in_and_out, &out_goes_out, &_aidl_return));
+atrace_end(ATRACE_TAG_AIDL);
+_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+if (!_aidl_status.isOk()) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeInt32Vector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeDoubleVector(in_goes_in_and_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeBoolVector(out_goes_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+}
+break;
+case Call::PIFF:
+{
+int32_t in_times;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+_aidl_ret_status = _aidl_data.readInt32(&in_times);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::Piff::cppServer");
+::android::binder::Status _aidl_status(Piff(in_times));
+atrace_end(ATRACE_TAG_AIDL);
+}
+break;
+case Call::TAKESABINDER:
+{
+::android::sp<::foo::IFooType> in_f;
+::android::sp<::foo::IFooType> _aidl_return;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+_aidl_ret_status = _aidl_data.readStrongBinder(&in_f);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesABinder::cppServer");
+::android::binder::Status _aidl_status(TakesABinder(in_f, &_aidl_return));
+atrace_end(ATRACE_TAG_AIDL);
+_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+if (!_aidl_status.isOk()) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeStrongBinder(::foo::IFooType::asBinder(_aidl_return));
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+}
+break;
+case Call::NULLABLEBINDER:
+{
+::android::sp<::foo::IFooType> _aidl_return;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::NullableBinder::cppServer");
+::android::binder::Status _aidl_status(NullableBinder(&_aidl_return));
+atrace_end(ATRACE_TAG_AIDL);
+_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+if (!_aidl_status.isOk()) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeStrongBinder(::foo::IFooType::asBinder(_aidl_return));
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+}
+break;
+case Call::STRINGLISTMETHOD:
+{
+::std::vector<::android::String16> in_input;
+::std::vector<::android::String16> out_output;
+::std::vector<::android::String16> _aidl_return;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+_aidl_ret_status = _aidl_data.readString16Vector(&in_input);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::StringListMethod::cppServer");
+::android::binder::Status _aidl_status(StringListMethod(in_input, &out_output, &_aidl_return));
+atrace_end(ATRACE_TAG_AIDL);
+_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+if (!_aidl_status.isOk()) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeString16Vector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeString16Vector(out_output);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+}
+break;
+case Call::BINDERLISTMETHOD:
+{
+::std::vector<::android::sp<::android::IBinder>> in_input;
+::std::vector<::android::sp<::android::IBinder>> out_output;
+::std::vector<::android::sp<::android::IBinder>> _aidl_return;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+_aidl_ret_status = _aidl_data.readStrongBinderVector(&in_input);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::BinderListMethod::cppServer");
+::android::binder::Status _aidl_status(BinderListMethod(in_input, &out_output, &_aidl_return));
+atrace_end(ATRACE_TAG_AIDL);
+_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+if (!_aidl_status.isOk()) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeStrongBinderVector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeStrongBinderVector(out_output);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+}
+break;
+case Call::TAKESAFILEDESCRIPTOR:
+{
+::android::base::unique_fd in_f;
+::android::base::unique_fd _aidl_return;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+_aidl_ret_status = _aidl_data.readUniqueFileDescriptor(&in_f);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptor::cppServer");
+::android::binder::Status _aidl_status(TakesAFileDescriptor(in_f, &_aidl_return));
+atrace_end(ATRACE_TAG_AIDL);
+_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+if (!_aidl_status.isOk()) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeUniqueFileDescriptor(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+}
+break;
+case Call::TAKESAFILEDESCRIPTORARRAY:
+{
+::std::vector<::android::base::unique_fd> in_f;
+::std::vector<::android::base::unique_fd> _aidl_return;
+if (!(_aidl_data.checkInterface(this))) {
+_aidl_ret_status = ::android::BAD_TYPE;
+break;
+}
+_aidl_ret_status = _aidl_data.readUniqueFileDescriptorVector(&in_f);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptorArray::cppServer");
+::android::binder::Status _aidl_status(TakesAFileDescriptorArray(in_f, &_aidl_return));
+atrace_end(ATRACE_TAG_AIDL);
+_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+if (!_aidl_status.isOk()) {
+break;
+}
+_aidl_ret_status = _aidl_reply->writeUniqueFileDescriptorVector(_aidl_return);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
+}
+break;
+default:
+{
+_aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
+}
+break;
+}
+if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
+_aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+}
+return _aidl_ret_status;
+}
+
+} // namespace os
+
+} // namespace android
+)";
+
const char kExpectedComplexTypeInterfaceHeaderOutput[] =
R"(#ifndef AIDL_GENERATED_ANDROID_OS_I_COMPLEX_TYPE_INTERFACE_H_
#define AIDL_GENERATED_ANDROID_OS_I_COMPLEX_TYPE_INTERFACE_H_
@@ -734,6 +1295,7 @@ class ASTTest : public ::testing::Test {
{}, // no preprocessed files
{"."},
file_path_,
+ false, // generate_traces
io_delegate_,
&types_,
&ret,
@@ -789,6 +1351,14 @@ TEST_F(ComplexTypeInterfaceASTTest, GeneratesClientSource) {
Compare(doc.get(), kExpectedComplexTypeClientSourceOutput);
}
+TEST_F(ComplexTypeInterfaceASTTest, GeneratesClientSourceWithTrace) {
+ unique_ptr<AidlInterface> interface = Parse();
+ ASSERT_NE(interface, nullptr);
+ interface->SetGenerateTraces(true);
+ unique_ptr<Document> doc = internals::BuildClientSource(types_, *interface);
+ Compare(doc.get(), kExpectedComplexTypeClientWithTraceSourceOutput);
+}
+
TEST_F(ComplexTypeInterfaceASTTest, GeneratesServerHeader) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
@@ -803,6 +1373,14 @@ TEST_F(ComplexTypeInterfaceASTTest, GeneratesServerSource) {
Compare(doc.get(), kExpectedComplexTypeServerSourceOutput);
}
+TEST_F(ComplexTypeInterfaceASTTest, GeneratesServerSourceWithTrace) {
+ unique_ptr<AidlInterface> interface = Parse();
+ ASSERT_NE(interface, nullptr);
+ interface->SetGenerateTraces(true);
+ unique_ptr<Document> doc = internals::BuildServerSource(types_, *interface);
+ Compare(doc.get(), kExpectedComplexTypeServerWithTraceSourceOutput);
+}
+
TEST_F(ComplexTypeInterfaceASTTest, GeneratesInterfaceHeader) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index ad993a80..522715c5 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -342,7 +342,8 @@ static std::unique_ptr<Method> generate_interface_method(
return decl;
}
-static void generate_stub_code(const AidlMethod& method,
+static void generate_stub_code(const AidlInterface& iface,
+ const AidlMethod& method,
const std::string& transactCodeName,
bool oneway,
Variable* transact_data,
@@ -350,6 +351,8 @@ static void generate_stub_code(const AidlMethod& method,
JavaTypeNamespace* types,
StatementBlock* statements,
StubClass* stubClass) {
+ TryStatement* tryStatement = nullptr;
+ FinallyStatement* finallyStatement = nullptr;
MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());
// interface token validation is the very first thing we do
@@ -391,9 +394,31 @@ static void generate_stub_code(const AidlMethod& method,
}
}
+ if (iface.ShouldGenerateTraces()) {
+ // try and finally, but only when generating trace code
+ tryStatement = new TryStatement();
+ finallyStatement = new FinallyStatement();
+
+ tryStatement->statements->Add(new MethodCall(
+ new LiteralExpression("android.os.Trace"), "traceBegin", 2,
+ new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
+ new StringLiteralExpression(iface.GetName() + "::"
+ + method.GetName() + "::server")));
+
+ finallyStatement->statements->Add(new MethodCall(
+ new LiteralExpression("android.os.Trace"), "traceEnd", 1,
+ new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
+ }
+
// the real call
if (method.GetType().GetName() == "void") {
- statements->Add(realCall);
+ if (iface.ShouldGenerateTraces()) {
+ statements->Add(tryStatement);
+ tryStatement->statements->Add(realCall);
+ statements->Add(finallyStatement);
+ } else {
+ statements->Add(realCall);
+ }
if (!oneway) {
// report that there were no exceptions
@@ -406,7 +431,14 @@ static void generate_stub_code(const AidlMethod& method,
new Variable(method.GetType().GetLanguageType<Type>(),
"_result",
method.GetType().IsArray() ? 1 : 0);
- statements->Add(new VariableDeclaration(_result, realCall));
+ if (iface.ShouldGenerateTraces()) {
+ statements->Add(new VariableDeclaration(_result));
+ statements->Add(tryStatement);
+ tryStatement->statements->Add(new Assignment(_result, realCall));
+ statements->Add(finallyStatement);
+ } else {
+ statements->Add(new VariableDeclaration(_result, realCall));
+ }
if (!oneway) {
// report that there were no exceptions
@@ -443,14 +475,16 @@ static void generate_stub_code(const AidlMethod& method,
}
-static void generate_stub_case(const AidlMethod& method,
+static void generate_stub_case(const AidlInterface& iface,
+ const AidlMethod& method,
const std::string& transactCodeName,
bool oneway,
StubClass* stubClass,
JavaTypeNamespace* types) {
Case* c = new Case(transactCodeName);
- generate_stub_code(method,
+ generate_stub_code(iface,
+ method,
transactCodeName,
oneway,
stubClass->transact_data,
@@ -462,7 +496,8 @@ static void generate_stub_case(const AidlMethod& method,
stubClass->transact_switch->cases.push_back(c);
}
-static void generate_stub_case_outline(const AidlMethod& method,
+static void generate_stub_case_outline(const AidlInterface& iface,
+ const AidlMethod& method,
const std::string& transactCodeName,
bool oneway,
StubClass* stubClass,
@@ -482,7 +517,8 @@ static void generate_stub_case_outline(const AidlMethod& method,
onTransact_case->exceptions.push_back(types->RemoteExceptionType());
stubClass->elements.push_back(onTransact_case);
- generate_stub_code(method,
+ generate_stub_code(iface,
+ method,
transactCodeName,
oneway,
transact_data,
@@ -508,6 +544,7 @@ static void generate_stub_case_outline(const AidlMethod& method,
}
static std::unique_ptr<Method> generate_proxy_method(
+ const AidlInterface& iface,
const AidlMethod& method,
const std::string& transactCodeName,
bool oneway,
@@ -552,6 +589,14 @@ static std::unique_ptr<Method> generate_proxy_method(
FinallyStatement* finallyStatement = new FinallyStatement();
proxy->statements->Add(finallyStatement);
+ if (iface.ShouldGenerateTraces()) {
+ tryStatement->statements->Add(new MethodCall(
+ new LiteralExpression("android.os.Trace"), "traceBegin", 2,
+ new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
+ new StringLiteralExpression(iface.GetName() + "::" +
+ method.GetName() + "::client")));
+ }
+
// the interface identifier token: the DESCRIPTOR constant, marshalled as a
// string
tryStatement->statements->Add(new MethodCall(
@@ -615,6 +660,12 @@ static std::unique_ptr<Method> generate_proxy_method(
}
finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
+ if (iface.ShouldGenerateTraces()) {
+ finallyStatement->statements->Add(new MethodCall(
+ new LiteralExpression("android.os.Trace"), "traceEnd", 1,
+ new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
+ }
+
if (_result != NULL) {
proxy->statements->Add(new ReturnStatement(_result));
}
@@ -622,7 +673,8 @@ static std::unique_ptr<Method> generate_proxy_method(
return proxy;
}
-static void generate_methods(const AidlMethod& method,
+static void generate_methods(const AidlInterface& iface,
+ const AidlMethod& method,
Class* interface,
StubClass* stubClass,
ProxyClass* proxyClass,
@@ -648,17 +700,19 @@ static void generate_methods(const AidlMethod& method,
bool outline_stub = stubClass->transact_outline &&
stubClass->outline_methods.count(&method) != 0;
if (outline_stub) {
- generate_stub_case_outline(method,
+ generate_stub_case_outline(iface,
+ method,
transactCodeName,
oneway,
stubClass,
types);
} else {
- generate_stub_case(method, transactCodeName, oneway, stubClass, types);
+ generate_stub_case(iface, method, transactCodeName, oneway, stubClass, types);
}
// == the proxy method ===================================================
- Method* proxy = generate_proxy_method(method,
+ Method* proxy = generate_proxy_method(iface,
+ method,
transactCodeName,
oneway,
proxyClass,
@@ -768,7 +822,8 @@ Class* generate_binder_interface_class(const AidlInterface* iface,
// all the declared methods of the interface
for (const auto& item : iface->GetMethods()) {
- generate_methods(*item,
+ generate_methods(*iface,
+ *item,
interface,
stub,
proxy,
diff --git a/options.cpp b/options.cpp
index 72c75758..3ed110b0 100644
--- a/options.cpp
+++ b/options.cpp
@@ -48,6 +48,9 @@ unique_ptr<JavaOptions> java_usage() {
" -p<FILE> file created by --preprocess to import.\n"
" -o<FOLDER> base output folder for generated files.\n"
" -b fail when trying to compile a parcelable.\n"
+ " -t include tracing code for systrace. Note that if either "
+ "the client or server code is not auto-generated by this tool, that "
+ "part will not be traced.\n"
"\n"
"INPUT:\n"
" An aidl interface file.\n"
@@ -126,6 +129,8 @@ unique_ptr<JavaOptions> JavaOptions::Parse(int argc, const char* const* argv) {
options->fail_on_parcelable_ = true;
} else if (strcmp(s, "-ninja") == 0) {
options->dep_file_ninja_ = true;
+ } else if (strcmp(s, "-t") == 0) {
+ options->gen_traces_ = true;
} else {
// s[1] is not known
fprintf(stderr, "unknown option (%d): %s\n", i, s);
@@ -190,6 +195,9 @@ unique_ptr<CppOptions> cpp_usage() {
<< "OPTIONS:" << endl
<< " -I<DIR> search path for import statements" << endl
<< " -d<FILE> generate dependency file" << endl
+ << " -t include tracing code for systrace. Note that if the "
+ "client or server code is not auto-generated by this tool, that part "
+ "will not be traced." << endl
<< " -ninja generate dependency file in a format ninja "
"understands" << endl
<< endl
@@ -224,6 +232,8 @@ unique_ptr<CppOptions> CppOptions::Parse(int argc, const char* const* argv) {
options->import_paths_.push_back(the_rest);
} else if (s[1] == 'd') {
options->dep_file_name_ = the_rest;
+ } else if (s[1] == 't') {
+ options->gen_traces_ = true;
} else if (strcmp(s, "-ninja") == 0) {
options->dep_file_ninja_ = true;
} else {
diff --git a/options.h b/options.h
index 6b3ac265..11f3525d 100644
--- a/options.h
+++ b/options.h
@@ -54,6 +54,7 @@ class JavaOptions final {
std::string dep_file_name_;
bool auto_dep_file_{false};
bool dep_file_ninja_{false};
+ bool gen_traces_{false};
std::vector<std::string> files_to_preprocess_;
// The following are for testability, but cannot be influenced on the command line.
@@ -67,6 +68,7 @@ class JavaOptions final {
JavaOptions() = default;
FRIEND_TEST(EndToEndTest, IExampleInterface);
+ FRIEND_TEST(EndToEndTest, IExampleInterface_WithTrace);
FRIEND_TEST(EndToEndTest, IExampleInterface_Outlining);
FRIEND_TEST(AidlTest, FailOnParcelable);
FRIEND_TEST(AidlTest, WritePreprocessedFile);
@@ -94,6 +96,7 @@ class CppOptions final {
std::vector<std::string> ImportPaths() const { return import_paths_; }
std::string DependencyFilePath() const { return dep_file_name_; }
bool DependencyFileNinja() const { return dep_file_ninja_; }
+ bool ShouldGenTraces() const { return gen_traces_; }
private:
CppOptions() = default;
@@ -103,6 +106,7 @@ class CppOptions final {
std::string output_header_dir_;
std::string output_file_name_;
std::string dep_file_name_;
+ bool gen_traces_{false};
bool dep_file_ninja_{false};
FRIEND_TEST(CppOptionsTests, ParsesCompileCpp);
diff --git a/tests/end_to_end_tests.cpp b/tests/end_to_end_tests.cpp
index 344c4c2a..555d8dce 100644
--- a/tests/end_to_end_tests.cpp
+++ b/tests/end_to_end_tests.cpp
@@ -92,6 +92,29 @@ TEST_F(EndToEndTest, IExampleInterface) {
CheckFileContents(options.DependencyFilePath(), kExpectedJavaDepsOutput);
}
+TEST_F(EndToEndTest, IExampleInterface_WithTrace) {
+ using namespace ::android::aidl::test_data::example_interface;
+
+ JavaOptions options;
+ options.fail_on_parcelable_ = true;
+ options.import_paths_.push_back("");
+ options.input_file_name_ = CanonicalNameToPath(kCanonicalName, ".aidl");
+ options.output_file_name_ = kJavaOutputPath;
+ options.dep_file_name_ = "an/arbitrary/path/to/deps.P";
+ options.gen_traces_ = true;
+
+ // Load up our fake file system with data.
+ io_delegate_.SetFileContents(options.input_file_name_, kInterfaceDefinition);
+ io_delegate_.AddCompoundParcelable("android.test.CompoundParcelable",
+ {"Subclass1", "Subclass2"});
+ AddStubAidls(kImportedParcelables, kImportedInterfaces);
+
+ // Check that we parse correctly.
+ EXPECT_EQ(android::aidl::compile_aidl_to_java(options, io_delegate_), 0);
+ CheckFileContents(kJavaOutputPath, kExpectedJavaOutputWithTrace);
+ CheckFileContents(options.DependencyFilePath(), kExpectedJavaDepsOutput);
+}
+
TEST_F(EndToEndTest, IExampleInterface_Outlining) {
using namespace ::android::aidl::test_data::example_interface;
diff --git a/tests/test_data.h b/tests/test_data.h
index ae2c573e..0b5aaf09 100644
--- a/tests/test_data.h
+++ b/tests/test_data.h
@@ -33,6 +33,7 @@ extern const char* kImportedInterfaces[];
extern const char kExpectedJavaDepsOutput[];
extern const char kExpectedJavaOutput[];
extern const char kExpectedJavaOutputOutlining[];
+extern const char kExpectedJavaOutputWithTrace[];
} // namespace example_interface
diff --git a/tests/test_data_example_interface.cpp b/tests/test_data_example_interface.cpp
index 731efcd0..9b0e0ee6 100644
--- a/tests/test_data_example_interface.cpp
+++ b/tests/test_data_example_interface.cpp
@@ -485,6 +485,458 @@ public int takesAParcelable(android.test.CompoundParcelable.Subclass1 arg, andro
}
)";
+const char kExpectedJavaOutputWithTrace[] =
+R"(/*
+ * This file is auto-generated. DO NOT MODIFY.
+ * Original file: android/test/IExampleInterface.aidl
+ */
+package android.test;
+public interface IExampleInterface extends android.os.IInterface
+{
+/** Local-side IPC implementation stub class. */
+public static abstract class Stub extends android.os.Binder implements android.test.IExampleInterface
+{
+private static final java.lang.String DESCRIPTOR = "android.test.IExampleInterface";
+/** Construct the stub at attach it to the interface. */
+public Stub()
+{
+this.attachInterface(this, DESCRIPTOR);
+}
+/**
+ * Cast an IBinder object into an android.test.IExampleInterface interface,
+ * generating a proxy if needed.
+ */
+public static android.test.IExampleInterface asInterface(android.os.IBinder obj)
+{
+if ((obj==null)) {
+return null;
+}
+android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+if (((iin!=null)&&(iin instanceof android.test.IExampleInterface))) {
+return ((android.test.IExampleInterface)iin);
+}
+return new android.test.IExampleInterface.Stub.Proxy(obj);
+}
+@Override public android.os.IBinder asBinder()
+{
+return this;
+}
+@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+{
+java.lang.String descriptor = DESCRIPTOR;
+switch (code)
+{
+case INTERFACE_TRANSACTION:
+{
+reply.writeString(descriptor);
+return true;
+}
+case TRANSACTION_isEnabled:
+{
+data.enforceInterface(descriptor);
+boolean _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::isEnabled::server");
+_result = this.isEnabled();
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+case TRANSACTION_getState:
+{
+data.enforceInterface(descriptor);
+int _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getState::server");
+_result = this.getState();
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeInt(_result);
+return true;
+}
+case TRANSACTION_getAddress:
+{
+data.enforceInterface(descriptor);
+java.lang.String _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getAddress::server");
+_result = this.getAddress();
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeString(_result);
+return true;
+}
+case TRANSACTION_getParcelables:
+{
+data.enforceInterface(descriptor);
+android.foo.ExampleParcelable[] _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getParcelables::server");
+_result = this.getParcelables();
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+return true;
+}
+case TRANSACTION_setScanMode:
+{
+data.enforceInterface(descriptor);
+int _arg0;
+_arg0 = data.readInt();
+int _arg1;
+_arg1 = data.readInt();
+boolean _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::setScanMode::server");
+_result = this.setScanMode(_arg0, _arg1);
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+case TRANSACTION_registerBinder:
+{
+data.enforceInterface(descriptor);
+android.bar.IAuxInterface _arg0;
+_arg0 = android.bar.IAuxInterface.Stub.asInterface(data.readStrongBinder());
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::registerBinder::server");
+this.registerBinder(_arg0);
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_getRecursiveBinder:
+{
+data.enforceInterface(descriptor);
+android.test.IExampleInterface _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getRecursiveBinder::server");
+_result = this.getRecursiveBinder();
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
+return true;
+}
+case TRANSACTION_takesAnInterface:
+{
+data.enforceInterface(descriptor);
+android.test.IAuxInterface2 _arg0;
+_arg0 = android.test.IAuxInterface2.Stub.asInterface(data.readStrongBinder());
+int _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAnInterface::server");
+_result = this.takesAnInterface(_arg0);
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeInt(_result);
+return true;
+}
+case TRANSACTION_takesAParcelable:
+{
+data.enforceInterface(descriptor);
+android.test.CompoundParcelable.Subclass1 _arg0;
+if ((0!=data.readInt())) {
+_arg0 = android.test.CompoundParcelable.Subclass1.CREATOR.createFromParcel(data);
+}
+else {
+_arg0 = null;
+}
+android.test.CompoundParcelable.Subclass2 _arg1;
+if ((0!=data.readInt())) {
+_arg1 = android.test.CompoundParcelable.Subclass2.CREATOR.createFromParcel(data);
+}
+else {
+_arg1 = null;
+}
+int _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAParcelable::server");
+_result = this.takesAParcelable(_arg0, _arg1);
+}
+finally {
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+reply.writeNoException();
+reply.writeInt(_result);
+if ((_arg1!=null)) {
+reply.writeInt(1);
+_arg1.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+}
+else {
+reply.writeInt(0);
+}
+return true;
+}
+default:
+{
+return super.onTransact(code, data, reply, flags);
+}
+}
+}
+private static class Proxy implements android.test.IExampleInterface
+{
+private android.os.IBinder mRemote;
+Proxy(android.os.IBinder remote)
+{
+mRemote = remote;
+}
+@Override public android.os.IBinder asBinder()
+{
+return mRemote;
+}
+public java.lang.String getInterfaceDescriptor()
+{
+return DESCRIPTOR;
+}
+@Override public boolean isEnabled() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+boolean _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::isEnabled::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_isEnabled, _data, _reply, 0);
+_reply.readException();
+_result = (0!=_reply.readInt());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+@Override public int getState() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+int _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getState::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getState, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readInt();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+@Override public java.lang.String getAddress() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+java.lang.String _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getAddress::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getAddress, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readString();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+/* Test long comment */
+@Override public android.foo.ExampleParcelable[] getParcelables() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+android.foo.ExampleParcelable[] _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getParcelables::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getParcelables, _data, _reply, 0);
+_reply.readException();
+_result = _reply.createTypedArray(android.foo.ExampleParcelable.CREATOR);
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+// Test short comment
+
+@Override public boolean setScanMode(int mode, int duration) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+boolean _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::setScanMode::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeInt(mode);
+_data.writeInt(duration);
+mRemote.transact(Stub.TRANSACTION_setScanMode, _data, _reply, 0);
+_reply.readException();
+_result = (0!=_reply.readInt());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+/* Test long comment */// And short comment
+
+@Override public void registerBinder(android.bar.IAuxInterface foo) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::registerBinder::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeStrongBinder((((foo!=null))?(foo.asBinder()):(null)));
+mRemote.transact(Stub.TRANSACTION_registerBinder, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+}
+@Override public android.test.IExampleInterface getRecursiveBinder() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+android.test.IExampleInterface _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getRecursiveBinder::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getRecursiveBinder, _data, _reply, 0);
+_reply.readException();
+_result = android.test.IExampleInterface.Stub.asInterface(_reply.readStrongBinder());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+@Override public int takesAnInterface(android.test.IAuxInterface2 arg) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+int _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAnInterface::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeStrongBinder((((arg!=null))?(arg.asBinder()):(null)));
+mRemote.transact(Stub.TRANSACTION_takesAnInterface, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readInt();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+@Override public int takesAParcelable(android.test.CompoundParcelable.Subclass1 arg, android.test.CompoundParcelable.Subclass2 arg2) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+int _result;
+try {
+android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAParcelable::client");
+_data.writeInterfaceToken(DESCRIPTOR);
+if ((arg!=null)) {
+_data.writeInt(1);
+arg.writeToParcel(_data, 0);
+}
+else {
+_data.writeInt(0);
+}
+if ((arg2!=null)) {
+_data.writeInt(1);
+arg2.writeToParcel(_data, 0);
+}
+else {
+_data.writeInt(0);
+}
+mRemote.transact(Stub.TRANSACTION_takesAParcelable, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readInt();
+if ((0!=_reply.readInt())) {
+arg2.readFromParcel(_reply);
+}
+}
+finally {
+_reply.recycle();
+_data.recycle();
+android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+}
+return _result;
+}
+}
+static final int TRANSACTION_isEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+static final int TRANSACTION_getState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+static final int TRANSACTION_getAddress = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+static final int TRANSACTION_getParcelables = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
+static final int TRANSACTION_setScanMode = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
+static final int TRANSACTION_registerBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
+static final int TRANSACTION_getRecursiveBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
+static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
+static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
+}
+public static final int EXAMPLE_CONSTANT = 3;
+public boolean isEnabled() throws android.os.RemoteException;
+public int getState() throws android.os.RemoteException;
+public java.lang.String getAddress() throws android.os.RemoteException;
+/* Test long comment */
+public android.foo.ExampleParcelable[] getParcelables() throws android.os.RemoteException;
+// Test short comment
+
+public boolean setScanMode(int mode, int duration) throws android.os.RemoteException;
+/* Test long comment */// And short comment
+
+public void registerBinder(android.bar.IAuxInterface foo) throws android.os.RemoteException;
+public android.test.IExampleInterface getRecursiveBinder() throws android.os.RemoteException;
+public int takesAnInterface(android.test.IAuxInterface2 arg) throws android.os.RemoteException;
+public int takesAParcelable(android.test.CompoundParcelable.Subclass1 arg, android.test.CompoundParcelable.Subclass2 arg2) throws android.os.RemoteException;
+}
+)";
+
const char kExpectedJavaOutputOutlining[] =
R"(/*
* This file is auto-generated. DO NOT MODIFY.