Snap for 7961397 from 3067a416e9e44377a4734c5da86f4738c8e89e7e to sdk-release

Change-Id: I966a1d3c492d103e9b631146e4d575e232871845
diff --git a/Android.bp b/Android.bp
index 7567893..1f12f81 100644
--- a/Android.bp
+++ b/Android.bp
@@ -588,6 +588,7 @@
         // warning: keep this list up to date with tests/golden_test.sh
         ":aidl-test-interface-cpp-source",
         ":aidl-test-interface-java-source",
+        ":aidl-test-versioned-interface-V2-java-source",
         ":aidl-test-interface-ndk-source",
         ":aidl-test-interface-rust-source",
         ":aidl_test_loggable_interface-cpp-source",
diff --git a/aidl.cpp b/aidl.cpp
index 568ccb8..bb798b7 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -749,7 +749,7 @@
       return false;
     }
     for (const auto& defined_type : typenames.MainDocument().DefinedTypes()) {
-      auto mappings = mappings::generate_mappings(defined_type.get(), typenames);
+      auto mappings = mappings::generate_mappings(defined_type.get());
       all_mappings.insert(mappings.begin(), mappings.end());
     }
   }
diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp
index f21d127..1b2bb85 100644
--- a/aidl_checkapi.cpp
+++ b/aidl_checkapi.cpp
@@ -78,6 +78,7 @@
       AidlAnnotation::Type::NULLABLE,
       // @JavaDerive doesn't affect read/write
       AidlAnnotation::Type::JAVA_DERIVE,
+      AidlAnnotation::Type::JAVA_DEFAULT,
       AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
       // @Backing for a enum type is checked by the enum checker
       AidlAnnotation::Type::BACKING,
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index 2d19efd..14afa12 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -279,6 +279,11 @@
 
 bool AidlBinaryConstExpression::AreCompatibleTypes(Type t1, Type t2) {
   switch (t1) {
+    case Type::ARRAY:
+      if (t2 == Type::ARRAY) {
+        return true;
+      }
+      break;
     case Type::STRING:
       if (t2 == Type::STRING) {
         return true;
@@ -329,6 +334,12 @@
 AidlConstantValue* AidlConstantValue::Default(const AidlTypeSpecifier& specifier) {
   AidlLocation location = specifier.GetLocation();
 
+  // Initialize non-nullable fixed-size arrays with {}("empty list").
+  // Each backend will handle it differently. For example, in Rust, it can be mapped to
+  // "Default::default()".
+  if (specifier.IsFixedSizeArray() && !specifier.IsNullable()) {
+    return Array(location, std::make_unique<std::vector<std::unique_ptr<AidlConstantValue>>>());
+  }
   // allocation of int[0] is a bit wasteful in Java
   if (specifier.IsArray()) {
     return nullptr;
@@ -462,11 +473,13 @@
 AidlConstantValue* AidlConstantValue::Array(
     const AidlLocation& location, std::unique_ptr<vector<unique_ptr<AidlConstantValue>>> values) {
   AIDL_FATAL_IF(values == nullptr, location);
+  // Reconstruct literal value
   std::vector<std::string> str_values;
   for (const auto& v : *values) {
     str_values.push_back(v->value_);
   }
-  return new AidlConstantValue(location, Type::ARRAY, std::move(values), Join(str_values, ", "));
+  return new AidlConstantValue(location, Type::ARRAY, std::move(values),
+                               "{" + Join(str_values, ", ") + "}");
 }
 
 AidlConstantValue* AidlConstantValue::String(const AidlLocation& location, const string& value) {
@@ -517,7 +530,7 @@
     return decorator(type, value_);
   }
 
-  const string& type_string = type.GetName();
+  const string& type_string = type.Signature();
   int err = 0;
 
   switch (final_type_) {
@@ -566,11 +579,10 @@
       bool success = true;
 
       for (const auto& value : values_) {
-        // Pass array type(T[]) as it is instead of converting it to base type(T)
-        // so that decorator can decorate the value in the context of array.
-        // In C++/NDK, 'byte[]' and 'byte' are mapped to different types. If we pass 'byte'
-        // decorator can't know the value should be treated as 'uint8_t'.
-        string value_string = value->ValueString(type, decorator);
+        string value_string;
+        type.ViewAsArrayBase([&](const auto& base_type) {
+          value_string = value->ValueString(base_type, decorator);
+        });
         if (value_string.empty()) {
           success = false;
           break;
@@ -581,8 +593,17 @@
         err = -1;
         break;
       }
-
-      return decorator(type, "{" + Join(value_strings, ", ") + "}");
+      if (type.IsFixedSizeArray()) {
+        auto size =
+            std::get<FixedSizeArray>(type.GetArray()).dimensions.front()->EvaluatedValue<int32_t>();
+        if (values_.size() > static_cast<size_t>(size)) {
+          AIDL_ERROR(this) << "Expected an array of " << size << " elements, but found one with "
+                           << values_.size() << " elements";
+          err = -1;
+          break;
+        }
+      }
+      return decorator(type, value_strings);
     }
     case Type::FLOATING: {
       if (type_string == "double") {
@@ -760,7 +781,8 @@
   if (pos == string::npos) {
     field_name_ = value;
   } else {
-    ref_type_ = std::make_unique<AidlTypeSpecifier>(location, value.substr(0, pos), false, nullptr,
+    ref_type_ = std::make_unique<AidlTypeSpecifier>(location, value.substr(0, pos),
+                                                    /*array=*/std::nullopt, /*type_params=*/nullptr,
                                                     Comments{});
     field_name_ = value.substr(pos + 1);
   }
diff --git a/aidl_language.cpp b/aidl_language.cpp
index ad9d129..426fad8 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -111,14 +111,16 @@
 
 std::vector<AidlLocation> AidlNode::unvisited_locations_;
 
-static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr,
-                                           Comments{}};
-static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr,
-                                                Comments{}};
-static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, Comments{}};
-static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, Comments{}};
-static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr,
-                                            Comments{}};
+static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", /*array=*/std::nullopt,
+                                           nullptr, Comments{}};
+static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", DynamicArray{},
+                                                nullptr, Comments{}};
+static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", /*array=*/std::nullopt, nullptr,
+                                        Comments{}};
+static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", /*array=*/std::nullopt,
+                                         nullptr, Comments{}};
+static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", /*array=*/std::nullopt,
+                                            nullptr, Comments{}};
 
 const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
   static const std::vector<Schema> kSchemas{
@@ -155,6 +157,7 @@
        "JavaDerive",
        CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
        {{"toString", kBooleanType}, {"equals", kBooleanType}}},
+      {AidlAnnotation::Type::JAVA_DEFAULT, "JavaDefault", CONTEXT_TYPE_INTERFACE, {}},
       {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
        "JavaOnlyImmutable",
        CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
@@ -491,6 +494,10 @@
   return false;
 }
 
+bool AidlAnnotatable::IsJavaDefault() const {
+  return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DEFAULT);
+}
+
 std::string AidlAnnotatable::GetDescriptor() const {
   auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
   if (annotation != nullptr) {
@@ -530,23 +537,50 @@
 }
 
 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
-                                     bool is_array,
+                                     std::optional<ArrayType> array,
                                      vector<unique_ptr<AidlTypeSpecifier>>* type_params,
                                      const Comments& comments)
     : AidlAnnotatable(location, comments),
       AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
       unresolved_name_(unresolved_name),
-      is_array_(is_array),
+      array_(std::move(array)),
       split_name_(Split(unresolved_name, ".")) {}
 
 void AidlTypeSpecifier::ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const {
-  AIDL_FATAL_IF(!is_array_, this);
+  AIDL_FATAL_IF(!array_.has_value(), this);
   // Declaring array of generic type cannot happen, it is grammar error.
   AIDL_FATAL_IF(IsGeneric(), this);
 
-  is_array_ = false;
-  func(*this);
-  is_array_ = true;
+  if (IsFixedSizeArray() && std::get<FixedSizeArray>(*array_).dimensions.size() > 1) {
+    auto& dimensions = std::get<FixedSizeArray>(*array_).dimensions;
+    auto dim = std::move(dimensions.front());
+    dimensions.erase(dimensions.begin());
+    func(*this);
+    dimensions.insert(dimensions.begin(), std::move(dim));
+  } else {
+    ArrayType array_type = std::move(array_.value());
+    array_ = std::nullopt;
+    func(*this);
+    array_ = std::move(array_type);
+  }
+}
+
+bool AidlTypeSpecifier::MakeArray(ArrayType array_type) {
+  // T becomes T[] or T[N]
+  if (!IsArray()) {
+    array_ = std::move(array_type);
+    return true;
+  }
+  // T[N] becomes T[N][M]
+  if (auto fixed_size_array = std::get_if<FixedSizeArray>(&array_type);
+      fixed_size_array != nullptr && IsFixedSizeArray()) {
+    // concat dimensions
+    for (auto& dim : fixed_size_array->dimensions) {
+      std::get<FixedSizeArray>(*array_).dimensions.push_back(std::move(dim));
+    }
+    return true;
+  }
+  return false;
 }
 
 string AidlTypeSpecifier::Signature() const {
@@ -559,7 +593,13 @@
     ret += "<" + Join(arg_names, ",") + ">";
   }
   if (IsArray()) {
-    ret += "[]";
+    if (IsFixedSizeArray()) {
+      for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
+        ret += "[" + dim->ValueString(kIntType, AidlConstantValueDecorator) + "]";
+      }
+    } else {
+      ret += "[]";
+    }
   }
   return ret;
 }
@@ -717,21 +757,54 @@
       }
     }
   }
+
+  if (IsFixedSizeArray()) {
+    for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
+      if (!dim->CheckValid()) {
+        return false;
+      }
+      if (dim->GetType() > AidlConstantValue::Type::INT32) {
+        AIDL_ERROR(this) << "Array size must be a positive number: " << dim->Literal();
+        return false;
+      }
+      auto value = dim->EvaluatedValue<int32_t>();
+      if (value < 0) {
+        AIDL_ERROR(this) << "Array size must be a positive number: " << value;
+        return false;
+      }
+    }
+  }
   return true;
 }
 
-std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
-                                       const std::string& raw_value) {
-  if (type.IsArray()) {
-    return raw_value;
+void AidlTypeSpecifier::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
+  AidlAnnotatable::TraverseChildren(traverse);
+  if (IsGeneric()) {
+    for (const auto& tp : GetTypeParameters()) {
+      traverse(*tp);
+    }
   }
+  if (IsFixedSizeArray()) {
+    for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
+      traverse(*dim);
+    }
+  }
+}
 
+std::string AidlConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
+  if (type.IsArray()) {
+    const auto& values = std::get<std::vector<std::string>>(raw_value);
+    return "{" + Join(values, ", ") + "}";
+  }
+  const std::string& value = std::get<std::string>(raw_value);
   if (auto defined_type = type.GetDefinedType(); defined_type) {
     auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
+    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
+    return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
   }
-  return raw_value;
+  return value;
 }
 
 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
diff --git a/aidl_language.h b/aidl_language.h
index 44e6f51..1eb2737 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -20,6 +20,7 @@
 #include <regex>
 #include <string>
 #include <unordered_set>
+#include <variant>
 #include <vector>
 
 #include <android-base/result.h>
@@ -215,8 +216,9 @@
 
 // Transforms a value string into a language specific form. Raw value as produced by
 // AidlConstantValue.
-using ConstantValueDecorator =
-    std::function<std::string(const AidlTypeSpecifier& type, const std::string& raw_value)>;
+using ConstantValueDecorator = std::function<std::string(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value)>;
 
 class AidlAnnotation : public AidlNode {
  public:
@@ -231,6 +233,7 @@
     SENSITIVE_DATA,
     JAVA_PASSTHROUGH,
     JAVA_DERIVE,
+    JAVA_DEFAULT,
     JAVA_ONLY_IMMUTABLE,
     FIXED_SIZE,
     DESCRIPTOR,
@@ -350,6 +353,7 @@
   bool IsStableApiParcelable(Options::Language lang) const;
   bool IsHide() const;
   bool JavaDerive(const std::string& method) const;
+  bool IsJavaDefault() const;
   std::string GetDescriptor() const;
 
   const AidlAnnotation* UnsupportedAppUsage() const;
@@ -377,16 +381,28 @@
   vector<std::unique_ptr<AidlAnnotation>> annotations_;
 };
 
+// Represents `[]`
+struct DynamicArray {};
+// Represents `[N][M]..`
+struct FixedSizeArray {
+  FixedSizeArray(std::unique_ptr<AidlConstantValue> dim) { dimensions.push_back(std::move(dim)); }
+  std::vector<std::unique_ptr<AidlConstantValue>> dimensions;
+};
+// Represents `[]` or `[N]` part of type specifier
+using ArrayType = std::variant<DynamicArray, FixedSizeArray>;
+
 // AidlTypeSpecifier represents a reference to either a built-in type,
 // a defined type, or a variant (e.g., array of generic) of a type.
 class AidlTypeSpecifier final : public AidlAnnotatable,
                                 public AidlParameterizable<unique_ptr<AidlTypeSpecifier>> {
  public:
-  AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name, bool is_array,
+  AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
+                    std::optional<ArrayType> array,
                     vector<unique_ptr<AidlTypeSpecifier>>* type_params, const Comments& comments);
   virtual ~AidlTypeSpecifier() = default;
 
-  // View of this type which is not an array.
+  // View of this type which has one-less dimension(s).
+  // e.g.) T[] => T, T[N][M] => T[M]
   void ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const;
 
   // Returns the full-qualified name of the base type.
@@ -420,14 +436,23 @@
 
   bool IsResolved() const { return fully_qualified_name_ != ""; }
 
