aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJooyung Han <jooyung@google.com>2020-12-01 12:41:50 +0900
committerJooyung Han <jooyung@google.com>2020-12-03 00:40:48 +0000
commit3f347ca3625b82dea5207919fe1816da3924a49a (patch)
treed5e84bcc53e911c2a580aa1027c8a4cc93794556
parent717fc697942ccd4e35ac3616806959b57a80dcc9 (diff)
downloadaidl-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.cpp19
-rw-r--r--aidl_checkapi.cpp61
-rw-r--r--aidl_language.cpp57
-rw-r--r--aidl_language.h74
-rw-r--r--aidl_language_y.yy37
-rw-r--r--aidl_unittest.cpp56
-rw-r--r--generate_cpp.cpp128
-rw-r--r--generate_java.cpp6
-rw-r--r--generate_java.h3
-rw-r--r--generate_java_binder.cpp41
-rw-r--r--generate_ndk.cpp21
-rw-r--r--generate_rust.cpp41
-rw-r--r--tests/aidl_test_client_parcelables.cpp4
-rw-r--r--tests/aidl_test_service.cpp3
-rw-r--r--tests/android/aidl/tests/StructuredParcelable.aidl6
-rw-r--r--tests/android/aidl/tests/Union.aidl2
-rw-r--r--tests/java/src/android/aidl/tests/TestServiceClient.java8
-rw-r--r--tests/rust/test_client.rs5
-rw-r--r--tests/rust/test_service.rs4
19 files changed, 374 insertions, 202 deletions
diff --git a/aidl.cpp b/aidl.cpp
index 94e83871..696f681f 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -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(())
}