diff options
author | Jooyung Han <jooyung@google.com> | 2020-12-01 12:41:50 +0900 |
---|---|---|
committer | Jooyung Han <jooyung@google.com> | 2020-12-03 00:40:48 +0000 |
commit | 3f347ca3625b82dea5207919fe1816da3924a49a (patch) | |
tree | d5e84bcc53e911c2a580aa1027c8a4cc93794556 | |
parent | 717fc697942ccd4e35ac3616806959b57a80dcc9 (diff) | |
download | aidl-3f347ca3625b82dea5207919fe1816da3924a49a.tar.gz |
support const in parcelable/union
const values are now available in parcelable/union as well as interface.
Bug: 173225412
Test: CtsNdkBinderTestCases
Test: aidl_unittests
Test: aidl_integration_test
Change-Id: Ifab53c6b0e6674710f1206b7d2e2ca677d5430c6
-rw-r--r-- | aidl.cpp | 19 | ||||
-rw-r--r-- | aidl_checkapi.cpp | 61 | ||||
-rw-r--r-- | aidl_language.cpp | 57 | ||||
-rw-r--r-- | aidl_language.h | 74 | ||||
-rw-r--r-- | aidl_language_y.yy | 37 | ||||
-rw-r--r-- | aidl_unittest.cpp | 56 | ||||
-rw-r--r-- | generate_cpp.cpp | 128 | ||||
-rw-r--r-- | generate_java.cpp | 6 | ||||
-rw-r--r-- | generate_java.h | 3 | ||||
-rw-r--r-- | generate_java_binder.cpp | 41 | ||||
-rw-r--r-- | generate_ndk.cpp | 21 | ||||
-rw-r--r-- | generate_rust.cpp | 41 | ||||
-rw-r--r-- | tests/aidl_test_client_parcelables.cpp | 4 | ||||
-rw-r--r-- | tests/aidl_test_service.cpp | 3 | ||||
-rw-r--r-- | tests/android/aidl/tests/StructuredParcelable.aidl | 6 | ||||
-rw-r--r-- | tests/android/aidl/tests/Union.aidl | 2 | ||||
-rw-r--r-- | tests/java/src/android/aidl/tests/TestServiceClient.java | 8 | ||||
-rw-r--r-- | tests/rust/test_client.rs | 5 | ||||
-rw-r--r-- | tests/rust/test_service.rs | 4 |
19 files changed, 374 insertions, 202 deletions
@@ -389,7 +389,7 @@ bool parse_preprocessed_file(const IoDelegate& io_delegate, const string& filena AidlParcelable* doc = new AidlParcelable(location, class_name, package, "" /* comments */); typenames->AddPreprocessedType(unique_ptr<AidlParcelable>(doc)); } else if (decl == "structured_parcelable") { - auto temp = new std::vector<std::unique_ptr<AidlVariableDeclaration>>(); + auto temp = new std::vector<std::unique_ptr<AidlMember>>(); AidlStructuredParcelable* doc = new AidlStructuredParcelable( location, class_name, package, "" /* comments */, temp, nullptr); typenames->AddPreprocessedType(unique_ptr<AidlStructuredParcelable>(doc)); @@ -647,10 +647,10 @@ AidlError load_and_validate_aidl(const std::string& input_file_name, const Optio new AidlTypeSpecifier(AIDL_LOCATION_HERE, "int", false, nullptr, ""); ret->Resolve(*typenames); vector<unique_ptr<AidlArgument>>* args = new vector<unique_ptr<AidlArgument>>(); - AidlMethod* method = - new AidlMethod(AIDL_LOCATION_HERE, false, ret, "getInterfaceVersion", args, "", - kGetInterfaceVersionId, false /* is_user_defined */); - interface->GetMutableMethods().emplace_back(method); + auto method = std::make_unique<AidlMethod>( + AIDL_LOCATION_HERE, false, ret, "getInterfaceVersion", args, "", kGetInterfaceVersionId, + false /* is_user_defined */); + interface->AddMethod(std::move(method)); } // add the meta-method 'string getInterfaceHash()' if hash is specified. if (!options.Hash().empty()) { @@ -658,9 +658,10 @@ AidlError load_and_validate_aidl(const std::string& input_file_name, const Optio new AidlTypeSpecifier(AIDL_LOCATION_HERE, "String", false, nullptr, ""); ret->Resolve(*typenames); vector<unique_ptr<AidlArgument>>* args = new vector<unique_ptr<AidlArgument>>(); - AidlMethod* method = new AidlMethod(AIDL_LOCATION_HERE, false, ret, kGetInterfaceHash, args, - "", kGetInterfaceHashId, false /* is_user_defined */); - interface->GetMutableMethods().emplace_back(method); + auto method = + std::make_unique<AidlMethod>(AIDL_LOCATION_HERE, false, ret, kGetInterfaceHash, args, + "", kGetInterfaceHashId, false /* is_user_defined */); + interface->AddMethod(std::move(method)); } if (!check_and_assign_method_ids(interface->GetMethods())) { return AidlError::BAD_METHOD_ID; @@ -727,7 +728,7 @@ AidlError load_and_validate_aidl(const std::string& input_file_name, const Optio } }; const AidlInterface* iface = type.AsInterface(); - const AidlWithFields* data_structure = type.AsStructuredParcelable(); + const AidlWithMembers* data_structure = type.AsStructuredParcelable(); if (!data_structure) { data_structure = type.AsUnionDeclaration(); } diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp index d752f449..2dfbdae9 100644 --- a/aidl_checkapi.cpp +++ b/aidl_checkapi.cpp @@ -101,6 +101,39 @@ static bool are_compatible_types(const AidlTypeSpecifier& older, const AidlTypeS return compatible; } +template <typename TypeWithConstants> +static bool are_compatible_constants(const TypeWithConstants& older, + const TypeWithConstants& newer) { + bool compatible = true; + + map<string, AidlConstantDeclaration*> new_constdecls; + for (const auto& c : newer.GetConstantDeclarations()) { + new_constdecls[c->GetName()] = &*c; + } + + for (const auto& old_c : older.GetConstantDeclarations()) { + const auto found = new_constdecls.find(old_c->GetName()); + if (found == new_constdecls.end()) { + AIDL_ERROR(old_c) << "Removed constant declaration: " << older.GetCanonicalName() << "." + << old_c->GetName(); + compatible = false; + continue; + } + + const auto new_c = found->second; + compatible &= are_compatible_types(old_c->GetType(), new_c->GetType()); + + const string old_value = old_c->ValueString(AidlConstantValueDecorator); + const string new_value = new_c->ValueString(AidlConstantValueDecorator); + if (old_value != new_value) { + AIDL_ERROR(newer) << "Changed constant value: " << older.GetCanonicalName() << "." + << old_c->GetName() << " from " << old_value << " to " << new_value << "."; + compatible = false; + } + } + return compatible; +} + static bool are_compatible_interfaces(const AidlInterface& older, const AidlInterface& newer) { bool compatible = true; @@ -155,31 +188,8 @@ static bool are_compatible_interfaces(const AidlInterface& older, const AidlInte } } - map<string, AidlConstantDeclaration*> new_constdecls; - for (const auto& c : newer.AsInterface()->GetConstantDeclarations()) { - new_constdecls.emplace(c->GetName(), c.get()); - } + compatible = are_compatible_constants(older, newer) && compatible; - for (const auto& old_c : older.AsInterface()->GetConstantDeclarations()) { - const auto found = new_constdecls.find(old_c->GetName()); - if (found == new_constdecls.end()) { - AIDL_ERROR(old_c) << "Removed constant declaration: " << older.GetCanonicalName() << "." - << old_c->GetName(); - compatible = false; - continue; - } - - const auto new_c = found->second; - compatible &= are_compatible_types(old_c->GetType(), new_c->GetType()); - - const string old_value = old_c->ValueString(AidlConstantValueDecorator); - const string new_value = new_c->ValueString(AidlConstantValueDecorator); - if (old_value != new_value) { - AIDL_ERROR(newer) << "Changed constant value: " << older.GetCanonicalName() << "." - << old_c->GetName() << " from " << old_value << " to " << new_value << "."; - compatible = false; - } - } return compatible; } @@ -310,6 +320,9 @@ static bool are_compatible_parcelables(const ParcelableType& older, const AidlTy "cause a semantic change to this parcelable."; compatible = false; } + + compatible = are_compatible_constants(older, newer) && compatible; + return compatible; } diff --git a/aidl_language.cpp b/aidl_language.cpp index b541a7b7..e2881fa6 100644 --- a/aidl_language.cpp +++ b/aidl_language.cpp @@ -595,7 +595,7 @@ AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location, AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location, AidlTypeSpecifier* type, const std::string& name, AidlConstantValue* default_value) - : AidlNode(location), + : AidlMember(location), type_(type), name_(name), default_user_specified_(true), @@ -860,8 +860,21 @@ void AidlParcelable::Dump(CodeWriter* writer) const { writer->Write("parcelable %s ;\n", GetName().c_str()); } -bool AidlWithFields::CheckValid(const AidlParcelable& parcel, - const AidlTypenames& typenames) const { +AidlWithMembers::AidlWithMembers(vector<unique_ptr<AidlMember>>* members) { + for (auto& m : *members) { + if (auto constant = m->AsConstantDeclaration(); constant) { + constants_.emplace_back(constant); + } else if (auto variable = m->AsVariableDeclaration(); variable) { + variables_.emplace_back(variable); + } else { + AIDL_FATAL(*m); + } + m.release(); + } +} + +bool AidlWithMembers::CheckValid(const AidlParcelable& parcel, + const AidlTypenames& typenames) const { bool success = true; for (const auto& v : GetFields()) { @@ -891,10 +904,20 @@ bool AidlWithFields::CheckValid(const AidlParcelable& parcel, } } + set<string> constant_names; + for (const auto& constant : GetConstantDeclarations()) { + if (constant_names.count(constant->GetName()) > 0) { + AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'"; + success = false; + } + constant_names.insert(constant->GetName()); + success = success && constant->CheckValid(typenames); + } + return success; } -bool AidlWithFields::CheckValidForGetterNames(const AidlParcelable& parcel) const { +bool AidlWithMembers::CheckValidForGetterNames(const AidlParcelable& parcel) const { bool success = true; std::set<std::string> getters; for (const auto& v : GetFields()) { @@ -910,10 +933,10 @@ bool AidlWithFields::CheckValidForGetterNames(const AidlParcelable& parcel) cons AidlStructuredParcelable::AidlStructuredParcelable( const AidlLocation& location, const std::string& name, const std::string& package, - const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables, + const std::string& comments, std::vector<std::unique_ptr<AidlMember>>* members, std::vector<std::string>* type_params) : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params), - AidlWithFields(variables) {} + AidlWithMembers(members) {} void AidlStructuredParcelable::Dump(CodeWriter* writer) const { DumpHeader(writer); @@ -925,6 +948,12 @@ void AidlStructuredParcelable::Dump(CodeWriter* writer) const { } writer->Write("%s;\n", field->ToString().c_str()); } + for (const auto& constdecl : GetConstantDeclarations()) { + if (constdecl->GetType().IsHidden()) { + AddHideComment(writer); + } + writer->Write("%s;\n", constdecl->ToString().c_str()); + } writer->Dedent(); writer->Write("}\n"); } @@ -944,7 +973,7 @@ bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const if (!AidlParcelable::CheckValid(typenames)) { return false; } - if (!AidlWithFields::CheckValid(*this, typenames)) { + if (!AidlWithMembers::CheckValid(*this, typenames)) { return false; } @@ -1170,10 +1199,10 @@ void AidlEnumDeclaration::Dump(CodeWriter* writer) const { AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name, const std::string& package, const std::string& comments, - std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables, + std::vector<std::unique_ptr<AidlMember>>* members, std::vector<std::string>* type_params) : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params), - AidlWithFields(variables) {} + AidlWithMembers(members) {} std::set<AidlAnnotation::Type> AidlUnionDecl::GetSupportedAnnotations() const { return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::HIDE, @@ -1191,6 +1220,12 @@ void AidlUnionDecl::Dump(CodeWriter* writer) const { } writer->Write("%s;\n", field->ToString().c_str()); } + for (const auto& constdecl : GetConstantDeclarations()) { + if (constdecl->GetType().IsHidden()) { + AddHideComment(writer); + } + writer->Write("%s;\n", constdecl->ToString().c_str()); + } writer->Dedent(); writer->Write("}\n"); } @@ -1200,7 +1235,7 @@ bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const { if (!AidlParcelable::CheckValid(typenames)) { return false; } - if (!AidlWithFields::CheckValid(*this, typenames)) { + if (!AidlWithMembers::CheckValid(*this, typenames)) { return false; } @@ -1402,7 +1437,7 @@ bool AidlInterface::CheckValid(const AidlTypenames& typenames) const { bool success = true; set<string> constant_names; - for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) { + for (const auto& constant : GetConstantDeclarations()) { if (constant_names.count(constant->GetName()) > 0) { AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'"; success = false; diff --git a/aidl_language.h b/aidl_language.h index 5b0ecc3e..9e41bbb9 100644 --- a/aidl_language.h +++ b/aidl_language.h @@ -361,10 +361,30 @@ class AidlTypeSpecifier final : public AidlAnnotatable, std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value); class AidlConstantValue; +class AidlMethod; +class AidlConstantDeclaration; +class AidlVariableDeclaration; + +class AidlMember : public AidlNode { + public: + AidlMember(const AidlLocation& location); + virtual ~AidlMember() = default; + + // non-copyable, non-movable + AidlMember(const AidlMember&) = delete; + AidlMember(AidlMember&&) = delete; + AidlMember& operator=(const AidlMember&) = delete; + AidlMember& operator=(AidlMember&&) = delete; + + virtual AidlMethod* AsMethod() { return nullptr; } + virtual AidlConstantDeclaration* AsConstantDeclaration() { return nullptr; } + virtual AidlVariableDeclaration* AsVariableDeclaration() { return nullptr; } +}; + // TODO: This class is used for method arguments and also parcelable fields, // and it should be split up since default values don't apply to method // arguments -class AidlVariableDeclaration : public AidlNode { +class AidlVariableDeclaration : public AidlMember { public: AidlVariableDeclaration(const AidlLocation& location, AidlTypeSpecifier* type, const std::string& name); @@ -378,6 +398,8 @@ class AidlVariableDeclaration : public AidlNode { AidlVariableDeclaration& operator=(const AidlVariableDeclaration&) = delete; AidlVariableDeclaration& operator=(AidlVariableDeclaration&&) = delete; + AidlVariableDeclaration* AsVariableDeclaration() override { return this; } + std::string GetName() const { return name_; } std::string GetCapitalizedName() const; const AidlTypeSpecifier& GetType() const { return *type_; } @@ -444,24 +466,6 @@ class AidlArgument : public AidlVariableDeclaration { bool direction_specified_; }; -class AidlMethod; -class AidlConstantDeclaration; -class AidlEnumDeclaration; -class AidlMember : public AidlNode { - public: - AidlMember(const AidlLocation& location); - virtual ~AidlMember() = default; - - // non-copyable, non-movable - AidlMember(const AidlMember&) = delete; - AidlMember(AidlMember&&) = delete; - AidlMember& operator=(const AidlMember&) = delete; - AidlMember& operator=(AidlMember&&) = delete; - - virtual AidlMethod* AsMethod() { return nullptr; } - virtual AidlConstantDeclaration* AsConstantDeclaration() { return nullptr; } -}; - class AidlUnaryConstExpression; class AidlBinaryConstExpression; @@ -705,12 +709,8 @@ class AidlDefinedType; class AidlInterface; class AidlParcelable; class AidlStructuredParcelable; - -class AidlInterface; -class AidlParcelable; -class AidlStructuredParcelable; - class AidlUnionDecl; + // AidlDefinedType represents either an interface, parcelable, or enum that is // defined in the source file. class AidlDefinedType : public AidlAnnotatable { @@ -821,28 +821,31 @@ class AidlParcelable : public AidlDefinedType, public AidlParameterizable<std::s std::string cpp_header_; }; -class AidlWithFields { +class AidlWithMembers { public: - AidlWithFields(std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables) - : variables_(std::move(*variables)) {} + AidlWithMembers(std::vector<std::unique_ptr<AidlMember>>* members); const std::vector<std::unique_ptr<AidlVariableDeclaration>>& GetFields() const { return variables_; } + const std::vector<std::unique_ptr<AidlConstantDeclaration>>& GetConstantDeclarations() const { + return constants_; + } protected: bool CheckValid(const AidlParcelable& parcel, const AidlTypenames& typenames) const; bool CheckValidForGetterNames(const AidlParcelable& parcel) const; private: - const std::vector<std::unique_ptr<AidlVariableDeclaration>> variables_; + std::vector<std::unique_ptr<AidlVariableDeclaration>> variables_; + std::vector<std::unique_ptr<AidlConstantDeclaration>> constants_; }; -class AidlStructuredParcelable : public AidlParcelable, public AidlWithFields { +class AidlStructuredParcelable : public AidlParcelable, public AidlWithMembers { public: AidlStructuredParcelable(const AidlLocation& location, const std::string& name, const std::string& package, const std::string& comments, - std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables, + std::vector<std::unique_ptr<AidlMember>>* members, std::vector<std::string>* type_params); virtual ~AidlStructuredParcelable() = default; @@ -927,11 +930,10 @@ class AidlEnumDeclaration : public AidlDefinedType { std::unique_ptr<const AidlTypeSpecifier> backing_type_; }; -class AidlUnionDecl : public AidlParcelable, public AidlWithFields { +class AidlUnionDecl : public AidlParcelable, public AidlWithMembers { public: AidlUnionDecl(const AidlLocation& location, const std::string& name, const std::string& package, - const std::string& comments, - std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables, + const std::string& comments, std::vector<std::unique_ptr<AidlMember>>* members, std::vector<std::string>* type_params); virtual ~AidlUnionDecl() = default; @@ -967,13 +969,13 @@ class AidlInterface final : public AidlDefinedType { AidlInterface& operator=(const AidlInterface&) = delete; AidlInterface& operator=(AidlInterface&&) = delete; - const std::vector<std::unique_ptr<AidlMethod>>& GetMethods() const - { return methods_; } - std::vector<std::unique_ptr<AidlMethod>>& GetMutableMethods() { return methods_; } + const std::vector<std::unique_ptr<AidlMethod>>& GetMethods() const { return methods_; } const std::vector<std::unique_ptr<AidlConstantDeclaration>>& GetConstantDeclarations() const { return constants_; } + void AddMethod(std::unique_ptr<AidlMethod> method) { methods_.push_back(std::move(method)); } + const AidlInterface* AsInterface() const override { return this; } std::string GetPreprocessDeclarationName() const override { return "interface"; } diff --git a/aidl_language_y.yy b/aidl_language_y.yy index d5789941..8fe38da5 100644 --- a/aidl_language_y.yy +++ b/aidl_language_y.yy @@ -84,10 +84,9 @@ AidlLocation loc(const yy::parser::location_type& l) { std::vector<std::unique_ptr<AidlConstantValue>>* constant_value_list; std::vector<std::unique_ptr<AidlArgument>>* arg_list; AidlVariableDeclaration* variable; - std::vector<std::unique_ptr<AidlVariableDeclaration>>* variable_list; AidlMethod* method; AidlMember* constant; - std::vector<std::unique_ptr<AidlMember>>* interface_members; + std::vector<std::unique_ptr<AidlMember>>* members; AidlDefinedType* declaration; std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args; std::vector<std::string>* type_params; @@ -154,10 +153,9 @@ AidlLocation loc(const yy::parser::location_type& l) { %type<declaration> parcelable_decl %type<declaration> enum_decl %type<declaration> union_decl -%type<variable_list> variable_decls +%type<members> parcelable_members interface_members %type<variable> variable_decl %type<type_params> optional_type_params -%type<interface_members> interface_members %type<method> method_decl %type<constant> constant_decl %type<enumerator> enumerator @@ -301,7 +299,7 @@ parcelable_decl delete $1; delete $2; } - | PARCELABLE qualified_name optional_type_params '{' variable_decls '}' { + | PARCELABLE qualified_name optional_type_params '{' parcelable_members '}' { $$ = new AidlStructuredParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $5, $3); delete $1; delete $2; @@ -320,16 +318,22 @@ parcelable_decl delete $1; }; -variable_decls +parcelable_members : /* empty */ { - $$ = new std::vector<std::unique_ptr<AidlVariableDeclaration>>; - } - | variable_decls variable_decl { + $$ = new std::vector<std::unique_ptr<AidlMember>>(); + } + | parcelable_members variable_decl { + $1->emplace_back($2); $$ = $1; - if ($2 != nullptr) { - $$->push_back(std::unique_ptr<AidlVariableDeclaration>($2)); - } - }; + } + | parcelable_members constant_decl { + $1->emplace_back($2); + $$ = $1; + } + | parcelable_members error ';' { + ps->AddError(); + $$ = $1; + }; variable_decl : type identifier ';' { @@ -341,10 +345,7 @@ variable_decl $$ = new AidlVariableDeclaration(loc(@2), $1, $2->GetText(), $4); delete $2; } - | error ';' { - ps->AddError(); - $$ = nullptr; - } + ; interface_decl : INTERFACE identifier '{' interface_members '}' { @@ -560,7 +561,7 @@ enum_decl ; union_decl - : UNION qualified_name optional_type_params '{' variable_decls '}' { + : UNION qualified_name optional_type_params '{' parcelable_members '}' { $$ = new AidlUnionDecl(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $5, $3); delete $1; delete $2; diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp index 7bf63d9b..4991b2fd 100644 --- a/aidl_unittest.cpp +++ b/aidl_unittest.cpp @@ -1378,6 +1378,24 @@ TEST_P(AidlTest, RejectNullableParcelableHolderField) { EXPECT_EQ(expected_stderr, GetCapturedStderr()); } +TEST_P(AidlTest, ParcelablesWithConstants) { + io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo { const int BIT = 0x1 << 3; }"); + Options options = + Options::From("aidl Foo.aidl --lang=" + Options::LanguageToString(GetLanguage())); + CaptureStderr(); + EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_)); + EXPECT_EQ("", GetCapturedStderr()); +} + +TEST_P(AidlTest, UnionWithConstants) { + io_delegate_.SetFileContents("Foo.aidl", "union Foo { const int BIT = 0x1 << 3; int n; }"); + Options options = + Options::From("aidl Foo.aidl --lang=" + Options::LanguageToString(GetLanguage())); + CaptureStderr(); + EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_)); + EXPECT_EQ("", GetCapturedStderr()); +} + TEST_F(AidlTest, ApiDump) { io_delegate_.SetFileContents( "foo/bar/IFoo.aidl", @@ -3735,6 +3753,44 @@ TEST_P(AidlTest, GenericStructuredParcelable) { EXPECT_EQ(expected_stderr, GetCapturedStderr()); } +TEST_F(AidlTest, GenericStructuredParcelableWithStringConstants_Cpp) { + io_delegate_.SetFileContents("Foo.aidl", + "parcelable Foo<T, U> { int a; const String s = \"\"; }"); + Options options = + Options::From("aidl Foo.aidl --lang=" + Options::LanguageToString(Options::Language::CPP) + + " -o out -h out"); + const string expected_stderr = ""; + CaptureStderr(); + EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_)); + EXPECT_EQ(expected_stderr, GetCapturedStderr()); + + string code; + EXPECT_TRUE(io_delegate_.GetWrittenContents("out/Foo.h", &code)); + EXPECT_THAT(code, testing::HasSubstr(R"--(template <typename T, typename U> +const ::android::String16& Foo<T,U>::s() { + static const ::android::String16 value(::android::String16("")); + return value; +})--")); +} + +TEST_F(AidlTest, GenericStructuredParcelableWithStringConstants_Ndk) { + io_delegate_.SetFileContents("Foo.aidl", + "parcelable Foo<T, U> { int a; const String s = \"\"; }"); + Options options = + Options::From("aidl Foo.aidl --lang=" + Options::LanguageToString(Options::Language::NDK) + + " -o out -h out"); + const string expected_stderr = ""; + CaptureStderr(); + EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_)); + EXPECT_EQ(expected_stderr, GetCapturedStderr()); + + string code; + EXPECT_TRUE(io_delegate_.GetWrittenContents("out/aidl/Foo.h", &code)); + EXPECT_THAT(code, testing::HasSubstr(R"--(template <typename T, typename U> +const char* Foo<T, U>::s = ""; +)--")); +} + TEST_F(AidlTest, NestedTypeArgs) { io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar<A> { }"); io_delegate_.SetFileContents("a/Baz.aidl", "package a; parcelable Baz<A, B> { }"); diff --git a/generate_cpp.cpp b/generate_cpp.cpp index ddcfc4a7..2ed49c32 100644 --- a/generate_cpp.cpp +++ b/generate_cpp.cpp @@ -509,6 +509,73 @@ unique_ptr<Document> BuildClientSource(const AidlTypenames& typenames, namespace { +template <typename TypeWithConstants> +void BuildConstantDefinitions(const TypeWithConstants& type, const AidlTypenames& typenames, + const std::vector<std::string>& type_params, + const std::string& class_name, + vector<unique_ptr<Declaration>>& decls) { + for (const auto& constant : type.GetConstantDeclarations()) { + const AidlConstantValue& value = constant->GetValue(); + if (value.GetType() != AidlConstantValue::Type::STRING) continue; + + std::string cppType = CppNameOf(constant->GetType(), typenames); + unique_ptr<MethodImpl> getter( + new MethodImpl("const " + cppType + "&", class_name, constant->GetName(), type_params, {})); + getter->GetStatementBlock()->AddLiteral( + StringPrintf("static const %s value(%s)", cppType.c_str(), + constant->ValueString(ConstantValueDecorator).c_str())); + getter->GetStatementBlock()->AddLiteral("return value"); + decls.push_back(std::move(getter)); + } +} + +template <typename TypeWithConstants> +void BuildConstantDeclarations(const TypeWithConstants& type, const AidlTypenames& typenames, + unique_ptr<ClassDecl>& cls, set<string>& includes) { + std::vector<std::unique_ptr<Declaration>> string_constants; + unique_ptr<Enum> byte_constant_enum{new Enum{"", "int8_t", false}}; + unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t", false}}; + unique_ptr<Enum> long_constant_enum{new Enum{"", "int64_t", false}}; + for (const auto& constant : type.GetConstantDeclarations()) { + const AidlTypeSpecifier& type = constant->GetType(); + const AidlConstantValue& value = constant->GetValue(); + + if (type.Signature() == "String") { + std::string cppType = CppNameOf(constant->GetType(), typenames); + unique_ptr<Declaration> getter( + new MethodDecl("const " + cppType + "&", constant->GetName(), {}, MethodDecl::IS_STATIC)); + string_constants.push_back(std::move(getter)); + } else if (type.Signature() == "byte") { + byte_constant_enum->AddValue(constant->GetName(), + constant->ValueString(ConstantValueDecorator)); + } else if (type.Signature() == "int") { + int_constant_enum->AddValue(constant->GetName(), + constant->ValueString(ConstantValueDecorator)); + } else if (type.Signature() == "long") { + long_constant_enum->AddValue(constant->GetName(), + constant->ValueString(ConstantValueDecorator)); + } else { + AIDL_FATAL(value) << "Unrecognized constant type: " << type.Signature(); + } + } + if (byte_constant_enum->HasValues()) { + cls->AddPublic(std::move(byte_constant_enum)); + } + if (int_constant_enum->HasValues()) { + cls->AddPublic(std::move(int_constant_enum)); + } + if (long_constant_enum->HasValues()) { + cls->AddPublic(std::move(long_constant_enum)); + } + if (!string_constants.empty()) { + includes.insert(kString16Header); + + for (auto& string_constant : string_constants) { + cls->AddPublic(std::move(string_constant)); + } + } +} + bool HandleServerTransaction(const AidlTypenames& typenames, const AidlInterface& interface, const AidlMethod& method, const Options& options, StatementBlock* b) { // Declare all the parameters now. In the common case, we expect no errors @@ -776,20 +843,8 @@ unique_ptr<Document> BuildInterfaceSource(const AidlTypenames& typenames, '"' + interface.GetDescriptor() + '"'}}}}; decls.push_back(std::move(meta_if)); - for (const auto& constant : interface.GetConstantDeclarations()) { - const AidlConstantValue& value = constant->GetValue(); - if (value.GetType() != AidlConstantValue::Type::STRING) continue; - - std::string cppType = CppNameOf(constant->GetType(), typenames); - unique_ptr<MethodImpl> getter(new MethodImpl("const " + cppType + "&", - ClassName(interface, ClassNames::INTERFACE), - constant->GetName(), {}, {})); - getter->GetStatementBlock()->AddLiteral( - StringPrintf("static const %s value(%s)", cppType.c_str(), - constant->ValueString(ConstantValueDecorator).c_str())); - getter->GetStatementBlock()->AddLiteral("return value"); - decls.push_back(std::move(getter)); - } + BuildConstantDefinitions(interface, typenames, {}, ClassName(interface, ClassNames::INTERFACE), + decls); return unique_ptr<Document>{new CppSource{ include_list, @@ -950,48 +1005,7 @@ unique_ptr<Document> BuildInterfaceHeader(const AidlTypenames& typenames, if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str()))); } - std::vector<std::unique_ptr<Declaration>> string_constants; - unique_ptr<Enum> byte_constant_enum{new Enum{"", "int8_t", false}}; - unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t", false}}; - unique_ptr<Enum> long_constant_enum{new Enum{"", "int64_t", false}}; - for (const auto& constant : interface.GetConstantDeclarations()) { - const AidlTypeSpecifier& type = constant->GetType(); - const AidlConstantValue& value = constant->GetValue(); - - if (type.Signature() == "String") { - std::string cppType = CppNameOf(constant->GetType(), typenames); - unique_ptr<Declaration> getter( - new MethodDecl("const " + cppType + "&", constant->GetName(), {}, MethodDecl::IS_STATIC)); - string_constants.push_back(std::move(getter)); - } else if (type.Signature() == "byte") { - byte_constant_enum->AddValue(constant->GetName(), - constant->ValueString(ConstantValueDecorator)); - } else if (type.Signature() == "int") { - int_constant_enum->AddValue(constant->GetName(), - constant->ValueString(ConstantValueDecorator)); - } else if (type.Signature() == "long") { - long_constant_enum->AddValue(constant->GetName(), - constant->ValueString(ConstantValueDecorator)); - } else { - AIDL_FATAL(value) << "Unrecognized constant type: " << type.Signature(); - } - } - if (byte_constant_enum->HasValues()) { - if_class->AddPublic(std::move(byte_constant_enum)); - } - if (int_constant_enum->HasValues()) { - if_class->AddPublic(std::move(int_constant_enum)); - } - if (long_constant_enum->HasValues()) { - if_class->AddPublic(std::move(long_constant_enum)); - } - if (!string_constants.empty()) { - includes.insert(kString16Header); - - for (auto& string_constant : string_constants) { - if_class->AddPublic(std::move(string_constant)); - } - } + BuildConstantDeclarations(interface, typenames, if_class, includes); if (options.GenTraces()) { includes.insert(kTraceHeader); @@ -1232,6 +1246,7 @@ std::unique_ptr<Document> BuildParcelHeader(const AidlTypenames& typenames, cons parcel_class->AddPublic(std::make_unique<LiteralDecl>(operator_code)); Traits::AddFields(*parcel_class, parcel, typenames); + BuildConstantDeclarations(parcel, typenames, parcel_class, includes); if (parcel.IsVintfStability()) { parcel_class->AddPublic(std::unique_ptr<LiteralDecl>( @@ -1289,6 +1304,7 @@ std::unique_ptr<Document> BuildParcelSource(const AidlTypenames& typenames, cons Traits::GenWriteToParcel(parcel, typenames, write->GetStatementBlock()); vector<unique_ptr<Declaration>> file_decls; + BuildConstantDefinitions(parcel, typenames, type_params, parcel.GetName(), file_decls); file_decls.push_back(std::move(read)); file_decls.push_back(std::move(write)); diff --git a/generate_java.cpp b/generate_java.cpp index e100ab4e..143a99dc 100644 --- a/generate_java.cpp +++ b/generate_java.cpp @@ -576,6 +576,10 @@ std::unique_ptr<android::aidl::java::Class> generate_parcel_class( parcel_class->elements.push_back(read_or_create_method); + auto constants = + CodeWriter::RunWith(generate_constant_declarations, parcel->GetConstantDeclarations()); + parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(constants)); + auto method = CodeWriter::RunWith(GenerateDerivedMethods, *parcel, typenames); parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(method)); @@ -823,6 +827,8 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena out.Dedent(); out << "}\n\n"; + generate_constant_declarations(out, decl->GetConstantDeclarations()); + GenerateParcelableDescribeContents(out, *decl, typenames); out << "\n"; GenerateDerivedMethods(out, *decl, typenames); diff --git a/generate_java.h b/generate_java.h index 3ed2546a..90553e4e 100644 --- a/generate_java.h +++ b/generate_java.h @@ -44,6 +44,9 @@ void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypena std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a); +void generate_constant_declarations( + CodeWriter& out, const std::vector<std::unique_ptr<AidlConstantDeclaration>>& constants); + } // namespace java } // namespace aidl } // namespace android diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp index 9c3329d9..f7befa7e 100644 --- a/generate_java_binder.cpp +++ b/generate_java_binder.cpp @@ -386,11 +386,20 @@ static void generate_write_to_parcel(const AidlTypeSpecifier& type, addTo->Add(std::make_shared<LiteralStatement>(code)); } -static void generate_constant(Class* interface, const std::string& type, const std::string& name, - const std::string& value) { - auto code = - StringPrintf("public static final %s %s = %s;\n", type.c_str(), name.c_str(), value.c_str()); - interface->elements.push_back(std::make_shared<LiteralClassElement>(code)); +void generate_constant_declarations( + CodeWriter& out, const std::vector<std::unique_ptr<AidlConstantDeclaration>>& constants) { + for (const auto& constant : constants) { + const AidlTypeSpecifier& type = constant->GetType(); + auto comment = base::Trim(constant->GetType().GetComments()); + if (comment.length() != 0) { + out << comment << "\n"; + } + for (const auto& annotation : generate_java_annotations(constant->GetType())) { + out << annotation << "\n"; + } + out << "public static final " << type.Signature() << " " << constant->GetName() << " = " + << constant->ValueString(ConstantValueDecorator) << ";\n"; + } } static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method, @@ -977,7 +986,7 @@ static void compute_outline_methods(const AidlInterface* iface, 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()) { + for (const auto& ptr : iface->GetMethods()) { methods.push_back(ptr.get()); } @@ -1027,7 +1036,7 @@ static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface, for (const auto& m : iface.GetMethods()) { if (m->IsUserDefined()) { - default_class->elements.emplace_back(generate_default_impl_method(*m.get(), typenames)); + default_class->elements.emplace_back(generate_default_impl_method(*m, typenames)); } else { // These are called only when the remote side does not implement these // methods, which is normally impossible, because these methods are @@ -1113,21 +1122,9 @@ std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* ifac generate_interface_descriptors(options, iface, interface.get(), stub, proxy); // all the declared constants of the interface - for (const auto& constant : iface->GetConstantDeclarations()) { - const AidlTypeSpecifier& type = constant->GetType(); - auto comment = constant->GetType().GetComments(); - if (comment.length() != 0) { - auto code = StringPrintf("%s\n", comment.c_str()); - interface->elements.push_back(std::make_shared<LiteralClassElement>(code)); - } - for (const std::string& annotation : generate_java_annotations(constant->GetType())) { - auto code = StringPrintf("%s\n", annotation.c_str()); - interface->elements.push_back(std::make_shared<LiteralClassElement>(code)); - } - - generate_constant(interface.get(), type.Signature(), constant->GetName(), - constant->ValueString(ConstantValueDecorator)); - } + auto constants = + CodeWriter::RunWith(generate_constant_declarations, iface->GetConstantDeclarations()); + interface->elements.push_back(std::make_shared<LiteralClassElement>(constants)); // all the declared methods of the interface diff --git a/generate_ndk.cpp b/generate_ndk.cpp index 3b07eb19..baaaeff9 100644 --- a/generate_ndk.cpp +++ b/generate_ndk.cpp @@ -307,9 +307,10 @@ static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types, }); } +template <typename TypeWithConstants> static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& types, - const AidlInterface& interface) { - for (const auto& constant : interface.GetConstantDeclarations()) { + const TypeWithConstants& type) { + for (const auto& constant : type.GetConstantDeclarations()) { const AidlTypeSpecifier& type = constant->GetType(); if (type.Signature() == "String") { @@ -321,15 +322,17 @@ static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& t } } -static void GenerateConstantDefinitions(CodeWriter& out, const AidlInterface& interface) { - const std::string clazz = ClassName(interface, ClassNames::INTERFACE); - +template <typename TypeWithConstants> +static void GenerateConstantDefinitions(CodeWriter& out, const TypeWithConstants& interface, + const std::string& clazz, + const std::string& tmpl_decl = "") { for (const auto& constant : interface.GetConstantDeclarations()) { const AidlConstantValue& value = constant->GetValue(); AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY || value.GetType() == AidlConstantValue::Type::BINARY, value); if (value.GetType() == AidlConstantValue::Type::STRING) { + out << tmpl_decl; out << "const char* " << clazz << "::" << constant->GetName() << " = " << constant->ValueString(ConstantValueDecorator) << ";\n"; } @@ -684,7 +687,7 @@ void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types, out << clazz << "::" << clazz << "() {}\n"; out << clazz << "::~" << clazz << "() {}\n"; out << "\n"; - GenerateConstantDefinitions(out, defined_type); + GenerateConstantDefinitions(out, defined_type, clazz); out << "\n"; out << "std::shared_ptr<" << clazz << "> " << clazz @@ -1021,6 +1024,7 @@ void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types, out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::" << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n"; + GenerateConstantDeclarations(out, types, defined_type); cpp::GenerateToString(out, defined_type); out.Dedent(); @@ -1050,6 +1054,8 @@ void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types, << defined_type.GetCanonicalName() << "\";\n"; out << "\n"; + GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type)); + out << cpp::TemplateDecl(defined_type); out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n"; out.Indent(); @@ -1153,6 +1159,7 @@ void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types, out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::" << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n"; + GenerateConstantDeclarations(out, types, defined_type); cpp::GenerateToString(out, defined_type); out.Dedent(); out << "private:\n"; @@ -1203,6 +1210,8 @@ void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types, << defined_type.GetCanonicalName() << "\";\n"; out << "\n"; + GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type)); + out << cpp::TemplateDecl(defined_type); out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* _parcel) {\n"; out.Indent(); diff --git a/generate_rust.cpp b/generate_rust.cpp index 71a49f2f..6ac7a0d7 100644 --- a/generate_rust.cpp +++ b/generate_rust.cpp @@ -310,6 +310,28 @@ void GenerateServerItems(CodeWriter& out, const AidlInterface* iface, out << "}\n"; } +template <typename TypeWithConstants> +void GenerateConstantDeclarations(CodeWriter& out, const TypeWithConstants& type, + const AidlTypenames& typenames) { + for (const auto& constant : type.GetConstantDeclarations()) { + const AidlTypeSpecifier& type = constant->GetType(); + const AidlConstantValue& value = constant->GetValue(); + + string const_type; + if (type.Signature() == "String") { + const_type = "&str"; + } else if (type.Signature() == "byte" || type.Signature() == "int" || + type.Signature() == "long") { + const_type = RustNameOf(type, typenames, StorageMode::VALUE); + } else { + AIDL_FATAL(value) << "Unrecognized constant type: " << type.Signature(); + } + + out << "pub const " << constant->GetName() << ": " << const_type << " = " + << constant->ValueString(ConstantValueDecoratorRef) << ";\n"; + } +} + bool GenerateRustInterface(const string& filename, const AidlInterface* iface, const AidlTypenames& typenames, const IoDelegate& io_delegate, const Options& options) { @@ -416,23 +438,7 @@ bool GenerateRustInterface(const string& filename, const AidlInterface* iface, *code_writer << "}\n"; // Emit the interface constants - for (const auto& constant : iface->GetConstantDeclarations()) { - const AidlTypeSpecifier& type = constant->GetType(); - const AidlConstantValue& value = constant->GetValue(); - - string const_type; - if (type.Signature() == "String") { - const_type = "&str"; - } else if (type.Signature() == "byte" || type.Signature() == "int" || - type.Signature() == "long") { - const_type = RustNameOf(type, typenames, StorageMode::VALUE); - } else { - AIDL_FATAL(value) << "Unrecognized constant type: " << type.Signature(); - } - - *code_writer << "pub const " << constant->GetName() << ": " << const_type << " = " - << constant->ValueString(ConstantValueDecoratorRef) << ";\n"; - } + GenerateConstantDeclarations(*code_writer, *iface, typenames); GenerateMangledAlias(*code_writer, iface); @@ -708,6 +714,7 @@ bool GenerateRustParcel(const string& filename, const ParcelableType* parcel, *code_writer << "#[derive(" << Join(derives, ", ") << ")]\n"; GenerateParcelBody(*code_writer, parcel, typenames); + GenerateConstantDeclarations(*code_writer, *parcel, typenames); GenerateMangledAlias(*code_writer, parcel); GenerateParcelDefault(*code_writer, parcel); GenerateParcelSerialize(*code_writer, parcel, typenames); diff --git a/tests/aidl_test_client_parcelables.cpp b/tests/aidl_test_client_parcelables.cpp index 04ea939b..333852e9 100644 --- a/tests/aidl_test_client_parcelables.cpp +++ b/tests/aidl_test_client_parcelables.cpp @@ -303,7 +303,11 @@ TEST_F(AidlTest, ConfirmStructuredParcelables) { EXPECT_EQ(parcelable.addString1, "hello world!"); EXPECT_EQ(parcelable.addString2, "The quick brown fox jumps over the lazy dog."); + EXPECT_EQ(StructuredParcelable::BIT0 | StructuredParcelable::BIT2, + parcelable.shouldSetBit0AndBit2); + EXPECT_EQ(parcelable.u->get<Union::ns>(), vector<int32_t>({1, 2, 3})); + EXPECT_EQ(parcelable.shouldBeConstS1->get<Union::s>(), Union::S1()); } TEST_F(AidlTest, EmptyParcelableHolder) { diff --git a/tests/aidl_test_service.cpp b/tests/aidl_test_service.cpp index 7304dfd5..2c6524b9 100644 --- a/tests/aidl_test_service.cpp +++ b/tests/aidl_test_service.cpp @@ -579,7 +579,10 @@ class NativeService : public BnTestService { parcelable->const_exprs_9 = ConstantExpressionEnum::hexInt32_3; parcelable->const_exprs_10 = ConstantExpressionEnum::hexInt64_1; + parcelable->shouldSetBit0AndBit2 = StructuredParcelable::BIT0 | StructuredParcelable::BIT2; + parcelable->u = Union::make<Union::ns>({1, 2, 3}); + parcelable->shouldBeConstS1 = Union::S1(); return Status::ok(); } diff --git a/tests/android/aidl/tests/StructuredParcelable.aidl b/tests/android/aidl/tests/StructuredParcelable.aidl index 9809de3c..0028ae2c 100644 --- a/tests/android/aidl/tests/StructuredParcelable.aidl +++ b/tests/android/aidl/tests/StructuredParcelable.aidl @@ -165,6 +165,12 @@ parcelable StructuredParcelable { @utf8InCpp String addString1 = "hello" + " world!"; @utf8InCpp String addString2 = "The quick brown fox jumps " + "over the lazy dog."; + const int BIT0 = 0x1; + const int BIT1 = 0x1 << 1; + const int BIT2 = 0x1 << 2; + int shouldSetBit0AndBit2; + @nullable Union u; + @nullable Union shouldBeConstS1; } diff --git a/tests/android/aidl/tests/Union.aidl b/tests/android/aidl/tests/Union.aidl index a65d9c8d..1b4c6715 100644 --- a/tests/android/aidl/tests/Union.aidl +++ b/tests/android/aidl/tests/Union.aidl @@ -27,5 +27,7 @@ union Union { @nullable IBinder ibinder; @utf8InCpp List<String> ss; ByteEnum be; + + const @utf8InCpp String S1 = "a string constant in union"; } diff --git a/tests/java/src/android/aidl/tests/TestServiceClient.java b/tests/java/src/android/aidl/tests/TestServiceClient.java index c92f1a4d..c4e5bee4 100644 --- a/tests/java/src/android/aidl/tests/TestServiceClient.java +++ b/tests/java/src/android/aidl/tests/TestServiceClient.java @@ -609,7 +609,11 @@ public class TestServiceClient { assertThat(p.const_exprs_9, is(1)); assertThat(p.const_exprs_10, is(1)); + assertThat( + p.shouldSetBit0AndBit2, is(StructuredParcelable.BIT0 | StructuredParcelable.BIT2)); + assertThat(p.u.getNs(), is(new int[] {1, 2, 3})); + assertThat(p.shouldBeConstS1.getS(), is(Union.S1)); final String expected = "android.aidl.tests.StructuredParcelable{" + "shouldContainThreeFs: [17, 17, 17], " @@ -663,7 +667,9 @@ public class TestServiceClient { + "const_exprs_10: 1, " + "addString1: hello world!, " + "addString2: The quick brown fox jumps over the lazy dog., " - + "u: android.aidl.tests.Union.ns([1, 2, 3])" + + "shouldSetBit0AndBit2: 5, " + + "u: android.aidl.tests.Union.ns([1, 2, 3]), " + + "shouldBeConstS1: android.aidl.tests.Union.s(a string constant in union)" + "}"; assertThat(p.toString(), is(expected)); } diff --git a/tests/rust/test_client.rs b/tests/rust/test_client.rs index be9a5e5a..0c77d476 100644 --- a/tests/rust/test_client.rs +++ b/tests/rust/test_client.rs @@ -529,7 +529,10 @@ fn test_parcelable() { "The quick brown fox jumps over the lazy dog." ); - assert_eq!(parcelable.u, Some(Union::Union::Ns(vec![1, 2, 3]))) + assert_eq!(parcelable.shouldSetBit0AndBit2, StructuredParcelable::BIT0 | StructuredParcelable::BIT2); + + assert_eq!(parcelable.u, Some(Union::Union::Ns(vec![1, 2, 3]))); + assert_eq!(parcelable.shouldBeConstS1, Some(Union::Union::S(Union::S1.to_string()))) } const EXPECTED_ARG_VALUE: i32 = 100; diff --git a/tests/rust/test_service.rs b/tests/rust/test_service.rs index 7e6641ab..a87ce026 100644 --- a/tests/rust/test_service.rs +++ b/tests/rust/test_service.rs @@ -270,8 +270,10 @@ impl ITestService::ITestService for TestService { parcelable.const_exprs_9 = ConstantExpressionEnum::hexInt32_3; parcelable.const_exprs_10 = ConstantExpressionEnum::hexInt64_1; - parcelable.u = Some(Union::Union::Ns(vec![1, 2, 3])); + parcelable.shouldSetBit0AndBit2 = StructuredParcelable::BIT0 | StructuredParcelable::BIT2; + parcelable.u = Some(Union::Union::Ns(vec![1, 2, 3])); + parcelable.shouldBeConstS1 = Some(Union::Union::S(Union::S1.to_string())); Ok(()) } |