-  bool IsArray() const { return is_array_; }
+  bool IsArray() const { return array_.has_value(); }
 
-  __attribute__((warn_unused_result)) bool SetArray() {
-    if (is_array_) return false;
-    is_array_ = true;
-    return true;
+  bool IsFixedSizeArray() const {
+    return array_.has_value() && std::get_if<FixedSizeArray>(&*array_) != nullptr;
   }
 
+  const ArrayType& GetArray() const {
+    AIDL_FATAL_IF(!array_.has_value(), this) << "GetArray() for non-array type";
+    return array_.value();
+  }
+
+  // Accept transitions from
+  //    T    to T[]
+  // or T    to T[N]
+  // or T[N] to T[N][M]
+  __attribute__((warn_unused_result)) bool MakeArray(ArrayType array_type);
+
   // Resolve the base type name to a fully-qualified name. Return false if the
   // resolution fails.
   bool Resolve(const AidlTypenames& typenames, const AidlScope* scope);
@@ -437,26 +462,21 @@
   const AidlNode& AsAidlNode() const override { return *this; }
 
   const AidlDefinedType* GetDefinedType() const;
-  void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
-    AidlAnnotatable::TraverseChildren(traverse);
-    if (IsGeneric()) {
-      for (const auto& tp : GetTypeParameters()) {
-        traverse(*tp);
-      }
-    }
-  }
+  void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override;
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 
  private:
   const string unresolved_name_;
   string fully_qualified_name_;
-  mutable bool is_array_;
+  mutable std::optional<ArrayType> array_;
   vector<string> split_name_;
   const AidlDefinedType* defined_type_ = nullptr;  // set when Resolve() for defined types
 };
 
 // Returns the universal value unaltered.
-std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string AidlConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 class AidlMember : public AidlAnnotatable {
  public:
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index 66e6f1e..1665709 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -675,7 +675,7 @@
 
 non_array_type
  : annotation_list qualified_name {
-    $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), false, nullptr, $2->GetComments());
+    $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), /*array=*/std::nullopt, nullptr, $2->GetComments());
     if (!$1->empty()) {
       $$->SetComments($1->begin()->get()->GetComments());
       $$->Annotate(std::move(*$1));
@@ -708,8 +708,20 @@
       AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported.";
       ps->AddError();
     }
-    if (!$1->SetArray()) {
-      AIDL_ERROR(loc(@1)) << "Can only have one dimensional arrays.";
+    if (!$1->MakeArray(DynamicArray{})) {
+      AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size.";
+      ps->AddError();
+    }
+    $$ = $1;
+    delete $2;
+  }
+ | type annotation_list '[' const_expr ']' {
+    if (!$2->empty()) {
+      AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported.";
+      ps->AddError();
+    }
+    if (!$1->MakeArray(FixedSizeArray{std::unique_ptr<AidlConstantValue>($4)})) {
+      AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size.";
       ps->AddError();
     }
     $$ = $1;
diff --git a/aidl_to_cpp.cpp b/aidl_to_cpp.cpp
index c476c90..422a2e5 100644
--- a/aidl_to_cpp.cpp
+++ b/aidl_to_cpp.cpp
@@ -200,7 +200,9 @@
   return WrapIfNullable(cpp_name, raw_type, typenames);
 }
 }  // namespace
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
   return CppConstantValueDecorator(type, raw_value, /*is_ndk=*/false);
 };
 
diff --git a/aidl_to_cpp.h b/aidl_to_cpp.h
index eab471e..73b79bb 100644
--- a/aidl_to_cpp.h
+++ b/aidl_to_cpp.h
@@ -23,7 +23,9 @@
 
 // This header provides functions that translate AIDL things to cpp things.
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 struct CodeGeneratorContext {
   CodeWriter& writer;
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 6a2f60e..aa57037 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -482,8 +482,10 @@
                                 first_field->ValueString(decorator) + ")";
 
     out << "Tag _tag __attribute__((aligned (1))) = " << default_name << ";\n";
-    out << "union {\n";
+    out << "union _value_t {\n";
     out.Indent();
+    out << "_value_t() {}\n";
+    out << "~_value_t() {}\n";
     for (const auto& f : decl.GetFields()) {
       const auto& fn = f->GetName();
       out << name_of(f->GetType(), typenames) << " " << fn;
@@ -691,56 +693,64 @@
   out << "__assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, \"can't reach here\");\n";
 }
 
-std::string CppConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value,
-                                      bool is_ndk) {
-  AIDL_FATAL_IF(raw_value.empty(), type) << "Empty value for constants";
-
-  // apply array type only if raw_value is actually an array value(`{...}`).
-  if (type.IsArray() && raw_value[0] == '{') {
-    return raw_value;
+std::string CppConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value, bool is_ndk) {
+  if (type.IsArray()) {
+    const auto& values = std::get<std::vector<std::string>>(raw_value);
+    // Hexadecimal literals for byte arrays should be casted to uint8_t
+    if (type.GetName() == "byte" &&
+        std::any_of(values.begin(), values.end(),
+                    [](const auto& value) { return !value.empty() && value[0] == '-'; })) {
+      std::vector<std::string> copy = values;
+      for (auto& value : copy) {
+        // cast only if necessary
+        if (value[0] == '-') {
+          value = "uint8_t(" + value + ")";
+        }
+      }
+      return "{" + Join(copy, ", ") + "}";
+    }
+    return "{" + Join(values, ", ") + "}";
   }
 
+  const std::string& value = std::get<std::string>(raw_value);
   if (AidlTypenames::IsBuiltinTypename(type.GetName())) {
     if (type.GetName() == "boolean") {
-      return raw_value;
+      return value;
     } else if (type.GetName() == "byte") {
-      // cast only if necessary
-      if (type.IsArray() && raw_value[0] == '-') {
-        return "uint8_t(" + raw_value + ")";
-      } else {
-        return raw_value;
-      }
+      return value;
     } else if (type.GetName() == "char") {
       // TODO: consider 'L'-prefix for wide char literal
-      return raw_value;
+      return value;
     } else if (type.GetName() == "double") {
-      return raw_value;
+      return value;
     } else if (type.GetName() == "float") {
-      return raw_value;  // raw_value has 'f' suffix
+      return value;  // value has 'f' suffix
     } else if (type.GetName() == "int") {
-      return raw_value;
+      return value;
     } else if (type.GetName() == "long") {
-      return raw_value + "L";
+      return value + "L";
     } else if (type.GetName() == "String") {
       if (is_ndk || type.IsUtf8InCpp()) {
-        return raw_value;
+        return value;
       } else {
-        return "::android::String16(" + raw_value + ")";
+        return "::android::String16(" + value + ")";
       }
     }
     AIDL_FATAL(type) << "Unknown built-in type: " << type.GetName();
   }
 
   auto defined_type = type.GetDefinedType();
-  AIDL_FATAL_IF(!defined_type, type) << "Invalid type for \"" << raw_value << "\"";
+  AIDL_FATAL_IF(!defined_type, type) << "Invalid type for \"" << value << "\"";
   auto enum_type = defined_type->AsEnumDeclaration();
-  AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
+  AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
 
   auto cpp_type_name = "::" + Join(Split(enum_type->GetCanonicalName(), "."), "::");
   if (is_ndk) {
     cpp_type_name = "::aidl" + cpp_type_name;
   }
-  return cpp_type_name + "::" + raw_value.substr(raw_value.find_last_of('.') + 1);
+  return cpp_type_name + "::" + value.substr(value.find_last_of('.') + 1);
 }
 }  // namespace cpp
 }  // namespace aidl
diff --git a/aidl_to_cpp_common.h b/aidl_to_cpp_common.h
index e639a7c..e6733b6 100644
--- a/aidl_to_cpp_common.h
+++ b/aidl_to_cpp_common.h
@@ -44,6 +44,12 @@
 
 string ClassName(const AidlDefinedType& defined_type, ClassNames type);
 
+// Return the alignment of known types and enum backing types.
+// If the alignment is unknown, or it is a FizedSize parcelable with its
+// own guaranteed alignment(so it does not need to be specified), 0 will be
+// returned.
+size_t AlignmentOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
+
 // Generate the relative path to a header file.  If |use_os_sep| we'll use the
 // operating system specific path separator rather than C++'s expected '/' when
 // including headers.
@@ -123,8 +129,9 @@
   void WriteToParcel(CodeWriter& out, const ParcelWriterContext&) const;
 };
 
-std::string CppConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value,
-                                      bool is_ndk);
+std::string CppConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value, bool is_ndk);
 }  // namespace cpp
 }  // namespace aidl
 }  // namespace android
diff --git a/aidl_to_java.cpp b/aidl_to_java.cpp
index 154456a..d8a05d5 100644
--- a/aidl_to_java.cpp
+++ b/aidl_to_java.cpp
@@ -38,23 +38,27 @@
 using std::string;
 using std::vector;
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
-  if (type.IsArray() && !raw_value.empty() && raw_value[0] == '{') {
-    return raw_value;
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
+  if (type.IsArray()) {
+    const auto& values = std::get<std::vector<std::string>>(raw_value);
+    return "{" + Join(values, ", ") + "}";
   }
+  const std::string& value = std::get<std::string>(raw_value);
   if (type.GetName() == "long") {
-    return raw_value + "L";
+    return value + "L";
   }
   if (auto defined_type = type.GetDefinedType(); defined_type) {
     auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
+    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
+    return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
   }
-  return raw_value;
+  return value;
 };
 
-const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
-                         bool instantiable = false, bool boxing = false) {
+const string& JavaNameOf(const AidlTypeSpecifier& aidl, bool instantiable = false,
+                         bool boxing = false) {
   AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
 
   if (instantiable) {
@@ -102,8 +106,9 @@
 
   // Enums in Java are represented by their backing type when
   // referenced in parcelables, methods, etc.
-  if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
-      enum_decl != nullptr) {
+  const auto defined_type = aidl.GetDefinedType();
+  if (defined_type && defined_type->AsEnumDeclaration()) {
+    const auto enum_decl = defined_type->AsEnumDeclaration();
     const string& backing_type_name = enum_decl->GetBackingType().GetName();
     AIDL_FATAL_IF(m.find(backing_type_name) == m.end(), enum_decl);
     AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(backing_type_name), enum_decl);
@@ -131,14 +136,13 @@
 
 namespace {
 string JavaSignatureOfInternal(
-    const AidlTypeSpecifier& aidl, const AidlTypenames& typenames, bool instantiable,
-    bool omit_array, bool boxing = false /* boxing can be true only if it is a type parameter */) {
-  string ret = JavaNameOf(aidl, typenames, instantiable, boxing && !aidl.IsArray());
+    const AidlTypeSpecifier& aidl, bool instantiable, bool omit_array,
+    bool boxing = false /* boxing can be true only if it is a type parameter */) {
+  string ret = JavaNameOf(aidl, instantiable, boxing && !aidl.IsArray());
   if (aidl.IsGeneric()) {
     vector<string> arg_names;
     for (const auto& ta : aidl.GetTypeParameters()) {
-      arg_names.emplace_back(
-          JavaSignatureOfInternal(*ta, typenames, false, false, true /* boxing */));
+      arg_names.emplace_back(JavaSignatureOfInternal(*ta, false, false, true /* boxing */));
     }
     ret += "<" + Join(arg_names, ",") + ">";
   }
@@ -152,10 +156,11 @@
 // returns type names as used in AIDL, not a Java signature.
 // For enums, this is the enum's backing type.
 // For all other types, this is the type itself.
-string AidlBackingTypeName(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+string AidlBackingTypeName(const AidlTypeSpecifier& type) {
   string type_name;
-  if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(type);
-      enum_decl != nullptr) {
+  const auto defined_type = type.GetDefinedType();
+  if (defined_type && defined_type->AsEnumDeclaration()) {
+    const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
     type_name = enum_decl->GetBackingType().GetName();
   } else {
     type_name = type.GetName();
@@ -168,21 +173,21 @@
 
 }  // namespace
 
-string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
-  return JavaSignatureOfInternal(aidl, typenames, false, false);
+string JavaSignatureOf(const AidlTypeSpecifier& aidl) {
+  return JavaSignatureOfInternal(aidl, false, false);
 }
 
-string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
-  return JavaSignatureOfInternal(aidl, typenames, true, true);
+string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl) {
+  return JavaSignatureOfInternal(aidl, true, true);
 }
 
-string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
+string DefaultJavaValueOf(const AidlTypeSpecifier& aidl) {
   static map<string, string> m = {
       {"boolean", "false"}, {"byte", "0"},     {"char", R"('\u0000')"}, {"int", "0"},
       {"long", "0L"},       {"float", "0.0f"}, {"double", "0.0d"},
   };
 
-  const string name = AidlBackingTypeName(aidl, typenames);
+  const string name = AidlBackingTypeName(aidl);
   AIDL_FATAL_IF(name == "void", aidl);
 
   if (!aidl.IsArray() && m.find(name) != m.end()) {
@@ -457,7 +462,7 @@
          c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
        }},
   };
-  const string type_name = AidlBackingTypeName(c.type, c.typenames);
+  const string type_name = AidlBackingTypeName(c.type);
   const auto found = method_map.find(type_name);
   if (found != method_map.end()) {
     found->second(c);
@@ -579,7 +584,7 @@
              c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
            } else if (c.typenames.IsParcelable(element_type_name)) {
              c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
-                      << JavaNameOf(element_type, c.typenames) << ".CREATOR);\n";
+                      << JavaNameOf(element_type) << ".CREATOR);\n";
            } else if (c.typenames.GetInterface(element_type)) {
              auto as_interface = element_type_name + ".Stub::asInterface";
              c.writer << c.var << " = " << c.parcel << ".createInterfaceArrayList(" << as_interface
@@ -600,11 +605,11 @@
            c.writer << "int N = " << c.parcel << ".readInt();\n";
            c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
 
-           auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) + ".CREATOR";
+           auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1))) + ".CREATOR";
            c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
            c.writer.Indent();
            c.writer << "String k = " << c.parcel << ".readString();\n";
-           c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
+           c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
            CodeGeneratorContext value_context{
                c.writer,
                c.typenames,
@@ -679,7 +684,7 @@
          c.writer << "}\n";
        }},
   };
