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}