From 5a7cbce2e68af89b5299e2c039cfc62e4314e561 Mon Sep 17 00:00:00 2001 From: Luis Vidal Date: Wed, 22 Jun 2016 17:17:52 -0700 Subject: AIDL: Add option to generate No-Op methods Add the option to generate a default (no-op) implementation of an interface (cyanogen: Refactor for CM14) Change-Id: I2631e93c8b85e056cf928e9592342dc4466f293e --- aidl.cpp | 7 +++- generate_java.cpp | 4 +-- generate_java.h | 8 +++-- generate_java_binder.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++++-- options.cpp | 3 ++ options.h | 1 + type_java.cpp | 14 ++++++-- type_java.h | 4 ++- 8 files changed, 120 insertions(+), 11 deletions(-) diff --git a/aidl.cpp b/aidl.cpp index 1815e56..a24d1ab 100644 --- a/aidl.cpp +++ b/aidl.cpp @@ -703,8 +703,13 @@ int compile_aidl_to_java(const JavaOptions& options, return 1; } + unsigned int flags = 0; + if (options.generate_no_op_methods_) { + flags |= GENERATE_NO_OP_CLASS; + } + return generate_java(output_file_name, options.input_file_name_.c_str(), - interface.get(), types.get(), io_delegate); + interface.get(), types.get(), io_delegate, flags); } bool preprocess_aidl(const JavaOptions& options, diff --git a/generate_java.cpp b/generate_java.cpp index 14df353..3d485d9 100644 --- a/generate_java.cpp +++ b/generate_java.cpp @@ -56,8 +56,8 @@ namespace java { 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, unsigned int flags) { + Class* cl = generate_binder_interface_class(iface, types, flags); Document* document = new Document( "" /* no comment */, diff --git a/generate_java.h b/generate_java.h index 6719030..2baa77f 100644 --- a/generate_java.h +++ b/generate_java.h @@ -32,10 +32,11 @@ 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, unsigned int flags); android::aidl::java::Class* generate_binder_interface_class( - const AidlInterface* iface, java::JavaTypeNamespace* types); + const AidlInterface* iface, java::JavaTypeNamespace* types, + unsigned int flags); } // namespace java @@ -59,4 +60,7 @@ class VariableFactory { } // namespace android } // namespace aidl +// Flags that can be passed to generate_java +#define GENERATE_NO_OP_CLASS 1 << 0 + #endif // AIDL_GENERATE_JAVA_H_ diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp index 87d8d0c..035b265 100644 --- a/generate_java_binder.cpp +++ b/generate_java_binder.cpp @@ -219,6 +219,36 @@ ProxyClass::ProxyClass(const JavaTypeNamespace* types, const Type* type, ProxyClass::~ProxyClass() {} +// ================================================= +class DefaultNoOpClass : public Class { + public: + DefaultNoOpClass(const JavaTypeNamespace* types, const Type* type, + const InterfaceType* interfaceType); + virtual ~DefaultNoOpClass(); +}; + +DefaultNoOpClass::DefaultNoOpClass(const JavaTypeNamespace* types, const Type* type, + const InterfaceType* interfaceType) + : Class() { + this->comment = "/** No-Op implementation */"; + this->comment += "\n/** @hide */"; + this->modifiers = PUBLIC | STATIC; + this->what = Class::CLASS; + this->type = type; + this->interfaces.push_back(interfaceType); + + // IBinder asBinder() + Method* asBinder = new Method; + asBinder->modifiers = PUBLIC | OVERRIDE; + asBinder->returnType = types->IBinderType(); + asBinder->name = "asBinder"; + asBinder->statements = new StatementBlock; + asBinder->statements->Add(new ReturnStatement(NULL_VALUE)); + this->elements.push_back(asBinder); +} + +DefaultNoOpClass::~DefaultNoOpClass() {} + // ================================================= static void generate_new_array(const Type* t, StatementBlock* addTo, Variable* v, Variable* parcel, @@ -259,8 +289,22 @@ static void generate_constant(const AidlConstant& constant, Class* interface) { interface->elements.push_back(decl); } +static bool is_numeric_java_type(const std::string name) { + static const char* KEYWORDS[] = { "int", "byte", "char", "float", "double", + "short", "long", NULL }; + const char** k = KEYWORDS; + while (*k) { + if (name == *k) { + return true; + } + k++; + } + return false; +} + static void generate_method(const AidlMethod& method, Class* interface, StubClass* stubClass, ProxyClass* proxyClass, + DefaultNoOpClass *noOpClass, int index, JavaTypeNamespace* types) { int i; bool hasOutParams = false; @@ -304,6 +348,39 @@ static void generate_method(const AidlMethod& method, Class* interface, interface->elements.push_back(decl); + // == the no-op method =================================================== + + if (noOpClass != NULL) { + Method* noOpMethod = new Method; + noOpMethod->comment = method.GetComments(); + noOpMethod->modifiers = OVERRIDE | PUBLIC; + noOpMethod->returnType = method.GetType().GetLanguageType(); + noOpMethod->returnTypeDimension = method.GetType().IsArray() ? 1 : 0; + noOpMethod->name = method.GetName(); + noOpMethod->statements = new StatementBlock; + for (const std::unique_ptr& arg : method.GetArguments()) { + noOpMethod->parameters.push_back( + new Variable(arg->GetType().GetLanguageType(), arg->GetName(), + arg->GetType().IsArray() ? 1 : 0)); + } + + std::string typeName = method.GetType().GetLanguageType()->JavaType(); + if (typeName != "void") { + bool isNumeric = is_numeric_java_type(typeName); + bool isBoolean = typeName == "boolean"; + + if (isNumeric && !method.GetType().IsArray()) { + noOpMethod->statements->Add(new ReturnStatement(new LiteralExpression("0"))); + } else if (isBoolean && !method.GetType().IsArray()) { + noOpMethod->statements->Add(new ReturnStatement(FALSE_VALUE)); + } else { + noOpMethod->statements->Add(new ReturnStatement(NULL_VALUE)); + } + } + noOpMethod->exceptions.push_back(types->RemoteExceptionType()); + noOpClass->elements.push_back(noOpMethod); + } + // == the stub method ==================================================== Case* c = new Case(transactCodeName); @@ -514,7 +591,8 @@ static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy, } Class* generate_binder_interface_class(const AidlInterface* iface, - JavaTypeNamespace* types) { + JavaTypeNamespace* types, + unsigned int flags) { const InterfaceType* interfaceType = iface->GetLanguageType(); // the interface class @@ -525,6 +603,14 @@ Class* generate_binder_interface_class(const AidlInterface* iface, interface->type = interfaceType; interface->interfaces.push_back(types->IInterfaceType()); + // the No-Op inner class + DefaultNoOpClass* noOpClass = NULL; + if ((flags & GENERATE_NO_OP_CLASS) != 0) { + noOpClass = + new DefaultNoOpClass(types, interfaceType->GetNoOp(), interfaceType); + interface->elements.push_back(noOpClass); + } + // the stub inner class StubClass* stub = new StubClass(interfaceType->GetStub(), interfaceType, types); @@ -545,7 +631,7 @@ Class* generate_binder_interface_class(const AidlInterface* iface, // all the declared methods of the interface for (const auto& item : iface->GetMethods()) { - generate_method(*item, interface, stub, proxy, item->GetId(), types); + generate_method(*item, interface, stub, proxy, noOpClass, item->GetId(), types); } return interface; diff --git a/options.cpp b/options.cpp index c7cef5c..b7d0512 100644 --- a/options.cpp +++ b/options.cpp @@ -46,6 +46,7 @@ unique_ptr java_usage() { " -p file created by --preprocess to import.\n" " -o base output folder for generated files.\n" " -b fail when trying to compile a parcelable.\n" + " -n generate no-op classes.\n" "\n" "INPUT:\n" " An aidl interface file.\n" @@ -122,6 +123,8 @@ unique_ptr JavaOptions::Parse(int argc, const char* const* argv) { } } else if (strcmp(s, "-b") == 0) { options->fail_on_parcelable_ = true; + } else if (s[1] == 'n') { + options->generate_no_op_methods_ = true; } else { // s[1] is not known fprintf(stderr, "unknown option (%d): %s\n", i, s); diff --git a/options.h b/options.h index 6f32c62..844190c 100644 --- a/options.h +++ b/options.h @@ -53,6 +53,7 @@ class JavaOptions final { std::string dep_file_name_; bool auto_dep_file_{false}; std::vector files_to_preprocess_; + bool generate_no_op_methods_{false}; private: JavaOptions() = default; diff --git a/type_java.cpp b/type_java.cpp index 18d27a2..0e9be88 100644 --- a/type_java.cpp +++ b/type_java.cpp @@ -682,13 +682,15 @@ void UserDataArrayType::ReadFromParcel(StatementBlock* addTo, Variable* v, InterfaceType::InterfaceType(const JavaTypeNamespace* types, const string& package, const string& name, bool builtIn, bool oneway, const string& declFile, - int declLine, const Type* stub, const Type* proxy) + int declLine, const Type* stub, const Type* proxy, + const Type* no_op) : Type(types, package, name, builtIn ? ValidatableType::KIND_BUILT_IN : ValidatableType::KIND_INTERFACE, true, false, declFile, declLine), m_oneway(oneway), stub_(stub), - proxy_(proxy) {} + proxy_(proxy), + no_op_(no_op) {} bool InterfaceType::OneWay() const { return m_oneway; } @@ -877,14 +879,20 @@ bool JavaTypeNamespace::AddBinderType(const AidlInterface& b, b.GetName() + ".Stub.Proxy", ValidatableType::KIND_GENERATED, false, false, filename, b.GetLine()); + Type* no_op = new Type(this, b.GetPackage(), + b.GetName() + ".NoOp", + ValidatableType::KIND_GENERATED, + false, false, filename, b.GetLine()); + Type* type = new InterfaceType(this, b.GetPackage(), b.GetName(), false, - b.IsOneway(), filename, b.GetLine(), stub, proxy); + b.IsOneway(), filename, b.GetLine(), stub, proxy, no_op); bool success = true; success &= Add(type); success &= Add(stub); success &= Add(proxy); + success &= Add(no_op); return success; } diff --git a/type_java.h b/type_java.h index f74fd62..ac48de3 100644 --- a/type_java.h +++ b/type_java.h @@ -388,7 +388,7 @@ class InterfaceType : public Type { InterfaceType(const JavaTypeNamespace* types, const std::string& package, const std::string& name, bool builtIn, bool oneway, const std::string& declFile, int declLine, const Type* stub, - const Type* proxy); + const Type* proxy, const Type* no_op); bool OneWay() const; @@ -398,11 +398,13 @@ class InterfaceType : public Type { Variable** cl) const override; const Type* GetStub() const { return stub_; } const Type* GetProxy() const { return proxy_; } + const Type* GetNoOp() const { return no_op_; } private: bool m_oneway; const Type* stub_; const Type* proxy_; + const Type* no_op_; }; class ClassLoaderType : public Type { -- cgit v1.2.3