-  const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
+  const auto found = method_map.find(AidlBackingTypeName(c.type));
   if (found != method_map.end()) {
     found->second(c);
   } else {
@@ -698,8 +703,8 @@
       }
     } else if (t->AsParcelable() != nullptr) {
       if (c.type.IsArray()) {
-        c.writer << c.var << " = " << c.parcel << ".createTypedArray("
-                 << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
+        c.writer << c.var << " = " << c.parcel << ".createTypedArray(" << JavaNameOf(c.type)
+                 << ".CREATOR);\n";
       } else {
         if (c.min_sdk_version >= 23u) {
           c.writer << c.var << " = " << c.parcel << ".readTypedObject(" << c.type.GetName()
@@ -760,8 +765,7 @@
              c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
            } else if (c.typenames.IsParcelable(element_type_name)) {
              c.writer << c.parcel << ".readTypedList(" << c.var << ", "
-                      << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
-                      << ".CREATOR);\n";
+                      << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
            } else if (c.typenames.GetInterface(element_type)) {
              auto as_interface = element_type_name + ".Stub::asInterface";
              c.writer << c.parcel << ".readInterfaceList(" << c.var << ", " << as_interface
@@ -782,7 +786,7 @@
                     << ".readInt()).forEach(i -> {\n";
            c.writer.Indent();
            c.writer << "String k = " << c.parcel << ".readString();\n";
-           c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
+           c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
            CodeGeneratorContext value_context{
                c.writer,
                c.typenames,
@@ -826,7 +830,7 @@
                   << ", android.os.ParcelFileDescriptor.CREATOR);\n";
        }},
   };
-  const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
+  const auto& found = method_map.find(AidlBackingTypeName(c.type));
   if (found != method_map.end()) {
     found->second(c);
   } else {
diff --git a/aidl_to_java.h b/aidl_to_java.h
index 25c07a4..5a4632c 100644
--- a/aidl_to_java.h
+++ b/aidl_to_java.h
@@ -39,18 +39,20 @@
 
 // This header provides functions that translate AIDL things to Java things.
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 // Returns the Java type signature of the AIDL type spec
 // This includes generic type parameters with array modifiers.
-string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames);
+string JavaSignatureOf(const AidlTypeSpecifier& aidl);
 
 // Returns the instantiable Jva type signature of the AIDL type spec
 // This includes generic type parameters, but excludes array modifiers.
-string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames);
+string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl);
 
 // Returns the default Java value of the AIDL type spec
-string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames);
+string DefaultJavaValueOf(const AidlTypeSpecifier& aidl);
 
 // This carries information that is required to generate code for
 // marshalling and unmarshalling a method argument or a parcelable field
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index 6a797bb..b9b632c 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -70,7 +70,9 @@
   std::shared_ptr<Aspect> nullable_array;
 };
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
   return cpp::CppConstantValueDecorator(type, raw_value, /*is_ndk=*/true);
 };
 
@@ -456,26 +458,6 @@
   }
 }
 
-size_t NdkAlignmentOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
-  // map from NDK type name to the corresponding alignment size
-  static map<string, int> alignment = {
-      {"bool", 1},  {"int8_t", 1},  {"char16_t", 2}, {"double", 8},
-      {"float", 4}, {"int32_t", 4}, {"int64_t", 8},
-  };
-
-  const string& name = NdkNameOf(types, aidl, StorageMode::STACK);
-  if (alignment.find(name) != alignment.end()) {
-    return alignment[name];
-  } else {
-    const auto& definedType = types.TryGetDefinedType(aidl.GetName());
-    AIDL_FATAL_IF(definedType == nullptr, aidl) << "Failed to resolve type.";
-    if (const auto& enumType = definedType->AsEnumDeclaration(); enumType != nullptr) {
-      return NdkAlignmentOf(types, enumType->GetBackingType());
-    }
-  }
-  return 0;
-}
-
 void WriteToParcelFor(const CodeGeneratorContext& c) {
   TypeInfo::Aspect aspect = GetTypeAspect(c.types, c.type);
   aspect.write_func(c);
diff --git a/aidl_to_ndk.h b/aidl_to_ndk.h
index 370d07b..7d815c5 100644
--- a/aidl_to_ndk.h
+++ b/aidl_to_ndk.h
@@ -31,7 +31,9 @@
 std::string NdkHeaderFile(const AidlDefinedType& defined_type, cpp::ClassNames name,
                           bool use_os_sep = true);
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 // Returns ::aidl::some_package::some_sub_package::foo::IFoo/BpFoo/BnFoo
 std::string NdkFullClassName(const AidlDefinedType& type, cpp::ClassNames name);
@@ -40,12 +42,6 @@
 // array modifiers.
 std::string NdkNameOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl, StorageMode mode);
 
-// Return the alignment of known types and enum backing types.
-// If the alignment is unknown, or it is a FizedSize parcelable with its
-// own guaranteed alignment(so it does not need to be specified), 0 will be
-// returned.
-size_t NdkAlignmentOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl);
-
 struct CodeGeneratorContext {
   CodeWriter& writer;
 
diff --git a/aidl_to_rust.cpp b/aidl_to_rust.cpp
index 21e67cd..ad64b6e 100644
--- a/aidl_to_rust.cpp
+++ b/aidl_to_rust.cpp
@@ -39,40 +39,44 @@
 namespace {
 std::string GetRawRustName(const AidlTypeSpecifier& type);
 
-std::string ConstantValueDecoratorInternal(const AidlTypeSpecifier& type,
-                                           const std::string& raw_value, bool by_ref) {
-  if (type.IsArray() && !raw_value.empty() && raw_value[0] == '{') {
-    // Convert `{ ... }` to `vec!{ ... }`
-    return "vec!" + raw_value;
+std::string ConstantValueDecoratorInternal(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value, bool by_ref) {
+  if (type.IsArray()) {
+    // Convert `{ ... }` to `vec![ ... ]`
+    const auto& values = std::get<std::vector<std::string>>(raw_value);
+    return "vec![" + Join(values, ", ") + "]";
   }
 
+  const std::string& value = std::get<std::string>(raw_value);
+
   const auto& aidl_name = type.GetName();
   if (aidl_name == "char") {
-    return raw_value + " as u16";
+    return value + " as u16";
   }
 
   if (aidl_name == "float") {
-    // raw_value already ends in `f`, so just add `32`
-    return raw_value + "32";
+    // value already ends in `f`, so just add `32`
+    return value + "32";
   }
 
   if (aidl_name == "double") {
-    return raw_value + "f64";
+    return value + "f64";
   }
 
   if (aidl_name == "String" && !by_ref) {
     // The actual type might be String or &str,
     // and .into() transparently converts into either one
-    return raw_value + ".into()";
+    return value + ".into()";
   }
 
   if (auto defined_type = type.GetDefinedType(); defined_type) {
     auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return GetRawRustName(type) + "::" + raw_value.substr(raw_value.find_last_of('.') + 1);
+    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
+    return GetRawRustName(type) + "::" + value.substr(value.find_last_of('.') + 1);
   }
 
-  return raw_value;
+  return value;
 }
 
 std::string GetRawRustName(const AidlTypeSpecifier& type) {
@@ -140,7 +144,9 @@
 }
 }  // namespace
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
   auto rust_value = ConstantValueDecoratorInternal(type, raw_value, false);
   if (type.IsNullable()) {
     return "Some(" + rust_value + ")";
@@ -148,7 +154,9 @@
   return rust_value;
 }
 
-std::string ConstantValueDecoratorRef(const AidlTypeSpecifier& type, const std::string& raw_value) {
+std::string ConstantValueDecoratorRef(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
   auto rust_value = ConstantValueDecoratorInternal(type, raw_value, true);
   if (type.IsNullable()) {
     return "Some(" + rust_value + ")";
diff --git a/aidl_to_rust.h b/aidl_to_rust.h
index 6145122..2fe73ae 100644
--- a/aidl_to_rust.h
+++ b/aidl_to_rust.h
@@ -58,9 +58,13 @@
   }
 }
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
-std::string ConstantValueDecoratorRef(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecoratorRef(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 // Returns "'lifetime_name " including the initial apostrophe and the trailing space.
 // Returns empty string for NONE.
diff --git a/aidl_typenames.cpp b/aidl_typenames.cpp
index 77fa266..67da4e7 100644
--- a/aidl_typenames.cpp
+++ b/aidl_typenames.cpp
@@ -252,8 +252,12 @@
 std::unique_ptr<AidlTypeSpecifier> AidlTypenames::MakeResolvedType(const AidlLocation& location,
                                                                    const string& name,
                                                                    bool is_array) const {
+  std::optional<ArrayType> array;
+  if (is_array) {
+    array = DynamicArray{};
+  }
   std::unique_ptr<AidlTypeSpecifier> type(
-      new AidlTypeSpecifier(location, name, is_array, nullptr, {}));
+      new AidlTypeSpecifier(location, name, std::move(array), nullptr, {}));
   AIDL_FATAL_IF(!type->Resolve(*this, nullptr), type) << "Can't make unknown type: " << name;
   type->MarkVisited();
   return type;
@@ -287,10 +291,16 @@
   return t->IsJavaOnlyImmutable();
 }
 
-// Only FixedSize Parcelable, primitive types, and enum types can be FixedSize.
+// Followings can be FixedSize:
+// - @FixedSize parcelables
+// - primitive types and enum types
+// - fixed-size arrays of FixedSize types
 bool AidlTypenames::CanBeFixedSize(const AidlTypeSpecifier& type) const {
   const string& name = type.GetName();
-  if (type.IsGeneric() || type.IsArray() || type.IsNullable()) {
+  if (type.IsGeneric() || type.IsNullable()) {
+    return false;
+  }
+  if (type.IsArray() && !type.IsFixedSizeArray()) {
     return false;
   }
   if (IsPrimitiveTypename(name)) {
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 376e166..f5bf617 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -792,7 +792,7 @@
   EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
   EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
   // But if we request just "IBar" we should get our imported one.
-  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, {});
+  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", /*array=*/std::nullopt, nullptr, {});
   ambiguous_type.Resolve(typenames_, parse_result);
   EXPECT_EQ("one.IBar", ambiguous_type.GetName());
 }
@@ -814,7 +814,7 @@
   EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
   EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
   // But if we request just "IBar" we should get our imported one.
-  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, {});
+  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", /*array=*/std::nullopt, nullptr, {});
   ambiguous_type.Resolve(typenames_, parse_result);
   EXPECT_EQ("one.IBar", ambiguous_type.GetName());
 }
@@ -1130,8 +1130,7 @@
                       {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
                       {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
                       {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
-                      // TODO(b/177860423) support "deprecated" in Rust enum
-                      // {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
+                      {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
                   });
 }
 
@@ -1263,6 +1262,11 @@
   EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_err));
 }
 
+TEST_F(AidlTest, CosntantValueType) {
+  unique_ptr<AidlConstantValue> num{AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1")};
+  EXPECT_EQ(num->GetType(), AidlConstantValue::Type::INT8);
+}
+
 TEST_P(AidlTest, FailOnTooBigConstant) {
   AidlError error;
   const string expected_stderr =
@@ -1482,7 +1486,8 @@
 
   EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
   // C++ uses "::" instead of "." to refer to a inner class.
-  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", false, nullptr, {});
+  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", /*array=*/std::nullopt,
+                                nullptr, {});
   EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
 }
 
@@ -1498,7 +1503,8 @@
 
   EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
   // C++ uses "::" instead of "." to refer to a inner class.
-  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", false, nullptr, {});
+  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", /*array=*/std::nullopt,
+                                nullptr, {});
   EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
 }
 
@@ -1522,7 +1528,8 @@
 
   EXPECT_TRUE(typenames_.ResolveTypename("p.IOuter.Inner").is_resolved);
   // C++ uses "::" instead of "." to refer to a inner class.
-  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.IOuter.Inner", false, nullptr, {});
+  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.IOuter.Inner", /*array=*/std::nullopt,
+                                nullptr, {});
   EXPECT_EQ("::p::IOuter::Inner", cpp::CppNameOf(nested_type, typenames_));
 }
 
@@ -1914,7 +1921,8 @@
   auto type = [](std::string name, auto&&... type_params) -> std::unique_ptr<AidlTypeSpecifier> {
     auto params = new std::vector<std::unique_ptr<AidlTypeSpecifier>>;
     (..., params->emplace_back(std::move(type_params)));
-    return std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, name, false, params, Comments{});
+    return std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, name, std::nullopt, params,
+                                               Comments{});
   };
 
   auto set_nullable = [](std::unique_ptr<AidlTypeSpecifier>&& type) {
@@ -1926,7 +1934,7 @@
   };
 
   auto set_array = [](std::unique_ptr<AidlTypeSpecifier>&& type) {
-    (void)type->SetArray();
+    (void)type->MakeArray(DynamicArray{});
     return std::move(type);
   };
 
@@ -1964,10 +1972,10 @@
   auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
   EXPECT_NE(nullptr, parse_result);
   EXPECT_TRUE(typenames_.ResolveTypename("p.Bar").is_resolved);
-  AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", false, nullptr, {});
+  AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", /*array=*/std::nullopt, nullptr, {});
   native_type.Resolve(typenames_, parse_result);
 
