aidl: support byte/long constants
before: 'const int foo = 3;'
now: 'const byte bar = 3;'
now: 'const long baz = 4;'
This is helpful to create constants which are a specific size, and it
opens up the ability to create larger constants.
Bug: 172246790
Test: atest aidl_unittests aidl_integration_test
Change-Id: I614658cd0a5e5eb6b0dea6d9212aa082cbb16317
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 33f6a2b..57bc733 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -706,7 +706,7 @@
valid &= value_->CheckValid();
if (!valid) return false;
- const static set<string> kSupportedConstTypes = {"String", "int"};
+ const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
return false;
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 02cbf5f..9b899d1 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -958,6 +958,22 @@
EXPECT_EQ(AidlError::BAD_TYPE, error);
}
+TEST_P(AidlTest, FailOnTooBigConstant) {
+ AidlError error;
+ const string expected_stderr =
+ "ERROR: p/IFoo.aidl:3.48-52: Invalid type specifier for an int32 literal: byte\n";
+ CaptureStderr();
+ EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
+ R"(package p;
+ interface IFoo {
+ const byte type2small = 256;
+ }
+ )",
+ typenames_, GetLanguage(), &error));
+ EXPECT_EQ(expected_stderr, GetCapturedStderr());
+ EXPECT_EQ(AidlError::BAD_TYPE, error);
+}
+
TEST_P(AidlTest, FailOnManyDefinedTypes) {
AidlError error;
const string expected_stderr =
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 7784a97..f0dace0 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -943,35 +943,40 @@
}
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();
- switch (value.GetType()) {
- case AidlConstantValue::Type::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));
- break;
- }
- case AidlConstantValue::Type::BOOLEAN: // fall-through
- case AidlConstantValue::Type::INT8: // fall-through
- case AidlConstantValue::Type::INT32: // fall-through
- // Type promotion may cause this. Value should be small enough to fit in int32.
- case AidlConstantValue::Type::INT64: {
- int_constant_enum->AddValue(constant->GetName(),
- constant->ValueString(ConstantValueDecorator));
- break;
- }
- default: {
- AIDL_FATAL(value) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
- }
+ if (type.ToString() == "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.ToString() == "byte") {
+ byte_constant_enum->AddValue(constant->GetName(),
+ constant->ValueString(ConstantValueDecorator));
+ } else if (type.ToString() == "int") {
+ int_constant_enum->AddValue(constant->GetName(),
+ constant->ValueString(ConstantValueDecorator));
+ } else if (type.ToString() == "long") {
+ long_constant_enum->AddValue(constant->GetName(),
+ constant->ValueString(ConstantValueDecorator));
+ } else {
+ AIDL_FATAL(value) << "Unrecognized constant type: " << type.ToString();
}
}
+ 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);
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index 551e866..073c8c4 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -385,15 +385,10 @@
addTo->Add(std::make_shared<LiteralStatement>(code));
}
-static void generate_int_constant(Class* interface, const std::string& name,
- const std::string& value) {
- auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
- interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
-}
-
-static void generate_string_constant(Class* interface, const std::string& name,
- const std::string& value) {
- auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
+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));
}
@@ -1109,7 +1104,7 @@
// all the declared constants of the interface
for (const auto& constant : iface->GetConstantDeclarations()) {
- const AidlConstantValue& value = constant->GetValue();
+ const AidlTypeSpecifier& type = constant->GetType();
auto comment = constant->GetType().GetComments();
if (comment.length() != 0) {
auto code = StringPrintf("%s\n", comment.c_str());
@@ -1119,25 +1114,9 @@
auto code = StringPrintf("%s\n", annotation.c_str());
interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
}
- switch (value.GetType()) {
- case AidlConstantValue::Type::STRING: {
- generate_string_constant(interface.get(), constant->GetName(),
- constant->ValueString(ConstantValueDecorator));
- break;
- }
- case AidlConstantValue::Type::BOOLEAN: // fall-through
- case AidlConstantValue::Type::INT8: // fall-through
- case AidlConstantValue::Type::INT32: // fall-through
- // Type promotion may cause this. Value should be small enough to fit in int32.
- case AidlConstantValue::Type::INT64: {
- generate_int_constant(interface.get(), constant->GetName(),
- constant->ValueString(ConstantValueDecorator));
- break;
- }
- default: {
- AIDL_FATAL(value) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
- }
- }
+
+ generate_constant(interface.get(), type.ToString(), constant->GetName(),
+ constant->ValueString(ConstantValueDecorator));
}
// all the declared methods of the interface
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index 8ef2a67..d42b8b7 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -302,48 +302,20 @@
});
}
-static void GenerateConstantDeclarations(CodeWriter& out, const AidlInterface& interface) {
+static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& types,
+ const AidlInterface& interface) {
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) {
+ const AidlTypeSpecifier& type = constant->GetType();
+
+ if (type.ToString() == "String") {
out << "static const char* " << constant->GetName() << ";\n";
+ } else {
+ out << "enum : " << NdkNameOf(types, type, StorageMode::STACK) << " { " << constant->GetName()
+ << " = " << constant->ValueString(ConstantValueDecorator) << " };\n";
}
}
- out << "\n";
-
- bool hasIntegralConstant = false;
- 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::BOOLEAN ||
- value.GetType() == AidlConstantValue::Type::INT8 ||
- value.GetType() == AidlConstantValue::Type::INT32) {
- hasIntegralConstant = true;
- break;
- }
- }
-
- if (hasIntegralConstant) {
- out << "enum : int32_t {\n";
- out.Indent();
- for (const auto& constant : interface.GetConstantDeclarations()) {
- const AidlConstantValue& value = constant->GetValue();
- if (value.GetType() == AidlConstantValue::Type::BOOLEAN ||
- value.GetType() == AidlConstantValue::Type::INT8 ||
- value.GetType() == AidlConstantValue::Type::INT32) {
- out << constant->GetName() << " = " << constant->ValueString(ConstantValueDecorator)
- << ",\n";
- }
- }
- out.Dedent();
- out << "};\n";
- }
}
+
static void GenerateConstantDefinitions(CodeWriter& out, const AidlInterface& interface) {
const std::string clazz = ClassName(interface, ClassNames::INTERFACE);
@@ -926,7 +898,7 @@
out << clazz << "();\n";
out << "virtual ~" << clazz << "();\n";
out << "\n";
- GenerateConstantDeclarations(out, defined_type);
+ GenerateConstantDeclarations(out, types, defined_type);
if (options.Version() > 0) {
out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
<< ";\n";
diff --git a/generate_rust.cpp b/generate_rust.cpp
index e768820..4ef2765 100644
--- a/generate_rust.cpp
+++ b/generate_rust.cpp
@@ -408,25 +408,18 @@
// Emit the interface constants
for (const auto& constant : iface->GetConstantDeclarations()) {
+ const AidlTypeSpecifier& type = constant->GetType();
const AidlConstantValue& value = constant->GetValue();
+
string const_type;
- switch (value.GetType()) {
- case AidlConstantValue::Type::STRING: {
- const_type = "&str";
- break;
- }
- case AidlConstantValue::Type::BOOLEAN: // fall-through
- case AidlConstantValue::Type::INT8: // fall-through
- case AidlConstantValue::Type::INT32: // fall-through
- // Type promotion may cause this. Value should be small enough to fit in int32.
- case AidlConstantValue::Type::INT64: {
- const_type = "i32";
- break;
- }
- default: {
- AIDL_FATAL(value) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
- }
+ if (type.ToString() == "String") {
+ const_type = "&str";
+ } else if (type.ToString() == "byte" || type.ToString() == "int" || type.ToString() == "long") {
+ const_type = RustNameOf(type, typenames, StorageMode::VALUE);
+ } else {
+ AIDL_FATAL(value) << "Unrecognized constant type: " << type.ToString();
}
+
*code_writer << "pub const " << constant->GetName() << ": " << const_type << " = "
<< constant->ValueString(ConstantValueDecoratorRef) << ";\n";
}
diff --git a/tests/aidl_test_client_primitives.cpp b/tests/aidl_test_client_primitives.cpp
index 1cda014..9c2a00b 100644
--- a/tests/aidl_test_client_primitives.cpp
+++ b/tests/aidl_test_client_primitives.cpp
@@ -94,6 +94,13 @@
DoTest(&ITestService::RepeatDouble, double{1.0 / 3.0});
}
+TEST_F(AidlPrimitiveTest, byteConstants) {
+ constexpr int8_t consts[] = {ITestService::BYTE_TEST_CONSTANT};
+ for (auto sent : consts) {
+ DoTest(&ITestService::RepeatByte, sent);
+ }
+}
+
TEST_F(AidlPrimitiveTest, intConstants) {
constexpr int32_t consts[] = {
ITestService::TEST_CONSTANT, ITestService::TEST_CONSTANT2, ITestService::TEST_CONSTANT3,
@@ -105,6 +112,13 @@
}
}
+TEST_F(AidlPrimitiveTest, longConstants) {
+ constexpr int64_t consts[] = {ITestService::LONG_TEST_CONSTANT};
+ for (auto sent : consts) {
+ DoTest(&ITestService::RepeatLong, sent);
+ }
+}
+
TEST_F(AidlPrimitiveTest, strings) {
std::vector<String16> strings = {
String16("Deliver us from evil."), String16(), String16("\0\0", 2),
diff --git a/tests/android/aidl/tests/ITestService.aidl b/tests/android/aidl/tests/ITestService.aidl
index 3b49032..089f5ba 100644
--- a/tests/android/aidl/tests/ITestService.aidl
+++ b/tests/android/aidl/tests/ITestService.aidl
@@ -40,6 +40,9 @@
const int TEST_CONSTANT11 = 0xFA;
const int TEST_CONSTANT12 = 0xffffffff;
+ const byte BYTE_TEST_CONSTANT = 17;
+ const long LONG_TEST_CONSTANT = 1L << 40;
+
const String STRING_TEST_CONSTANT = "foo";
const String STRING_TEST_CONSTANT2 = "bar";
diff --git a/tests/rust/test_client.rs b/tests/rust/test_client.rs
index 6492782..bf950b1 100644
--- a/tests/rust/test_client.rs
+++ b/tests/rust/test_client.rs
@@ -124,6 +124,7 @@
test_primitive! {test_primitive_long, RepeatLong, 1i64 << 60}
test_primitive! {test_primitive_float, RepeatFloat, 1.0f32 / 3.0f32}
test_primitive! {test_primitive_double, RepeatDouble, 1.0f64 / 3.0f64}
+test_primitive! {test_primitive_byte_constant, RepeatByte, ITestService::BYTE_TEST_CONSTANT}
test_primitive! {test_primitive_constant1, RepeatInt, ITestService::TEST_CONSTANT}
test_primitive! {test_primitive_constant2, RepeatInt, ITestService::TEST_CONSTANT2}
test_primitive! {test_primitive_constant3, RepeatInt, ITestService::TEST_CONSTANT3}
@@ -136,6 +137,7 @@
test_primitive! {test_primitive_constant10, RepeatInt, ITestService::TEST_CONSTANT10}
test_primitive! {test_primitive_constant11, RepeatInt, ITestService::TEST_CONSTANT11}
test_primitive! {test_primitive_constant12, RepeatInt, ITestService::TEST_CONSTANT12}
+test_primitive! {test_primitive_long_constant, RepeatLong, ITestService::LONG_TEST_CONSTANT}
test_primitive! {test_primitive_byte_enum, RepeatByteEnum, ByteEnum::FOO}
test_primitive! {test_primitive_int_enum, RepeatIntEnum, IntEnum::BAR}
test_primitive! {test_primitive_long_enum, RepeatLongEnum, LongEnum::FOO}