Snap for 4677756 from b06c82923869f50e9641f7dac56df0aebe637845 to pi-release

Change-Id: I3e22914eee11c7539daabc36d1219bb309f546dd
diff --git a/aidl.cpp b/aidl.cpp
index e0eef0d..88a42f8 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -548,6 +548,7 @@
     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 @@
 
   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 @@
       std::vector<std::string>{},  // no preprocessed files
       options.ImportPaths(),
       options.InputFileName(),
+      options.ShouldGenTraces(),
       io_delegate,
       types.get(),
       &interface,
@@ -710,6 +714,7 @@
       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 2e5b0ee..eb260c0 100644
--- a/aidl.h
+++ b/aidl.h
@@ -58,6 +58,7 @@
     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 7982e76..4119628 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -345,6 +345,14 @@
     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 @@
   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 570ecc7..597a766 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -80,6 +80,7 @@
         preprocessed_files_,
         import_paths_,
         path,
+        false, /* generate_traces */
         io_delegate_,
         types,
         &ret,
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 41e9fb4..7e8892b 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -52,6 +52,7 @@
 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 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 @@
   // 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 @@
   b->AddLiteral(
       StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
                    kAndroidStatusVarName));
+
   b->AddLiteral(StringPrintf("return %s", kStatusVarName));
 
   return unique_ptr<Declaration>(ret.release());
@@ -417,6 +426,7 @@
 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 @@
     }
   }
 
+  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 @@
       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 @@
     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 @@
   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 50bfd9c..32e9362 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -378,6 +378,304 @@
 }  // 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 @@
 }  // 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 @@
         {},  // no preprocessed files
         {"."},
         file_path_,
+        false, // generate_traces
         io_delegate_,
         &types_,
         &ret,
@@ -789,6 +1351,14 @@
   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 @@
   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 ad993a8..522715c 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -342,7 +342,8 @@
   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 @@
                                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 @@
     }
   }
 
+  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 @@
         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_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 @@
   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 @@
     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 std::unique_ptr<Method> generate_proxy_method(
+    const AidlInterface& iface,
     const AidlMethod& method,
     const std::string& transactCodeName,
     bool oneway,
@@ -552,6 +589,14 @@
   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 @@
   }
   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 @@
   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 @@
   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 @@
   // 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 72c7575..3ed110b 100644
--- a/options.cpp
+++ b/options.cpp
@@ -48,6 +48,9 @@
           "   -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 @@
       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 @@
        << "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 @@
       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 6b3ac26..11f3525 100644
--- a/options.h
+++ b/options.h
@@ -54,6 +54,7 @@
   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 @@
   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 @@
   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 @@
   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 344c4c2..555d8dc 100644
--- a/tests/end_to_end_tests.cpp
+++ b/tests/end_to_end_tests.cpp
@@ -92,6 +92,29 @@
   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 ae2c573..0b5aaf0 100644
--- a/tests/test_data.h
+++ b/tests/test_data.h
@@ -33,6 +33,7 @@
 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 731efcd..9b0e0ee 100644
--- a/tests/test_data_example_interface.cpp
+++ b/tests/test_data_example_interface.cpp
@@ -485,6 +485,458 @@
 }
 )";
 
+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.