-  EXPECT_EQ("p.Bar", java::InstantiableJavaSignatureOf(native_type, typenames_));
+  EXPECT_EQ("p.Bar", java::InstantiableJavaSignatureOf(native_type));
   // C++ understands C++ specific stuff
   EXPECT_EQ("::p::Bar", cpp::CppNameOf(native_type, typenames_));
   set<string> headers;
@@ -2188,6 +2196,7 @@
       "    int foo(out int[] a, String b, boolean c, inout List<String> d);\n"
       "    int foo2(@utf8InCpp String x, inout List<String> y);\n"
       "    IFoo foo3(IFoo foo);\n"
+      "    void foo4(in int[2][3] fixedArray);\n"
       "    Data getData();\n"
       "    // @hide not applied\n"
       "    /** blahblah\n"
@@ -2229,6 +2238,7 @@
   int foo(out int[] a, String b, boolean c, inout List<String> d);
   int foo2(@utf8InCpp String x, inout List<String> y);
   foo.bar.IFoo foo3(foo.bar.IFoo foo);
+  void foo4(in int[2][3] fixedArray);
   foo.bar.Data getData();
   /**
    * @deprecated reason why...
@@ -3567,6 +3577,7 @@
                                "  int isFixedSize;\n"
                                "  @nullable OtherFixed nullable1;\n"
                                "  @nullable(heap=true) OtherFixed nullable2;\n"
+                               "  float[16] floats;\n"
                                "}");
   io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { int a; }");
   io_delegate_.SetFileContents("OtherFixed.aidl", "@FixedSize parcelable OtherFixed { int a; }");
@@ -3606,6 +3617,7 @@
                                "  int isFixedSize;\n"
                                "  @nullable OtherFixed nullable1;\n"
                                "  @nullable(heap=true) OtherFixed nullable2;\n"
+                               "  float[16] floats;\n"
                                "}");
   io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { int a; }");
   io_delegate_.SetFileContents("OtherFixed.aidl", "@FixedSize parcelable OtherFixed { int a; }");
@@ -4366,15 +4378,58 @@
                   "a.Baz<a.Bar<a.Bar<java.lang.String[]>>[],a.Bar<java.lang.String>> barss;"));
 }
 
-TEST_F(AidlTest, DoubleArrayError) {
+TEST_F(AidlTest, AcceptMultiDimensionalFixedSizeArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[2][3] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, RejectArrayOfFixedSizeArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[2][] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
+}
+
+TEST_F(AidlTest, RejectFixedSizeArrayOfDynamicArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[][3] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
+}
+
+TEST_F(AidlTest, RejectArrayOfArray) {
   io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[][] a; }");
 
   Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
-  const string expected_stderr =
-      "ERROR: a/Bar.aidl:1.28-37: Can only have one dimensional arrays.\n";
   CaptureStderr();
   EXPECT_FALSE(compile_aidl(options, io_delegate_));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
+}
+
+TEST_F(AidlTest, RejectInvalidArraySize_Negative) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[-1] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Array size must be a positive number"));
+}
+
+TEST_F(AidlTest, RejectInvalidArraySize_WrongType) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[\"3\"] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Array size must be a positive number"));
 }
 
 TEST_F(AidlTest, DoubleGenericError) {
@@ -4419,6 +4474,46 @@
               testing::HasSubstr("Annotations for type arguments are not supported."));
 }
 
+TEST_F(AidlTest, DefaultShouldMatchWithFixedSizeArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl",
+                               "package a;\n"
+                               "parcelable Bar {\n"
+                               "  int[2][3] a = {{1,2,3}, {4,5,6}};\n"
+                               "}");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithWrongTypeDefaultValue) {
+  io_delegate_.SetFileContents("a/Bar.aidl",
+                               "package a;\n"
+                               "parcelable Bar {\n"
+                               "  int[2][3] a = {{\"1\",\"2\",\"3\"}, {4,5,6}};\n"
+                               "}");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Invalid type specifier for a literal string: int"));
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithWrongSizeDefaultValue) {
+  io_delegate_.SetFileContents("a/Bar.aidl",
+                               "package a;\n"
+                               "parcelable Bar {\n"
+                               "  int[2][3] a = {{1,2,3,4}, {4,5,6}};\n"
+                               "}");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(),
+              HasSubstr("Expected an array of 3 elements, but found one with 4 elements"));
+}
+
 struct GenericAidlTest : ::testing::Test {
   FakeIoDelegate io_delegate_;
   void Compile(string cmd) {
@@ -4896,7 +4991,7 @@
   io_delegate_.SetFileContents(
       "IFoo.aidl",
       "interface IFoo {\n"
-      "  void foo(in @SuppressWarnings(value=\"inout-parameter\") int x);\n"
+      "  void foo(in @SuppressWarnings(value={\"inout-parameter\"}) int x);\n"
       "}");
   auto options = Options::From("aidl --lang=java IFoo.aidl");
   CaptureStderr();
@@ -4938,11 +5033,17 @@
 };
 
 const TypeParam kTypeParams[] = {
-    {"primitive", "int"},    {"primitiveArray", "int[]"},
-    {"String", "String"},    {"StringArray", "String[]"},
-    {"IBinder", "IBinder"},  {"ParcelFileDescriptor", "ParcelFileDescriptor"},
-    {"parcelable", "a.Foo"}, {"enum", "a.Enum"},
-    {"union", "a.Union"},    {"interface", "a.IBar"},
+    {"primitive", "int"},
+    {"primitiveArray", "int[]"},
+    {"primitiveFixedArray", "int[3]"},
+    {"String", "String"},
+    {"StringArray", "String[]"},
+    {"IBinder", "IBinder"},
+    {"ParcelFileDescriptor", "ParcelFileDescriptor"},
+    {"parcelable", "a.Foo"},
+    {"enum", "a.Enum"},
+    {"union", "a.Union"},
+    {"interface", "a.IBar"},
 };
 
 struct ExpectedResult {
@@ -4959,6 +5060,14 @@
     {"java_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
     {"ndk_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
     {"rust_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"cpp_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"java_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"ndk_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"rust_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
     {"cpp_String", {"", ""}},
     {"java_String", {"", ""}},
     {"ndk_String", {"", ""}},
@@ -4998,18 +5107,46 @@
     {"java_primitive", {"", ""}},
     {"ndk_primitive", {"", ""}},
     {"rust_primitive", {"", ""}},
-    {"cpp_primitiveArray", {"Can only have one dimensional", "Can only have one dimensional"}},
-    {"java_primitiveArray", {"Can only have one dimensional", "Can only have one dimensional"}},
-    {"ndk_primitiveArray", {"Can only have one dimensional", "Can only have one dimensional"}},
-    {"rust_primitiveArray", {"Can only have one dimensional", "Can only have one dimensional"}},
+    {"cpp_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"java_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"ndk_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"rust_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"cpp_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"java_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"ndk_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"rust_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
     {"cpp_String", {"", ""}},
     {"java_String", {"", ""}},
     {"ndk_String", {"", ""}},
     {"rust_String", {"", ""}},
-    {"cpp_StringArray", {"Can only have one dimensional", "Can only have one dimensional"}},
-    {"java_StringArray", {"Can only have one dimensional", "Can only have one dimensional"}},
-    {"ndk_StringArray", {"Can only have one dimensional", "Can only have one dimensional"}},
-    {"rust_StringArray", {"Can only have one dimensional", "Can only have one dimensional"}},
+    {"cpp_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"java_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"ndk_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"rust_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
     {"cpp_IBinder", {"", ""}},
     {"java_IBinder", {"", ""}},
     {"ndk_IBinder", {"", ""}},
@@ -5045,6 +5182,10 @@
     {"java_primitiveArray", {"", ""}},
     {"ndk_primitiveArray", {"", ""}},
     {"rust_primitiveArray", {"", ""}},
+    {"cpp_primitiveFixedArray", {"", ""}},
+    {"java_primitiveFixedArray", {"", ""}},
+    {"ndk_primitiveFixedArray", {"", ""}},
+    {"rust_primitiveFixedArray", {"", ""}},
     {"cpp_String", {"", ""}},
     {"java_String", {"", ""}},
     {"ndk_String", {"", ""}},
diff --git a/generate_aidl_mappings.cpp b/generate_aidl_mappings.cpp
index 994d6a3..4d2a5a0 100644
--- a/generate_aidl_mappings.cpp
+++ b/generate_aidl_mappings.cpp
@@ -27,8 +27,7 @@
   return method.PrintLine();
 }
 
-SignatureMap generate_mappings(const AidlDefinedType* defined_type,
-                               const AidlTypenames& typenames) {
+SignatureMap generate_mappings(const AidlDefinedType* defined_type) {
   const AidlInterface* interface = defined_type->AsInterface();
   SignatureMap mappings;
   if (interface == nullptr) {
@@ -40,10 +39,10 @@
       signature << interface->GetCanonicalName() << "|";
       signature << method->GetName() << "|";
       for (const auto& arg : method->GetArguments()) {
-        signature << java::JavaSignatureOf(arg->GetType(), typenames) << ",";
+        signature << java::JavaSignatureOf(arg->GetType()) << ",";
       }
       signature << "|";
-      signature << java::JavaSignatureOf(method->GetType(), typenames);
+      signature << java::JavaSignatureOf(method->GetType());
       mappings[signature.str()] = dump_location(*method);
     }
   }
diff --git a/generate_aidl_mappings.h b/generate_aidl_mappings.h
index d74a17f..09f611e 100644
--- a/generate_aidl_mappings.h
+++ b/generate_aidl_mappings.h
@@ -26,7 +26,7 @@
 
 using SignatureMap = std::unordered_map<std::string, std::string>;
 
-SignatureMap generate_mappings(const AidlDefinedType* iface, const AidlTypenames& typenames);
+SignatureMap generate_mappings(const AidlDefinedType* iface);
 }  // namespace mappings
 }  // namespace aidl
 }  // namespace android
diff --git a/generate_java.cpp b/generate_java.cpp
index 788e384..42218e7 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -335,12 +335,12 @@
     if (variable->GetType().GetName() == "ParcelableHolder" || parcel->IsJavaOnlyImmutable()) {
       out << "final ";
     }
-    out << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName();
+    out << JavaSignatureOf(variable->GetType()) << " " << variable->GetName();
     if (!parcel->IsJavaOnlyImmutable() && variable->GetDefaultValue()) {
       out << " = " << variable->ValueString(ConstantValueDecorator);
     } else if (variable->GetType().GetName() == "ParcelableHolder") {
       out << std::boolalpha;
-      out << " = new " << JavaSignatureOf(variable->GetType(), typenames) << "(";
+      out << " = new " << JavaSignatureOf(variable->GetType()) << "(";
       if (parcel->IsVintfStability()) {
         out << "android.os.Parcelable.PARCELABLE_STABILITY_VINTF";
       } else {
@@ -362,15 +362,13 @@
 
     out.str("");
     for (const auto& variable : parcel->GetFields()) {
-      out << "private " << JavaSignatureOf(variable->GetType(), typenames) << " "
-          << variable->GetName();
+      out << "private " << JavaSignatureOf(variable->GetType()) << " " << variable->GetName();
       if (variable->GetDefaultValue()) {
         out << " = " << variable->ValueString(ConstantValueDecorator);
       }
       out << ";\n";
       out << "public Builder " << SetterName(*variable) << "("
-          << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName()
-          << ") {\n"
+          << JavaSignatureOf(variable->GetType()) << " " << variable->GetName() << ") {\n"
           << "  "
           << "this." << variable->GetName() << " = " << variable->GetName() << ";\n"
           << "  return this;\n"
@@ -462,8 +460,8 @@
     constructor->name = parcel->GetName();
     constructor->statements = std::make_shared<StatementBlock>();
     for (const auto& field : parcel->GetFields()) {
-      constructor->parameters.push_back(std::make_shared<Variable>(
-          JavaSignatureOf(field->GetType(), typenames), field->GetName()));
+      constructor->parameters.push_back(
+          std::make_shared<Variable>(JavaSignatureOf(field->GetType()), field->GetName()));
       out.str("");
 
       out << "this." << field->GetName() << " = ";
@@ -542,7 +540,7 @@
     };
     context.writer.Indent();
     if (parcel->IsJavaOnlyImmutable()) {
-      context.writer.Write("%s %s;\n", JavaSignatureOf(field->GetType(), typenames).c_str(),
+      context.writer.Write("%s %s;\n", JavaSignatureOf(field->GetType()).c_str(),
                            field_variable_name.c_str());
     }
     CreateFromParcelFor(context);
@@ -604,8 +602,7 @@
   return parcel_class;
 }
 
-void GenerateEnumClass(CodeWriter& out, const AidlEnumDeclaration& enum_decl,
-                       const AidlTypenames& typenames) {
+void GenerateEnumClass(CodeWriter& out, const AidlEnumDeclaration& enum_decl) {
   out << GenerateComments(enum_decl);
   out << GenerateAnnotations(enum_decl);
   out << "public ";
@@ -618,8 +615,7 @@
     out << GenerateComments(*enumerator);
     out << GenerateAnnotations(*enumerator);
     out << fmt::format("public static final {} {} = {};\n",
-                       JavaSignatureOf(enum_decl.GetBackingType(), typenames),
-                       enumerator->GetName(),
+                       JavaSignatureOf(enum_decl.GetBackingType()), enumerator->GetName(),
                        enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator));
   }
   out.Dedent();
@@ -659,15 +655,14 @@
 
   AIDL_FATAL_IF(decl->GetFields().empty(), *decl) << "Union '" << clazz << "' is empty.";
   const auto& first_field = decl->GetFields()[0];
-  const auto& first_type = JavaSignatureOf(first_field->GetType(), typenames);
+  const auto& first_type = JavaSignatureOf(first_field->GetType());
   const auto& first_value = first_field->ValueString(ConstantValueDecorator);
 
   // default ctor() inits with first member's default value
   out << "public " + clazz + "() {\n";
   out.Indent();
   out << first_type + " _value = "
-      << (first_value.empty() ? DefaultJavaValueOf(first_field->GetType(), typenames) : first_value)
-      << ";\n";
+      << (first_value.empty() ? DefaultJavaValueOf(first_field->GetType()) : first_value) << ";\n";
   out << "this._tag = " << first_field->GetName() << ";\n";
   out << "this._value = _value;\n";
   out.Dedent();
@@ -700,7 +695,7 @@
     out << "// " + variable->Signature() + ";\n\n";
 
     auto var_name = variable->GetName();
-    auto var_type = JavaSignatureOf(variable->GetType(), typenames);
+    auto var_type = JavaSignatureOf(variable->GetType());
 
     // value ctor
     out << GenerateComments(*variable);
@@ -822,7 +817,7 @@
   out << "switch (_aidl_tag) {\n";
   for (const auto& variable : decl->GetFields()) {
     auto var_name = variable->GetName();
-    auto var_type = JavaSignatureOf(variable->GetType(), typenames);
+    auto var_type = JavaSignatureOf(variable->GetType());
     out << "case " + var_name + ": {\n";
     out.Indent();
     out << var_type + " _aidl_value;\n";
@@ -980,7 +975,7 @@
     GenerateParcelableClass(parcelable, types, options)->Write(&out);
   } else if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
              enum_decl != nullptr) {
-    GenerateEnumClass(out, *enum_decl, types);
+    GenerateEnumClass(out, *enum_decl);
   } else if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
     GenerateInterfaceClass(interface, types, options)->Write(&out);
   } else if (const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index e028cbe..7a46282 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -51,8 +51,8 @@
   using Variable = ::android::aidl::java::Variable;
 
   explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
-  std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
-    auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames),
+  std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type) {
+    auto v = std::make_shared<Variable>(JavaSignatureOf(type),
                                         StringPrintf("%s%d", base_.c_str(), index_));
     vars_.push_back(v);
     index_++;
@@ -378,9 +378,8 @@
 ProxyClass::~ProxyClass() {}
 
 // =================================================
-static void GenerateNewArray(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
-                             std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
-                             std::shared_ptr<Variable> parcel) {
+static void GenerateNewArray(const AidlTypeSpecifier& type, std::shared_ptr<StatementBlock> addTo,
+                             std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel) {
   auto len = std::make_shared<Variable>("int", v->name + "_length");
   addTo->Add(
       std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
@@ -390,7 +389,7 @@
   lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
   lencheck->elseif = std::make_shared<IfStatement>();
   lencheck->elseif->statements->Add(std::make_shared<Assignment>(
-      v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
+      v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type), len)));
   addTo->Add(lencheck);
 }
 
@@ -424,17 +423,16 @@
   }
 }
 
-static std::shared_ptr<Method> GenerateInterfaceMethod(const AidlMethod& method,
-                                                       const AidlTypenames& typenames) {
+static std::shared_ptr<Method> GenerateInterfaceMethod(const AidlMethod& method) {
   auto decl = std::make_shared<Method>();
   decl->comment = GenerateComments(method);
   decl->modifiers = PUBLIC;
-  decl->returnType = JavaSignatureOf(method.GetType(), typenames);
+  decl->returnType = JavaSignatureOf(method.GetType());
   decl->name = method.GetName();
   decl->annotations = JavaAnnotationsFor(method);
 
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
-    auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
+    auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName());
     var->annotations = JavaAnnotationsFor(arg->GetType());
     decl->parameters.push_back(var);
   }
@@ -591,7 +589,7 @@
     // at most once.
     bool is_classloader_created = false;
     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
-      std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
+      std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType());
 
       statements->Add(std::make_shared<VariableDeclaration>(v));
 
@@ -611,10 +609,9 @@
       } else {
         if (!arg->GetType().IsArray()) {
           statements->Add(std::make_shared<Assignment>(
-              v, std::make_shared<NewExpression>(
-                     InstantiableJavaSignatureOf(arg->GetType(), typenames))));
+              v, std::make_shared<NewExpression>(InstantiableJavaSignatureOf(arg->GetType()))));
         } else {
-          GenerateNewArray(arg->GetType(), typenames, statements, v, transact_data);
+          GenerateNewArray(arg->GetType(), statements, v, transact_data);
         }
       }
 
@@ -632,9 +629,8 @@
       statements->Add(ex);
     }
   } else {
-    auto _result =
-        std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
-      statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
+    auto _result = std::make_shared<Variable>(JavaSignatureOf(method.GetType()), "_result");
+    statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
 
     if (!oneway) {
       // report that there were no exceptions
@@ -718,12 +714,12 @@
   auto proxy = std::make_shared<Method>();
   proxy->comment = GenerateComments(method);
   proxy->modifiers = PUBLIC | OVERRIDE;
-  proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
+  proxy->returnType = JavaSignatureOf(method.GetType());
   proxy->name = method.GetName();
   proxy->statements = std::make_shared<StatementBlock>();
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
     proxy->parameters.push_back(
-        std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
+        std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
   }
   proxy->exceptions.push_back("android.os.RemoteException");
 
@@ -778,7 +774,7 @@
 
   // the parameters
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
-    auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
+    auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName());
     AidlArgument::Direction dir = arg->GetDirection();
     if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
       auto checklen = std::make_shared<IfStatement>();
@@ -833,19 +829,24 @@
                                     Join(arg_names, ", ").c_str())));
     checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
   }
+
+  auto checkTransactionError = std::make_shared<IfStatement>();
+  checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
+
+  if (iface.IsJavaDefault()) {
+    checkTransactionError->statements->Add(checkDefaultImpl);
+  }
+
   if (options.Version() > 0) {
-    checkDefaultImpl->elseif = std::make_shared<IfStatement>();
-    checkDefaultImpl->elseif->statements->Add(
+    checkTransactionError->statements->Add(
         std::make_shared<LiteralStatement>(android::base::StringPrintf(
             "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
             method.GetName().c_str())));
   }
 
-  auto checkTransactionError = std::make_shared<IfStatement>();
-  checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
-  checkTransactionError->statements->Add(checkDefaultImpl);
-
-  tryStatement->statements->Add(checkTransactionError);
+  if (iface.IsJavaDefault() || options.Version() > 0) {
+    tryStatement->statements->Add(checkTransactionError);
+  }
 
   // throw back exceptions.
   if (_reply) {
@@ -936,7 +937,7 @@
   // == the declaration in the interface ===================================
   std::shared_ptr<ClassElement> decl;
   if (method.IsUserDefined()) {
-    decl = GenerateInterfaceMethod(method, typenames);
+    decl = GenerateInterfaceMethod(method);
   } else {
     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
       std::ostringstream code;
@@ -1006,13 +1007,15 @@
       code << "    try {\n"
            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
-           << "data, reply, 0);\n"
-           << "      if (!_status) {\n"
-           << "        if (getDefaultImpl() != null) {\n"
-           << "          return getDefaultImpl().getInterfaceVersion();\n"
-           << "        }\n"
-           << "      }\n"
-           << "      reply.readException();\n"
+           << "data, reply, 0);\n";
+      if (iface.IsJavaDefault()) {
+        code << "      if (!_status) {\n"
+             << "        if (getDefaultImpl() != null) {\n"
+             << "          return getDefaultImpl().getInterfaceVersion();\n"
+             << "        }\n"
+             << "      }\n";
+      }
+      code << "      reply.readException();\n"
            << "      mCachedVersion = reply.readInt();\n"
            << "    } finally {\n"
            << "      reply.recycle();\n"
@@ -1038,13 +1041,15 @@
       code << "    try {\n"
            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
-           << "data, reply, 0);\n"
-           << "      if (!_status) {\n"
-           << "        if (getDefaultImpl() != null) {\n"
-           << "          return getDefaultImpl().getInterfaceHash();\n"
-           << "        }\n"
-           << "      }\n"
-           << "      reply.readException();\n"
+           << "data, reply, 0);\n";
+      if (iface.IsJavaDefault()) {
+        code << "      if (!_status) {\n"
+             << "        if (getDefaultImpl() != null) {\n"
+             << "          return getDefaultImpl().getInterfaceHash();\n"
+             << "        }\n"
+             << "      }\n";
+      }
+      code << "      reply.readException();\n"
            << "      mCachedHash = reply.readString();\n"
            << "    } finally {\n"
            << "      reply.recycle();\n"
@@ -1142,22 +1147,21 @@
   }
 }
 
-static shared_ptr<ClassElement> GenerateDefaultImplMethod(const AidlMethod& method,
-                                                          const AidlTypenames& typenames) {
+static shared_ptr<ClassElement> GenerateDefaultImplMethod(const AidlMethod& method) {
   auto default_method = std::make_shared<Method>();
   default_method->comment = GenerateComments(method);
   default_method->modifiers = PUBLIC | OVERRIDE;
-  default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
+  default_method->returnType = JavaSignatureOf(method.GetType());
   default_method->name = method.GetName();
   default_method->statements = std::make_shared<StatementBlock>();
   for (const auto& arg : method.GetArguments()) {
     default_method->parameters.push_back(
-        std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
+        std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
   }
   default_method->exceptions.push_back("android.os.RemoteException");
 
   if (method.GetType().GetName() != "void") {
-    const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
+    const string& defaultValue = DefaultJavaValueOf(method.GetType());
     default_method->statements->Add(
         std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
   }
@@ -1165,7 +1169,6 @@
 }
 
 static shared_ptr<Class> GenerateDefaultImplClass(const AidlInterface& iface,
-                                                  const AidlTypenames& typenames,
                                                   const Options& options) {
   auto default_class = std::make_shared<Class>();
   default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
@@ -1176,7 +1179,7 @@
 
   for (const auto& m : iface.GetMethods()) {
     if (m->IsUserDefined()) {
-      default_class->elements.emplace_back(GenerateDefaultImplMethod(*m, typenames));
+      default_class->elements.emplace_back(GenerateDefaultImplMethod(*m));
     } else {
       // These are called only when the remote side does not implement these
       // methods, which is normally impossible, because these methods are
@@ -1242,7 +1245,7 @@
   }
 
   // the default impl class
-  auto default_impl = GenerateDefaultImplClass(*iface, typenames, options);
+  auto default_impl = GenerateDefaultImplClass(*iface, options);
   interface->elements.emplace_back(default_impl);
 
   // the stub inner class
@@ -1280,38 +1283,40 @@
   writer->Close();
   interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
 
-  // additional static methods for the default impl set/get to the
-  // stub class. Can't add them to the interface as the generated java files
-  // may be compiled with Java < 1.7 where static interface method isn't
-  // supported.
-  // TODO(b/111417145) make this conditional depending on the Java language
-  // version requested
-  const string i_name = iface->GetCanonicalName();
-  stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
-      StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
-                   "  // Only one user of this interface can use this function\n"
-                   "  // at a time. This is a heuristic to detect if two different\n"
-                   "  // users in the same process use this function.\n"
-                   "  if (Stub.Proxy.sDefaultImpl != null) {\n"
-                   "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
-                   "  }\n"
-                   "  if (impl != null) {\n"
-                   "    Stub.Proxy.sDefaultImpl = impl;\n"
-                   "    return true;\n"
-                   "  }\n"
-                   "  return false;\n"
-                   "}\n",
-                   i_name.c_str())));
-  stub->elements.emplace_back(
-      std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
-                                                         "  return Stub.Proxy.sDefaultImpl;\n"
-                                                         "}\n",
-                                                         i_name.c_str())));
+  if (iface->IsJavaDefault()) {
+    // additional static methods for the default impl set/get to the
+    // stub class. Can't add them to the interface as the generated java files
+    // may be compiled with Java < 1.7 where static interface method isn't
+    // supported.
+    // TODO(b/111417145) make this conditional depending on the Java language
+    // version requested
+    const string i_name = iface->GetCanonicalName();
+    stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
+        StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
+                     "  // Only one user of this interface can use this function\n"
+                     "  // at a time. This is a heuristic to detect if two different\n"
+                     "  // users in the same process use this function.\n"
+                     "  if (Stub.Proxy.sDefaultImpl != null) {\n"
+                     "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
+                     "  }\n"
+                     "  if (impl != null) {\n"
+                     "    Stub.Proxy.sDefaultImpl = impl;\n"
+                     "    return true;\n"
+                     "  }\n"
+                     "  return false;\n"
+                     "}\n",
+                     i_name.c_str())));
+    stub->elements.emplace_back(
+        std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
+                                                           "  return Stub.Proxy.sDefaultImpl;\n"
+                                                           "}\n",
+                                                           i_name.c_str())));
 
-  // the static field is defined in the proxy class, not in the interface class
-  // because all fields in an interface class are by default final.
-  proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
-      StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
+    // the static field is defined in the proxy class, not in the interface class
+    // because all fields in an interface class are by default final.
+    proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
+        StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
+  }
 
   stub->Finish();
 
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index 0863149..7d44ff0 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -1144,7 +1144,7 @@
           << "}";
     }
     if (defined_type.IsFixedSize()) {
-      int alignment = NdkAlignmentOf(types, variable->GetType());
+      int alignment = cpp::AlignmentOf(variable->GetType(), types);
       if (alignment > 0) {
         out << " __attribute__((aligned (" << std::to_string(alignment) << ")))";
       }
diff --git a/generate_rust.cpp b/generate_rust.cpp
index a0b9dad..dc7f465 100644
--- a/generate_rust.cpp
+++ b/generate_rust.cpp
@@ -979,18 +979,24 @@
   const auto& aidl_backing_type = enum_decl->GetBackingType();
   auto backing_type = RustNameOf(aidl_backing_type, typenames, StorageMode::VALUE, Lifetime::NONE);
 
-  // TODO(b/177860423) support "deprecated" for enum types
   *code_writer << "#![allow(non_upper_case_globals)]\n";
   *code_writer << "use binder::declare_binder_enum;\n";
-  *code_writer << "declare_binder_enum! { " << enum_decl->GetName() << " : [" << backing_type
-               << "; " << std::to_string(enum_decl->GetEnumerators().size()) << "] {\n";
+  *code_writer << "declare_binder_enum! {\n";
+  code_writer->Indent();
+
+  GenerateDeprecated(*code_writer, *enum_decl);
+  *code_writer << enum_decl->GetName() << " : [" << backing_type << "; "
+               << std::to_string(enum_decl->GetEnumerators().size()) << "] {\n";
   code_writer->Indent();
   for (const auto& enumerator : enum_decl->GetEnumerators()) {
     auto value = enumerator->GetValue()->ValueString(aidl_backing_type, ConstantValueDecorator);
     *code_writer << enumerator->GetName() << " = " << value << ",\n";
   }
   code_writer->Dedent();
-  *code_writer << "} }\n";
+  *code_writer << "}\n";
+
+  code_writer->Dedent();
+  *code_writer << "}\n";
 }
 
 void GenerateClass(CodeWriter* code_writer, const AidlDefinedType& defined_type,
diff --git a/tests/android/aidl/tests/ITestService.aidl b/tests/android/aidl/tests/ITestService.aidl
index c6fffe3..bc1cf44 100644
--- a/tests/android/aidl/tests/ITestService.aidl
+++ b/tests/android/aidl/tests/ITestService.aidl
@@ -32,6 +32,7 @@
  */
 @SuppressWarnings(value={"inout-parameter", "mixed-oneway", "out-array"})
 @SensitiveData
