Snap for 4662252 from 0805f17188b640d2078d1b381b78ca377c44ad08 to pi-release
Change-Id: If8c0f514b759e33a7adf210de632920b7f0480a1
diff --git a/aidl.cpp b/aidl.cpp
index 142f5f2..e0eef0d 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -742,7 +742,7 @@
}
return generate_java(output_file_name, options.input_file_name_.c_str(),
- interface.get(), types.get(), io_delegate);
+ interface.get(), types.get(), io_delegate, options);
}
bool preprocess_aidl(const JavaOptions& options,
diff --git a/generate_java.cpp b/generate_java.cpp
index 30b9f2c..afa188a 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -56,8 +56,8 @@
int generate_java(const string& filename, const string& originalSrc,
AidlInterface* iface, JavaTypeNamespace* types,
- const IoDelegate& io_delegate) {
- Class* cl = generate_binder_interface_class(iface, types);
+ const IoDelegate& io_delegate, const JavaOptions& options) {
+ Class* cl = generate_binder_interface_class(iface, types, options);
Document* document = new Document(
"" /* no comment */,
diff --git a/generate_java.h b/generate_java.h
index ed04ba1..59fed62 100644
--- a/generate_java.h
+++ b/generate_java.h
@@ -26,16 +26,19 @@
namespace android {
namespace aidl {
+class JavaOptions;
+
namespace java {
class JavaTypeNamespace;
int generate_java(const std::string& filename, const std::string& originalSrc,
AidlInterface* iface, java::JavaTypeNamespace* types,
- const IoDelegate& io_delegate);
+ const IoDelegate& io_delegate, const JavaOptions& options);
android::aidl::java::Class* generate_binder_interface_class(
- const AidlInterface* iface, java::JavaTypeNamespace* types);
+ const AidlInterface* iface, java::JavaTypeNamespace* types,
+ const JavaOptions& options);
} // namespace java
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index 8ca5d1b..ad993a8 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -20,9 +20,13 @@
#include <stdlib.h>
#include <string.h>
+#include <algorithm>
+#include <unordered_set>
+
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
+#include "options.h"
#include "type_java.h"
using std::string;
@@ -47,10 +51,18 @@
SwitchStatement* transact_switch;
StatementBlock* transact_statements;
+ // Where onTransact cases should be generated as separate methods.
+ bool transact_outline;
+ // Specific methods that should be outlined when transact_outline is true.
+ std::unordered_set<const AidlMethod*> outline_methods;
+ // Number of all methods.
+ size_t all_method_count;
+
// Finish generation. This will add a default case to the switch.
void finish();
- Expression* get_transact_descriptor(const JavaTypeNamespace* types);
+ Expression* get_transact_descriptor(const JavaTypeNamespace* types,
+ const AidlMethod* method);
private:
void make_as_interface(const InterfaceType* interfaceType,
@@ -65,6 +77,8 @@
JavaTypeNamespace* types)
: Class() {
transact_descriptor = nullptr;
+ transact_outline = false;
+ all_method_count = 0; // Will be set when outlining may be enabled.
this->comment = "/** Local-side IPC implementation stub class. */";
this->modifiers = PUBLIC | ABSTRACT | STATIC;
@@ -138,9 +152,28 @@
transact_statements->Add(this->transact_switch);
}
-Expression* StubClass::get_transact_descriptor(const JavaTypeNamespace* types) {
- // Store the descriptor literal into a local variable, in an effort to save
- // const-string instructions in each switch case.
+// The the expression for the interface's descriptor to be used when
+// generating code for the given method. Null is acceptable for method
+// and stands for synthetic cases.
+Expression* StubClass::get_transact_descriptor(const JavaTypeNamespace* types,
+ const AidlMethod* method) {
+ if (transact_outline) {
+ if (method != nullptr) {
+ // When outlining, each outlined method needs its own literal.
+ if (outline_methods.count(method) != 0) {
+ return new LiteralExpression("DESCRIPTOR");
+ }
+ } else {
+ // Synthetic case. A small number is assumed. Use its own descriptor
+ // if there are only synthetic cases.
+ if (outline_methods.size() == all_method_count) {
+ return new LiteralExpression("DESCRIPTOR");
+ }
+ }
+ }
+
+ // When not outlining, store the descriptor literal into a local variable, in
+ // an effort to save const-string instructions in each switch case.
if (transact_descriptor == nullptr) {
transact_descriptor = new Variable(types->StringType(), "descriptor");
transact_statements->Add(
@@ -322,7 +355,8 @@
// interface token validation is the very first thing we do
statements->Add(new MethodCall(transact_data,
"enforceInterface", 1,
- stubClass->get_transact_descriptor(types)));
+ stubClass->get_transact_descriptor(types,
+ &method)));
// args
VariableFactory stubArgs("_arg");
@@ -428,6 +462,51 @@
stubClass->transact_switch->cases.push_back(c);
}
+static void generate_stub_case_outline(const AidlMethod& method,
+ const std::string& transactCodeName,
+ bool oneway,
+ StubClass* stubClass,
+ JavaTypeNamespace* types) {
+ std::string outline_name = "onTransact$" + method.GetName() + "$";
+ // Generate an "outlined" method with the actual code.
+ {
+ Variable* transact_data = new Variable(types->ParcelType(), "data");
+ Variable* transact_reply = new Variable(types->ParcelType(), "reply");
+ Method* onTransact_case = new Method;
+ onTransact_case->modifiers = PRIVATE;
+ onTransact_case->returnType = types->BoolType();
+ onTransact_case->name = outline_name;
+ onTransact_case->parameters.push_back(transact_data);
+ onTransact_case->parameters.push_back(transact_reply);
+ onTransact_case->statements = new StatementBlock;
+ onTransact_case->exceptions.push_back(types->RemoteExceptionType());
+ stubClass->elements.push_back(onTransact_case);
+
+ generate_stub_code(method,
+ transactCodeName,
+ oneway,
+ transact_data,
+ transact_reply,
+ types,
+ onTransact_case->statements,
+ stubClass);
+ }
+
+ // Generate the case dispatch.
+ {
+ Case* c = new Case(transactCodeName);
+
+ MethodCall* helper_call = new MethodCall(THIS_VALUE,
+ outline_name,
+ 2,
+ stubClass->transact_data,
+ stubClass->transact_reply);
+ c->statements->Add(new ReturnStatement(helper_call));
+
+ stubClass->transact_switch->cases.push_back(c);
+ }
+}
+
static std::unique_ptr<Method> generate_proxy_method(
const AidlMethod& method,
const std::string& transactCodeName,
@@ -566,7 +645,17 @@
interface->elements.push_back(decl);
// == the stub method ====================================================
- generate_stub_case(method, transactCodeName, oneway, stubClass, types);
+ bool outline_stub = stubClass->transact_outline &&
+ stubClass->outline_methods.count(&method) != 0;
+ if (outline_stub) {
+ generate_stub_case_outline(method,
+ transactCodeName,
+ oneway,
+ stubClass,
+ types);
+ } else {
+ generate_stub_case(method, transactCodeName, oneway, stubClass, types);
+ }
// == the proxy method ===================================================
Method* proxy = generate_proxy_method(method,
@@ -582,7 +671,8 @@
// the interface descriptor transaction handler
Case* c = new Case("INTERFACE_TRANSACTION");
c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1,
- stub->get_transact_descriptor(types)));
+ stub->get_transact_descriptor(types,
+ nullptr)));
c->statements->Add(new ReturnStatement(TRUE_VALUE));
stub->transact_switch->cases.push_back(c);
@@ -598,8 +688,47 @@
proxy->elements.push_back(getDesc);
}
+// Check whether (some) methods in this interface should be "outlined," that
+// is, have specific onTransact methods for certain cases. Set up StubClass
+// metadata accordingly.
+//
+// Outlining will be enabled if the interface has more than outline_threshold
+// methods. In that case, the methods are sorted by number of arguments
+// (so that more "complex" methods come later), and the first non_outline_count
+// number of methods not outlined (are kept in the onTransact() method).
+//
+// Requirements: non_outline_count <= outline_threshold.
+static void compute_outline_methods(const AidlInterface* iface,
+ StubClass* stub,
+ size_t outline_threshold,
+ size_t non_outline_count) {
+ CHECK_LE(non_outline_count, outline_threshold);
+ // We'll outline (create sub methods) if there are more than min_methods
+ // cases.
+ stub->transact_outline = iface->GetMethods().size() > outline_threshold;
+ if (stub->transact_outline) {
+ stub->all_method_count = iface->GetMethods().size();
+ std::vector<const AidlMethod*> methods;
+ methods.reserve(iface->GetMethods().size());
+ for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
+ methods.push_back(ptr.get());
+ }
+
+ std::stable_sort(
+ methods.begin(),
+ methods.end(),
+ [](const AidlMethod* m1, const AidlMethod* m2) {
+ return m1->GetArguments().size() < m2->GetArguments().size();
+ });
+
+ stub->outline_methods.insert(methods.begin() + non_outline_count,
+ methods.end());
+ }
+}
+
Class* generate_binder_interface_class(const AidlInterface* iface,
- JavaTypeNamespace* types) {
+ JavaTypeNamespace* types,
+ const JavaOptions& options) {
const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>();
// the interface class
@@ -615,6 +744,11 @@
new StubClass(interfaceType->GetStub(), interfaceType, types);
interface->elements.push_back(stub);
+ compute_outline_methods(iface,
+ stub,
+ options.onTransact_outline_threshold_,
+ options.onTransact_non_outline_count_);
+
// the proxy inner class
ProxyClass* proxy =
new ProxyClass(types, interfaceType->GetProxy(), interfaceType);
@@ -632,8 +766,14 @@
}
// all the declared methods of the interface
+
for (const auto& item : iface->GetMethods()) {
- generate_methods(*item, interface, stub, proxy, item->GetId(), types);
+ generate_methods(*item,
+ interface,
+ stub,
+ proxy,
+ item->GetId(),
+ types);
}
stub->finish();
diff --git a/options.h b/options.h
index 89a4412..6b3ac26 100644
--- a/options.h
+++ b/options.h
@@ -56,10 +56,18 @@
bool dep_file_ninja_{false};
std::vector<std::string> files_to_preprocess_;
+ // The following are for testability, but cannot be influenced on the command line.
+
+ // Threshold of interface methods to enable outlining of onTransact cases.
+ size_t onTransact_outline_threshold_{275u};
+ // Number of cases to _not_ outline, if outlining is enabled.
+ size_t onTransact_non_outline_count_{275u};
+
private:
JavaOptions() = default;
FRIEND_TEST(EndToEndTest, IExampleInterface);
+ FRIEND_TEST(EndToEndTest, IExampleInterface_Outlining);
FRIEND_TEST(AidlTest, FailOnParcelable);
FRIEND_TEST(AidlTest, WritePreprocessedFile);
FRIEND_TEST(AidlTest, WritesCorrectDependencyFile);
diff --git a/tests/end_to_end_tests.cpp b/tests/end_to_end_tests.cpp
index 480bfd9..344c4c2 100644
--- a/tests/end_to_end_tests.cpp
+++ b/tests/end_to_end_tests.cpp
@@ -92,6 +92,30 @@
CheckFileContents(options.DependencyFilePath(), kExpectedJavaDepsOutput);
}
+TEST_F(EndToEndTest, IExampleInterface_Outlining) {
+ 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.onTransact_outline_threshold_ = 4;
+ options.onTransact_non_outline_count_ = 3;
+
+ // Load up our fake file system with data.
+ io_delegate_.SetFileContents(options.input_file_name_, kInterfaceDefinitionOutlining);
+ 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, kExpectedJavaOutputOutlining);
+ CheckFileContents(options.DependencyFilePath(), kExpectedJavaDepsOutput);
+}
+
TEST_F(EndToEndTest, IPingResponderCpp) {
using namespace ::android::aidl::test_data::ping_responder;
diff --git a/tests/test_data.h b/tests/test_data.h
index d3a5f6c..ae2c573 100644
--- a/tests/test_data.h
+++ b/tests/test_data.h
@@ -26,11 +26,13 @@
extern const char kCanonicalName[];
extern const char kJavaOutputPath[];
extern const char kInterfaceDefinition[];
+extern const char kInterfaceDefinitionOutlining[];
extern const char* kImportedParcelables[];
extern const char* kImportedInterfaces[];
extern const char kExpectedJavaDepsOutput[];
extern const char kExpectedJavaOutput[];
+extern const char kExpectedJavaOutputOutlining[];
} // namespace example_interface
diff --git a/tests/test_data_example_interface.cpp b/tests/test_data_example_interface.cpp
index 81b919f..731efcd 100644
--- a/tests/test_data_example_interface.cpp
+++ b/tests/test_data_example_interface.cpp
@@ -67,6 +67,37 @@
}
)";
+const char kInterfaceDefinitionOutlining[] = R"(
+package android.test;
+
+import android.foo.ExampleParcelable;
+import android.test.CompoundParcelable;
+import android.bar.IAuxInterface;
+import android.test.IAuxInterface2;
+
+interface IExampleInterface {
+ const int EXAMPLE_CONSTANT = 3;
+ boolean isEnabled();
+ int getState(int a, int b);
+ String getAddress();
+
+ /* Test long comment */
+ ExampleParcelable[] getParcelables();
+
+ // Test short comment
+ boolean setScanMode(int mode, int duration);
+
+ /* Test long comment */
+ // And short comment
+ void registerBinder(IAuxInterface foo);
+ IExampleInterface getRecursiveBinder();
+
+ int takesAnInterface(in IAuxInterface2 arg);
+ int takesAParcelable(in CompoundParcelable.Subclass1 arg,
+ inout CompoundParcelable.Subclass2 arg2);
+}
+)";
+
const char kExpectedJavaDepsOutput[] =
R"(some/path/to/output.java : \
android/test/IExampleInterface.aidl \
@@ -120,16 +151,17 @@
}
@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);
+reply.writeString(descriptor);
return true;
}
case TRANSACTION_isEnabled:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
boolean _result = this.isEnabled();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
@@ -137,7 +169,7 @@
}
case TRANSACTION_getState:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
int _result = this.getState();
reply.writeNoException();
reply.writeInt(_result);
@@ -145,7 +177,7 @@
}
case TRANSACTION_getAddress:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
java.lang.String _result = this.getAddress();
reply.writeNoException();
reply.writeString(_result);
@@ -153,7 +185,7 @@
}
case TRANSACTION_getParcelables:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
android.foo.ExampleParcelable[] _result = this.getParcelables();
reply.writeNoException();
reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
@@ -161,7 +193,7 @@
}
case TRANSACTION_setScanMode:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
@@ -173,7 +205,7 @@
}
case TRANSACTION_registerBinder:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
android.bar.IAuxInterface _arg0;
_arg0 = android.bar.IAuxInterface.Stub.asInterface(data.readStrongBinder());
this.registerBinder(_arg0);
@@ -182,7 +214,7 @@
}
case TRANSACTION_getRecursiveBinder:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
android.test.IExampleInterface _result = this.getRecursiveBinder();
reply.writeNoException();
reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
@@ -190,7 +222,7 @@
}
case TRANSACTION_takesAnInterface:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
android.test.IAuxInterface2 _arg0;
_arg0 = android.test.IAuxInterface2.Stub.asInterface(data.readStrongBinder());
int _result = this.takesAnInterface(_arg0);
@@ -200,7 +232,7 @@
}
case TRANSACTION_takesAParcelable:
{
-data.enforceInterface(DESCRIPTOR);
+data.enforceInterface(descriptor);
android.test.CompoundParcelable.Subclass1 _arg0;
if ((0!=data.readInt())) {
_arg0 = android.test.CompoundParcelable.Subclass1.CREATOR.createFromParcel(data);
@@ -227,9 +259,12 @@
}
return true;
}
-}
+default:
+{
return super.onTransact(code, data, reply, flags);
}
+}
+}
private static class Proxy implements android.test.IExampleInterface
{
private android.os.IBinder mRemote;
@@ -450,6 +485,408 @@
}
)";
+const char kExpectedJavaOutputOutlining[] =
+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 = this.isEnabled();
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+case TRANSACTION_getState:
+{
+return this.onTransact$getState$(data, reply);
+}
+case TRANSACTION_getAddress:
+{
+data.enforceInterface(descriptor);
+java.lang.String _result = this.getAddress();
+reply.writeNoException();
+reply.writeString(_result);
+return true;
+}
+case TRANSACTION_getParcelables:
+{
+data.enforceInterface(descriptor);
+android.foo.ExampleParcelable[] _result = this.getParcelables();
+reply.writeNoException();
+reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+return true;
+}
+case TRANSACTION_setScanMode:
+{
+return this.onTransact$setScanMode$(data, reply);
+}
+case TRANSACTION_registerBinder:
+{
+return this.onTransact$registerBinder$(data, reply);
+}
+case TRANSACTION_getRecursiveBinder:
+{
+return this.onTransact$getRecursiveBinder$(data, reply);
+}
+case TRANSACTION_takesAnInterface:
+{
+return this.onTransact$takesAnInterface$(data, reply);
+}
+case TRANSACTION_takesAParcelable:
+{
+return this.onTransact$takesAParcelable$(data, reply);
+}
+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 {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_isEnabled, _data, _reply, 0);
+_reply.readException();
+_result = (0!=_reply.readInt());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public int getState(int a, int b) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+int _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeInt(a);
+_data.writeInt(b);
+mRemote.transact(Stub.TRANSACTION_getState, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readInt();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+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 {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getAddress, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readString();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+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 {
+_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();
+}
+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 {
+_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();
+}
+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 {
+_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();
+}
+}
+@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 {
+_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();
+}
+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 {
+_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();
+}
+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 {
+_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();
+}
+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);
+private boolean onTransact$getState$(android.os.Parcel data, android.os.Parcel reply) throws android.os.RemoteException
+{
+data.enforceInterface(DESCRIPTOR);
+int _arg0;
+_arg0 = data.readInt();
+int _arg1;
+_arg1 = data.readInt();
+int _result = this.getState(_arg0, _arg1);
+reply.writeNoException();
+reply.writeInt(_result);
+return true;
+}
+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);
+private boolean onTransact$setScanMode$(android.os.Parcel data, android.os.Parcel reply) throws android.os.RemoteException
+{
+data.enforceInterface(DESCRIPTOR);
+int _arg0;
+_arg0 = data.readInt();
+int _arg1;
+_arg1 = data.readInt();
+boolean _result = this.setScanMode(_arg0, _arg1);
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+static final int TRANSACTION_registerBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
+private boolean onTransact$registerBinder$(android.os.Parcel data, android.os.Parcel reply) throws android.os.RemoteException
+{
+data.enforceInterface(DESCRIPTOR);
+android.bar.IAuxInterface _arg0;
+_arg0 = android.bar.IAuxInterface.Stub.asInterface(data.readStrongBinder());
+this.registerBinder(_arg0);
+reply.writeNoException();
+return true;
+}
+static final int TRANSACTION_getRecursiveBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
+private boolean onTransact$getRecursiveBinder$(android.os.Parcel data, android.os.Parcel reply) throws android.os.RemoteException
+{
+data.enforceInterface(DESCRIPTOR);
+android.test.IExampleInterface _result = this.getRecursiveBinder();
+reply.writeNoException();
+reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
+return true;
+}
+static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
+private boolean onTransact$takesAnInterface$(android.os.Parcel data, android.os.Parcel reply) throws android.os.RemoteException
+{
+data.enforceInterface(DESCRIPTOR);
+android.test.IAuxInterface2 _arg0;
+_arg0 = android.test.IAuxInterface2.Stub.asInterface(data.readStrongBinder());
+int _result = this.takesAnInterface(_arg0);
+reply.writeNoException();
+reply.writeInt(_result);
+return true;
+}
+static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
+private boolean onTransact$takesAParcelable$(android.os.Parcel data, android.os.Parcel reply) throws android.os.RemoteException
+{
+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 = this.takesAParcelable(_arg0, _arg1);
+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;
+}
+}
+public static final int EXAMPLE_CONSTANT = 3;
+public boolean isEnabled() throws android.os.RemoteException;
+public int getState(int a, int b) 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;
+}
+)";
+
} // namespace example_interface
} // namespace test_data
} // namespace aidl
diff --git a/tests/test_data_string_constants.cpp b/tests/test_data_string_constants.cpp
index 4674843..1fb84d2 100644
--- a/tests/test_data_string_constants.cpp
+++ b/tests/test_data_string_constants.cpp
@@ -69,16 +69,20 @@
}
@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);
+reply.writeString(descriptor);
return true;
}
-}
+default:
+{
return super.onTransact(code, data, reply, flags);
}
+}
+}
private static class Proxy implements android.os.IStringConstants
{
private android.os.IBinder mRemote;