aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-03-25 07:27:21 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-03-25 07:27:21 +0000
commit0a0b47e1e67c20f6b6d6e76a2e9abf33216446c2 (patch)
treeaf1e6202837e0644f9c1fd19fc468e25af6fd37a
parent8d198d61bab837521bdd93665c8c49dae93a80b2 (diff)
parentb06c82923869f50e9641f7dac56df0aebe637845 (diff)
downloadaidl-android-security-9.0.0_r70.tar.gz
Snap for 4677756 from b06c82923869f50e9641f7dac56df0aebe637845 to pi-releaseandroid-wear-9.0.0_r9android-wear-9.0.0_r8android-wear-9.0.0_r7android-wear-9.0.0_r6android-wear-9.0.0_r5android-wear-9.0.0_r4android-wear-9.0.0_r34android-wear-9.0.0_r33android-wear-9.0.0_r32android-wear-9.0.0_r31android-wear-9.0.0_r30android-wear-9.0.0_r3android-wear-9.0.0_r29android-wear-9.0.0_r28android-wear-9.0.0_r27android-wear-9.0.0_r26android-wear-9.0.0_r25android-wear-9.0.0_r24android-wear-9.0.0_r23android-wear-9.0.0_r22android-wear-9.0.0_r21android-wear-9.0.0_r20android-wear-9.0.0_r2android-wear-9.0.0_r19android-wear-9.0.0_r18android-wear-9.0.0_r17android-wear-9.0.0_r16android-wear-9.0.0_r15android-wear-9.0.0_r14android-wear-9.0.0_r13android-wear-9.0.0_r12android-wear-9.0.0_r11android-wear-9.0.0_r10android-wear-9.0.0_r1android-vts-9.0_r9android-vts-9.0_r8android-vts-9.0_r7android-vts-9.0_r6android-vts-9.0_r5android-vts-9.0_r4android-vts-9.0_r19android-vts-9.0_r18android-vts-9.0_r17android-vts-9.0_r16android-vts-9.0_r15android-vts-9.0_r14android-vts-9.0_r13android-vts-9.0_r12android-vts-9.0_r11android-vts-9.0_r10android-security-9.0.0_r76android-security-9.0.0_r75android-security-9.0.0_r74android-security-9.0.0_r73android-security-9.0.0_r72android-security-9.0.0_r71android-security-9.0.0_r70android-security-9.0.0_r69android-security-9.0.0_r68android-security-9.0.0_r67android-security-9.0.0_r66android-security-9.0.0_r65android-security-9.0.0_r64android-security-9.0.0_r63android-security-9.0.0_r62android-cts-9.0_r9android-cts-9.0_r8android-cts-9.0_r7android-cts-9.0_r6android-cts-9.0_r5android-cts-9.0_r4android-cts-9.0_r3android-cts-9.0_r20android-cts-9.0_r2android-cts-9.0_r19android-cts-9.0_r18android-cts-9.0_r17android-cts-9.0_r16android-cts-9.0_r15android-cts-9.0_r14android-cts-9.0_r13android-cts-9.0_r12android-cts-9.0_r11android-cts-9.0_r10android-cts-9.0_r1android-9.0.0_r9android-9.0.0_r8android-9.0.0_r7android-9.0.0_r61android-9.0.0_r60android-9.0.0_r6android-9.0.0_r59android-9.0.0_r58android-9.0.0_r57android-9.0.0_r56android-9.0.0_r55android-9.0.0_r54android-9.0.0_r53android-9.0.0_r52android-9.0.0_r51android-9.0.0_r50android-9.0.0_r5android-9.0.0_r49android-9.0.0_r48android-9.0.0_r3android-9.0.0_r2android-9.0.0_r18android-9.0.0_r17android-9.0.0_r10android-9.0.0_r1security-pi-releasepie-vts-releasepie-security-releasepie-s2-releasepie-release-2pie-releasepie-r2-s2-releasepie-r2-s1-releasepie-r2-releasepie-platform-releasepie-gsipie-cuttlefish-testingpie-cts-release
Change-Id: I3e22914eee11c7539daabc36d1219bb309f546dd
-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.