+@JavaDefault
 interface ITestService {
     // Test that constants are accessible
 
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h
index 2c889e7..f5f7f73 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h
@@ -120,7 +120,9 @@
     }
   private:
     Tag _tag __attribute__((aligned (1))) = booleanValue;
-    union {
+    union _value_t {
+      _value_t() {}
+      ~_value_t() {}
       bool booleanValue __attribute__((aligned (1))) = bool(false);
       int8_t byteValue __attribute__((aligned (1)));
       char16_t charValue __attribute__((aligned (2)));
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java
index 8a13c13..c871aa5 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java
@@ -114,23 +114,6 @@
         {
           return DESCRIPTOR;
         }
-        public static android.aidl.tests.ArrayOfInterfaces.IEmptyInterface sDefaultImpl;
-      }
-      public static boolean setDefaultImpl(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface impl) {
-        // Only one user of this interface can use this function
-        // at a time. This is a heuristic to detect if two different
-        // users in the same process use this function.
-        if (Stub.Proxy.sDefaultImpl != null) {
-          throw new IllegalStateException("setDefaultImpl() called twice");
-        }
-        if (impl != null) {
-          Stub.Proxy.sDefaultImpl = impl;
-          return true;
-        }
-        return false;
-      }
-      public static android.aidl.tests.ArrayOfInterfaces.IEmptyInterface getDefaultImpl() {
-        return Stub.Proxy.sDefaultImpl;
       }
     }
     public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ArrayOfInterfaces$IEmptyInterface".replace('$', '.');
@@ -279,11 +262,6 @@
             }
             _data.writeInterfaceArray(nullable_iface_array_inout);
             boolean _status = mRemote.transact(Stub.TRANSACTION_methodWithInterfaces, _data, _reply, 0);
-            if (!_status) {
-              if (getDefaultImpl() != null) {
-                return getDefaultImpl().methodWithInterfaces(iface, nullable_iface, iface_array_in, iface_array_out, iface_array_inout, nullable_iface_array_in, nullable_iface_array_out, nullable_iface_array_inout);
-              }
-            }
             _reply.readException();
             _result = _reply.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
             _reply.readInterfaceArray(iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
@@ -297,25 +275,8 @@
           }
           return _result;
         }
-        public static android.aidl.tests.ArrayOfInterfaces.IMyInterface sDefaultImpl;
       }
       static final int TRANSACTION_methodWithInterfaces = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-      public static boolean setDefaultImpl(android.aidl.tests.ArrayOfInterfaces.IMyInterface impl) {
-        // Only one user of this interface can use this function
-        // at a time. This is a heuristic to detect if two different
-        // users in the same process use this function.
-        if (Stub.Proxy.sDefaultImpl != null) {
-          throw new IllegalStateException("setDefaultImpl() called twice");
-        }
-        if (impl != null) {
-          Stub.Proxy.sDefaultImpl = impl;
-          return true;
-        }
-        return false;
-      }
-      public static android.aidl.tests.ArrayOfInterfaces.IMyInterface getDefaultImpl() {
-        return Stub.Proxy.sDefaultImpl;
-      }
     }
     public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ArrayOfInterfaces$IMyInterface".replace('$', '.');
     public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] methodWithInterfaces(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_inout, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_inout) throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java
index 0290c7a..09578f5 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java
@@ -75,23 +75,6 @@
       {
         return DESCRIPTOR;
       }
-      public static android.aidl.tests.IDeprecated sDefaultImpl;
-    }
-    public static boolean setDefaultImpl(android.aidl.tests.IDeprecated impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.tests.IDeprecated getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
     }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$IDeprecated".replace('$', '.');
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java
index 2e1ac4a..3500271 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java
@@ -96,11 +96,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_GetName, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().GetName();
-            }
-          }
           _reply.readException();
           _result = _reply.readString();
         }
@@ -110,25 +105,8 @@
         }
         return _result;
       }
-      public static android.aidl.tests.INamedCallback sDefaultImpl;
     }
     static final int TRANSACTION_GetName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.tests.INamedCallback impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.tests.INamedCallback getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$INamedCallback".replace('$', '.');
   public java.lang.String GetName() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java
index a1d80fe..265f8ef 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java
@@ -96,11 +96,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_RealName, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().RealName();
-            }
-          }
           _reply.readException();
           _result = _reply.readString();
         }
@@ -110,25 +105,8 @@
         }
         return _result;
       }
-      public static android.aidl.tests.INewName sDefaultImpl;
     }
     static final int TRANSACTION_RealName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.tests.INewName impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.tests.INewName getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$IOldName".replace('$', '.');
   public java.lang.String RealName() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java
index d4967fc..7013fce 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java
@@ -96,11 +96,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_RealName, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().RealName();
-            }
-          }
           _reply.readException();
           _result = _reply.readString();
         }
@@ -110,25 +105,8 @@
         }
         return _result;
       }
-      public static android.aidl.tests.IOldName sDefaultImpl;
     }
     static final int TRANSACTION_RealName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.tests.IOldName impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.tests.IOldName getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$IOldName".replace('$', '.');
   public java.lang.String RealName() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java
index c20a699..fadd458 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java
@@ -114,23 +114,6 @@
         {
           return DESCRIPTOR;
         }
-        public static android.aidl.tests.ListOfInterfaces.IEmptyInterface sDefaultImpl;
-      }
-      public static boolean setDefaultImpl(android.aidl.tests.ListOfInterfaces.IEmptyInterface impl) {
-        // Only one user of this interface can use this function
-        // at a time. This is a heuristic to detect if two different
-        // users in the same process use this function.
-        if (Stub.Proxy.sDefaultImpl != null) {
-          throw new IllegalStateException("setDefaultImpl() called twice");
-        }
-        if (impl != null) {
-          Stub.Proxy.sDefaultImpl = impl;
-          return true;
-        }
-        return false;
-      }
-      public static android.aidl.tests.ListOfInterfaces.IEmptyInterface getDefaultImpl() {
-        return Stub.Proxy.sDefaultImpl;
       }
     }
     public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ListOfInterfaces$IEmptyInterface".replace('$', '.');
@@ -255,11 +238,6 @@
             _data.writeInterfaceList(nullable_iface_list_in);
             _data.writeInterfaceList(nullable_iface_list_inout);
             boolean _status = mRemote.transact(Stub.TRANSACTION_methodWithInterfaces, _data, _reply, 0);
-            if (!_status) {
-              if (getDefaultImpl() != null) {
-                return getDefaultImpl().methodWithInterfaces(iface, nullable_iface, iface_list_in, iface_list_out, iface_list_inout, nullable_iface_list_in, nullable_iface_list_out, nullable_iface_list_inout);
-              }
-            }
             _reply.readException();
             _result = _reply.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
             _reply.readInterfaceList(iface_list_out, android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
@@ -273,25 +251,8 @@
           }
           return _result;
         }
-        public static android.aidl.tests.ListOfInterfaces.IMyInterface sDefaultImpl;
       }
       static final int TRANSACTION_methodWithInterfaces = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-      public static boolean setDefaultImpl(android.aidl.tests.ListOfInterfaces.IMyInterface impl) {
-        // Only one user of this interface can use this function
-        // at a time. This is a heuristic to detect if two different
-        // users in the same process use this function.
-        if (Stub.Proxy.sDefaultImpl != null) {
-          throw new IllegalStateException("setDefaultImpl() called twice");
-        }
-        if (impl != null) {
-          Stub.Proxy.sDefaultImpl = impl;
-          return true;
-        }
-        return false;
-      }
-      public static android.aidl.tests.ListOfInterfaces.IMyInterface getDefaultImpl() {
-        return Stub.Proxy.sDefaultImpl;
-      }
     }
     public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ListOfInterfaces$IMyInterface".replace('$', '.');
     public java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> methodWithInterfaces(android.aidl.tests.ListOfInterfaces.IEmptyInterface iface, android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_inout, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_inout) throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java
index 4bb9a18..a79e0b8 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java
@@ -112,11 +112,6 @@
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeTypedObject(p, 0);
           boolean _status = mRemote.transact(Stub.TRANSACTION_flipStatus, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().flipStatus(p);
-            }
-          }
           _reply.readException();
           _result = _reply.readTypedObject(android.aidl.tests.nested.INestedService.Result.CREATOR);
         }
@@ -135,12 +130,6 @@
           _data.writeByte(status);
           _data.writeStrongInterface(cb);
           boolean _status = mRemote.transact(Stub.TRANSACTION_flipStatusWithCallback, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              getDefaultImpl().flipStatusWithCallback(status, cb);
-              return;
-            }
-          }
           _reply.readException();
         }
         finally {
@@ -148,26 +137,9 @@
           _data.recycle();
         }
       }
-      public static android.aidl.tests.nested.INestedService sDefaultImpl;
     }
     static final int TRANSACTION_flipStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
     static final int TRANSACTION_flipStatusWithCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
-    public static boolean setDefaultImpl(android.aidl.tests.nested.INestedService impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.tests.nested.INestedService getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$nested$INestedService".replace('$', '.');
   public android.aidl.tests.nested.INestedService.Result flipStatus(android.aidl.tests.nested.ParcelableWithNested p) throws android.os.RemoteException;
@@ -312,12 +284,6 @@
             _data.writeInterfaceToken(DESCRIPTOR);
             _data.writeByte(status);
             boolean _status = mRemote.transact(Stub.TRANSACTION_done, _data, _reply, 0);
-            if (!_status) {
-              if (getDefaultImpl() != null) {
-                getDefaultImpl().done(status);
-                return;
-              }
-            }
             _reply.readException();
           }
           finally {
@@ -325,25 +291,8 @@
             _data.recycle();
           }
         }
-        public static android.aidl.tests.nested.INestedService.ICallback sDefaultImpl;
       }
       static final int TRANSACTION_done = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-      public static boolean setDefaultImpl(android.aidl.tests.nested.INestedService.ICallback impl) {
-        // Only one user of this interface can use this function
-        // at a time. This is a heuristic to detect if two different
-        // users in the same process use this function.
-        if (Stub.Proxy.sDefaultImpl != null) {
-          throw new IllegalStateException("setDefaultImpl() called twice");
-        }
-        if (impl != null) {
-          Stub.Proxy.sDefaultImpl = impl;
-          return true;
-        }
-        return false;
-      }
-      public static android.aidl.tests.nested.INestedService.ICallback getDefaultImpl() {
-        return Stub.Proxy.sDefaultImpl;
-      }
     }
     public static final java.lang.String DESCRIPTOR = "android$aidl$tests$nested$INestedService$ICallback".replace('$', '.');
     public void done(byte status) throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java
index bcada36..dab6802 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java
@@ -120,12 +120,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_PermissionProtected, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              getDefaultImpl().PermissionProtected();
-              return;
-            }
-          }
           _reply.readException();
         }
         finally {
@@ -140,12 +134,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_MultiplePermissions, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              getDefaultImpl().MultiplePermissions();
-              return;
-            }
-          }
           _reply.readException();
         }
         finally {
@@ -160,12 +148,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_MultiplePermissions2, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              getDefaultImpl().MultiplePermissions2();
-              return;
-            }
-          }
           _reply.readException();
         }
         finally {
@@ -173,27 +155,10 @@
           _data.recycle();
         }
       }
-      public static android.aidl.tests.permission.IProtected sDefaultImpl;
     }
     static final int TRANSACTION_PermissionProtected = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
     static final int TRANSACTION_MultiplePermissions = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
     static final int TRANSACTION_MultiplePermissions2 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
-    public static boolean setDefaultImpl(android.aidl.tests.permission.IProtected impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.tests.permission.IProtected getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$permission$IProtected".replace('$', '.');
   public void PermissionProtected() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java
index bca9289..51da803 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java
@@ -108,12 +108,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_Method1, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              getDefaultImpl().Method1();
-              return;
-            }
-          }
           _reply.readException();
         }
         finally {
@@ -128,12 +122,6 @@
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_Method2, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              getDefaultImpl().Method2();
-              return;
-            }
-          }
           _reply.readException();
         }
         finally {
@@ -141,26 +129,9 @@
           _data.recycle();
         }
       }
-      public static android.aidl.tests.permission.IProtectedInterface sDefaultImpl;
     }
     static final int TRANSACTION_Method1 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
     static final int TRANSACTION_Method2 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
-    public static boolean setDefaultImpl(android.aidl.tests.permission.IProtectedInterface impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.tests.permission.IProtectedInterface getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$permission$IProtectedInterface".replace('$', '.');
   public void Method1() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h
index 91da0ce..f8dcdd2 100644
--- a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h
@@ -131,7 +131,9 @@
     }
   private:
     Tag _tag __attribute__((aligned (1))) = booleanValue;
-    union {
+    union _value_t {
+      _value_t() {}
+      ~_value_t() {}
       bool booleanValue __attribute__((aligned (1))) = bool(false);
       int8_t byteValue __attribute__((aligned (1)));
       char16_t charValue __attribute__((aligned (2)));
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs
index 796be4b..7f4be56 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs
@@ -2,12 +2,14 @@
 #![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { BackendType : [i8; 4] {
-  CPP = 0,
-  JAVA = 1,
-  NDK = 2,
-  RUST = 3,
-} }
+declare_binder_enum! {
+  BackendType : [i8; 4] {
+    CPP = 0,
+    JAVA = 1,
+    NDK = 2,
+    RUST = 3,
+  }
+}
 pub(crate) mod mangled {
  pub use super::BackendType as _7_android_4_aidl_5_tests_11_BackendType;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs
index a56be6b..57c61ee 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs
@@ -2,11 +2,13 @@
 #![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { ByteEnum : [i8; 3] {
-  FOO = 1,
-  BAR = 2,
-  BAZ = 3,
-} }
+declare_binder_enum! {
+  ByteEnum : [i8; 3] {
+    FOO = 1,
+    BAR = 2,
+    BAZ = 3,
+  }
+}
 pub(crate) mod mangled {
  pub use super::ByteEnum as _7_android_4_aidl_5_tests_8_ByteEnum;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs
index 7240b73..32a1942 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs
@@ -2,18 +2,20 @@
 #![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { ConstantExpressionEnum : [i32; 10] {
-  decInt32_1 = 1,
-  decInt32_2 = 1,
-  decInt64_1 = 1,
-  decInt64_2 = 1,
-  decInt64_3 = 1,
-  decInt64_4 = 1,
-  hexInt32_1 = 1,
-  hexInt32_2 = 1,
-  hexInt32_3 = 1,
-  hexInt64_1 = 1,
-} }
+declare_binder_enum! {
+  ConstantExpressionEnum : [i32; 10] {
+    decInt32_1 = 1,
+    decInt32_2 = 1,
+    decInt64_1 = 1,
+    decInt64_2 = 1,
+    decInt64_3 = 1,
+    decInt64_4 = 1,
+    hexInt32_1 = 1,
+    hexInt32_2 = 1,
+    hexInt32_3 = 1,
+    hexInt64_1 = 1,
+  }
+}
 pub(crate) mod mangled {
  pub use super::ConstantExpressionEnum as _7_android_4_aidl_5_tests_22_ConstantExpressionEnum;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs
index 07cdfbf..5d3b054 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs
@@ -2,11 +2,14 @@
 #![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { DeprecatedEnum : [i32; 3] {
-  A = 0,
-  B = 1,
-  C = 2,
-} }
+declare_binder_enum! {
+  #[deprecated = "test"]
+  DeprecatedEnum : [i32; 3] {
+    A = 0,
+    B = 1,
+    C = 2,
+  }
+}
 pub(crate) mod mangled {
  pub use super::DeprecatedEnum as _7_android_4_aidl_5_tests_14_DeprecatedEnum;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs
index 54f672a..5ff4d95 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs
@@ -2,11 +2,13 @@
 #![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { IntEnum : [i32; 3] {
-  FOO = 1000,
-  BAR = 2000,
-  BAZ = 2001,
-} }
+declare_binder_enum! {
+  IntEnum : [i32; 3] {
+    FOO = 1000,
+    BAR = 2000,
+    BAZ = 2001,
+  }
+}
 pub(crate) mod mangled {
  pub use super::IntEnum as _7_android_4_aidl_5_tests_7_IntEnum;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs
index 62a164c..ae93821 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs
@@ -2,11 +2,13 @@
 #![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { LongEnum : [i64; 3] {
-  FOO = 100000000000,
-  BAR = 200000000000,
-  BAZ = 200000000001,
-} }
+declare_binder_enum! {
+  LongEnum : [i64; 3] {
+    FOO = 100000000000,
+    BAR = 200000000000,
+    BAZ = 200000000001,
+  }
+}
 pub(crate) mod mangled {
  pub use super::LongEnum as _7_android_4_aidl_5_tests_8_LongEnum;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs
index d0710b9..10326ac 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs
@@ -80,8 +80,8 @@
       charDefaultsToC: 'C' as u16,
       floatDefaultsToPi: 3.140000f32,
       doubleWithDefault: -314000000000000000.000000f64,
-      arrayDefaultsTo123: vec!{1, 2, 3},
-      arrayDefaultsToEmpty: vec!{},
+      arrayDefaultsTo123: vec![1, 2, 3],
+      arrayDefaultsToEmpty: vec![],
       boolDefault: false,
       byteDefault: 0,
       intDefault: 0,
@@ -89,16 +89,16 @@
       floatDefault: 0.000000f32,
       doubleDefault: 0.000000f64,
       checkDoubleFromFloat: 3.140000f64,
-      checkStringArray1: vec!{"a".into(), "b".into()},
-      checkStringArray2: vec!{"a".into(), "b".into()},
+      checkStringArray1: vec!["a".into(), "b".into()],
+      checkStringArray2: vec!["a".into(), "b".into()],
       int32_min: -2147483648,
       int32_max: 2147483647,
       int64_max: 9223372036854775807,
       hexInt32_neg_1: -1,
       ibinder: Default::default(),
-      int8_1: vec!{1, 1, 1, 1, 1},
-      int32_1: vec!{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
-      int64_1: vec!{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+      int8_1: vec![1, 1, 1, 1, 1],
+      int32_1: vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
+      int64_1: vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       hexInt32_pos_1: 1,
       hexInt64_pos_1: 1,
       const_exprs_1: Default::default(),
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs
index bf1c8a3..d9cddc4 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs
@@ -13,7 +13,7 @@
 pub const S1: &str = "a string constant in union";
 impl Default for Union {
   fn default() -> Self {
-    Self::Ns(vec!{})
+    Self::Ns(vec![])
   }
 }
 impl binder::parcel::Parcelable for Union {
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs
index 7bdcd32..a5dbaf3 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs
@@ -144,9 +144,11 @@
       pub mod E {
         #![allow(non_upper_case_globals)]
         use binder::declare_binder_enum;
-        declare_binder_enum! { E : [i8; 1] {
-          OK = 0,
-        } }
+        declare_binder_enum! {
+          E : [i8; 1] {
+            OK = 0,
+          }
+        }
       }
     }
   }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs
index 9223df5..26ae1f4 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs
@@ -35,10 +35,12 @@
 pub mod Status {
   #![allow(non_upper_case_globals)]
   use binder::declare_binder_enum;
-  declare_binder_enum! { Status : [i8; 2] {
-    OK = 0,
-    NOT_OK = 1,
-  } }
+  declare_binder_enum! {
+    Status : [i8; 2] {
+      OK = 0,
+      NOT_OK = 1,
+    }
+  }
 }
 pub(crate) mod mangled {
  pub use super::ParcelableWithNested as _7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested;
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java
new file mode 100644
index 0000000..7a85c41
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java
@@ -0,0 +1,130 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.versioned.tests;
+public final class BazUnion implements android.os.Parcelable {
+  // tags for union fields
+  public final static int intNum = 0;  // int intNum;
+  public final static int longNum = 1;  // long longNum;
+
+  private int _tag;
+  private Object _value;
+
+  public BazUnion() {
+    int _value = 0;
+    this._tag = intNum;
+    this._value = _value;
+  }
+
+  private BazUnion(android.os.Parcel _aidl_parcel) {
+    readFromParcel(_aidl_parcel);
+  }
+
+  private BazUnion(int _tag, Object _value) {
+    this._tag = _tag;
+    this._value = _value;
+  }
+
+  public int getTag() {
+    return _tag;
+  }
+
+  // int intNum;
+
+  public static BazUnion intNum(int _value) {
+    return new BazUnion(intNum, _value);
+  }
+
+  public int getIntNum() {
+    _assertTag(intNum);
+    return (int) _value;
+  }
+
+  public void setIntNum(int _value) {
+    _set(intNum, _value);
+  }
+
+  // long longNum;
+
+  public static BazUnion longNum(long _value) {
+    return new BazUnion(longNum, _value);
+  }
+
+  public long getLongNum() {
+    _assertTag(longNum);
+    return (long) _value;
+  }
+
+  public void setLongNum(long _value) {
+    _set(longNum, _value);
+  }
+
+  public static final android.os.Parcelable.Creator<BazUnion> CREATOR = new android.os.Parcelable.Creator<BazUnion>() {
+    @Override
+    public BazUnion createFromParcel(android.os.Parcel _aidl_source) {
+      return new BazUnion(_aidl_source);
+    }
+    @Override
+    public BazUnion[] newArray(int _aidl_size) {
+      return new BazUnion[_aidl_size];
+    }
+  };
+
+  @Override
+  public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {
+    _aidl_parcel.writeInt(_tag);
+    switch (_tag) {
+    case intNum:
+      _aidl_parcel.writeInt(getIntNum());
+      break;
+    case longNum:
+      _aidl_parcel.writeLong(getLongNum());
+      break;
+    }
+  }
+
+  public void readFromParcel(android.os.Parcel _aidl_parcel) {
+    int _aidl_tag;
+    _aidl_tag = _aidl_parcel.readInt();
+    switch (_aidl_tag) {
+    case intNum: {
+      int _aidl_value;
+      _aidl_value = _aidl_parcel.readInt();
+      _set(_aidl_tag, _aidl_value);
+      return; }
+    case longNum: {
+      long _aidl_value;
+      _aidl_value = _aidl_parcel.readLong();
+      _set(_aidl_tag, _aidl_value);
+      return; }
+    }
+    throw new IllegalArgumentException("union: unknown tag: " + _aidl_tag);
+  }
+
+  @Override
+  public int describeContents() {
+    int _mask = 0;
+    switch (getTag()) {
+    }
+    return _mask;
+  }
+
+  private void _assertTag(int tag) {
+    if (getTag() != tag) {
+      throw new IllegalStateException("bad access: " + _tagString(tag) + ", " + _tagString(getTag()) + " is available.");
+    }
+  }
+
+  private String _tagString(int _tag) {
+    switch (_tag) {
+    case intNum: return "intNum";
+    case longNum: return "longNum";
+    }
+    throw new IllegalStateException("unknown field: " + _tag);
+  }
+
+  private void _set(int _tag, Object _value) {
+    this._tag = _tag;
+    this._value = _value;
+  }
+}
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java.d b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java.d
new file mode 100644
index 0000000..68d7b75
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java : \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/BazUnion.aidl
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java
new file mode 100644
index 0000000..12d069e
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java
@@ -0,0 +1,50 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.versioned.tests;
+public class Foo implements android.os.Parcelable
+{
+  public int intDefault42 = 42;
+  public static final android.os.Parcelable.Creator<Foo> CREATOR = new android.os.Parcelable.Creator<Foo>() {
+    @Override
+    public Foo createFromParcel(android.os.Parcel _aidl_source) {
+      Foo _aidl_out = new Foo();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public Foo[] newArray(int _aidl_size) {
+      return new Foo[_aidl_size];
+    }
+  };
+  @Override public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag)
+  {
+    int _aidl_start_pos = _aidl_parcel.dataPosition();
+    _aidl_parcel.writeInt(0);
+    _aidl_parcel.writeInt(intDefault42);
+    int _aidl_end_pos = _aidl_parcel.dataPosition();
+    _aidl_parcel.setDataPosition(_aidl_start_pos);
+    _aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);
+    _aidl_parcel.setDataPosition(_aidl_end_pos);
+  }
+  public final void readFromParcel(android.os.Parcel _aidl_parcel)
+  {
+    int _aidl_start_pos = _aidl_parcel.dataPosition();
+    int _aidl_parcelable_size = _aidl_parcel.readInt();
+    try {
+      if (_aidl_parcelable_size < 0) return;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intDefault42 = _aidl_parcel.readInt();
+    } finally {
+      if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
+        throw new android.os.BadParcelableException("Overflow in the size of parcelable");
+      }
+      _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+    }
+  }
+  @Override
+  public int describeContents() {
+    int _mask = 0;
+    return _mask;
+  }
+}
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java.d b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java.d
new file mode 100644
index 0000000..b7db41a
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java : \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/Foo.aidl
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java
new file mode 100644
index 0000000..5c942db
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java
@@ -0,0 +1,331 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.versioned.tests;
+public interface IFooInterface extends android.os.IInterface
+{
+  /**
+   * The version of this interface that the caller is built against.
+   * This might be different from what {@link #getInterfaceVersion()
+   * getInterfaceVersion} returns as that is the version of the interface
+   * that the remote object is implementing.
+   */
+  public static final int VERSION = 2;
+  public static final String HASH = "da8c4bc94ca7feff0e0a65563a466787698b5891";
+  /** Default implementation for IFooInterface. */
+  public static class Default implements android.aidl.versioned.tests.IFooInterface
+  {
+    @Override public void originalApi() throws android.os.RemoteException
+    {
+    }
+    @Override public java.lang.String acceptUnionAndReturnString(android.aidl.versioned.tests.BazUnion u) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public int ignoreParcelablesAndRepeatInt(android.aidl.versioned.tests.Foo inFoo, android.aidl.versioned.tests.Foo inoutFoo, android.aidl.versioned.tests.Foo outFoo, int value) throws android.os.RemoteException
+    {
+      return 0;
+    }
+    @Override public int returnsLengthOfFooArray(android.aidl.versioned.tests.Foo[] foos) throws android.os.RemoteException
+    {
+      return 0;
+    }
+    @Override public void newApi() throws android.os.RemoteException
+    {
+    }
+    @Override
+    public int getInterfaceVersion() {
+      return 0;
+    }
+    @Override
+    public String getInterfaceHash() {
+      return "";
+    }
+    @Override
+    public android.os.IBinder asBinder() {
+      return null;
+    }
+  }
+  /** Local-side IPC implementation stub class. */
+  public static abstract class Stub extends android.os.Binder implements android.aidl.versioned.tests.IFooInterface
+  {
+    /** Construct the stub at attach it to the interface. */
+    public Stub()
+    {
+      this.attachInterface(this, DESCRIPTOR);
+    }
+    /**
+     * Cast an IBinder object into an android.aidl.versioned.tests.IFooInterface interface,
+     * generating a proxy if needed.
+     */
+    public static android.aidl.versioned.tests.IFooInterface asInterface(android.os.IBinder obj)
+    {
+      if ((obj==null)) {
+        return null;
+      }
+      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+      if (((iin!=null)&&(iin instanceof android.aidl.versioned.tests.IFooInterface))) {
+        return ((android.aidl.versioned.tests.IFooInterface)iin);
+      }
+      return new android.aidl.versioned.tests.IFooInterface.Stub.Proxy(obj);
+    }
+    @Override public android.os.IBinder asBinder()
+    {
+      return this;
+    }
+    @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+    {
+      java.lang.String descriptor = DESCRIPTOR;
+      if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
+        data.enforceInterface(descriptor);
+      }
+      switch (code)
+      {
+        case INTERFACE_TRANSACTION:
+        {
+          reply.writeString(descriptor);
+          return true;
+        }
+        case TRANSACTION_getInterfaceVersion:
+        {
+          reply.writeNoException();
+          reply.writeInt(getInterfaceVersion());
+          return true;
+        }
+        case TRANSACTION_getInterfaceHash:
+        {
+          reply.writeNoException();
+          reply.writeString(getInterfaceHash());
+          return true;
+        }
+      }
+      switch (code)
+      {
+        case TRANSACTION_originalApi:
+        {
+          this.originalApi();
+          reply.writeNoException();
+          break;
+        }
+        case TRANSACTION_acceptUnionAndReturnString:
+        {
+          android.aidl.versioned.tests.BazUnion _arg0;
+          _arg0 = data.readTypedObject(android.aidl.versioned.tests.BazUnion.CREATOR);
+          java.lang.String _result = this.acceptUnionAndReturnString(_arg0);
+          reply.writeNoException();
+          reply.writeString(_result);
+          break;
+        }
+        case TRANSACTION_ignoreParcelablesAndRepeatInt:
+        {
+          android.aidl.versioned.tests.Foo _arg0;
+          _arg0 = data.readTypedObject(android.aidl.versioned.tests.Foo.CREATOR);
+          android.aidl.versioned.tests.Foo _arg1;
+          _arg1 = data.readTypedObject(android.aidl.versioned.tests.Foo.CREATOR);
+          android.aidl.versioned.tests.Foo _arg2;
+          _arg2 = new android.aidl.versioned.tests.Foo();
+          int _arg3;
+          _arg3 = data.readInt();
+          int _result = this.ignoreParcelablesAndRepeatInt(_arg0, _arg1, _arg2, _arg3);
+          reply.writeNoException();
+          reply.writeInt(_result);
+          reply.writeTypedObject(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          reply.writeTypedObject(_arg2, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_returnsLengthOfFooArray:
+        {
+          android.aidl.versioned.tests.Foo[] _arg0;
+          _arg0 = data.createTypedArray(android.aidl.versioned.tests.Foo.CREATOR);
+          int _result = this.returnsLengthOfFooArray(_arg0);
+          reply.writeNoException();
+          reply.writeInt(_result);
+          break;
+        }
+        case TRANSACTION_newApi:
+        {
+          this.newApi();
+          reply.writeNoException();
+          break;
+        }
+        default:
+        {
+          return super.onTransact(code, data, reply, flags);
+        }
+      }
+      return true;
+    }
+    private static class Proxy implements android.aidl.versioned.tests.IFooInterface
+    {
+      private android.os.IBinder mRemote;
+      Proxy(android.os.IBinder remote)
+      {
+        mRemote = remote;
+      }
+      private int mCachedVersion = -1;
+      private String mCachedHash = "-1";
+      @Override public android.os.IBinder asBinder()
+      {
+        return mRemote;
+      }
+      public java.lang.String getInterfaceDescriptor()
+      {
+        return DESCRIPTOR;
+      }
+      @Override public void originalApi() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_originalApi, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method originalApi is unimplemented.");
+          }
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override public java.lang.String acceptUnionAndReturnString(android.aidl.versioned.tests.BazUnion u) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        java.lang.String _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(u, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_acceptUnionAndReturnString, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method acceptUnionAndReturnString is unimplemented.");
+          }
+          _reply.readException();
+          _result = _reply.readString();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public int ignoreParcelablesAndRepeatInt(android.aidl.versioned.tests.Foo inFoo, android.aidl.versioned.tests.Foo inoutFoo, android.aidl.versioned.tests.Foo outFoo, int value) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        int _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(inFoo, 0);
+          _data.writeTypedObject(inoutFoo, 0);
+          _data.writeInt(value);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_ignoreParcelablesAndRepeatInt, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method ignoreParcelablesAndRepeatInt is unimplemented.");
+          }
+          _reply.readException();
+          _result = _reply.readInt();
+          if ((0!=_reply.readInt())) {
+            inoutFoo.readFromParcel(_reply);
+          }
+          if ((0!=_reply.readInt())) {
+            outFoo.readFromParcel(_reply);
+          }
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public int returnsLengthOfFooArray(android.aidl.versioned.tests.Foo[] foos) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        int _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedArray(foos, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_returnsLengthOfFooArray, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method returnsLengthOfFooArray is unimplemented.");
+          }
+          _reply.readException();
+          _result = _reply.readInt();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public void newApi() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_newApi, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method newApi is unimplemented.");
+          }
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override
+      public int getInterfaceVersion() throws android.os.RemoteException {
+        if (mCachedVersion == -1) {
+          android.os.Parcel data = android.os.Parcel.obtain();
+          android.os.Parcel reply = android.os.Parcel.obtain();
+          try {
+            data.writeInterfaceToken(DESCRIPTOR);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_getInterfaceVersion, data, reply, 0);
+            reply.readException();
+            mCachedVersion = reply.readInt();
+          } finally {
+            reply.recycle();
+            data.recycle();
+          }
+        }
+        return mCachedVersion;
+      }
+      @Override
+      public synchronized String getInterfaceHash() throws android.os.RemoteException {
+        if ("-1".equals(mCachedHash)) {
+          android.os.Parcel data = android.os.Parcel.obtain();
+          android.os.Parcel reply = android.os.Parcel.obtain();
+          try {
+            data.writeInterfaceToken(DESCRIPTOR);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_getInterfaceHash, data, reply, 0);
+            reply.readException();
+            mCachedHash = reply.readString();
+          } finally {
+            reply.recycle();
+            data.recycle();
+          }
+        }
+        return mCachedHash;
+      }
+    }
+    static final int TRANSACTION_originalApi = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    static final int TRANSACTION_acceptUnionAndReturnString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+    static final int TRANSACTION_ignoreParcelablesAndRepeatInt = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+    static final int TRANSACTION_returnsLengthOfFooArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
+    static final int TRANSACTION_newApi = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
+    static final int TRANSACTION_getInterfaceVersion = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777214);
+    static final int TRANSACTION_getInterfaceHash = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777213);
+  }
+  public static final java.lang.String DESCRIPTOR = "android$aidl$versioned$tests$IFooInterface".replace('$', '.');
+  public void originalApi() throws android.os.RemoteException;
+  public java.lang.String acceptUnionAndReturnString(android.aidl.versioned.tests.BazUnion u) throws android.os.RemoteException;
+  public int ignoreParcelablesAndRepeatInt(android.aidl.versioned.tests.Foo inFoo, android.aidl.versioned.tests.Foo inoutFoo, android.aidl.versioned.tests.Foo outFoo, int value) throws android.os.RemoteException;
+  public int returnsLengthOfFooArray(android.aidl.versioned.tests.Foo[] foos) throws android.os.RemoteException;
+  public void newApi() throws android.os.RemoteException;
+  public int getInterfaceVersion() throws android.os.RemoteException;
+  public String getInterfaceHash() throws android.os.RemoteException;
+}
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java.d b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java.d
new file mode 100644
index 0000000..b6dd541
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java.d
@@ -0,0 +1,4 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java : \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/IFooInterface.aidl \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/BazUnion.aidl \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/Foo.aidl
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/timestamp b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/timestamp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/timestamp
diff --git a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java
index d7390de..a1ebf47 100644
--- a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java
+++ b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java
@@ -177,11 +177,6 @@
           _data.writeTypedObject(pfdValue, 0);
           _data.writeTypedArray(pfdArray, 0);
           boolean _status = mRemote.transact(Stub.TRANSACTION_LogThis, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().LogThis(boolValue, boolArray, byteValue, byteArray, charValue, charArray, intValue, intArray, longValue, longArray, floatValue, floatArray, doubleValue, doubleArray, stringValue, stringArray, listValue, dataValue, binderValue, pfdValue, pfdArray);
-            }
-          }
           _reply.readException();
           _result = _reply.createStringArray();
           _reply.readBooleanArray(boolArray);
@@ -205,25 +200,8 @@
         }
         return _result;
       }
-      public static android.aidl.loggable.ILoggableInterface sDefaultImpl;
     }
     static final int TRANSACTION_LogThis = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.loggable.ILoggableInterface impl) {
-      // Only one user of this interface can use this function
-      // at a time. This is a heuristic to detect if two different
-      // users in the same process use this function.
-      if (Stub.Proxy.sDefaultImpl != null) {
-        throw new IllegalStateException("setDefaultImpl() called twice");
-      }
-      if (impl != null) {
-        Stub.Proxy.sDefaultImpl = impl;
-        return true;
-      }
-      return false;
-    }
-    public static android.aidl.loggable.ILoggableInterface getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$loggable$ILoggableInterface".replace('$', '.');
   public java.lang.String[] LogThis(boolean boolValue, boolean[] boolArray, byte byteValue, byte[] byteArray, char charValue, char[] charArray, int intValue, int[] intArray, long longValue, long[] longArray, float floatValue, float[] floatArray, double doubleValue, double[] doubleArray, java.lang.String stringValue, java.lang.String[] stringArray, java.util.List<java.lang.String> listValue, android.aidl.loggable.Data dataValue, android.os.IBinder binderValue, android.os.ParcelFileDescriptor pfdValue, android.os.ParcelFileDescriptor[] pfdArray) throws android.os.RemoteException;
@@ -328,12 +306,6 @@
             _data.writeInterfaceToken(DESCRIPTOR);
             _data.writeInt(value);
             boolean _status = mRemote.transact(Stub.TRANSACTION_Log, _data, _reply, 0);
-            if (!_status) {
-              if (getDefaultImpl() != null) {
-                getDefaultImpl().Log(value);
-                return;
-              }
-            }
             _reply.readException();
           }
           finally {
@@ -342,25 +314,8 @@
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
         }
-        public static android.aidl.loggable.ILoggableInterface.ISub sDefaultImpl;
       }
       static final int TRANSACTION_Log = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-      public static boolean setDefaultImpl(android.aidl.loggable.ILoggableInterface.ISub impl) {
-        // Only one user of this interface can use this function
-        // at a time. This is a heuristic to detect if two different
-        // users in the same process use this function.
-        if (Stub.Proxy.sDefaultImpl != null) {
-          throw new IllegalStateException("setDefaultImpl() called twice");
-        }
-        if (impl != null) {
-          Stub.Proxy.sDefaultImpl = impl;
-          return true;
-        }
-        return false;
-      }
-      public static android.aidl.loggable.ILoggableInterface.ISub getDefaultImpl() {
-        return Stub.Proxy.sDefaultImpl;
-      }
     }
     public static final java.lang.String DESCRIPTOR = "android$aidl$loggable$ILoggableInterface$ISub".replace('$', '.');
     public void Log(int value) throws android.os.RemoteException;
diff --git a/tests/golden_test.sh b/tests/golden_test.sh
index 965fb82..634bcc4 100755
--- a/tests/golden_test.sh
+++ b/tests/golden_test.sh
@@ -39,6 +39,7 @@
   modules=(
     "aidl-test-interface-cpp-source"
     "aidl-test-interface-java-source"
+    "aidl-test-versioned-interface-V2-java-source"
     "aidl-test-interface-ndk-source"
     "aidl-test-interface-rust-source"
     "aidl_test_loggable_interface-cpp-source"