Snap for 6198741 from 6d02280c6bc1b17a1d5d51f33eceae2bf9d872b5 to sdk-release

Change-Id: I9bc711c0a5b415185389cdb9429534eb74233f08
diff --git a/Android.bp b/Android.bp
index fa5d485..0c2b367 100644
--- a/Android.bp
+++ b/Android.bp
@@ -47,7 +47,7 @@
 
     srcs: [
         "aidl.cpp",
-        "aidl_apicheck.cpp",
+        "aidl_checkapi.cpp",
         "aidl_const_expressions.cpp",
         "aidl_language.cpp",
         "aidl_language_l.ll",
@@ -84,17 +84,20 @@
     static_libs: [
         "libaidl-common",
         "libbase",
+        "liblog",
     ],
 }
 
-// aidl-cpp executable
+// aidl-cpp legacy executable, please use 'aidl' instead
 cc_binary_host {
     name: "aidl-cpp",
     defaults: ["aidl_defaults"],
-    srcs: ["main_cpp.cpp"],
+    srcs: ["main.cpp"],
+    cflags: ["-DAIDL_CPP_BUILD"],
     static_libs: [
         "libaidl-common",
         "libbase",
+        "liblog",
     ],
 }
 
@@ -110,7 +113,6 @@
         "-Wextra",
         "-Werror",
         "-g",
-        "-DUNIT_TEST",
     ],
 
     srcs: [
@@ -134,18 +136,40 @@
         "libaidl-common",
         "libbase",
         "libcutils",
+        "libgmock",
+        "liblog",
     ],
-    target: {
-        host: {
-            static_libs: ["libgmock_host"],
-        },
-        android: {
-            static_libs: [
-                "libgmock",
-                "liblog",
-            ],
-        },
+}
+
+cc_fuzz {
+    name: "aidl_parser_fuzzer",
+    host_supported: true,
+    dictionary: "tests/aidl_parser_fuzzer.dict",
+    corpus: [
+        "tests/corpus/*",
+    ],
+
+    fuzz_config: {
+        cc: [
+            "smoreland@google.com",
+            "jiyong@google.com",
+            "jeongik@google.com",
+        ],
     },
+
+    srcs: [
+        "tests/aidl_parser_fuzzer.cpp",
+        "tests/fake_io_delegate.cpp",
+        "tests/test_util.cpp",
+    ],
+    static_libs: [
+        "libaidl-common",
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+    // Enable this to show additional information about what is being parsed during fuzzing.
+    // cflags: ["-DFUZZ_LOG"],
 }
 
 //
@@ -237,11 +261,16 @@
     resource_dirs: ["tests/java_app/resources"],
     srcs: [
         "tests/android/aidl/tests/*.aidl",
+        "tests/android/aidl/tests/generic/*.aidl",
+        "tests/android/aidl/tests/map/*.aidl",
+        "tests/java_app/src/android/aidl/tests/GenericTests.java",
+        "tests/java_app/src/android/aidl/tests/MapTests.java",
         "tests/java_app/src/android/aidl/tests/NullableTests.java",
         "tests/java_app/src/android/aidl/tests/SimpleParcelable.java",
         "tests/java_app/src/android/aidl/tests/TestFailException.java",
         "tests/java_app/src/android/aidl/tests/TestLogger.java",
         "tests/java_app/src/android/aidl/tests/TestServiceClient.java",
+        "tests/java_app/src/android/aidl/tests/generic/Pair.java",
     ],
     aidl: {
         include_dirs: [
@@ -262,19 +291,6 @@
             gen_log: true,
         },
         ndk: {
-            enabled: false,
-        },
-    },
-}
-
-aidl_interface {
-    name: "aidl_test_loggable_interface_ndk",
-    local_include_dir: "tests",
-    srcs: [
-        "tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl",
-    ],
-    backend: {
-        ndk: {
             gen_log: true,
         },
     },
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 26cbca8..a54f480 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -5,6 +5,9 @@
     },
     {
       "name": "CtsNdkBinderTestCases"
+    },
+    {
+      "name": "aidl_lazy_test"
     }
   ]
 }
diff --git a/aidl.cpp b/aidl.cpp
index 90b6e45..083d520 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -75,6 +75,7 @@
 // are auto-implemented by the AIDL compiler.
 const int kFirstMetaMethodId = kLastCallTransaction - kFirstCallTransaction;
 const int kGetInterfaceVersionId = kFirstMetaMethodId;
+const int kGetInterfaceHashId = kFirstMetaMethodId - 1;
 // Additional meta transactions implemented by AIDL should use
 // kFirstMetaMethodId -1, -2, ...and so on.
 
@@ -357,7 +358,7 @@
   }
 
   string line;
-  unsigned lineno = 1;
+  int lineno = 1;
   for ( ; line_reader->ReadLine(&line); ++lineno) {
     if (line.empty() || line.compare(0, 2, "//") == 0) {
       // skip comments and empty lines
@@ -449,10 +450,10 @@
   ImportResolver import_resolver{io_delegate, input_file_name, options.ImportDirs(),
                                  options.InputFiles()};
 
-  set<string> type_from_import_statements;
+  vector<string> type_from_import_statements;
   for (const auto& import : main_parser->GetImports()) {
     if (!AidlTypenames::IsBuiltinTypename(import->GetNeededClass())) {
-      type_from_import_statements.emplace(import->GetNeededClass());
+      type_from_import_statements.emplace_back(import->GetNeededClass());
     }
   }
 
@@ -467,8 +468,9 @@
       unresolved_types.emplace(type->GetName());
     }
   }
-  set<string> import_candidates(type_from_import_statements);
-  import_candidates.insert(unresolved_types.begin(), unresolved_types.end());
+  vector<string> import_candidates(type_from_import_statements);
+  import_candidates.insert(import_candidates.end(), unresolved_types.begin(),
+                           unresolved_types.end());
   for (const auto& import : import_candidates) {
     if (typenames->IsIgnorableImport(import)) {
       // There are places in the Android tree where an import doesn't resolve,
@@ -478,7 +480,16 @@
     }
     string import_path = import_resolver.FindImportFile(import);
     if (import_path.empty()) {
-      if (type_from_import_statements.find(import) != type_from_import_statements.end()) {
+      if (typenames->ResolveTypename(import).second) {
+        // Couldn't find the *.aidl file for the type from the include paths, but we
+        // have the type already resolved. This could happen when the type is
+        // from the preprocessed aidl file. In that case, use the type from the
+        // preprocessed aidl file as a last resort.
+        continue;
+      }
+
+      if (std::find(type_from_import_statements.begin(), type_from_import_statements.end(),
+                    import) != type_from_import_statements.end()) {
         // Complain only when the import from the import statement has failed.
         AIDL_ERROR(import) << "couldn't find import for class " << import;
         err = AidlError::BAD_IMPORT;
@@ -538,11 +549,14 @@
         enum_decl->SetBackingType(std::move(byte_type));
       }
 
-      // TODO(b/139877950): Support autofilling enumerators, and ensure that
-      // autofilling does not cause any enumerators to have a value larger than
-      // allowed by the backing type.
+      if (!enum_decl->Autofill()) {
+        err = AidlError::BAD_TYPE;
+      }
     }
   });
+  if (err != AidlError::OK) {
+    return err;
+  }
 
   //////////////////////////////////////////////////////////////////////////
   // Validation phase
@@ -568,7 +582,7 @@
       if (!unstructuredParcelable->CheckValid(*typenames)) {
         return AidlError::BAD_TYPE;
       }
-      bool isStable = unstructuredParcelable->IsStableParcelable();
+      bool isStable = unstructuredParcelable->IsStableApiParcelable(options.TargetLanguage());
       if (options.IsStructured() && !isStable) {
         AIDL_ERROR(unstructuredParcelable)
             << "Cannot declared parcelable in a --structured interface. Parcelable must be defined "
@@ -626,6 +640,16 @@
                            kGetInterfaceVersionId, false /* is_user_defined */);
         interface->GetMutableMethods().emplace_back(method);
       }
+      // add the meta-method 'string getInterfaceHash()' if hash is specified.
+      if (!options.Hash().empty()) {
+        AidlTypeSpecifier* ret =
+            new AidlTypeSpecifier(AIDL_LOCATION_HERE, "String", false, nullptr, "");
+        ret->Resolve(*typenames);
+        vector<unique_ptr<AidlArgument>>* args = new vector<unique_ptr<AidlArgument>>();
+        AidlMethod* method = new AidlMethod(AIDL_LOCATION_HERE, false, ret, kGetInterfaceHash, args,
+                                            "", kGetInterfaceHashId, false /* is_user_defined */);
+        interface->GetMutableMethods().emplace_back(method);
+      }
       if (!check_and_assign_method_ids(interface->GetMethods())) {
         return AidlError::BAD_METHOD_ID;
       }
@@ -660,7 +684,7 @@
 
   typenames->IterateTypes([&](const AidlDefinedType& type) {
     if (options.IsStructured() && type.AsUnstructuredParcelable() != nullptr &&
-        !type.AsUnstructuredParcelable()->IsStableParcelable()) {
+        !type.AsUnstructuredParcelable()->IsStableApiParcelable(options.TargetLanguage())) {
       err = AidlError::NOT_STRUCTURED;
       LOG(ERROR) << type.GetCanonicalName()
                  << " is not structured, but this is a structured interface.";
@@ -734,8 +758,13 @@
         ndk::GenerateNdk(output_file_name, options, typenames, *defined_type, io_delegate);
         success = true;
       } else if (lang == Options::Language::JAVA) {
-        success =
-            java::generate_java(output_file_name, defined_type, typenames, io_delegate, options);
+        if (defined_type->AsUnstructuredParcelable() != nullptr) {
+          // Legacy behavior. For parcelable declarations in Java, don't generate output file.
+          success = true;
+        } else {
+          success =
+              java::generate_java(output_file_name, defined_type, typenames, io_delegate, options);
+        }
       } else {
         LOG(FATAL) << "Should not reach here" << endl;
         return 1;
@@ -813,7 +842,7 @@
         if (!type->GetPackage().empty()) {
           (*writer) << "package " << type->GetPackage() << ";\n";
         }
-        type->Write(writer.get());
+        type->Dump(writer.get());
       }
     } else {
       return false;
diff --git a/aidl.h b/aidl.h
index 955b280..94eaf54 100644
--- a/aidl.h
+++ b/aidl.h
@@ -51,6 +51,7 @@
 bool dump_mappings(const Options& options, const IoDelegate& io_delegate);
 
 const string kGetInterfaceVersion("getInterfaceVersion");
+const string kGetInterfaceHash("getInterfaceHash");
 
 namespace internals {
 
diff --git a/aidl_apicheck.cpp b/aidl_checkapi.cpp
similarity index 100%
rename from aidl_apicheck.cpp
rename to aidl_checkapi.cpp
diff --git a/aidl_apicheck.h b/aidl_checkapi.h
similarity index 100%
rename from aidl_apicheck.h
rename to aidl_checkapi.h
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index b5450a7..6194d7d 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "aidl_language.h"
+#include "aidl_typenames.h"
 #include "logging.h"
 
 #include <stdlib.h>
@@ -195,11 +196,12 @@
 }
 
 AidlConstantValue* AidlConstantValue::Character(const AidlLocation& location, char value) {
+  const std::string explicit_value = string("'") + value + "'";
   if (!isValidLiteralChar(value)) {
     AIDL_ERROR(location) << "Invalid character literal " << value;
-    return new AidlConstantValue(location, Type::ERROR, "");
+    return new AidlConstantValue(location, Type::ERROR, explicit_value);
   }
-  return new AidlConstantValue(location, Type::CHARACTER, string("'") + value + "'");
+  return new AidlConstantValue(location, Type::CHARACTER, explicit_value);
 }
 
 AidlConstantValue* AidlConstantValue::Floating(const AidlLocation& location,
@@ -299,13 +301,33 @@
     if (!isValidLiteralChar(value[i])) {
       AIDL_ERROR(location) << "Found invalid character at index " << i << " in string constant '"
                            << value << "'";
-      return new AidlConstantValue(location, Type::ERROR, "");
+      return new AidlConstantValue(location, Type::ERROR, value);
     }
   }
 
   return new AidlConstantValue(location, Type::STRING, value);
 }
 
+AidlConstantValue* AidlConstantValue::ShallowIntegralCopy(const AidlConstantValue& other) {
+  // TODO(b/141313220) Perform a full copy instead of parsing+unparsing
+  AidlTypeSpecifier type = AidlTypeSpecifier(AIDL_LOCATION_HERE, "long", false, nullptr, "");
+  // TODO(b/142722772) CheckValid() should be called before ValueString()
+  if (!other.CheckValid() || !other.evaluate(type)) {
+    AIDL_ERROR(other) << "Failed to parse expression as integer: " << other.value_;
+    return nullptr;
+  }
+  const std::string& value = other.ValueString(type, AidlConstantValueDecorator);
+  if (value.empty()) {
+    return nullptr;  // error already logged
+  }
+
+  AidlConstantValue* result = Integral(AIDL_LOCATION_HERE, value);
+  if (result == nullptr) {
+    AIDL_FATAL(other) << "Unable to perform ShallowIntegralCopy.";
+  }
+  return result;
+}
+
 string AidlConstantValue::ValueString(const AidlTypeSpecifier& type,
                                       const ConstantValueDecorator& decorator) const {
   if (type.IsGeneric()) {
@@ -443,6 +465,8 @@
     case Type::BINARY:
       is_valid_ = true;
       break;
+    case Type::ERROR:
+      return false;
     default:
       AIDL_FATAL(this) << "Unrecognized constant value type: " << ToString(type_);
       return false;
@@ -529,27 +553,29 @@
 
 string AidlConstantValue::ToString(Type type) {
   switch (type) {
-    case Type::ARRAY:
-      return "a literal array";
     case Type::BOOLEAN:
       return "a literal boolean";
-    case Type::CHARACTER:
-      return "a literal char";
     case Type::INT8:
       return "an int8 literal";
     case Type::INT32:
       return "an int32 literal";
     case Type::INT64:
       return "an int64 literal";
+    case Type::ARRAY:
+      return "a literal array";
+    case Type::CHARACTER:
+      return "a literal char";
     case Type::STRING:
       return "a literal string";
-    case Type::ERROR:
-      LOG(FATAL) << "aidl internal error: error type failed to halt program";
-      return "";
+    case Type::FLOATING:
+      return "a literal float";
     case Type::UNARY:
       return "a unary expression";
     case Type::BINARY:
       return "a binary expression";
+    case Type::ERROR:
+      LOG(FATAL) << "aidl internal error: error type failed to halt program";
+      return "";
     default:
       LOG(FATAL) << "aidl internal error: unknown constant type: " << static_cast<int>(type);
       return "";  // not reached
@@ -566,7 +592,7 @@
     return false;
   }
 
-  return true;
+  return AidlConstantValue::CheckValid();
 }
 
 bool AidlUnaryConstExpression::evaluate(const AidlTypeSpecifier& type) const {
@@ -606,29 +632,6 @@
               is_valid_ = false; return false;)
 }
 
-string AidlUnaryConstExpression::ValueString(const AidlTypeSpecifier& type,
-                                             const ConstantValueDecorator& decorator) const {
-  if (type.IsGeneric()) {
-    AIDL_ERROR(type) << "Generic type cannot be specified with a constant literal.";
-    return "";
-  }
-  if (!is_evaluated_) {
-    // TODO(b/142722772) CheckValid() should be called before ValueString()
-    bool success = CheckValid();
-    success &= evaluate(type);
-    if (!success) {
-      // A detailed error message shall be printed in evaluate()
-      return "";
-    }
-  }
-  if (!is_valid_) {
-    AIDL_ERROR(this) << "Invalid constant unary expression";
-    return "";
-  }
-
-  return AidlConstantValue::ValueString(type, decorator);
-}
-
 bool AidlBinaryConstExpression::CheckValid() const {
   bool success = false;
   if (is_evaluated_) return is_valid_;
@@ -653,7 +656,7 @@
   }
 
   is_valid_ = true;
-  return true;
+  return AidlConstantValue::CheckValid();
 }
 
 bool AidlBinaryConstExpression::evaluate(const AidlTypeSpecifier& type) const {
@@ -721,10 +724,10 @@
 
   // CASE: + - *  / % | ^ & < > <= >= == !=
   if (isArithmeticOrBitflip || OP_IS_BIN_COMP) {
-    if (op_ == "/" && right_val_->final_value_ == 0) {
+    if ((op_ == "/" || op_ == "%") && right_val_->final_value_ == 0) {
       final_type_ = Type::ERROR;
       is_valid_ = false;
-      AIDL_ERROR(this) << "Divide by 0! const_expr: " + value_;
+      AIDL_ERROR(this) << "Cannot do division operation with zero for expression: " + value_;
       return false;
     }
 
@@ -752,7 +755,7 @@
     // instead of promoting rval, simply casting it to int64 should also be good.
     int64_t numBits = right_val_->cast<int64_t>();
     if (numBits < 0) {
-      // shifting with negative number of bits is undefined in C. In HIDL it
+      // shifting with negative number of bits is undefined in C. In AIDL it
       // is defined as shifting into the other direction.
       newOp = OPEQ("<<") ? ">>" : "<<";
       numBits = -numBits;
@@ -779,36 +782,11 @@
   return false;
 }
 
-string AidlBinaryConstExpression::ValueString(const AidlTypeSpecifier& type,
-                                              const ConstantValueDecorator& decorator) const {
-  if (type.IsGeneric()) {
-    AIDL_ERROR(type) << "Generic type cannot be specified with a constant literal.";
-    return "";
-  }
-  if (!is_evaluated_) {
-    // TODO(b/142722772) CheckValid() should be called before ValueString()
-    bool success = CheckValid();
-    success &= evaluate(type);
-    if (!success) {
-      AIDL_ERROR(this) << "Invalid constant binary expression";
-      return "";
-    }
-  }
-  if (!is_valid_) {
-    AIDL_ERROR(this) << "Invalid constant binary expression";
-    return "";
-  }
-
-  return AidlConstantValue::ValueString(type, decorator);
-}
-
 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type parsed_type,
                                      int64_t parsed_value, const string& checked_value)
     : AidlNode(location),
       type_(parsed_type),
       value_(checked_value),
-      is_valid_(true),
-      is_evaluated_(true),
       final_type_(parsed_type),
       final_value_(parsed_value) {
   CHECK(!value_.empty() || type_ == Type::ERROR);
@@ -820,8 +798,6 @@
     : AidlNode(location),
       type_(type),
       value_(checked_value),
-      is_valid_(false),
-      is_evaluated_(false),
       final_type_(type) {
   CHECK(!value_.empty() || type_ == Type::ERROR);
   switch (type_) {
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 336f97d..c591c45 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -31,7 +31,7 @@
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 
-#include "aidl_language_y.h"
+#include "aidl_language_y-module.h"
 #include "logging.h"
 
 #include "aidl.h"
@@ -55,7 +55,7 @@
 using std::vector;
 
 namespace {
-bool is_java_keyword(const char* str) {
+bool IsJavaKeyword(const char* str) {
   static const std::vector<std::string> kJavaKeywords{
       "abstract", "assert", "boolean",    "break",     "byte",       "case",      "catch",
       "char",     "class",  "const",      "continue",  "default",    "do",        "double",
@@ -68,6 +68,14 @@
   };
   return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
 }
+
+void AddHideComment(CodeWriter* writer) {
+  writer->Write("/* @hide */\n");
+}
+
+inline bool HasHideComment(const std::string& comment) {
+  return std::regex_search(comment, std::regex("@hide\\b"));
+}
 }  // namespace
 
 void yylex_init(void **);
@@ -95,22 +103,33 @@
 
 AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
 
-std::string AidlNode::PrintLocation() const {
+std::string AidlNode::PrintLine() const {
   std::stringstream ss;
   ss << location_.file_ << ":" << location_.begin_.line;
   return ss.str();
 }
 
+std::string AidlNode::PrintLocation() const {
+  std::stringstream ss;
+  ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
+     << location_.end_.line << ":" << location_.end_.column;
+  return ss.str();
+}
+
 AidlError::AidlError(bool fatal) : os_(std::cerr), fatal_(fatal) {
+  sHadError = true;
+
   os_ << "ERROR: ";
 }
 
+bool AidlError::sHadError = false;
+
 static const string kNullable("nullable");
 static const string kUtf8InCpp("utf8InCpp");
 static const string kVintfStability("VintfStability");
 static const string kUnsupportedAppUsage("UnsupportedAppUsage");
 static const string kSystemApi("SystemApi");
-static const string kStableParcelable("JavaOnlyStableParcelable");
+static const string kJavaStableParcelable("JavaOnlyStableParcelable");
 static const string kBacking("Backing");
 
 static const std::map<string, std::map<std::string, std::string>> kAnnotationParameters{
@@ -124,7 +143,7 @@
       {"publicAlternatives", "String"},
       {"trackingBug", "long"}}},
     {kSystemApi, {}},
-    {kStableParcelable, {}},
+    {kJavaStableParcelable, {}},
     {kBacking, {{"type", "String"}}}};
 
 AidlAnnotation* AidlAnnotation::Parse(
@@ -285,8 +304,8 @@
   return HasAnnotation(annotations_, kSystemApi);
 }
 
-bool AidlAnnotatable::IsStableParcelable() const {
-  return HasAnnotation(annotations_, kStableParcelable);
+bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
+  return HasAnnotation(annotations_, kJavaStableParcelable) && lang == Options::Language::JAVA;
 }
 
 bool AidlAnnotatable::CheckValidAnnotations() const {
@@ -313,18 +332,24 @@
                                      vector<unique_ptr<AidlTypeSpecifier>>* type_params,
                                      const string& comments)
     : AidlAnnotatable(location),
+      AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
       unresolved_name_(unresolved_name),
       is_array_(is_array),
-      type_params_(type_params),
       comments_(comments),
       split_name_(Split(unresolved_name, ".")) {}
 
 AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
   AIDL_FATAL_IF(!is_array_, this);
+  // Declaring array of generic type cannot happen, it is grammar error.
+  AIDL_FATAL_IF(IsGeneric(), this);
 
-  AidlTypeSpecifier arrayBase = *this;
-  arrayBase.is_array_ = false;
-  return arrayBase;
+  AidlTypeSpecifier array_base = *this;
+  array_base.is_array_ = false;
+  return array_base;
+}
+
+bool AidlTypeSpecifier::IsHidden() const {
+  return HasHideComment(GetComments());
 }
 
 string AidlTypeSpecifier::ToString() const {
@@ -367,22 +392,64 @@
   }
   if (IsGeneric()) {
     const string& type_name = GetName();
-    const int num = GetTypeParameters().size();
+
+    auto& types = GetTypeParameters();
+    // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
+    if (type_name == "List" || type_name == "Map") {
+      if (std::any_of(types.begin(), types.end(), [](auto& type_ptr) {
+            return AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
+          })) {
+        AIDL_ERROR(this) << "A generic type cannot has any primitive type parameters.";
+        return false;
+      }
+    }
+    const auto defined_type = typenames.TryGetDefinedType(type_name);
+    const auto parameterizable =
+        defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
+    const bool is_user_defined_generic_type =
+        parameterizable != nullptr && parameterizable->IsGeneric();
+    const size_t num_params = GetTypeParameters().size();
     if (type_name == "List") {
-      if (num > 1) {
+      if (num_params > 1) {
         AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
                          << "'" << ToString() << "'";
         return false;
       }
     } else if (type_name == "Map") {
-      if (num != 0 && num != 2) {
+      if (num_params != 0 && num_params != 2) {
         AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
                          << "'" << ToString() << "'";
         return false;
       }
+      if (num_params == 2) {
+        const string& key_type = GetTypeParameters()[0]->GetName();
+        if (key_type != "String") {
+          AIDL_ERROR(this) << "The type of key in map must be String, but it is "
+                           << "'" << key_type << "'";
+          return false;
+        }
+      }
+    } else if (is_user_defined_generic_type) {
+      const size_t allowed = parameterizable->GetTypeParameters().size();
+      if (num_params != allowed) {
+        AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
+                         << num_params;
+        return false;
+      }
+    } else {
+      AIDL_ERROR(this) << type_name << " is not a generic type.";
+      return false;
     }
   }
 
+  const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
+                                      GetTypeParameters().size() == 1 &&
+                                      GetTypeParameters()[0]->GetName() == "String";
+  if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
+    AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
+    return false;
+  }
+
   if (GetName() == "void") {
     if (IsArray() || IsNullable() || IsUtf8InCpp()) {
       AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
@@ -391,8 +458,8 @@
   }
 
   if (IsArray()) {
-    const auto definedType = typenames.TryGetDefinedType(GetName());
-    if (definedType != nullptr && definedType->AsInterface() != nullptr) {
+    const auto defined_type = typenames.TryGetDefinedType(GetName());
+    if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
       AIDL_ERROR(this) << "Binder type cannot be an array";
       return false;
     }
@@ -403,8 +470,8 @@
       AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
       return false;
     }
-    const auto definedType = typenames.TryGetDefinedType(GetName());
-    if (definedType != nullptr && definedType->AsEnumDeclaration() != nullptr && !IsArray()) {
+    const auto defined_type = typenames.TryGetDefinedType(GetName());
+    if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
       AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
       return false;
     }
@@ -430,6 +497,12 @@
   bool valid = true;
   valid &= type_->CheckValid(typenames);
 
+  if (type_->GetName() == "void") {
+    AIDL_ERROR(this) << "Declaration " << name_
+                     << " is void, but declarations cannot be of void type.";
+    valid = false;
+  }
+
   if (default_value_ == nullptr) return valid;
   valid &= default_value_->CheckValid();
 
@@ -559,6 +632,9 @@
   }
 }
 
+bool AidlMethod::IsHidden() const {
+  return HasHideComment(GetComments());
+}
 
 string AidlMethod::Signature() const {
   vector<string> arg_signatures;
@@ -590,6 +666,10 @@
   return Join(package_, '.');
 }
 
+bool AidlDefinedType::IsHidden() const {
+  return HasHideComment(GetComments());
+}
+
 std::string AidlDefinedType::GetCanonicalName() const {
   if (package_.empty()) {
     return GetName();
@@ -599,8 +679,9 @@
 
 AidlParcelable::AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
                                const std::vector<std::string>& package, const std::string& comments,
-                               const std::string& cpp_header)
+                               const std::string& cpp_header, std::vector<std::string>* type_params)
     : AidlDefinedType(location, name->GetDotName(), comments, package),
+      AidlParameterizable<std::string>(type_params),
       name_(name),
       cpp_header_(cpp_header) {
   // Strip off quotation marks if we actually have a cpp header.
@@ -608,12 +689,40 @@
     cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
   }
 }
+template <typename T>
+AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
+  // Copying is not supported if it has type parameters.
+  // It doesn't make a problem because only ArrayBase() makes a copy,
+  // and it can be called only if a type is not generic.
+  CHECK(!other.IsGeneric());
+}
+
+template <typename T>
+bool AidlParameterizable<T>::CheckValid() const {
+  return true;
+};
+
+template <>
+bool AidlParameterizable<std::string>::CheckValid() const {
+  if (!IsGeneric()) {
+    return true;
+  }
+  std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
+  if (set.size() != GetTypeParameters().size()) {
+    AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
+    return false;
+  }
+  return true;
+}
 
 bool AidlParcelable::CheckValid(const AidlTypenames&) const {
-  static const std::set<string> allowed{kStableParcelable};
+  static const std::set<string> allowed{kJavaStableParcelable};
   if (!CheckValidAnnotations()) {
     return false;
   }
+  if (!AidlParameterizable<std::string>::CheckValid()) {
+    return false;
+  }
   for (const auto& v : GetAnnotations()) {
     if (allowed.find(v.GetName()) == allowed.end()) {
       std::ostringstream stream;
@@ -630,7 +739,7 @@
   return true;
 }
 
-void AidlParcelable::Write(CodeWriter* writer) const {
+void AidlParcelable::Dump(CodeWriter* writer) const {
   writer->Write("parcelable %s ;\n", GetName().c_str());
 }
 
@@ -640,10 +749,16 @@
     : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
       variables_(std::move(*variables)) {}
 
-void AidlStructuredParcelable::Write(CodeWriter* writer) const {
+void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
+  if (this->IsHidden()) {
+    AddHideComment(writer);
+  }
   writer->Write("parcelable %s {\n", GetName().c_str());
   writer->Indent();
   for (const auto& field : GetFields()) {
+    if (field->GetType().IsHidden()) {
+      AddHideComment(writer);
+    }
     writer->Write("%s;\n", field->ToString().c_str());
   }
   writer->Dedent();
@@ -660,12 +775,16 @@
 
 // TODO: we should treat every backend all the same in future.
 bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
-  if (lang == Options::Language::CPP) {
+  if (lang != Options::Language::JAVA) {
     if (this->GetName() == "List" && !this->IsGeneric()) {
-      AIDL_ERROR(this) << "List without type isn't supported in cpp.";
+      AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
       return false;
     }
   }
+  if (this->GetName() == "FileDescriptor" && lang == Options::Language::NDK) {
+    AIDL_ERROR(this) << "FileDescriptor isn't supported with the NDK.";
+    return false;
+  }
   if (this->IsGeneric()) {
     if (this->GetName() == "List") {
       if (this->GetTypeParameters().size() != 1) {
@@ -678,32 +797,45 @@
           AIDL_ERROR(this) << "List in cpp supports only string and IBinder for now.";
           return false;
         }
-      } else if (lang == Options::Language::NDK) {
-        AIDL_ERROR(this) << "NDK backend does not support List yet.";
-        return false;
+      } else if (lang == Options::Language::JAVA) {
+        const string& contained_type = this->GetTypeParameters()[0]->GetName();
+        if (AidlTypenames::IsBuiltinTypename(contained_type)) {
+          if (contained_type != "String" && contained_type != "IBinder" &&
+              contained_type != "ParcelFileDescriptor") {
+            AIDL_ERROR(this) << "List<" << contained_type << "> isn't supported in Java";
+            return false;
+          }
+        }
       }
-
-    } else if (this->GetName() == "Map") {
-      if (lang != Options::Language::JAVA) {
-        AIDL_ERROR(this) << "Currently, only Java backend supports Map.";
+    }
+  }
+  if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
+    if (lang != Options::Language::JAVA) {
+      AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
+      return false;
+    }
+  }
+  if (lang == Options::Language::JAVA) {
+    const string name = this->GetName();
+    // List[], Map[], CharSequence[] are not supported.
+    if (AidlTypenames::IsBuiltinTypename(name) && this->IsArray()) {
+      if (name == "List" || name == "Map" || name == "CharSequence") {
+        AIDL_ERROR(this) << "List[], Map[], CharSequence[] are not supported.";
         return false;
       }
     }
   }
+
   return true;
 }
 
 // TODO: we should treat every backend all the same in future.
 bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
   if (lang != Options::Language::JAVA) {
-    if (this->IsStableParcelable()) {
-      AIDL_ERROR(this) << "@JavaOnlyStableParcelable supports only Java target.";
-      return false;
-    }
-    const AidlParcelable* unstructuredParcelable = this->AsUnstructuredParcelable();
-    if (unstructuredParcelable != nullptr) {
-      if (unstructuredParcelable->GetCppHeader().empty()) {
-        AIDL_ERROR(unstructuredParcelable)
+    const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
+    if (unstructured_parcelable != nullptr) {
+      if (unstructured_parcelable->GetCppHeader().empty()) {
+        AIDL_ERROR(unstructured_parcelable)
             << "Unstructured parcelable must have C++ header defined.";
         return false;
       }
@@ -758,6 +890,30 @@
   backing_type_ = std::move(type);
 }
 
+bool AidlEnumDeclaration::Autofill() {
+  const AidlEnumerator* previous = nullptr;
+  for (const auto& enumerator : enumerators_) {
+    if (enumerator->GetValue() == nullptr) {
+      if (previous == nullptr) {
+        enumerator->SetValue(std::unique_ptr<AidlConstantValue>(
+            AidlConstantValue::Integral(AIDL_LOCATION_HERE, "0")));
+      } else {
+        auto prev_value = std::unique_ptr<AidlConstantValue>(
+            AidlConstantValue::ShallowIntegralCopy(*previous->GetValue()));
+        if (prev_value == nullptr) {
+          return false;
+        }
+        enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
+            AIDL_LOCATION_HERE, std::move(prev_value), "+",
+            std::unique_ptr<AidlConstantValue>(
+                AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1"))));
+      }
+    }
+    previous = enumerator.get();
+  }
+  return true;
+}
+
 bool AidlEnumDeclaration::CheckValid(const AidlTypenames&) const {
   if (backing_type_ == nullptr) {
     AIDL_ERROR(this) << "Enum declaration missing backing type.";
@@ -770,13 +926,11 @@
   return success;
 }
 
-void AidlEnumDeclaration::Write(CodeWriter* writer) const {
+void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
   writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
   writer->Write("enum %s {\n", GetName().c_str());
   writer->Indent();
   for (const auto& enumerator : GetEnumerators()) {
-    // TODO(b/123321528): After autofilling is supported, determine if we want
-    // to leave out the assigned value for enumerators that were autofilled.
     writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
                   enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
   }
@@ -824,13 +978,22 @@
   delete members;
 }
 
-void AidlInterface::Write(CodeWriter* writer) const {
+void AidlInterface::Dump(CodeWriter* writer) const {
+  if (this->IsHidden()) {
+    AddHideComment(writer);
+  }
   writer->Write("interface %s {\n", GetName().c_str());
   writer->Indent();
   for (const auto& method : GetMethods()) {
+    if (method->IsHidden()) {
+      AddHideComment(writer);
+    }
     writer->Write("%s;\n", method->ToString().c_str());
   }
   for (const auto& constdecl : GetConstantDeclarations()) {
+    if (constdecl->GetType().IsHidden()) {
+      AddHideComment(writer);
+    }
     writer->Write("%s;\n", constdecl->ToString().c_str());
   }
   writer->Dedent();
@@ -884,7 +1047,7 @@
       }
 
       // check that the name doesn't match a keyword
-      if (is_java_keyword(arg->GetName().c_str())) {
+      if (IsJavaKeyword(arg->GetName().c_str())) {
         AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
         return false;
       }
@@ -906,7 +1069,7 @@
       return false;
     }
 
-    static set<string> reserved_methods{"asBinder()", "getInterfaceVersion()",
+    static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
                                         "getTransactionName(int)"};
 
     if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
@@ -977,8 +1140,13 @@
   return package_->GetTerms();
 }
 
-void Parser::AddImport(AidlImport* import) {
-  imports_.emplace_back(import);
+void Parser::AddImport(std::unique_ptr<AidlImport>&& import) {
+  for (const auto& i : imports_) {
+    if (i->GetNeededClass() == import->GetNeededClass()) {
+      return;
+    }
+  }
+  imports_.emplace_back(std::move(import));
 }
 
 bool Parser::Resolve() {
diff --git a/aidl_language.h b/aidl_language.h
index cb380bd..b8ee857 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -22,7 +22,9 @@
 #include "options.h"
 
 #include <memory>
+#include <regex>
 #include <string>
+#include <unordered_set>
 #include <vector>
 
 #include <android-base/macros.h>
@@ -45,6 +47,9 @@
 namespace mappings {
 std::string dump_location(const AidlNode& method);
 }  // namespace mappings
+namespace java {
+std::string dump_location(const AidlNode& method);
+}  // namespace java
 }  // namespace aidl
 }  // namespace android
 
@@ -65,8 +70,8 @@
 class AidlLocation {
  public:
   struct Point {
-    unsigned int line;
-    unsigned int column;
+    int line;
+    int column;
   };
 
   AidlLocation(const std::string& file, Point begin, Point end);
@@ -103,8 +108,10 @@
   // To be able to print AidlLocation (nothing else should use this information)
   friend class AidlError;
   friend std::string android::aidl::mappings::dump_location(const AidlNode&);
+  friend std::string android::aidl::java::dump_location(const AidlNode&);
 
  private:
+  std::string PrintLine() const;
   std::string PrintLocation() const;
   const AidlLocation location_;
 };
@@ -128,11 +135,15 @@
 
   std::ostream& os_;
 
+  static bool hadError() { return sHadError; }
+
  private:
   AidlError(bool fatal);
 
   bool fatal_;
 
+  static bool sHadError;
+
   DISALLOW_COPY_AND_ASSIGN(AidlError);
 };
 
@@ -144,12 +155,35 @@
 namespace android {
 namespace aidl {
 
-class ValidatableType;
 class AidlTypenames;
 
 }  // namespace aidl
 }  // namespace android
 
+// unique_ptr<AidlTypeSpecifier> for type arugment,
+// std::string for type parameter(T, U, and so on).
+template <typename T>
+class AidlParameterizable {
+ public:
+  AidlParameterizable(std::vector<T>* type_params) : type_params_(type_params) {}
+  virtual ~AidlParameterizable() = default;
+  bool IsGeneric() const { return type_params_ != nullptr; }
+  const std::vector<T>& GetTypeParameters() const { return *type_params_; }
+  bool CheckValid() const;
+
+  virtual const AidlNode& AsAidlNode() const = 0;
+
+ protected:
+  AidlParameterizable(const AidlParameterizable&);
+
+ private:
+  const unique_ptr<std::vector<T>> type_params_;
+  static_assert(std::is_same<T, unique_ptr<AidlTypeSpecifier>>::value ||
+                std::is_same<T, std::string>::value);
+};
+template <>
+bool AidlParameterizable<std::string>::CheckValid() const;
+
 class AidlConstantValue;
 class AidlConstantDeclaration;
 
@@ -209,7 +243,7 @@
   bool IsUtf8InCpp() const;
   bool IsVintfStability() const;
   bool IsSystemApi() const;
-  bool IsStableParcelable() const;
+  bool IsStableApiParcelable(Options::Language lang) const;
 
   const AidlAnnotation* UnsupportedAppUsage() const;
   const AidlTypeSpecifier* BackingType(const AidlTypenames& typenames) const;
@@ -226,7 +260,8 @@
 
 // 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 {
+class AidlTypeSpecifier final : public AidlAnnotatable,
+                                public AidlParameterizable<unique_ptr<AidlTypeSpecifier>> {
  public:
   AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name, bool is_array,
                     vector<unique_ptr<AidlTypeSpecifier>>* type_params, const string& comments);
@@ -256,6 +291,8 @@
 
   const string& GetUnresolvedName() const { return unresolved_name_; }
 
+  bool IsHidden() const;
+
   const string& GetComments() const { return comments_; }
 
   const std::vector<std::string> GetSplitName() const { return split_name_; }
@@ -266,38 +303,24 @@
 
   bool IsArray() const { return is_array_; }
 
-  bool IsGeneric() const { return type_params_ != nullptr; }
-
-  const vector<unique_ptr<AidlTypeSpecifier>>& GetTypeParameters() const { return *type_params_; }
-
   // Resolve the base type name to a fully-qualified name. Return false if the
   // resolution fails.
   bool Resolve(const AidlTypenames& typenames);
 
   bool CheckValid(const AidlTypenames& typenames) const;
   bool LanguageSpecificCheckValid(Options::Language lang) const;
+  const AidlNode& AsAidlNode() const override { return *this; }
 
-  void SetLanguageType(const android::aidl::ValidatableType* language_type) {
-    language_type_ = language_type;
-  }
-
-  template<typename T>
-  const T* GetLanguageType() const {
-    return reinterpret_cast<const T*>(language_type_);
-  }
  private:
   AidlTypeSpecifier(const AidlTypeSpecifier&) = default;
 
   const string unresolved_name_;
   string fully_qualified_name_;
   bool is_array_;
-  const shared_ptr<vector<unique_ptr<AidlTypeSpecifier>>> type_params_;
   string comments_;
-  const android::aidl::ValidatableType* language_type_ = nullptr;
   vector<string> split_name_;
 };
 
-
 // Returns the universal value unaltered.
 std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
 
@@ -409,13 +432,17 @@
   // example: "\"asdf\""
   static AidlConstantValue* String(const AidlLocation& location, const string& value);
 
+  // Construct an AidlConstantValue by evaluating the other integral constant's
+  // value string. This does not preserve the structure of the copied constant.
+  // Returns nullptr and logs if value cannot be copied.
+  static AidlConstantValue* ShallowIntegralCopy(const AidlConstantValue& other);
+
   Type GetType() const { return final_type_; }
 
   virtual bool CheckValid() const;
 
   // Raw value of type (currently valid in C++ and Java). Empty string on error.
-  virtual string ValueString(const AidlTypeSpecifier& type,
-                             const ConstantValueDecorator& decorator) const;
+  string ValueString(const AidlTypeSpecifier& type, const ConstantValueDecorator& decorator) const;
 
  private:
   AidlConstantValue(const AidlLocation& location, Type parsed_type, int64_t parsed_value,
@@ -426,6 +453,7 @@
   static string ToString(Type type);
   static bool ParseIntegral(const string& value, int64_t* parsed_value, Type* parsed_type);
   static bool IsHex(const string& value);
+
   virtual bool evaluate(const AidlTypeSpecifier& type) const;
 
   const Type type_ = Type::ERROR;
@@ -433,8 +461,8 @@
   const string value_;                                  // otherwise
 
   // State for tracking evaluation of expressions
-  mutable bool is_valid_;
-  mutable bool is_evaluated_;
+  mutable bool is_valid_ = false;      // cache of CheckValid, but may be marked false in evaluate
+  mutable bool is_evaluated_ = false;  // whether evaluate has been called
   mutable Type final_type_;
   mutable int64_t final_value_;
   mutable string final_string_value_ = "";
@@ -452,9 +480,6 @@
 
   static bool IsCompatibleType(Type type, const string& op);
   bool CheckValid() const override;
-  string ValueString(const AidlTypeSpecifier& type,
-                     const ConstantValueDecorator& decorator) const override;
-
  private:
   bool evaluate(const AidlTypeSpecifier& type) const override;
 
@@ -468,8 +493,6 @@
                             const string& op, std::unique_ptr<AidlConstantValue> rval);
 
   bool CheckValid() const override;
-  string ValueString(const AidlTypeSpecifier& type,
-                     const ConstantValueDecorator& decorator) const override;
 
   static bool AreCompatibleTypes(Type t1, Type t2);
   // Returns the promoted kind for both operands
@@ -528,7 +551,7 @@
   virtual ~AidlMethod() = default;
 
   AidlMethod* AsMethod() override { return this; }
-
+  bool IsHidden() const;
   const string& GetComments() const { return comments_; }
   const AidlTypeSpecifier& GetType() const { return *type_; }
   AidlTypeSpecifier* GetMutableType() { return type_.get(); }
@@ -617,6 +640,7 @@
   virtual ~AidlDefinedType() = default;
 
   const std::string& GetName() const { return name_; };
+  bool IsHidden() const;
   const std::string& GetComments() const { return comments_; }
   void SetComments(const std::string comments) { comments_ = comments; }
 
@@ -632,6 +656,7 @@
   virtual const AidlParcelable* AsParcelable() const { return nullptr; }
   virtual const AidlEnumDeclaration* AsEnumDeclaration() const { return nullptr; }
   virtual const AidlInterface* AsInterface() const { return nullptr; }
+  virtual const AidlParameterizable<std::string>* AsParameterizable() const { return nullptr; }
   virtual bool CheckValid(const AidlTypenames&) const { return CheckValidAnnotations(); }
   virtual bool LanguageSpecificCheckValid(Options::Language lang) const = 0;
   AidlStructuredParcelable* AsStructuredParcelable() {
@@ -649,6 +674,11 @@
     return const_cast<AidlInterface*>(const_cast<const AidlDefinedType*>(this)->AsInterface());
   }
 
+  AidlParameterizable<std::string>* AsParameterizable() {
+    return const_cast<AidlParameterizable<std::string>*>(
+        const_cast<const AidlDefinedType*>(this)->AsParameterizable());
+  }
+
   const AidlParcelable* AsUnstructuredParcelable() const {
     if (this->AsStructuredParcelable() != nullptr) return nullptr;
     return this->AsParcelable();
@@ -658,31 +688,22 @@
         const_cast<const AidlDefinedType*>(this)->AsUnstructuredParcelable());
   }
 
-  void SetLanguageType(const android::aidl::ValidatableType* language_type) {
-    language_type_ = language_type;
-  }
-
-  template <typename T>
-  const T* GetLanguageType() const {
-    return reinterpret_cast<const T*>(language_type_);
-  }
-
-  virtual void Write(CodeWriter* writer) const = 0;
+  virtual void Dump(CodeWriter* writer) const = 0;
 
  private:
   std::string name_;
   std::string comments_;
-  const android::aidl::ValidatableType* language_type_ = nullptr;
   const std::vector<std::string> package_;
 
   DISALLOW_COPY_AND_ASSIGN(AidlDefinedType);
 };
 
-class AidlParcelable : public AidlDefinedType {
+class AidlParcelable : public AidlDefinedType, public AidlParameterizable<std::string> {
  public:
   AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
                  const std::vector<std::string>& package, const std::string& comments,
-                 const std::string& cpp_header = "");
+                 const std::string& cpp_header = "",
+                 std::vector<std::string>* type_params = nullptr);
   virtual ~AidlParcelable() = default;
 
   // C++ uses "::" instead of "." to refer to a inner class.
@@ -692,9 +713,11 @@
   bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(Options::Language lang) const override;
   const AidlParcelable* AsParcelable() const override { return this; }
+  const AidlParameterizable<std::string>* AsParameterizable() const override { return this; }
+  const AidlNode& AsAidlNode() const override { return *this; }
   std::string GetPreprocessDeclarationName() const override { return "parcelable"; }
 
-  void Write(CodeWriter* writer) const override;
+  void Dump(CodeWriter* writer) const override;
 
  private:
   std::unique_ptr<AidlQualifiedName> name_;
@@ -716,7 +739,7 @@
   const AidlStructuredParcelable* AsStructuredParcelable() const override { return this; }
   std::string GetPreprocessDeclarationName() const override { return "structured_parcelable"; }
 
-  void Write(CodeWriter* writer) const override;
+  void Dump(CodeWriter* writer) const override;
 
   bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(Options::Language lang) const override;
@@ -741,6 +764,8 @@
   string ValueString(const AidlTypeSpecifier& backing_type,
                      const ConstantValueDecorator& decorator) const;
 
+  void SetValue(std::unique_ptr<AidlConstantValue> value) { value_ = std::move(value); }
+
  private:
   const std::string name_;
   unique_ptr<AidlConstantValue> value_;
@@ -761,10 +786,11 @@
   const std::vector<std::unique_ptr<AidlEnumerator>>& GetEnumerators() const {
     return enumerators_;
   }
+  bool Autofill();
   bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(Options::Language) const override { return true; }
   std::string GetPreprocessDeclarationName() const override { return "enum"; }
-  void Write(CodeWriter*) const override;
+  void Dump(CodeWriter* writer) const override;
 
   const AidlEnumDeclaration* AsEnumDeclaration() const override { return this; }
 
@@ -793,7 +819,7 @@
   const AidlInterface* AsInterface() const override { return this; }
   std::string GetPreprocessDeclarationName() const override { return "interface"; }
 
-  void Write(CodeWriter* writer) const override;
+  void Dump(CodeWriter* writer) const override;
 
   bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(Options::Language lang) const override;
@@ -835,14 +861,10 @@
   const std::string& FileName() const { return filename_; }
   void* Scanner() const { return scanner_; }
 
-  void AddImport(AidlImport* import);
+  void AddImport(std::unique_ptr<AidlImport>&& import);
   const std::vector<std::unique_ptr<AidlImport>>& GetImports() {
     return imports_;
   }
-  void ReleaseImports(std::vector<std::unique_ptr<AidlImport>>* ret) {
-    *ret = std::move(imports_);
-    imports_.clear();
-  }
 
   void SetPackage(unique_ptr<AidlQualifiedName> name) { package_ = std::move(name); }
   std::vector<std::string> Package() const;
diff --git a/aidl_language_l.ll b/aidl_language_l.ll
index 658b906..4813da6 100644
--- a/aidl_language_l.ll
+++ b/aidl_language_l.ll
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 
 #include "aidl_language.h"
-#include "aidl_language_y.h"
+#include "aidl_language_y-module.h"
 
 #define YY_USER_ACTION yylloc->columns(yyleng);
 %}
@@ -32,7 +32,7 @@
 %option bison-bridge
 %option bison-locations
 
-%x COPYING LONG_COMMENT
+%x LONG_COMMENT
 
 identifier  [_a-zA-Z][_a-zA-Z0-9]*
 whitespace  ([ \t\r]+)
@@ -47,12 +47,6 @@
   yylloc->step();
 %}
 
-
-\%\%\{                { extra_text += "/**"; BEGIN(COPYING); }
-<COPYING>\}\%\%       { extra_text += "**/"; yylloc->step(); BEGIN(INITIAL); }
-<COPYING>.*           { extra_text += yytext; }
-<COPYING>\n+          { extra_text += yytext; yylloc->lines(yyleng); }
-
 \/\*                  { extra_text += yytext; BEGIN(LONG_COMMENT); }
 <LONG_COMMENT>\*+\/   { extra_text += yytext; yylloc->step(); BEGIN(INITIAL);  }
 <LONG_COMMENT>\*+     { extra_text += yytext; }
@@ -100,9 +94,6 @@
 ">="                  { return(yy::parser::token::GEQ); }
 "=="                  { return(yy::parser::token::EQUALITY); }
 "!="                  { return(yy::parser::token::NEQ); }
-"?"                   { return('?'); }
-"@"                   { return('@'); }
-"#"                   { return('#'); }
 
     /* annotations */
 @{identifier}         { yylval->token = new AidlToken(yytext + 1, extra_text);
@@ -119,7 +110,8 @@
 out                   { return yy::parser::token::OUT; }
 inout                 { return yy::parser::token::INOUT; }
 cpp_header            { return yy::parser::token::CPP_HEADER; }
-const                 { return yy::parser::token::CONST; }
+const                 { yylval->token = new AidlToken("const", extra_text);
+                        return yy::parser::token::CONST; }
 true                  { return yy::parser::token::TRUE_LITERAL; }
 false                 { return yy::parser::token::FALSE_LITERAL; }
 
diff --git a/aidl_language_y-module.h b/aidl_language_y-module.h
new file mode 100644
index 0000000..34b1620
--- /dev/null
+++ b/aidl_language_y-module.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// generated code prints std::string* which is disallowed
+// by android-base/logging.h
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wuser-defined-warnings"
+#include <aidl_language_y.h>
+#pragma clang diagnostic pop
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index ba7de96..67a7b11 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -16,8 +16,9 @@
 
 %{
 #include "aidl_language.h"
-#include "aidl_language_y.h"
+#include "aidl_language_y-module.h"
 #include "logging.h"
+#include <android-base/parseint.h>
 #include <set>
 #include <map>
 #include <stdio.h>
@@ -26,17 +27,23 @@
 
 int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *);
 
+AidlLocation loc(const yy::parser::location_type& begin, const yy::parser::location_type& end) {
+  CHECK(begin.begin.filename == begin.end.filename);
+  CHECK(begin.end.filename == end.begin.filename);
+  CHECK(end.begin.filename == end.end.filename);
+  AidlLocation::Point begin_point {
+    .line = begin.begin.line,
+    .column = begin.begin.column,
+  };
+  AidlLocation::Point end_point {
+    .line = end.end.line,
+    .column = end.end.column,
+  };
+  return AidlLocation(*begin.begin.filename, begin_point, end_point);
+}
+
 AidlLocation loc(const yy::parser::location_type& l) {
-  CHECK(l.begin.filename == l.end.filename);
-  AidlLocation::Point begin {
-    .line = l.begin.line,
-    .column = l.begin.column,
-  };
-  AidlLocation::Point end {
-    .line = l.end.line,
-    .column = l.end.column,
-  };
-  return AidlLocation(*l.begin.filename, begin, end);
+  return loc(l, l);
 }
 
 #define lex_scanner ps->Scanner()
@@ -51,13 +58,13 @@
 %parse-param { Parser* ps }
 %lex-param { void *lex_scanner }
 
-%pure-parser
 %glr-parser
 %skeleton "glr.cc"
 
 %expect-rr 0
 
-%error-verbose
+%define parse.error verbose
+%locations
 
 %union {
     AidlToken* token;
@@ -86,6 +93,7 @@
     AidlParcelable* parcelable;
     AidlDefinedType* declaration;
     std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args;
+    std::vector<std::string>* type_params;
 }
 
 %destructor { } <character>
@@ -99,6 +107,7 @@
 %token<token> PARCELABLE "parcelable"
 %token<token> ONEWAY "oneway"
 %token<token> ENUM "enum"
+%token<token> CONST "const"
 
 %token<character> CHARVALUE "char literal"
 %token<token> FLOATVALUE "float literal"
@@ -106,7 +115,6 @@
 %token<token> INTVALUE "int literal"
 
 %token '(' ')' ',' '=' '[' ']' '.' '{' '}' ';'
-%token CONST "const"
 %token UNKNOWN "unrecognized character"
 %token CPP_HEADER "cpp_header"
 %token IMPORT "import"
@@ -158,10 +166,11 @@
 %type<annotation_list>annotation_list
 %type<type> type
 %type<type> unannotated_type
-%type<arg_list> arg_list
+%type<arg_list> arg_list arg_non_empty_list
 %type<arg> arg
 %type<direction> direction
 %type<type_args> type_args
+%type<type_params> type_params
 %type<qname> qualified_name
 %type<const_expr> const_expr
 %type<constant_value_list> constant_value_list
@@ -195,7 +204,7 @@
 
 import
  : IMPORT qualified_name ';'
-  { ps->AddImport(new AidlImport(loc(@2), $2->GetDotName()));
+  { ps->AddImport(std::make_unique<AidlImport>(loc(@2), $2->GetDotName()));
     delete $2;
   };
 
@@ -212,10 +221,14 @@
 
 decls
  : decl {
-    ps->AddDefinedType(unique_ptr<AidlDefinedType>($1));
+    if ($1 != nullptr) {
+      ps->AddDefinedType(unique_ptr<AidlDefinedType>($1));
+    }
   }
  | decls decl {
-    ps->AddDefinedType(unique_ptr<AidlDefinedType>($2));
+    if ($2 != nullptr) {
+      ps->AddDefinedType(unique_ptr<AidlDefinedType>($2));
+    }
   };
 
 decl
@@ -223,12 +236,12 @@
    {
     $$ = $2;
 
-    if ($1->size() > 0) {
+    if ($1->size() > 0 && $$ != nullptr) {
       // copy comments from annotation to decl
-      $2->SetComments($1->begin()->GetComments());
+      $$->SetComments($1->begin()->GetComments());
+      $$->Annotate(std::move(*$1));
     }
 
-    $$->Annotate(std::move(*$1));
     delete $1;
    }
  ;
@@ -242,11 +255,28 @@
   { $$ = $1; }
  ;
 
+type_params
+ : identifier {
+    $$ = new std::vector<std::string>();
+    $$->emplace_back($1->GetText());
+    delete $1;
+  }
+ | type_params ',' identifier {
+    $1->emplace_back($3->GetText());
+    $$ = $1;
+    delete $3;
+  };
+
+
 parcelable_decl
  : PARCELABLE qualified_name ';' {
     $$ = new AidlParcelable(loc(@2), $2, ps->Package(), $1->GetComments());
     delete $1;
   }
+ | PARCELABLE qualified_name '<' type_params '>' ';' {
+    $$ = new AidlParcelable(loc(@2), $2, ps->Package(), $1->GetComments(), "", $4);
+    delete $1;
+ }
  | PARCELABLE qualified_name CPP_HEADER C_STR ';' {
     $$ = new AidlParcelable(loc(@2), $2, ps->Package(), $1->GetComments(), $4->GetText());
     delete $1;
@@ -307,7 +337,6 @@
     ps->AddError();
     $$ = nullptr;
     delete $1;
-    delete $2;
     delete $4;
   };
 
@@ -430,10 +459,9 @@
   }
  | '(' error ')'
    {
-     std::cerr << "ERROR: invalid const expression within parenthesis: "
-               << $2->GetText() << " at " << @1 << ".\n";
-     // to avoid segfaults
+     std::cerr << "ERROR: invalid const expression within parenthesis at " << @1 << ".\n";
      ps->AddError();
+     // to avoid segfaults
      $$ = AidlConstantValue::Integral(loc(@1), "0");
    }
  ;
@@ -460,17 +488,22 @@
 
 constant_decl
  : CONST type identifier '=' const_expr ';' {
+    $2->SetComments($1->GetComments());
     $$ = new AidlConstantDeclaration(loc(@3), $2, $3->GetText(), $5);
+    delete $1;
     delete $3;
    }
  ;
 
-// TODO(b/139877950): Support autofilling enumerator values
 enumerator
  : identifier '=' const_expr {
     $$ = new AidlEnumerator(loc(@1), $1->GetText(), $3, $1->GetComments());
     delete $1;
    }
+ | identifier {
+    $$ = new AidlEnumerator(loc(@1), $1->GetText(), nullptr, $1->GetComments());
+    delete $1;
+   }
  ;
 
 enumerators
@@ -512,13 +545,23 @@
     delete $4;
   }
  | type identifier '(' arg_list ')' '=' INTVALUE ';' {
-    $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments(), std::stoi($7->GetText()));
+    int32_t serial = 0;
+    if (!android::base::ParseInt($7->GetText(), &serial)) {
+        AIDL_ERROR(loc(@7)) << "Could not parse int value: " << $7->GetText();
+        ps->AddError();
+    }
+    $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments(), serial);
     delete $2;
     delete $7;
   }
  | annotation_list ONEWAY type identifier '(' arg_list ')' '=' INTVALUE ';' {
     const std::string& comments = ($1->size() > 0) ? $1->begin()->GetComments() : $2->GetComments();
-    $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments, std::stoi($9->GetText()));
+    int32_t serial = 0;
+    if (!android::base::ParseInt($9->GetText(), &serial)) {
+        AIDL_ERROR(loc(@9)) << "Could not parse int value: " << $9->GetText();
+        ps->AddError();
+    }
+    $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments, serial);
     $3->Annotate(std::move(*$1));
     delete $1;
     delete $2;
@@ -526,18 +569,22 @@
     delete $9;
   };
 
-arg_list
- :
-  { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); }
- | arg {
+arg_non_empty_list
+ : arg {
     $$ = new std::vector<std::unique_ptr<AidlArgument>>();
     $$->push_back(std::unique_ptr<AidlArgument>($1));
   }
- | arg_list ',' arg {
+ | arg_non_empty_list ',' arg {
     $$ = $1;
     $$->push_back(std::unique_ptr<AidlArgument>($3));
   };
 
+arg_list
+ : /*empty*/
+   { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); }
+ | arg_non_empty_list { $$ = $1; }
+ ;
+
 arg
  : direction type identifier {
     $$ = new AidlArgument(loc(@3), $1, $2, $3->GetText());
@@ -633,18 +680,20 @@
  : ANNOTATION
   {
     $$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), nullptr);
-    if ($$ == nullptr) {
+    if ($$) {
+      $$->SetComments($1->GetComments());
+    } else {
       ps->AddError();
     }
-    $$->SetComments($1->GetComments());
     delete $1;
   };
  | ANNOTATION '(' parameter_list ')' {
-    $$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), $3);
-    if ($$ == nullptr) {
+    $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), $3);
+    if ($$) {
+      $$->SetComments($1->GetComments());
+    } else {
       ps->AddError();
     }
-    $$->SetComments($1->GetComments());
     delete $1;
     delete $3;
  }
diff --git a/aidl_to_cpp.cpp b/aidl_to_cpp.cpp
index f5fa3f8..9f2963e 100644
--- a/aidl_to_cpp.cpp
+++ b/aidl_to_cpp.cpp
@@ -219,6 +219,18 @@
   return GetCppName(type, typenames);
 }
 
+bool IsNonCopyableType(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+  if (type.IsArray() || type.IsGeneric()) {
+    return false;
+  }
+
+  const std::string cpp_name = GetCppName(type, typenames);
+  if (cpp_name == "::android::base::unique_fd") {
+    return true;
+  }
+  return false;
+}
+
 std::string ParcelReadMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
   return "read" + RawParcelMethod(type, typenames, true /* readMethod */);
 }
diff --git a/aidl_to_cpp.h b/aidl_to_cpp.h
index 3bf608c..5816b2b 100644
--- a/aidl_to_cpp.h
+++ b/aidl_to_cpp.h
@@ -39,6 +39,8 @@
 
 std::string CppNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
 
+bool IsNonCopyableType(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
+
 // Returns the name of the Parcel method suitable for reading data of the
 // given type.
 std::string ParcelReadMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 8978311..d1aeb2e 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -13,13 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include "aidl_to_cpp_common.h"
 
+#include <android-base/strings.h>
 #include <unordered_map>
 
-#include "aidl_to_cpp_common.h"
+#include "ast_cpp.h"
 #include "logging.h"
 #include "os.h"
 
+using ::android::base::Join;
+
 namespace android {
 namespace aidl {
 namespace cpp {
@@ -352,6 +356,26 @@
   return code;
 }
 
+std::string GenerateEnumValues(const AidlEnumDeclaration& enum_decl,
+                               const std::vector<std::string>& enclosing_namespaces_of_enum_decl) {
+  const auto fq_name =
+      Join(Append(enclosing_namespaces_of_enum_decl, enum_decl.GetSplitPackage()), "::") +
+      "::" + enum_decl.GetName();
+  const auto size = enum_decl.GetEnumerators().size();
+  std::ostringstream code;
+  code << "#pragma clang diagnostic push\n";
+  code << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
+  code << "template <>\n";
+  code << "constexpr inline std::array<" << fq_name << ", " << size << "> enum_values<" << fq_name
+       << "> = {\n";
+  for (const auto& enumerator : enum_decl.GetEnumerators()) {
+    code << "  " << fq_name << "::" << enumerator->GetName() << ",\n";
+  }
+  code << "};\n";
+  code << "#pragma clang diagnostic pop\n";
+  return code.str();
+}
+
 }  // namespace cpp
 }  // namespace aidl
 }  // namespace android
diff --git a/aidl_to_cpp_common.h b/aidl_to_cpp_common.h
index 381a8c9..a5c7896 100644
--- a/aidl_to_cpp_common.h
+++ b/aidl_to_cpp_common.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <string>
+#include <type_traits>
 
 #include "aidl_language.h"
 
@@ -54,6 +55,24 @@
 const string GenLogAfterExecute(const string className, const AidlInterface& interface,
                                 const AidlMethod& method, const string& statusVarName,
                                 const string& returnVarName, bool isServer, bool isNdk);
+
+template <typename T, typename = std::enable_if_t<std::is_copy_constructible_v<T>>>
+std::vector<T> Append(std::vector<T> as, const std::vector<T>& bs) {
+  as.insert(as.end(), bs.begin(), bs.end());
+  return as;
+}
+
+template <typename T>
+std::vector<T> Append(std::vector<T>&& as, std::vector<T>&& bs) {
+  std::vector<T> appended = std::move(as);
+  std::copy(std::move_iterator(bs.begin()), std::move_iterator(bs.end()),
+            std::back_inserter(appended));
+  return appended;
+}
+
+std::string GenerateEnumValues(const AidlEnumDeclaration& enum_decl,
+                               const std::vector<std::string>& enclosing_namespaces_of_enum_decl);
+
 }  // namespace cpp
 }  // namespace aidl
 }  // namespace android
diff --git a/aidl_to_java.cpp b/aidl_to_java.cpp
index ec7909d..8910365 100644
--- a/aidl_to_java.cpp
+++ b/aidl_to_java.cpp
@@ -48,7 +48,7 @@
 };
 
 const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
-                         bool instantiable = false) {
+                         bool instantiable = false, bool boxing = false) {
   CHECK(aidl.IsResolved()) << aidl.ToString();
 
   if (instantiable) {
@@ -87,6 +87,12 @@
       {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
   };
 
+  // map from primitive types to the corresponding boxing types
+  static map<string, string> boxing_types = {
+      {"void", "Void"},   {"boolean", "Boolean"}, {"byte", "Byte"},   {"char", "Character"},
+      {"int", "Integer"}, {"long", "Long"},       {"float", "Float"}, {"double", "Double"},
+  };
+
   // Enums in Java are represented by their backing type when
   // referenced in parcelables, methods, etc.
   if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
@@ -98,6 +104,11 @@
   }
 
   const string& aidl_name = aidl.GetName();
+  if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
+    // Every primitive type must have the corresponding boxing type
+    CHECK(boxing_types.find(aidl_name) != m.end());
+    return boxing_types[aidl_name];
+  }
   if (m.find(aidl_name) != m.end()) {
     CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
     return m[aidl_name];
@@ -108,13 +119,15 @@
 }
 
 namespace {
-string JavaSignatureOfInternal(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
-                               bool instantiable, bool omit_array) {
-  string ret = JavaNameOf(aidl, typenames, instantiable);
+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());
   if (aidl.IsGeneric()) {
     vector<string> arg_names;
     for (const auto& ta : aidl.GetTypeParameters()) {
-      arg_names.emplace_back(JavaSignatureOfInternal(*ta, typenames, false, false));
+      arg_names.emplace_back(
+          JavaSignatureOfInternal(*ta, typenames, false, false, true /* boxing */));
     }
     ret += "<" + Join(arg_names, ",") + ">";
   }
@@ -169,51 +182,6 @@
   }
 }
 
-// These are supported by AIDL syntax, but are unsupported by the AIDL compiler
-static bool IsMarshallingUnsupportedFor(const AidlTypeSpecifier& aidl,
-                                        const AidlTypenames& typenames) {
-  const string name = aidl.GetName();
-
-  // List<T> is support only for String, Binder, ParcelFileDescriptor and Parcelable.
-  if (name == "List" && aidl.IsGeneric()) {
-    const string& contained_type = aidl.GetTypeParameters().at(0)->GetName();
-    if (AidlTypenames::IsBuiltinTypename(contained_type)) {
-      if (contained_type != "String" && contained_type != "IBinder" &&
-          contained_type != "ParcelFileDescriptor") {
-        return true;
-      }
-    } else {
-      const AidlDefinedType* t = typenames.TryGetDefinedType(contained_type);
-      if (t != nullptr && t->AsInterface() != nullptr) {
-        return true;
-      }
-    }
-  }
-
-  // List[], Map[], CharSequence[] are not supported.
-  if (AidlTypenames::IsBuiltinTypename(name) && aidl.IsArray()) {
-    if (name == "List" || name == "Map" || name == "CharSequence") {
-      return true;
-    }
-  }
-
-  // T[] is not supported for interfaces
-  const AidlDefinedType* t = typenames.TryGetDefinedType(name);
-  if (aidl.IsArray() && t != nullptr && t->AsInterface() != nullptr) {
-    return true;
-  }
-
-  return false;
-}
-
-static bool EnsureCodegenIsSupported(const CodeGeneratorContext& c) {
-  if (IsMarshallingUnsupportedFor(c.type, c.typenames)) {
-    AIDL_ERROR(c.type) << c.type.ToString() << "' is not yet supported.";
-    return false;
-  }
-  return true;
-}
-
 static string GetFlagFor(const CodeGeneratorContext& c) {
   if (c.is_return_value) {
     return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
@@ -223,9 +191,6 @@
 }
 
 bool WriteToParcelFor(const CodeGeneratorContext& c) {
-  if (!EnsureCodegenIsSupported(c)) {
-    return false;
-  }
   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
       {"boolean",
        [](const CodeGeneratorContext& c) {
@@ -314,7 +279,37 @@
        }},
       {"Map",
        [](const CodeGeneratorContext& c) {
-         c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
+         if (c.type.IsGeneric()) {
+           c.writer << "if (" << c.var << " == null) {\n";
+           c.writer.Indent();
+           c.writer << c.parcel << ".writeInt(-1);\n";
+           c.writer.Dedent();
+           c.writer << "} else {\n";
+           c.writer.Indent();
+           c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
+           c.writer << c.var << ".forEach((k, v) -> {\n";
+           c.writer.Indent();
+           c.writer << c.parcel << ".writeString(k);\n";
+
+           CodeGeneratorContext value_context{
+               c.writer,
+               c.typenames,
+               *c.type.GetTypeParameters()[1].get(),
+               c.parcel,
+               "v",
+               c.is_return_value,
+               c.is_classloader_created,
+               c.filename,
+           };
+           WriteToParcelFor(value_context);
+           c.writer.Dedent();
+           c.writer << "});\n";
+
+           c.writer.Dedent();
+           c.writer << "}\n";
+         } else {
+           c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
+         }
        }},
       {"IBinder",
        [](const CodeGeneratorContext& c) {
@@ -420,9 +415,6 @@
 }
 
 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
-  if (!EnsureCodegenIsSupported(c)) {
-    return false;
-  }
   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
       {"boolean",
        [](const CodeGeneratorContext& c) {
@@ -514,8 +506,39 @@
        }},
       {"Map",
        [](const CodeGeneratorContext& c) {
-         const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
-         c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
+         if (c.type.IsGeneric()) {
+           c.writer << "{\n";
+           c.writer.Indent();
+           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";
+           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 << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
+           CodeGeneratorContext value_context{
+               c.writer,
+               c.typenames,
+               *c.type.GetTypeParameters()[1].get(),
+               c.parcel,
+               "v",
+               c.is_return_value,
+               c.is_classloader_created,
+               c.filename,
+           };
+           CreateFromParcelFor(value_context);
+           c.writer << c.var << ".put(k, v);\n";
+
+           c.writer.Dedent();
+           c.writer << "});\n";
+
+           c.writer.Dedent();
+           c.writer << "}\n";
+         } else {
+           const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
+           c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
+         }
        }},
       {"IBinder",
        [](const CodeGeneratorContext& c) {
@@ -606,9 +629,6 @@
 }
 
 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
-  if (!EnsureCodegenIsSupported(c)) {
-    return false;
-  }
   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
       {"boolean[]",
        [](const CodeGeneratorContext& c) {
@@ -668,8 +688,35 @@
        }},
       {"Map",
        [](const CodeGeneratorContext& c) {
-         const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
-         c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
+         if (c.type.IsGeneric()) {
+           c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
+           c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
+                    << ".readInt()).forEach(i -> {\n";
+           c.writer.Indent();
+           c.writer << "String k = " << c.parcel << ".readString();\n";
+           c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
+           CodeGeneratorContext value_context{
+               c.writer,
+               c.typenames,
+               *c.type.GetTypeParameters()[1].get(),
+               c.parcel,
+               "v",
+               c.is_return_value,
+               c.is_classloader_created,
+               c.filename,
+           };
+           CreateFromParcelFor(value_context);
+           c.writer << c.var << ".put(k, v);\n";
+
+           c.writer.Dedent();
+           c.writer << "});\n";
+
+           c.writer.Dedent();
+           c.writer << "}\n";
+         } else {
+           const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
+           c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
+         }
        }},
       {"IBinder[]",
        [](const CodeGeneratorContext& c) {
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index 5379564..663a17e 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -120,7 +120,6 @@
           TypeInfo::Aspect{
               .cpp_name = "std::shared_ptr<" + clazz + ">",
               .value_is_cheap = false,
-              // TODO(b/111445392): these should be non-null
               .read_func = StandardRead(clazz + "::readFromParcel"),
               .write_func = StandardWrite(clazz + "::writeToParcel"),
           },
@@ -136,21 +135,15 @@
 }
 
 TypeInfo ParcelableTypeInfo(const AidlParcelable& type) {
-  const std::string clazz = NdkFullClassName(type, cpp::ClassNames::BASE);
+  const std::string clazz = NdkFullClassName(type, cpp::ClassNames::RAW);
 
   return TypeInfo{
       .raw =
           TypeInfo::Aspect{
               .cpp_name = clazz,
               .value_is_cheap = false,
-              .read_func =
-                  [](const CodeGeneratorContext& c) {
-                    c.writer << "(" << c.var << ")->readFromParcel(" << c.parcel << ")";
-                  },
-              .write_func =
-                  [](const CodeGeneratorContext& c) {
-                    c.writer << "(" << c.var << ").writeToParcel(" << c.parcel << ")";
-                  },
+              .read_func = StandardRead("::ndk::AParcel_readParcelable"),
+              .write_func = StandardWrite("::ndk::AParcel_writeParcelable"),
           },
       .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
           .cpp_name = "std::vector<" + clazz + ">",
@@ -158,13 +151,18 @@
           .read_func = StandardRead("::ndk::AParcel_readVector"),
           .write_func = StandardWrite("::ndk::AParcel_writeVector"),
       }),
-      .nullable = nullptr,
+      .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
+          .cpp_name = "std::optional<" + clazz + ">",
+          .value_is_cheap = false,
+          .read_func = StandardRead("::ndk::AParcel_readNullableParcelable"),
+          .write_func = StandardWrite("::ndk::AParcel_writeNullableParcelable"),
+      }),
       .nullable_array = nullptr,
   };
 }
 
 TypeInfo EnumDeclarationTypeInfo(const AidlEnumDeclaration& enum_decl) {
-  const std::string clazz = NdkFullClassName(enum_decl, cpp::ClassNames::BASE);
+  const std::string clazz = NdkFullClassName(enum_decl, cpp::ClassNames::RAW);
 
   static map<std::string, std::string> kAParcelTypeNameMap = {
       {"byte", "Byte"},
@@ -271,8 +269,7 @@
              .write_func = StandardWrite("::ndk::AParcel_writeVector"),
          }),
      }},
-    // TODO(b/111445392) {"List", ""},
-    // TODO(b/111445392) {"Map", ""},
+    // TODO(b/136048684) {"Map", ""},
     {"IBinder",
      TypeInfo{
          .raw =
@@ -291,7 +288,6 @@
          }),
          .nullable_array = nullptr,
      }},
-    // TODO(b/111445392) {"FileDescriptor", ""},
     {"ParcelFileDescriptor",
      TypeInfo{
          .raw =
@@ -301,7 +297,12 @@
                  .read_func = StandardRead("::ndk::AParcel_readRequiredParcelFileDescriptor"),
                  .write_func = StandardRead("::ndk::AParcel_writeRequiredParcelFileDescriptor"),
              },
-         .array = nullptr,
+         .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
+             .cpp_name = "std::vector<::ndk::ScopedFileDescriptor>",
+             .value_is_cheap = false,
+             .read_func = StandardRead("::ndk::AParcel_readVector"),
+             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
+         }),
          .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
              .cpp_name = "::ndk::ScopedFileDescriptor",
              .value_is_cheap = false,
@@ -310,18 +311,35 @@
          }),
          .nullable_array = nullptr,
      }},
-    // TODO(b/111445392) {"CharSequence", ""},
 };
 
 static TypeInfo::Aspect GetTypeAspect(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
   CHECK(aidl.IsResolved()) << aidl.ToString();
-
-  const string aidl_name = aidl.GetName();
-
-  // TODO(b/112664205): this is okay for some types
-  AIDL_FATAL_IF(aidl.IsGeneric(), aidl) << aidl.ToString();
+  auto& aidl_name = aidl.GetName();
 
   TypeInfo info;
+
+  // TODO(b/136048684): For now, List<T> is converted to T[].(Both are using vector<T>)
+  if (aidl_name == "List") {
+    AIDL_FATAL_IF(!aidl.IsGeneric(), aidl) << "List must be generic type.";
+    AIDL_FATAL_IF(aidl.GetTypeParameters().size() != 1, aidl)
+        << "List can accept only one type parameter.";
+    auto& type_param = aidl.GetTypeParameters()[0];
+    // TODO(b/136048684) AIDL doesn't support nested type parameter yet.
+    AIDL_FATAL_IF(type_param->IsGeneric(), aidl) << "AIDL doesn't support nested type parameter";
+
+    AidlTypeSpecifier array_type =
+        AidlTypeSpecifier(AIDL_LOCATION_HERE, type_param->GetUnresolvedName(), true /* isArray */,
+                          nullptr /* type_params */, aidl.GetComments());
+    if (!(array_type.Resolve(types) && array_type.CheckValid(types))) {
+      AIDL_FATAL(aidl) << "The type parameter is wrong.";
+    }
+    return GetTypeAspect(types, array_type);
+  }
+
+  // All generic types should be handled above.
+  AIDL_FATAL_IF(aidl.IsGeneric(), aidl);
+
   if (AidlTypenames::IsBuiltinTypename(aidl_name)) {
     auto it = kNdkTypeInfoMap.find(aidl_name);
     CHECK(it != kNdkTypeInfoMap.end());
diff --git a/aidl_typenames.cpp b/aidl_typenames.cpp
index 6f9b590..ad89c1c 100644
--- a/aidl_typenames.cpp
+++ b/aidl_typenames.cpp
@@ -85,7 +85,13 @@
   static set<string> ignore_import = {"android.os.IInterface",   "android.os.IBinder",
                                       "android.os.Parcelable",   "android.os.Parcel",
                                       "android.content.Context", "java.lang.String"};
-  return ResolveTypename(import).second || ignore_import.find(import) != ignore_import.end();
+  // these known built-in types don't need to be imported
+  const bool in_ignore_import = ignore_import.find(import) != ignore_import.end();
+  // an already defined type doesn't need to be imported again unless it is from
+  // the preprocessed file
+  auto ret = TryGetDefinedTypeImpl(import);
+  const bool defined_type_not_from_preprocessed = ret.type != nullptr && !ret.from_preprocessed;
+  return in_ignore_import || defined_type_not_from_preprocessed;
 }
 
 bool AidlTypenames::AddDefinedType(unique_ptr<AidlDefinedType> type) {
@@ -122,32 +128,37 @@
 }
 
 const AidlDefinedType* AidlTypenames::TryGetDefinedType(const string& type_name) const {
+  return TryGetDefinedTypeImpl(type_name).type;
+}
+
+AidlTypenames::DefinedImplResult AidlTypenames::TryGetDefinedTypeImpl(
+    const string& type_name) const {
   // Do the exact match first.
   auto found_def = defined_types_.find(type_name);
   if (found_def != defined_types_.end()) {
-    return found_def->second.get();
+    return DefinedImplResult(found_def->second.get(), false);
   }
 
   auto found_prep = preprocessed_types_.find(type_name);
   if (found_prep != preprocessed_types_.end()) {
-    return found_prep->second.get();
+    return DefinedImplResult(found_prep->second.get(), true);
   }
 
   // Then match with the class name. Defined types has higher priority than
   // types from the preprocessed file.
   for (auto it = defined_types_.begin(); it != defined_types_.end(); it++) {
     if (it->second->GetName() == type_name) {
-      return it->second.get();
+      return DefinedImplResult(it->second.get(), false);
     }
   }
 
   for (auto it = preprocessed_types_.begin(); it != preprocessed_types_.end(); it++) {
     if (it->second->GetName() == type_name) {
-      return it->second.get();
+      return DefinedImplResult(it->second.get(), true);
     }
   }
 
-  return nullptr;
+  return DefinedImplResult(nullptr, false);
 }
 
 pair<string, bool> AidlTypenames::ResolveTypename(const string& type_name) const {
diff --git a/aidl_typenames.h b/aidl_typenames.h
index c2ea12e..78b996f 100644
--- a/aidl_typenames.h
+++ b/aidl_typenames.h
@@ -71,6 +71,13 @@
   void IterateTypes(const std::function<void(const AidlDefinedType&)>& body) const;
 
  private:
+  struct DefinedImplResult {
+    DefinedImplResult(const AidlDefinedType* type, const bool from_preprocessed)
+        : type(type), from_preprocessed(from_preprocessed) {}
+    const AidlDefinedType* type;
+    const bool from_preprocessed;
+  };
+  DefinedImplResult TryGetDefinedTypeImpl(const string& type_name) const;
   map<string, unique_ptr<AidlDefinedType>> defined_types_;
   map<string, unique_ptr<AidlDefinedType>> preprocessed_types_;
 };
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 38cac7e..58e391e 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -23,7 +23,7 @@
 #include <gtest/gtest.h>
 
 #include "aidl.h"
-#include "aidl_apicheck.h"
+#include "aidl_checkapi.h"
 #include "aidl_language.h"
 #include "aidl_to_cpp.h"
 #include "aidl_to_java.h"
@@ -82,7 +82,7 @@
   @android.annotation.SystemApi
   public int x = 5;
 
-  @dalvik.annotation.compat.UnsupportedAppUsage(expectedSignature = "dummy", implicitMember = "dummy", maxTargetSdk = 28, publicAlternatives = "dummy", trackingBug = 42L)
+  @android.compat.annotation.UnsupportedAppUsage(expectedSignature = "dummy", implicitMember = "dummy", maxTargetSdk = 28, publicAlternatives = "dummy", trackingBug = 42L, overrideSourcePosition="Rect.aidl:7:1:10:14")
   @android.annotation.SystemApi
   public int y;
 
@@ -362,15 +362,19 @@
 
 TEST_F(AidlTest, ParsesJavaOnlyStableParcelable) {
   Options java_options = Options::From("aidl -o out --structured a/Foo.aidl");
-  Options cpp_options =
+  Options cpp_options = Options::From("aidl --lang=cpp -o out -h out/include a/Foo.aidl");
+  Options cpp_structured_options =
       Options::From("aidl --lang=cpp --structured -o out -h out/include a/Foo.aidl");
   io_delegate_.SetFileContents(
-      "a/Foo.aidl", StringPrintf("package a; @JavaOnlyStableParcelable parcelable Foo;"));
+      "a/Foo.aidl",
+      StringPrintf("package a; @JavaOnlyStableParcelable parcelable Foo cpp_header \"Foo.h\" ;"));
 
   EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(cpp_options, io_delegate_));
   AddExpectedStderr(
-      "ERROR: a/Foo.aidl:1.48-52: @JavaOnlyStableParcelable supports only Java target.\n");
-  EXPECT_NE(0, ::android::aidl::compile_aidl(cpp_options, io_delegate_));
+      "ERROR: a/Foo.aidl:1.48-52: Cannot declared parcelable in a --structured interface. "
+      "Parcelable must be defined in AIDL directly.\n");
+  EXPECT_NE(0, ::android::aidl::compile_aidl(cpp_structured_options, io_delegate_));
 }
 
 TEST_F(AidlTest, AcceptsOneway) {
@@ -448,6 +452,28 @@
   EXPECT_EQ("one.IBar", ambiguous_type.GetName());
 }
 
+// Special case of PreferImportToPreprocessed. Imported type should be preferred
+// even when the preprocessed file already has the same type.
+TEST_F(AidlTest, B147918827) {
+  io_delegate_.SetFileContents("preprocessed", "interface another.IBar;\ninterface one.IBar;");
+  io_delegate_.SetFileContents("one/IBar.aidl",
+                               "package one; "
+                               "interface IBar {}");
+  preprocessed_files_.push_back("preprocessed");
+  import_paths_.emplace("");
+  auto parse_result = Parse("p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}",
+                            typenames_, Options::Language::JAVA);
+  EXPECT_NE(nullptr, parse_result);
+
+  // We expect to know about both kinds of IBar
+  EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").second);
+  EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").second);
+  // But if we request just "IBar" we should get our imported one.
+  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, "");
+  ambiguous_type.Resolve(typenames_);
+  EXPECT_EQ("one.IBar", ambiguous_type.GetName());
+}
+
 TEST_F(AidlTest, WritePreprocessedFile) {
   io_delegate_.SetFileContents("p/Outer.aidl",
                                "package p; parcelable Outer.Inner;");
@@ -755,6 +781,19 @@
   EXPECT_EQ(actual_dep_file_contents, kExpectedStructuredParcelableDepFileContents);
 }
 
+TEST_F(AidlTest, NoJavaOutputForParcelableDeclaration) {
+ vector<string> args = {
+    "aidl",
+    "--lang=java",
+    "-o place/for/output",
+    "p/Foo.aidl"};
+  Options options = Options::From(args);
+  io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo;");
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  string output_file_contents;
+  EXPECT_FALSE(io_delegate_.GetWrittenContents(options.OutputFile(), &output_file_contents));
+}
+
 /* not working until type_namespace.h is fixed
 TEST_F(AidlTest, AcceptsNestedContainerType) {
   string nested_in_iface = "package a; interface IFoo {\n"
@@ -769,45 +808,75 @@
 }
 */
 
+// TODO(b/136048684)
+TEST_F(AidlTest, PrimitiveList) {
+  string primitive_interface =
+      "package a; interface IFoo {\n"
+      "  List<int> foo(); }";
+  string primitive_parcelable =
+      "package a; parcelable IData {\n"
+      "  List<int> foo;}";
+  EXPECT_EQ(nullptr,
+            Parse("a/IFoo.aidl", primitive_interface, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, typenames_, Options::Language::CPP));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, typenames_, Options::Language::NDK));
+  EXPECT_EQ(nullptr,
+            Parse("a/IFoo.aidl", primitive_parcelable, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr,
+            Parse("a/IFoo.aidl", primitive_parcelable, typenames_, Options::Language::CPP));
+  EXPECT_EQ(nullptr,
+            Parse("a/IFoo.aidl", primitive_parcelable, typenames_, Options::Language::NDK));
+}
+
 TEST_F(AidlTest, ApiDump) {
   io_delegate_.SetFileContents(
       "foo/bar/IFoo.aidl",
       "package foo.bar;\n"
       "import foo.bar.Data;\n"
-      "// comment\n"
+      "// comment @hide\n"
       "interface IFoo {\n"
+      "    /* @hide */\n"
       "    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"
       "    Data getData();\n"
+      "    // @hide\n"
       "    const int A = 1;\n"
       "    const String STR = \"Hello\";\n"
       "}\n");
   io_delegate_.SetFileContents("foo/bar/Data.aidl",
                                "package foo.bar;\n"
                                "import foo.bar.IFoo;\n"
+                               "/* @hide*/\n"
                                "parcelable Data {\n"
+                               "   // @hide\n"
                                "   int x = 10;\n"
+                               "   // @hide\n"
                                "   int y;\n"
                                "   IFoo foo;\n"
                                "   List<IFoo> a;\n"
+                               "   /*@hide2*/\n"
                                "   List<foo.bar.IFoo> b;\n"
+                               "   // It should be @hide property\n"
                                "   @nullable String[] c;\n"
                                "}\n");
   io_delegate_.SetFileContents("api.aidl", "");
-  vector<string> args = {"aidl", "--dumpapi", "--out=dump", "foo/bar/IFoo.aidl",
-                         "foo/bar/Data.aidl"};
+  vector<string> args = {"aidl", "--dumpapi", "--out=dump", "--include=.",
+                         "foo/bar/IFoo.aidl", "foo/bar/Data.aidl"};
   Options options = Options::From(args);
   bool result = dump_api(options, io_delegate_);
   ASSERT_TRUE(result);
   string actual;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/IFoo.aidl", &actual));
   EXPECT_EQ(actual, R"(package foo.bar;
+/* @hide */
 interface IFoo {
+  /* @hide */
   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);
   foo.bar.Data getData();
+  /* @hide */
   const int A = 1;
   const String STR = "Hello";
 }
@@ -815,12 +884,16 @@
 
   EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Data.aidl", &actual));
   EXPECT_EQ(actual, R"(package foo.bar;
+/* @hide */
 parcelable Data {
+  /* @hide */
   int x = 10;
+  /* @hide */
   int y;
   foo.bar.IFoo foo;
   List<foo.bar.IFoo> a;
   List<foo.bar.IFoo> b;
+  /* @hide */
   @nullable String[] c;
 }
 )");
@@ -890,6 +963,70 @@
   EXPECT_NE(0, ::android::aidl::compile_aidl(options2, io_delegate_));
 }
 
+TEST_F(AidlTest, CheckTypeParameterInMapType) {
+  Options options = Options::From("aidl -I p p/IFoo.aidl");
+  io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar { String s; }");
+
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Map<String, Bar> foo();}");
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Map<Bar, Bar> foo();}");
+  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Map<String, String> foo();}");
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Map<String, ParcelFileDescriptor> foo();}");
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+}
+
+TEST_F(AidlTest, WrongGenericType) {
+  Options options = Options::From("aidl p/IFoo.aidl IFoo.java");
+  io_delegate_.SetFileContents(options.InputFiles().front(),
+                               "package p; interface IFoo {"
+                               "String<String> foo(); }");
+  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+}
+
+TEST_F(AidlTest, UserDefinedUnstructuredGenericParcelableType) {
+  Options optionsForParcelable = Options::From("aidl -I p p/Bar.aidl");
+  io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T, T>;");
+  EXPECT_NE(0, ::android::aidl::compile_aidl(optionsForParcelable, io_delegate_));
+
+  Options options = Options::From("aidl -I p p/IFoo.aidl");
+  io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar;");
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Bar<String, String> foo();}");
+  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T>;");
+  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T, V>;");
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Bar<String, ParcelFileDescriptor> foo();}");
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Bar<int, long> foo();}");
+
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p; interface IFoo {"
+                               "Bar<int[], long[]> foo();}");
+
+  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+}
+
 TEST_F(AidlTest, FailOnMultipleTypesInSingleFile) {
   std::vector<std::string> rawOptions{"aidl --lang=java -o out foo/bar/Foo.aidl",
                                       "aidl --lang=cpp -o out -h out/include foo/bar/Foo.aidl"};
@@ -922,7 +1059,7 @@
 
 TEST_F(AidlTest, MultipleInputFiles) {
   Options options = Options::From(
-      "aidl --lang=java -o out foo/bar/IFoo.aidl foo/bar/Data.aidl");
+      "aidl --lang=java -o out -I . foo/bar/IFoo.aidl foo/bar/Data.aidl");
 
   io_delegate_.SetFileContents(options.InputFiles().at(0),
       "package foo.bar;\n"
@@ -947,7 +1084,7 @@
 
 TEST_F(AidlTest, MultipleInputFilesCpp) {
   Options options = Options::From("aidl --lang=cpp -o out -h out/include "
-      "foo/bar/IFoo.aidl foo/bar/Data.aidl");
+      "-I . foo/bar/IFoo.aidl foo/bar/Data.aidl");
 
   io_delegate_.SetFileContents(options.InputFiles().at(0),
       "package foo.bar;\n"
@@ -1600,5 +1737,19 @@
   EXPECT_EQ(AidlError::PARSE_ERROR, reported_error);
 }
 
+TEST_F(AidlTest, FailOnOutOfBoundsAutofilledEnum) {
+  AidlError reported_error;
+  EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
+                           R"(package p;
+                              @Backing(type="byte")
+                              enum TestEnum {
+                                FOO = 127,
+                                BAR,
+                              }
+                             )",
+                           typenames_, Options::Language::CPP, &reported_error));
+  EXPECT_EQ(AidlError::BAD_TYPE, reported_error);
+}
+
 }  // namespace aidl
 }  // namespace android
diff --git a/build/Android.bp b/build/Android.bp
index 9cf4125..df9ea80 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -28,9 +28,17 @@
         "aidl_interface.go",
         "properties.go",
     ],
+    testSrcs: [
+        "aidl_test.go",
+    ],
     pluginFor: ["soong_build"],
 }
 
+aidl_interfaces_metadata {
+    name: "aidl_metadata_json",
+    visibility: ["//system/tools/aidl:__subpackages__"],
+}
+
 // These configurations are inherited by all aidl-gen modules
 
 cc_defaults {
@@ -79,8 +87,11 @@
         "tests_1/some_package/Thing.aidl",
         "tests_1/some_package/sub_package/*.aidl", // testing glob w/o filegroup
     ],
-    api_dir: "api/test-piece-1",
-    versions: ["1"],
+    versions: [
+        "1",
+        "2",
+        "3",
+    ],
 }
 
 aidl_interface {
@@ -93,7 +104,6 @@
     imports: [
         "test-piece-1",
     ],
-    api_dir: "api/test-piece-2",
     versions: ["1"],
 }
 
@@ -106,7 +116,6 @@
     imports: [
         "test-piece-2",
     ],
-    api_dir: "api/test-piece-3",
     versions: ["1"],
 }
 
@@ -119,7 +128,6 @@
     imports: [
         "test-piece-1",
     ],
-    api_dir: "api/test-piece-4",
     versions: ["1"],
 }
 
@@ -131,5 +139,8 @@
     imports: [
         "test-piece-2",
     ],
-    versions: ["1", "2"],
+    versions: [
+        "1",
+        "2",
+    ],
 }
diff --git a/build/OWNERS b/build/OWNERS
new file mode 100644
index 0000000..4cac0f5
--- /dev/null
+++ b/build/OWNERS
@@ -0,0 +1 @@
+include platform/build/soong:/OWNERS
diff --git a/build/api/test-piece-1/1/some_package/IFoo.aidl b/build/aidl_api/test-piece-1/1/some_package/IFoo.aidl
similarity index 100%
rename from build/api/test-piece-1/1/some_package/IFoo.aidl
rename to build/aidl_api/test-piece-1/1/some_package/IFoo.aidl
diff --git a/build/api/test-piece-1/1/some_package/Thing.aidl b/build/aidl_api/test-piece-1/1/some_package/Thing.aidl
similarity index 100%
rename from build/api/test-piece-1/1/some_package/Thing.aidl
rename to build/aidl_api/test-piece-1/1/some_package/Thing.aidl
diff --git a/build/api/test-piece-1/1/some_package/sub_package/IFoo.aidl b/build/aidl_api/test-piece-1/1/some_package/sub_package/IFoo.aidl
similarity index 100%
rename from build/api/test-piece-1/1/some_package/sub_package/IFoo.aidl
rename to build/aidl_api/test-piece-1/1/some_package/sub_package/IFoo.aidl
diff --git a/build/api/test-piece-1/1/some_package/sub_package/SubThing.aidl b/build/aidl_api/test-piece-1/1/some_package/sub_package/SubThing.aidl
similarity index 100%
rename from build/api/test-piece-1/1/some_package/sub_package/SubThing.aidl
rename to build/aidl_api/test-piece-1/1/some_package/sub_package/SubThing.aidl
diff --git a/build/aidl_api/test-piece-1/2/.hash b/build/aidl_api/test-piece-1/2/.hash
new file mode 100644
index 0000000..c28f432
--- /dev/null
+++ b/build/aidl_api/test-piece-1/2/.hash
@@ -0,0 +1 @@
+09c794283cac3ff37406d1e5593f8a4f4940562f  -
diff --git a/build/aidl_api/test-piece-1/2/some_package/IFoo.aidl b/build/aidl_api/test-piece-1/2/some_package/IFoo.aidl
new file mode 100644
index 0000000..e50ee27
--- /dev/null
+++ b/build/aidl_api/test-piece-1/2/some_package/IFoo.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package;
+interface IFoo {
+  /* @hide */
+  void CanYouDealWithThisThing(inout some_package.Thing parcel);
+  /* @hide */
+  void CanYouDealWithThisSubThing(inout some_package.sub_package.SubThing parcel);
+}
diff --git a/build/aidl_api/test-piece-1/2/some_package/Thing.aidl b/build/aidl_api/test-piece-1/2/some_package/Thing.aidl
new file mode 100644
index 0000000..3a30cc5
--- /dev/null
+++ b/build/aidl_api/test-piece-1/2/some_package/Thing.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package;
+parcelable Thing {
+  int a;
+  int b;
+}
diff --git a/build/aidl_api/test-piece-1/2/some_package/sub_package/IFoo.aidl b/build/aidl_api/test-piece-1/2/some_package/sub_package/IFoo.aidl
new file mode 100644
index 0000000..f45996d
--- /dev/null
+++ b/build/aidl_api/test-piece-1/2/some_package/sub_package/IFoo.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package.sub_package;
+interface IFoo {
+  void CanYouDealWithThisThing(inout some_package.Thing parcel);
+  void CanYouDealWithThisSubThing(inout some_package.sub_package.SubThing parcel);
+}
diff --git a/build/aidl_api/test-piece-1/2/some_package/sub_package/SubThing.aidl b/build/aidl_api/test-piece-1/2/some_package/sub_package/SubThing.aidl
new file mode 100644
index 0000000..adad68f
--- /dev/null
+++ b/build/aidl_api/test-piece-1/2/some_package/sub_package/SubThing.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package.sub_package;
+parcelable SubThing {
+  int a;
+  int b;
+}
diff --git a/build/aidl_api/test-piece-1/3/.hash b/build/aidl_api/test-piece-1/3/.hash
new file mode 100644
index 0000000..24d0448
--- /dev/null
+++ b/build/aidl_api/test-piece-1/3/.hash
@@ -0,0 +1 @@
+09b8aace9633aa35010b28a424d647dfcb4db5ea  -
diff --git a/build/aidl_api/test-piece-1/3/some_package/IFoo.aidl b/build/aidl_api/test-piece-1/3/some_package/IFoo.aidl
new file mode 100644
index 0000000..686805c
--- /dev/null
+++ b/build/aidl_api/test-piece-1/3/some_package/IFoo.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package;
+interface IFoo {
+  void CanYouDealWithThisThing(inout some_package.Thing parcel);
+  void CanYouDealWithThisSubThing(inout some_package.sub_package.SubThing parcel);
+}
diff --git a/build/aidl_api/test-piece-1/3/some_package/Thing.aidl b/build/aidl_api/test-piece-1/3/some_package/Thing.aidl
new file mode 100644
index 0000000..3a30cc5
--- /dev/null
+++ b/build/aidl_api/test-piece-1/3/some_package/Thing.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package;
+parcelable Thing {
+  int a;
+  int b;
+}
diff --git a/build/aidl_api/test-piece-1/3/some_package/sub_package/IFoo.aidl b/build/aidl_api/test-piece-1/3/some_package/sub_package/IFoo.aidl
new file mode 100644
index 0000000..f45996d
--- /dev/null
+++ b/build/aidl_api/test-piece-1/3/some_package/sub_package/IFoo.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package.sub_package;
+interface IFoo {
+  void CanYouDealWithThisThing(inout some_package.Thing parcel);
+  void CanYouDealWithThisSubThing(inout some_package.sub_package.SubThing parcel);
+}
diff --git a/build/aidl_api/test-piece-1/3/some_package/sub_package/SubThing.aidl b/build/aidl_api/test-piece-1/3/some_package/sub_package/SubThing.aidl
new file mode 100644
index 0000000..adad68f
--- /dev/null
+++ b/build/aidl_api/test-piece-1/3/some_package/sub_package/SubThing.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package some_package.sub_package;
+parcelable SubThing {
+  int a;
+  int b;
+}
diff --git a/build/api/test-piece-2/1/INoPackage.aidl b/build/aidl_api/test-piece-2/1/INoPackage.aidl
similarity index 100%
rename from build/api/test-piece-2/1/INoPackage.aidl
rename to build/aidl_api/test-piece-2/1/INoPackage.aidl
diff --git a/build/api/test-piece-2/1/some_package/IBar.aidl b/build/aidl_api/test-piece-2/1/some_package/IBar.aidl
similarity index 100%
rename from build/api/test-piece-2/1/some_package/IBar.aidl
rename to build/aidl_api/test-piece-2/1/some_package/IBar.aidl
diff --git a/build/api/test-piece-3/1/other_package/IBaz.aidl b/build/aidl_api/test-piece-3/1/other_package/IBaz.aidl
similarity index 100%
rename from build/api/test-piece-3/1/other_package/IBaz.aidl
rename to build/aidl_api/test-piece-3/1/other_package/IBaz.aidl
diff --git a/build/api/test-piece-4/1/another_package/IFaz.aidl b/build/aidl_api/test-piece-4/1/another_package/IFaz.aidl
similarity index 100%
rename from build/api/test-piece-4/1/another_package/IFaz.aidl
rename to build/aidl_api/test-piece-4/1/another_package/IFaz.aidl
diff --git a/build/api/1/test_package/IBaz.aidl b/build/aidl_api/test-root-package/1/test_package/IBaz.aidl
similarity index 100%
rename from build/api/1/test_package/IBaz.aidl
rename to build/aidl_api/test-root-package/1/test_package/IBaz.aidl
diff --git a/build/api/2/test_package/IBaz.aidl b/build/aidl_api/test-root-package/2/test_package/IBaz.aidl
similarity index 100%
rename from build/api/2/test_package/IBaz.aidl
rename to build/aidl_api/test-root-package/2/test_package/IBaz.aidl
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index 6cca62b..1a4f3ea 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -34,18 +34,20 @@
 )
 
 var (
-	aidlInterfaceSuffix = "_interface"
-	aidlApiSuffix       = "-api"
-	langCpp             = "cpp"
-	langJava            = "java"
-	langNdk             = "ndk"
-	langNdkPlatform     = "ndk_platform"
+	aidlInterfaceSuffix       = "_interface"
+	aidlMetadataSingletonName = "aidl_metadata_json"
+	aidlApiDir                = "aidl_api"
+	aidlApiSuffix             = "-api"
+	langCpp                   = "cpp"
+	langJava                  = "java"
+	langNdk                   = "ndk"
+	langNdkPlatform           = "ndk_platform"
 
 	pctx = android.NewPackageContext("android/aidl")
 
 	aidlDirPrepareRule = pctx.StaticRule("aidlDirPrepareRule", blueprint.RuleParams{
 		Command: `rm -rf "${outDir}" && mkdir -p "${outDir}" && ` +
-			`touch ${out}`,
+			`touch ${out} # ${in}`,
 		Description: "create ${out}",
 	}, "outDir")
 
@@ -71,10 +73,21 @@
 	aidlDumpApiRule = pctx.StaticRule("aidlDumpApiRule", blueprint.RuleParams{
 		Command: `rm -rf "${outDir}" && mkdir -p "${outDir}" && ` +
 			`${aidlCmd} --dumpapi --structured ${imports} --out ${outDir} ${in} && ` +
-			`(cd ${outDir} && find ./ -name "*.aidl" -exec sha1sum {} ';' && echo ${latestVersion}) | sha1sum > ${hashFile} `,
+			`(cd ${outDir} && find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo ${latestVersion}) | sha1sum > ${hashFile} `,
 		CommandDeps: []string{"${aidlCmd}"},
 	}, "imports", "outDir", "hashFile", "latestVersion")
 
+	aidlMetadataRule = pctx.StaticRule("aidlMetadataRule", blueprint.RuleParams{
+		Command: `rm -f ${out} && { ` +
+			`echo '{' && ` +
+			`echo "\"name\": \"${name}\"," && ` +
+			`echo "\"stability\": \"${stability}\"," && ` +
+			`echo "\"types\": [${types}]" && ` +
+			`echo '}' ` +
+			`;} >> ${out}`,
+		Description: "AIDL metadata: ${out}",
+	}, "name", "stability", "types")
+
 	aidlDumpMappingsRule = pctx.StaticRule("aidlDumpMappingsRule", blueprint.RuleParams{
 		Command: `rm -rf "${outDir}" && mkdir -p "${outDir}" && ` +
 			`${aidlCmd} --apimapping ${outDir}/intermediate.txt ${in} ${imports} && ` +
@@ -87,8 +100,8 @@
 			Command: `mkdir -p ${to} && rm -rf ${to}/* && ` +
 				`${bpmodifyCmd} -w -m ${name} -parameter versions -a ${version} ${bp} && ` +
 				`cp -rf ${apiDir}/. ${to} && ` +
-				`find ${to} -type f -exec bash -c ` +
-				`"cat ${apiPreamble} {} > {}.temp; mv {}.temp {}" \; && ` +
+				`find ${to} -type f -name "*.aidl" | xargs -n 1 bash -c ` +
+				`'cat ${apiPreamble} $$0 > $$0.temp && mv $$0.temp $$0' && ` +
 				`touch ${out}`,
 			CommandDeps: []string{"${bpmodifyCmd}"},
 		}, "to", "name", "version", "bp", "apiDir", "apiPreamble")
@@ -105,6 +118,21 @@
 			`(cat ${messageFile} && exit 1)`,
 		Description: "Check equality of ${new} and ${old}",
 	}, "old", "new", "messageFile", "oldHashFile", "newHashFile")
+
+	joinJsonObjectsToArrayRule = pctx.StaticRule("joinJsonObjectsToArrayRule", blueprint.RuleParams{
+		Rspfile:        "$out.rsp",
+		RspfileContent: "$files",
+		Command: "rm -rf ${out} && " +
+			// Start the output array with an opening bracket.
+			"echo '[' >> ${out} && " +
+			// Append each input file and a comma to the output.
+			"for file in $$(cat ${out}.rsp); do " +
+			"cat $$file >> ${out}; echo ',' >> ${out}; " +
+			"done && " +
+			// Remove the last comma, replacing it with the closing bracket.
+			"sed -i '$$d' ${out} && echo ']' >> ${out}",
+		Description: "Joining JSON objects into array ${out}",
+	}, "files")
 )
 
 func init() {
@@ -114,6 +142,7 @@
 	android.RegisterModuleType("aidl_interface", aidlInterfaceFactory)
 	android.RegisterModuleType("aidl_mapping", aidlMappingFactory)
 	android.RegisterMakeVarsProvider(pctx, allAidlInterfacesMakeVars)
+	android.RegisterModuleType("aidl_interfaces_metadata", aidlInterfacesMetadataSingletonFactory)
 }
 
 // wrap(p, a, s) = [p + v + s for v in a]
@@ -134,22 +163,25 @@
 	return ret
 }
 
-func checkAndUpdateSources(ctx android.ModuleContext, rawSrcs []string, inDir string) android.Paths {
+func getPaths(ctx android.ModuleContext, rawSrcs []string) (paths android.Paths, imports []string) {
 	srcs := android.PathsForModuleSrc(ctx, rawSrcs)
-	srcs = android.PathsWithModuleSrcSubDir(ctx, srcs, inDir)
 
 	if len(srcs) == 0 {
 		ctx.PropertyErrorf("srcs", "No sources provided.")
 	}
 
-	for _, source := range srcs {
-		if source.Ext() != ".aidl" {
-			ctx.PropertyErrorf("srcs", "Source must be a .aidl file: "+source.String())
+	for _, src := range srcs {
+		if src.Ext() != ".aidl" {
+			// Silently ignore non-aidl files as some filegroups have both java and aidl files together
 			continue
 		}
+		baseDir := strings.TrimSuffix(src.String(), src.Rel())
+		if baseDir != "" && !android.InList(baseDir, imports) {
+			imports = append(imports, baseDir)
+		}
 	}
 
-	return srcs
+	return srcs, imports
 }
 
 func isRelativePath(path string) bool {
@@ -189,7 +221,7 @@
 var _ genrule.SourceFileGenerator = (*aidlGenRule)(nil)
 
 func (g *aidlGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	srcs := checkAndUpdateSources(ctx, g.properties.Srcs, g.properties.AidlRoot)
+	srcs, imports := getPaths(ctx, g.properties.Srcs)
 
 	if ctx.Failed() {
 		return
@@ -199,6 +231,7 @@
 	g.implicitInputs = append(g.implicitInputs, genDirTimestamp)
 
 	var importPaths []string
+	importPaths = append(importPaths, imports...)
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		if importedAidl, ok := dep.(*aidlInterface); ok {
 			importPaths = append(importPaths, importedAidl.properties.Full_import_paths...)
@@ -222,26 +255,60 @@
 
 	// This is to clean genOutDir before generating any file
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
-		Rule:      aidlDirPrepareRule,
-		Implicits: srcs,
-		Output:    genDirTimestamp,
+		Rule:   aidlDirPrepareRule,
+		Inputs: srcs,
+		Output: genDirTimestamp,
 		Args: map[string]string{
 			"outDir": g.genOutDir.String(),
 		},
 	})
 }
 
-func (g *aidlGenRule) generateBuildActionsForSingleAidl(ctx android.ModuleContext, src android.Path) (android.WritablePath, android.Paths) {
-	var outFile android.WritablePath
-	if g.properties.Lang == langJava {
-		outFile = android.PathForModuleGen(ctx, pathtools.ReplaceExtension(src.Rel(), "java"))
-	} else {
-		outFile = android.PathForModuleGen(ctx, pathtools.ReplaceExtension(src.Rel(), "cpp"))
+// baseDir is the directory where the package name starts. e.g. For an AIDL fil
+// mymodule/aidl_src/com/android/IFoo.aidl, baseDir is mymodule/aidl_src given that the package name is
+// com.android. The build system however don't know the package name without actually reading the AIDL file.
+// Therefore, we rely on the user to correctly set the base directory via following two methods:
+// 1) via the 'path' property of filegroup or
+// 2) via `local_include_dir' of the aidl_interface module.
+func getBaseDir(ctx android.ModuleContext, src android.Path, aidlRoot android.Path) string {
+	// By default, we try to get 1) by reading Rel() of the input path.
+	baseDir := strings.TrimSuffix(src.String(), src.Rel())
+	// However, if 2) is set and it's more specific (i.e. deeper) than 1), we use 2).
+	if strings.HasPrefix(aidlRoot.String(), baseDir) {
+		baseDir = aidlRoot.String()
 	}
+	return baseDir
+}
+
+func (g *aidlGenRule) generateBuildActionsForSingleAidl(ctx android.ModuleContext, src android.Path) (android.WritablePath, android.Paths) {
+	baseDir := getBaseDir(ctx, src, android.PathForModuleSrc(ctx, g.properties.AidlRoot))
+
+	var ext string
+	if g.properties.Lang == langJava {
+		ext = "java"
+	} else {
+		ext = "cpp"
+	}
+	relPath, _ := filepath.Rel(baseDir, src.String())
+	outFile := android.PathForModuleGen(ctx, pathtools.ReplaceExtension(relPath, ext))
+	implicits := g.implicitInputs
 
 	var optionalFlags []string
 	if g.properties.Version != "" {
 		optionalFlags = append(optionalFlags, "--version "+g.properties.Version)
+
+		hash := "notfrozen"
+		if !strings.HasPrefix(baseDir, ctx.Config().BuildDir()) {
+			hashFile := android.ExistentPathForSource(ctx, baseDir, ".hash")
+			if hashFile.Valid() {
+				hash = "$$(read -r <" + hashFile.Path().String() + " hash extra; printf '%s' \"$$hash\")"
+				implicits = append(implicits, hashFile.Path())
+			}
+		}
+		optionalFlags = append(optionalFlags, "--hash "+hash)
+	}
+	if g.properties.Stability != nil {
+		optionalFlags = append(optionalFlags, "--stability", *g.properties.Stability)
 	}
 
 	var headers android.WritablePaths
@@ -249,7 +316,7 @@
 		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 			Rule:      aidlJavaRule,
 			Input:     src,
-			Implicits: g.implicitInputs,
+			Implicits: implicits,
 			Output:    outFile,
 			Args: map[string]string{
 				"imports":       g.importFlags,
@@ -258,8 +325,8 @@
 			},
 		})
 	} else {
-		typeName := strings.TrimSuffix(filepath.Base(src.Rel()), ".aidl")
-		packagePath := filepath.Dir(src.Rel())
+		typeName := strings.TrimSuffix(filepath.Base(relPath), ".aidl")
+		packagePath := filepath.Dir(relPath)
 		baseName := typeName
 		// TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if
 		//   an interface name has a leading I. Those same heuristics have been
@@ -285,10 +352,6 @@
 			optionalFlags = append(optionalFlags, "--log")
 		}
 
-		if g.properties.Stability != nil {
-			optionalFlags = append(optionalFlags, "--stability", *g.properties.Stability)
-		}
-
 		aidlLang := g.properties.Lang
 		if aidlLang == langNdkPlatform {
 			aidlLang = "ndk"
@@ -297,7 +360,7 @@
 		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 			Rule:            aidlCppRule,
 			Input:           src,
-			Implicits:       g.implicitInputs,
+			Implicits:       implicits,
 			Output:          outFile,
 			ImplicitOutputs: headers,
 			Args: map[string]string{
@@ -344,10 +407,9 @@
 type aidlApiProperties struct {
 	BaseName string
 	Srcs     []string `android:"path"`
+	AidlRoot string   // base directory for the input aidl file
 	Imports  []string
-	Api_dir  *string
 	Versions []string
-	AidlRoot string // base directory for the input aidl file
 }
 
 type aidlApi struct {
@@ -363,11 +425,7 @@
 }
 
 func (m *aidlApi) apiDir() string {
-	if m.properties.Api_dir != nil {
-		return *(m.properties.Api_dir)
-	} else {
-		return "api"
-	}
+	return filepath.Join(aidlApiDir, m.properties.BaseName)
 }
 
 // Version of the interface at ToT if it is frozen
@@ -388,13 +446,14 @@
 }
 
 func (m *aidlApi) createApiDumpFromSource(ctx android.ModuleContext) (apiDir android.WritablePath, apiFiles android.WritablePaths, hashFile android.WritablePath) {
-	srcs := checkAndUpdateSources(ctx, m.properties.Srcs, m.properties.AidlRoot)
+	srcs, imports := getPaths(ctx, m.properties.Srcs)
 
 	if ctx.Failed() {
 		return
 	}
 
 	var importPaths []string
+	importPaths = append(importPaths, imports...)
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		if importedAidl, ok := dep.(*aidlInterface); ok {
 			importPaths = append(importPaths, importedAidl.properties.Full_import_paths...)
@@ -402,21 +461,24 @@
 	})
 
 	apiDir = android.PathForModuleOut(ctx, "dump")
+	aidlRoot := android.PathForModuleSrc(ctx, m.properties.AidlRoot)
 	for _, src := range srcs {
-		apiFiles = append(apiFiles, android.PathForModuleOut(ctx, "dump", src.Rel()))
+		baseDir := getBaseDir(ctx, src, aidlRoot)
+		relPath, _ := filepath.Rel(baseDir, src.String())
+		outFile := android.PathForModuleOut(ctx, "dump", relPath)
+		apiFiles = append(apiFiles, outFile)
 	}
 	hashFile = android.PathForModuleOut(ctx, "dump", ".hash")
 	latestVersion := "latest-version"
 	if len(m.properties.Versions) >= 1 {
 		latestVersion = m.properties.Versions[len(m.properties.Versions)-1]
 	}
-	imports := strings.Join(wrap("-I", importPaths, ""), " ")
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:    aidlDumpApiRule,
 		Outputs: append(apiFiles, hashFile),
 		Inputs:  srcs,
 		Args: map[string]string{
-			"imports":       imports,
+			"imports":       strings.Join(wrap("-I", importPaths, ""), " "),
 			"outDir":        apiDir.String(),
 			"hashFile":      hashFile.String(),
 			"latestVersion": latestVersion,
@@ -571,8 +633,24 @@
 	return m
 }
 
+type CommonBackendProperties struct {
+	// Whether to generate code in the corresponding backend.
+	// Default: true
+	Enabled *bool
+}
+
+type CommonNativeBackendProperties struct {
+	// Whether to generate additional code for gathering information
+	// about the transactions.
+	// Default: false
+	Gen_log *bool
+
+	// VNDK properties for correspdoning backend.
+	cc.VndkProperties
+}
+
 type aidlInterfaceProperties struct {
-	// Vndk properties for interface library only.
+	// Vndk properties for C++/NDK libraries only (preferred to use backend-specific settings)
 	cc.VndkProperties
 
 	// Whether the library can be installed on the vendor image.
@@ -585,7 +663,6 @@
 	// TODO(b/128940869): remove it if aidl_interface can depend on framework.aidl
 	Include_dirs []string
 	// Relative path for includes. By default assumes AIDL path is relative to current directory.
-	// TODO(b/111117220): automatically compute by letting AIDL parse multiple files simultaneously
 	Local_include_dir string
 
 	// List of .aidl files which compose this interface.
@@ -598,9 +675,6 @@
 	// Used by gen dependency to fill out aidl include path
 	Full_import_paths []string `blueprint:"mutated"`
 
-	// Directory where API dumps are. Default is "api".
-	Api_dir *string
-
 	// Stability promise. Currently only supports "vintf".
 	// If this is unset, this corresponds to an interface with stability within
 	// this compilation context (so an interface loaded here can only be used
@@ -614,31 +688,27 @@
 	Versions []string
 
 	Backend struct {
+		// Backend of the compiler generating code for Java clients.
 		Java struct {
-			// Whether to generate Java code using Java binder APIs
-			// Default: true
-			Enabled *bool
+			CommonBackendProperties
 			// Set to the version of the sdk to compile against
 			// Default: system_current
 			Sdk_version *string
+			// Whether to compile against platform APIs instead of
+			// an SDK.
+			Platform_apis *bool
 		}
+		// Backend of the compiler generating code for C++ clients using
+		// libbinder (unstable C++ interface)
 		Cpp struct {
-			// Whether to generate C++ code using C++ binder APIs
-			// Default: true
-			Enabled *bool
-			// Whether to generate additional code for gathering information
-			// about the transactions
-			// Default: false
-			Gen_log *bool
+			CommonBackendProperties
+			CommonNativeBackendProperties
 		}
+		// Backend of the compiler generating code for C++ clients using
+		// libbinder_ndk (stable C interface to system's libbinder)
 		Ndk struct {
-			// Whether to generate C++ code using NDK binder APIs
-			// Default: true
-			Enabled *bool
-			// Whether to generate additional code for gathering information
-			// about the transactions
-			// Default: false
-			Gen_log *bool
+			CommonBackendProperties
+			CommonNativeBackendProperties
 		}
 	}
 }
@@ -647,6 +717,8 @@
 	android.ModuleBase
 
 	properties aidlInterfaceProperties
+
+	computedTypes []string
 }
 
 func (i *aidlInterface) shouldGenerateJavaBackend() bool {
@@ -664,9 +736,16 @@
 	return i.properties.Backend.Ndk.Enabled == nil || *i.properties.Backend.Ndk.Enabled
 }
 
-func (i *aidlInterface) checkImports(mctx android.LoadHookContext) {
+func (i *aidlInterface) gatherInterface(mctx android.LoadHookContext) {
+	aidlInterfaces := aidlInterfaces(mctx.Config())
+	aidlInterfaceMutex.Lock()
+	defer aidlInterfaceMutex.Unlock()
+	*aidlInterfaces = append(*aidlInterfaces, i)
+}
+
+func (i *aidlInterface) checkImports(mctx android.BaseModuleContext) {
 	for _, anImport := range i.properties.Imports {
-		other := lookupInterface(anImport)
+		other := lookupInterface(anImport, mctx.Config())
 
 		if other == nil {
 			mctx.PropertyErrorf("imports", "Import does not exist: "+anImport)
@@ -694,31 +773,18 @@
 		return
 	}
 
-	if i.shouldGenerateJavaBackend() {
-		mctx.PropertyErrorf("stability", "Java backend does not yet support stability.")
-	}
-
 	// TODO(b/136027762): should we allow more types of stability (e.g. for APEX) or
 	// should we switch this flag to be something like "vintf { enabled: true }"
 	if *i.properties.Stability != "vintf" {
 		mctx.PropertyErrorf("stability", "must be empty or \"vintf\"")
 	}
-
-	// TODO(b/136027762): need some global way to understand AOSP interfaces. Also,
-	// need the implementation for vendor extensions to be merged. For now, restrict
-	// where this can be defined
-	if !filepath.HasPrefix(mctx.ModuleDir(), "hardware/interfaces/") {
-		mctx.PropertyErrorf("stability", "can only be set in hardware/interfaces")
-	}
 }
 
-func (i *aidlInterface) currentVersion(ctx android.BaseModuleContext) string {
-	if len(i.properties.Versions) == 0 {
+func (i *aidlInterface) currentVersion(ctx android.LoadHookContext) string {
+	if !i.hasVersion() {
 		return ""
 	} else {
-		latestVersion := i.properties.Versions[len(i.properties.Versions)-1]
-
-		i, err := strconv.Atoi(latestVersion)
+		i, err := strconv.Atoi(i.latestVersion())
 		if err != nil {
 			ctx.PropertyErrorf("versions", "must be integers")
 			return ""
@@ -728,30 +794,73 @@
 	}
 }
 
-func (i *aidlInterface) isCurrentVersion(ctx android.BaseModuleContext, version string) bool {
+func (i *aidlInterface) latestVersion() string {
+	if !i.hasVersion() {
+		return "0"
+	}
+	return i.properties.Versions[len(i.properties.Versions)-1]
+}
+func (i *aidlInterface) isLatestVersion(version string) bool {
+	if !i.hasVersion() {
+		return true
+	}
+	return version == i.latestVersion()
+}
+func (i *aidlInterface) hasVersion() bool {
+	return len(i.properties.Versions) > 0
+}
+
+func (i *aidlInterface) isCurrentVersion(ctx android.LoadHookContext, version string) bool {
 	return version == i.currentVersion(ctx)
 }
 
-func (i *aidlInterface) versionedName(ctx android.BaseModuleContext, version string) string {
+// This function returns module name with version. Assume that there is foo of which latest version is 2
+// Version -> Module name
+// "1"->foo-V1
+// "2"->foo-V2
+// "3"(unfrozen)->foo-unstable
+// ""-> foo
+func (i *aidlInterface) versionedName(ctx android.LoadHookContext, version string) string {
 	name := i.ModuleBase.Name()
-	if !i.isCurrentVersion(ctx, version) {
-		name = name + "-V" + version
+	if version == "" {
+		return name
 	}
-	return name
+	if i.isCurrentVersion(ctx, version) {
+		return name + "-unstable"
+	}
+	return name + "-V" + version
 }
 
-func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, base string) {
+// This function returns C++ artifact's name. Mostly, it returns same as versionedName(),
+// But, it returns different value only if it is the case below.
+// Assume that there is foo of which latest version is 2
+// foo-unstable -> foo-V3
+// foo -> foo-V2 (latest frozen version)
+// Assume that there is bar of which version hasn't been defined yet.
+// bar -> bar-V1
+func (i *aidlInterface) cppOutputName(version string) string {
+	name := i.ModuleBase.Name()
+	// Even if the module doesn't have version, it returns with version(-V1)
+	if !i.hasVersion() {
+		// latestVersion() always returns "0"
+		i, err := strconv.Atoi(i.latestVersion())
+		if err != nil {
+			panic(err)
+		}
+		return name + "-V" + strconv.Itoa(i+1)
+	}
+	if version == "" {
+		version = i.latestVersion()
+	}
+	return name + "-V" + version
+}
+
+func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, aidlRoot string) {
 	if i.isCurrentVersion(mctx, version) {
 		return i.properties.Srcs, i.properties.Local_include_dir
 	} else {
-		var apiDir string
-		if i.properties.Api_dir != nil {
-			apiDir = *(i.properties.Api_dir)
-		} else {
-			apiDir = "api"
-		}
-		base = filepath.Join(apiDir, version)
-		full_paths, err := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), base, "**/*.aidl"), nil)
+		aidlRoot = filepath.Join(aidlApiDir, i.ModuleBase.Name(), version)
+		full_paths, err := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), aidlRoot, "**/*.aidl"), nil)
 		if err != nil {
 			panic(err)
 		}
@@ -759,7 +868,7 @@
 			// Here, we need path local to the module
 			srcs = append(srcs, strings.TrimPrefix(path, mctx.ModuleDir()+"/"))
 		}
-		return srcs, base
+		return srcs, aidlRoot
 	}
 }
 
@@ -773,7 +882,7 @@
 
 	i.properties.Full_import_paths = importPaths
 
-	i.checkImports(mctx)
+	i.gatherInterface(mctx)
 	i.checkStability(mctx)
 
 	if mctx.Failed() {
@@ -784,31 +893,40 @@
 
 	currentVersion := i.currentVersion(mctx)
 
+	versionsForCpp := make([]string, len(i.properties.Versions))
+	copy(versionsForCpp, i.properties.Versions)
+	if i.hasVersion() {
+		// In C++ library, AIDL doesn't create the module of which name is with latest version,
+		// instead of it, there is a module without version.
+		versionsForCpp[len(i.properties.Versions)-1] = ""
+	}
 	if i.shouldGenerateCppBackend() {
 		libs = append(libs, addCppLibrary(mctx, i, currentVersion, langCpp))
-		for _, version := range i.properties.Versions {
+		for _, version := range versionsForCpp {
 			addCppLibrary(mctx, i, version, langCpp)
 		}
 	}
 
 	if i.shouldGenerateNdkBackend() {
-		// TODO(b/119771576): inherit properties and export 'is vendor' computation from cc.go
 		if !proptools.Bool(i.properties.Vendor_available) {
 			libs = append(libs, addCppLibrary(mctx, i, currentVersion, langNdk))
-			for _, version := range i.properties.Versions {
+			for _, version := range versionsForCpp {
 				addCppLibrary(mctx, i, version, langNdk)
 			}
 		}
 		// TODO(b/121157555): combine with '-ndk' variant
 		libs = append(libs, addCppLibrary(mctx, i, currentVersion, langNdkPlatform))
-		for _, version := range i.properties.Versions {
+		for _, version := range versionsForCpp {
 			addCppLibrary(mctx, i, version, langNdkPlatform)
 		}
 	}
-
+	versionsForJava := i.properties.Versions
+	if i.hasVersion() {
+		versionsForJava = append(i.properties.Versions, "")
+	}
 	if i.shouldGenerateJavaBackend() {
 		libs = append(libs, addJavaLibrary(mctx, i, currentVersion))
-		for _, version := range i.properties.Versions {
+		for _, version := range versionsForJava {
 			addJavaLibrary(mctx, i, version)
 		}
 	}
@@ -825,8 +943,11 @@
 func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
 	cppSourceGen := i.versionedName(mctx, version) + "-" + lang + "-source"
 	cppModuleGen := i.versionedName(mctx, version) + "-" + lang
-
-	srcs, base := i.srcsForVersion(mctx, version)
+	cppOutputGen := i.cppOutputName(version) + "-" + lang
+	if i.hasVersion() && version == "" {
+		version = i.latestVersion()
+	}
+	srcs, aidlRoot := i.srcsForVersion(mctx, version)
 	if len(srcs) == 0 {
 		// This can happen when the version is about to be frozen; the version
 		// directory is created but API dump hasn't been copied there.
@@ -834,18 +955,20 @@
 		return ""
 	}
 
-	genLog := false
+	var commonProperties *CommonNativeBackendProperties
 	if lang == langCpp {
-		genLog = proptools.Bool(i.properties.Backend.Cpp.Gen_log)
+		commonProperties = &i.properties.Backend.Cpp.CommonNativeBackendProperties
 	} else if lang == langNdk || lang == langNdkPlatform {
-		genLog = proptools.Bool(i.properties.Backend.Ndk.Gen_log)
+		commonProperties = &i.properties.Backend.Ndk.CommonNativeBackendProperties
 	}
 
+	genLog := proptools.Bool(commonProperties.Gen_log)
+
 	mctx.CreateModule(aidlGenFactory, &nameProperties{
 		Name: proptools.StringPtr(cppSourceGen),
 	}, &aidlGenProperties{
 		Srcs:      srcs,
-		AidlRoot:  base,
+		AidlRoot:  aidlRoot,
 		Imports:   concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
 		Stability: i.properties.Stability,
 		Lang:      lang,
@@ -904,7 +1027,8 @@
 		Stl:                       stl,
 		Cpp_std:                   cpp_std,
 		Cflags:                    append(addCflags, "-Wextra", "-Wall", "-Werror"),
-	}, &i.properties.VndkProperties)
+		Stem:                      proptools.StringPtr(cppOutputGen),
+	}, &i.properties.VndkProperties, &commonProperties.VndkProperties)
 
 	return cppModuleGen
 }
@@ -912,8 +1036,10 @@
 func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
 	javaSourceGen := i.versionedName(mctx, version) + "-java-source"
 	javaModuleGen := i.versionedName(mctx, version) + "-java"
-
-	srcs, base := i.srcsForVersion(mctx, version)
+	if i.hasVersion() && version == "" {
+		version = i.latestVersion()
+	}
+	srcs, aidlRoot := i.srcsForVersion(mctx, version)
 	if len(srcs) == 0 {
 		// This can happen when the version is about to be frozen; the version
 		// directory is created but API dump hasn't been copied there.
@@ -921,13 +1047,17 @@
 		return ""
 	}
 
-	sdkVersion := proptools.StringDefault(i.properties.Backend.Java.Sdk_version, "system_current")
+	sdkVersion := i.properties.Backend.Java.Sdk_version
+	if !proptools.Bool(i.properties.Backend.Java.Platform_apis) && sdkVersion == nil {
+		// platform apis requires no default
+		sdkVersion = proptools.StringPtr("system_current")
+	}
 
 	mctx.CreateModule(aidlGenFactory, &nameProperties{
 		Name: proptools.StringPtr(javaSourceGen),
 	}, &aidlGenProperties{
 		Srcs:      srcs,
-		AidlRoot:  base,
+		AidlRoot:  aidlRoot,
 		Imports:   concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
 		Stability: i.properties.Stability,
 		Lang:      langJava,
@@ -936,12 +1066,13 @@
 	})
 
 	mctx.CreateModule(java.LibraryFactory, &javaProperties{
-		Name:        proptools.StringPtr(javaModuleGen),
-		Installable: proptools.BoolPtr(true),
-		Defaults:    []string{"aidl-java-module-defaults"},
-		Sdk_version: proptools.StringPtr(sdkVersion),
-		Static_libs: wrap("", i.properties.Imports, "-java"),
-		Srcs:        []string{":" + javaSourceGen},
+		Name:          proptools.StringPtr(javaModuleGen),
+		Installable:   proptools.BoolPtr(true),
+		Defaults:      []string{"aidl-java-module-defaults"},
+		Sdk_version:   sdkVersion,
+		Platform_apis: i.properties.Backend.Java.Platform_apis,
+		Static_libs:   wrap("", i.properties.Imports, "-java"),
+		Srcs:          []string{":" + javaSourceGen},
 	})
 
 	return javaModuleGen
@@ -949,14 +1080,14 @@
 
 func addApiModule(mctx android.LoadHookContext, i *aidlInterface) string {
 	apiModule := i.ModuleBase.Name() + aidlApiSuffix
+	srcs, aidlRoot := i.srcsForVersion(mctx, i.currentVersion(mctx))
 	mctx.CreateModule(aidlApiFactory, &nameProperties{
 		Name: proptools.StringPtr(apiModule),
 	}, &aidlApiProperties{
 		BaseName: i.ModuleBase.Name(),
-		Srcs:     i.properties.Srcs,
+		Srcs:     srcs,
+		AidlRoot: aidlRoot,
 		Imports:  concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
-		Api_dir:  i.properties.Api_dir,
-		AidlRoot: i.properties.Local_include_dir,
 		Versions: i.properties.Versions,
 	})
 	return apiModule
@@ -966,28 +1097,41 @@
 	return i.ModuleBase.Name() + aidlInterfaceSuffix
 }
 func (i *aidlInterface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	aidlRoot := android.PathForModuleSrc(ctx, i.properties.Local_include_dir)
+	for _, src := range android.PathsForModuleSrc(ctx, i.properties.Srcs) {
+		baseDir := getBaseDir(ctx, src, aidlRoot)
+		relPath, _ := filepath.Rel(baseDir, src.String())
+		computedType := strings.TrimSuffix(strings.ReplaceAll(relPath, "/", "."), ".aidl")
+		i.computedTypes = append(i.computedTypes, computedType)
+	}
 }
 func (i *aidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) {
+	i.checkImports(ctx)
+
+	ctx.AddReverseDependency(ctx.Module(), nil, aidlMetadataSingletonName)
 }
 
-var aidlInterfaceMutex sync.Mutex
-var aidlInterfaces []*aidlInterface
+var (
+	aidlInterfacesKey  = android.NewOnceKey("aidlInterfaces")
+	aidlInterfaceMutex sync.Mutex
+)
+
+func aidlInterfaces(config android.Config) *[]*aidlInterface {
+	return config.Once(aidlInterfacesKey, func() interface{} {
+		return &[]*aidlInterface{}
+	}).(*[]*aidlInterface)
+}
 
 func aidlInterfaceFactory() android.Module {
 	i := &aidlInterface{}
 	i.AddProperties(&i.properties)
 	android.InitAndroidModule(i)
 	android.AddLoadHook(i, func(ctx android.LoadHookContext) { aidlInterfaceHook(ctx, i) })
-
-	aidlInterfaceMutex.Lock()
-	aidlInterfaces = append(aidlInterfaces, i)
-	aidlInterfaceMutex.Unlock()
-
 	return i
 }
 
-func lookupInterface(name string) *aidlInterface {
-	for _, i := range aidlInterfaces {
+func lookupInterface(name string, config android.Config) *aidlInterface {
+	for _, i := range *aidlInterfaces(config) {
 		if i.ModuleBase.Name() == name {
 			return i
 		}
@@ -995,6 +1139,66 @@
 	return nil
 }
 
+func aidlInterfacesMetadataSingletonFactory() android.Module {
+	i := &aidlInterfacesMetadataSingleton{}
+	android.InitAndroidModule(i)
+	return i
+}
+
+type aidlInterfacesMetadataSingleton struct {
+	android.ModuleBase
+
+	metadataPath android.OutputPath
+}
+
+var _ android.OutputFileProducer = (*aidlInterfacesMetadataSingleton)(nil)
+
+func (m *aidlInterfacesMetadataSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if m.Name() != aidlMetadataSingletonName {
+		ctx.PropertyErrorf("name", "must be %s", aidlMetadataSingletonName)
+		return
+	}
+
+	var metadataOutputs android.Paths
+	ctx.VisitDirectDeps(func(m android.Module) {
+		if !m.ExportedToMake() {
+			return
+		}
+		if t, ok := m.(*aidlInterface); ok {
+			metadataPath := android.PathForModuleOut(ctx, "metadata_"+m.Name())
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   aidlMetadataRule,
+				Output: metadataPath,
+				Args: map[string]string{
+					"name":      t.Name(),
+					"stability": proptools.StringDefault(t.properties.Stability, ""),
+					"types":     strings.Join(wrap(`\"`, t.computedTypes, `\"`), ", "),
+				},
+			})
+			metadataOutputs = append(metadataOutputs, metadataPath)
+		}
+	})
+
+	m.metadataPath = android.PathForModuleOut(ctx, "aidl_metadata.json").OutputPath
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   joinJsonObjectsToArrayRule,
+		Inputs: metadataOutputs,
+		Output: m.metadataPath,
+		Args: map[string]string{
+			"files": strings.Join(metadataOutputs.Strings(), " "),
+		},
+	})
+}
+
+func (m *aidlInterfacesMetadataSingleton) OutputFiles(tag string) (android.Paths, error) {
+	if tag != "" {
+		return nil, fmt.Errorf("unsupported tag %q", tag)
+	}
+
+	return android.Paths{m.metadataPath}, nil
+}
+
 type aidlMappingProperties struct {
 	// Source file of this prebuilt.
 	Srcs   []string `android:"path"`
@@ -1011,21 +1215,8 @@
 }
 
 func (s *aidlMapping) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	var aidlSrcs android.Paths
-	var importDirs []string
+	srcs, imports := getPaths(ctx, s.properties.Srcs)
 
-	srcs := android.PathsForModuleSrc(ctx, s.properties.Srcs)
-	for _, file := range srcs {
-		if file.Ext() == ".aidl" {
-			aidlSrcs = append(aidlSrcs, file)
-			baseDir := strings.TrimSuffix(file.String(), file.Rel())
-			if baseDir != "" && !android.InList(baseDir, importDirs) {
-				importDirs = append(importDirs, baseDir)
-			}
-		}
-	}
-
-	imports := android.JoinWithPrefix(importDirs, " -I")
 	s.outputFilePath = android.PathForModuleOut(ctx, s.properties.Output)
 	outDir := android.PathForModuleGen(ctx)
 	ctx.Build(pctx, android.BuildParams{
@@ -1033,7 +1224,7 @@
 		Inputs: srcs,
 		Output: s.outputFilePath,
 		Args: map[string]string{
-			"imports": imports,
+			"imports": android.JoinWithPrefix(imports, " -I"),
 			"outDir":  outDir.String(),
 		},
 	})
diff --git a/build/aidl_test.go b/build/aidl_test.go
new file mode 100644
index 0000000..7a9ff92
--- /dev/null
+++ b/build/aidl_test.go
@@ -0,0 +1,483 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package aidl
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+
+	"github.com/google/blueprint"
+
+	"android/soong/android"
+	"android/soong/cc"
+	"android/soong/java"
+)
+
+var buildDir string
+
+func setUp() {
+	var err error
+	buildDir, err = ioutil.TempDir("", "soong_aidl_test")
+	if err != nil {
+		panic(err)
+	}
+}
+
+func tearDown() {
+	os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+	run := func() int {
+		setUp()
+		defer tearDown()
+
+		return m.Run()
+	}
+
+	os.Exit(run())
+}
+
+type testCustomizer func(fs map[string][]byte, config android.Config)
+
+func withFiles(files map[string][]byte) testCustomizer {
+	return func(fs map[string][]byte, config android.Config) {
+		for k, v := range files {
+			fs[k] = v
+		}
+	}
+}
+
+func _testAidl(t *testing.T, bp string, customizers ...testCustomizer) (*android.TestContext, android.Config) {
+	t.Helper()
+
+	bp = bp + java.GatherRequiredDepsForTest()
+	bp = bp + cc.GatherRequiredDepsForTest(android.Android)
+	bp = bp + `
+		java_defaults {
+			name: "aidl-java-module-defaults",
+		}
+		cc_defaults {
+			name: "aidl-cpp-module-defaults",
+		}
+		cc_library {
+			name: "libbinder",
+		}
+		cc_library {
+			name: "libutils",
+		}
+		cc_library {
+			name: "libbinder_ndk",
+		}
+		ndk_library {
+			name: "libbinder_ndk",
+			symbol_file: "libbinder_ndk.map.txt",
+			first_version: "29",
+		}
+		ndk_prebuilt_shared_stl {
+			name: "ndk_libc++_shared",
+		}
+		ndk_prebuilt_static_stl {
+			name: "ndk_libunwind",
+		}
+		ndk_prebuilt_object {
+			name: "ndk_crtbegin_dynamic.27",
+			sdk_version: "27",
+		}
+		ndk_prebuilt_object {
+			name: "ndk_crtbegin_so.27",
+			sdk_version: "27",
+		}
+		ndk_prebuilt_object {
+			name: "ndk_crtbegin_static.27",
+			sdk_version: "27",
+		}
+		ndk_prebuilt_object {
+			name: "ndk_crtend_android.27",
+			sdk_version: "27",
+		}
+		ndk_prebuilt_object {
+			name: "ndk_crtend_so.27",
+			sdk_version: "27",
+		}
+		ndk_library {
+			name: "libc",
+			symbol_file: "libc.map.txt",
+			first_version: "9",
+		}
+		ndk_library {
+			name: "libm",
+			symbol_file: "libm.map.txt",
+			first_version: "9",
+		}
+		ndk_library {
+			name: "libdl",
+			symbol_file: "libdl.map.txt",
+			first_version: "9",
+		}
+		aidl_interfaces_metadata {
+			name: "aidl_metadata_json",
+		}
+	`
+	fs := map[string][]byte{
+		"a.java":              nil,
+		"AndroidManifest.xml": nil,
+		"build/make/target/product/security/testkey": nil,
+		"framework/aidl/a.aidl":                      nil,
+		"IFoo.aidl":                                  nil,
+		"libbinder_ndk.map.txt":                      nil,
+		"libc.map.txt":                               nil,
+		"libdl.map.txt":                              nil,
+		"libm.map.txt":                               nil,
+		"prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/ndk_crtbegin_so.so":       nil,
+		"prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/ndk_crtbegin_dynamic.o": nil,
+		"prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/ndk_crtbegin_so.so":     nil,
+		"prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/ndk_crtbegin_static.a":  nil,
+		"prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/ndk_crtend.so":          nil,
+		"prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/ndk_libc++_shared.so":          nil,
+		"system/tools/aidl/build/api_preamble.txt":                                             nil,
+		"system/tools/aidl/build/message_check_compatibility.txt":                              nil,
+	}
+
+	for _, c := range customizers {
+		// The fs now needs to be populated before creating the config, call customizers twice
+		// for now, once to get any fs changes, and later after the config was created to
+		// set product variables or targets.
+		tempConfig := android.TestArchConfig(buildDir, nil, bp, fs)
+		c(fs, tempConfig)
+	}
+
+	config := android.TestArchConfig(buildDir, nil, bp, fs)
+
+	for _, c := range customizers {
+		// The fs now needs to be populated before creating the config, call customizers twice
+		// for now, earlier to get any fs changes, and now after the config was created to
+		// set product variables or targets.
+		tempFS := map[string][]byte{}
+		c(tempFS, config)
+	}
+
+	ctx := android.NewTestArchContext()
+	cc.RegisterRequiredBuildComponentsForTest(ctx)
+	ctx.RegisterModuleType("aidl_interface", aidlInterfaceFactory)
+	ctx.RegisterModuleType("aidl_interfaces_metadata", aidlInterfacesMetadataSingletonFactory)
+	ctx.RegisterModuleType("android_app", java.AndroidAppFactory)
+	ctx.RegisterModuleType("java_defaults", func() android.Module {
+		return java.DefaultsFactory()
+	})
+	ctx.RegisterModuleType("java_library_static", java.LibraryStaticFactory)
+	ctx.RegisterModuleType("java_library", java.LibraryFactory)
+	ctx.RegisterModuleType("java_system_modules", java.SystemModulesFactory)
+	ctx.RegisterModuleType("ndk_library", cc.NdkLibraryFactory)
+	ctx.RegisterModuleType("ndk_prebuilt_object", cc.NdkPrebuiltObjectFactory)
+	ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory)
+	ctx.RegisterModuleType("ndk_prebuilt_static_stl", cc.NdkPrebuiltStaticStlFactory)
+
+	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
+
+	ctx.Register(config)
+
+	return ctx, config
+}
+
+func testAidl(t *testing.T, bp string, customizers ...testCustomizer) (*android.TestContext, android.Config) {
+	t.Helper()
+	ctx, config := _testAidl(t, bp, customizers...)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+	return ctx, config
+}
+
+func testAidlError(t *testing.T, pattern, bp string, customizers ...testCustomizer) {
+	t.Helper()
+	ctx, config := _testAidl(t, bp, customizers...)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+	_, errs = ctx.PrepareBuildActions(config)
+	if len(errs) > 0 {
+		android.FailIfNoMatchingErrors(t, pattern, errs)
+		return
+	}
+	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+}
+
+// asserts that there are expected module regardless of variants
+func assertModulesExists(t *testing.T, ctx *android.TestContext, names ...string) {
+	missing := []string{}
+	for _, name := range names {
+		variants := ctx.ModuleVariantsForTests(name)
+		if len(variants) == 0 {
+			missing = append(missing, name)
+		}
+	}
+	if len(missing) > 0 {
+		// find all the modules that do exist
+		allModuleNames := make(map[string]bool)
+		ctx.VisitAllModules(func(m blueprint.Module) {
+			allModuleNames[ctx.ModuleName(m)] = true
+		})
+		t.Errorf("expected modules(%v) not found. all modules: %v", missing, android.SortedStringKeys(allModuleNames))
+	}
+}
+
+func TestCreatesModulesWithNoVersions(t *testing.T) {
+	ctx, _ := testAidl(t, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+		}
+	`)
+
+	assertModulesExists(t, ctx, "foo-java", "foo-cpp", "foo-ndk", "foo-ndk_platform")
+}
+
+func TestCreatesModulesWithFrozenVersions(t *testing.T) {
+	// Each version should be under aidl_api/<name>/<ver>
+	testAidlError(t, `aidl_api/foo/1`, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			versions: [
+				"1",
+			],
+		}
+	`)
+
+	ctx, _ := testAidl(t, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			versions: [
+				"1",
+			],
+		}
+	`, withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+	}))
+
+	// For alias for the latest frozen version (=1)
+	assertModulesExists(t, ctx, "foo-java", "foo-cpp", "foo-ndk", "foo-ndk_platform")
+
+	// For frozen version "1"
+	// Note that it is not yet implemented to generate native modules for latest frozen version
+	assertModulesExists(t, ctx, "foo-V1-java")
+
+	// For ToT (current)
+	assertModulesExists(t, ctx, "foo-unstable-java", "foo-unstable-cpp", "foo-unstable-ndk", "foo-unstable-ndk_platform")
+}
+
+const (
+	androidVariant = "android_common"
+	nativeVariant  = "android_arm_armv7-a-neon_shared"
+)
+
+func TestNativeOutputIsAlwaysVersioned(t *testing.T) {
+	var ctx *android.TestContext
+	assertOutput := func(moduleName, variant, outputFilename string) {
+		t.Helper()
+		producer, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
+		if !ok {
+			t.Errorf("%s(%s): should be OutputFileProducer.", moduleName, variant)
+		}
+		paths, err := producer.OutputFiles("")
+		if err != nil {
+			t.Errorf("%s(%s): failed to get OutputFiles: %v", moduleName, variant, err)
+		}
+		if len(paths) != 1 || paths[0].Base() != outputFilename {
+			t.Errorf("%s(%s): expected output %q, but got %v", moduleName, variant, outputFilename, paths)
+		}
+	}
+
+	// No versions
+	ctx, _ = testAidl(t, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+		}
+	`)
+
+	assertOutput("foo-java", androidVariant, "foo-java.jar")
+	assertOutput("foo-cpp", nativeVariant, "foo-V1-cpp.so")
+
+	// With versions: "1", "2"
+	ctx, _ = testAidl(t, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			versions: [
+				"1", "2",
+			],
+		}
+	`, withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/2/foo.2.aidl": nil,
+	}))
+
+	// alias for the latest frozen version (=2)
+	assertOutput("foo-java", androidVariant, "foo-java.jar")
+	assertOutput("foo-cpp", nativeVariant, "foo-V2-cpp.so")
+
+	// frozen "1"
+	assertOutput("foo-V1-java", androidVariant, "foo-V1-java.jar")
+	assertOutput("foo-V1-cpp", nativeVariant, "foo-V1-cpp.so")
+
+	// tot
+	assertOutput("foo-unstable-java", androidVariant, "foo-unstable-java.jar")
+	assertOutput("foo-unstable-cpp", nativeVariant, "foo-V3-cpp.so")
+
+	// skip ndk/ndk_platform since they follow the same rule with cpp
+}
+
+func TestGenLogForNativeBackendRequiresJson(t *testing.T) {
+	testAidlError(t, `"foo-cpp" depends on .*"libjsoncpp"`, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			backend: {
+				cpp: {
+					gen_log: true,
+				},
+			},
+		}
+	`)
+	testAidl(t, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			backend: {
+				cpp: {
+					gen_log: true,
+				},
+			},
+		}
+		cc_library {
+			name: "libjsoncpp",
+		}
+	`)
+}
+
+func TestImports(t *testing.T) {
+	testAidlError(t, `Import does not exist:`, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			imports: [
+				"bar",
+			]
+		}
+	`)
+
+	testAidlError(t, `backend.java.enabled: Java backend not enabled in the imported AIDL interface "bar"`, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			imports: [
+				"bar",
+			]
+		}
+		aidl_interface {
+			name: "bar",
+			srcs: [
+				"IBar.aidl",
+			],
+			backend: {
+				java: {
+					enabled: false,
+				},
+			},
+		}
+	`, withFiles(map[string][]byte{
+		"IBar.aidl": nil,
+	}))
+
+	testAidlError(t, `backend.cpp.enabled: C\+\+ backend not enabled in the imported AIDL interface "bar"`, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			imports: [
+				"bar",
+			]
+		}
+		aidl_interface {
+			name: "bar",
+			srcs: [
+				"IBar.aidl",
+			],
+			backend: {
+				cpp: {
+					enabled: false,
+				},
+			},
+		}
+	`, withFiles(map[string][]byte{
+		"IBar.aidl": nil,
+	}))
+
+	ctx, _ := testAidl(t, `
+		aidl_interface {
+			name: "foo",
+			srcs: [
+				"IFoo.aidl",
+			],
+			imports: [
+				"bar",
+			]
+		}
+		aidl_interface {
+			name: "bar",
+			srcs: [
+				"IBar.aidl",
+			],
+		}
+	`, withFiles(map[string][]byte{
+		"IBar.aidl": nil,
+	}))
+
+	ldRule := ctx.ModuleForTests("foo-cpp", nativeVariant).Rule("ld")
+	libFlags := ldRule.Args["libFlags"]
+	libBar := filepath.Join("bar-cpp", nativeVariant, "bar-V1-cpp.so")
+	if !strings.Contains(libFlags, libBar) {
+		t.Errorf("%q is not found in %q", libBar, libFlags)
+	}
+}
diff --git a/build/go.mod b/build/go.mod
new file mode 100644
index 0000000..3ef7a49
--- /dev/null
+++ b/build/go.mod
@@ -0,0 +1,14 @@
+module android/soong/aidl
+
+require (
+	android/soong v0.0.0
+	github.com/google/blueprint v0.0.0
+)
+
+replace android/soong v0.0.0 => ../../../../build/soong
+
+replace github.com/golang/protobuf v0.0.0 => ../../../../external/golang-protobuf
+
+replace github.com/google/blueprint v0.0.0 => ../../../../build/blueprint
+
+go 1.13
diff --git a/build/properties.go b/build/properties.go
index b59db61..62c6a1a 100644
--- a/build/properties.go
+++ b/build/properties.go
@@ -43,16 +43,18 @@
 	Stl                       *string
 	Cpp_std                   *string
 	Cflags                    []string
+	Stem                      *string
 }
 
 type javaProperties struct {
-	Name        *string
-	Owner       *string
-	Defaults    []string
-	Installable *bool
-	Sdk_version *string
-	Srcs        []string
-	Static_libs []string
+	Name          *string
+	Owner         *string
+	Defaults      []string
+	Installable   *bool
+	Sdk_version   *string
+	Platform_apis *bool
+	Srcs          []string
+	Static_libs   []string
 }
 
 type phonyProperties struct {
diff --git a/build/test_package/IBaz.aidl b/build/test_package/IBaz.aidl
index 6a63292..357dc50 100644
--- a/build/test_package/IBaz.aidl
+++ b/build/test_package/IBaz.aidl
@@ -26,9 +26,7 @@
     void writePFD(in ParcelFileDescriptor fd);
     void readWritePFD(inout ParcelFileDescriptor fd);
 
-    // TODO(b/112664205) uncomment these when we have the support for array type in
-    // the ndk backend
-    //ParcelFileDescriptor[] readPFDArray();
-    //void writePFDArray(in ParcelFileDescriptor[] fds);
-    //void readWritePFDArray(inout ParcelFileDescriptor[] fds);
+    ParcelFileDescriptor[] readPFDArray();
+    void writePFDArray(in ParcelFileDescriptor[] fds);
+    void readWritePFDArray(inout ParcelFileDescriptor[] fds);
 }
diff --git a/code_writer.cpp b/code_writer.cpp
index 6d54d40..096c895 100644
--- a/code_writer.cpp
+++ b/code_writer.cpp
@@ -89,12 +89,12 @@
 }
 
 CodeWriter& CodeWriter::operator<<(const char* s) {
-  Write(s);
+  Write("%s", s);
   return *this;
 }
 
 CodeWriter& CodeWriter::operator<<(const std::string& str) {
-  Write(str.c_str());
+  Write("%s", str.c_str());
   return *this;
 }
 
diff --git a/code_writer.h b/code_writer.h
index 77e9385..d890d52 100644
--- a/code_writer.h
+++ b/code_writer.h
@@ -41,7 +41,7 @@
   static CodeWriterPtr ForString(std::string* buf);
   // Write a formatted string to this writer in the usual printf sense.
   // Returns false on error.
-  virtual bool Write(const char* format, ...);
+  virtual bool Write(const char* format, ...) __attribute__((format(printf, 2, 3)));
   void Indent();
   void Dedent();
   virtual bool Close();
diff --git a/generate_aidl_mappings.cpp b/generate_aidl_mappings.cpp
index 1624ee6..994d6a3 100644
--- a/generate_aidl_mappings.cpp
+++ b/generate_aidl_mappings.cpp
@@ -24,7 +24,7 @@
 namespace mappings {
 
 std::string dump_location(const AidlNode& method) {
-  return method.PrintLocation();
+  return method.PrintLine();
 }
 
 SignatureMap generate_mappings(const AidlDefinedType* defined_type,
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 70b9acb..b016b68 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -99,6 +99,11 @@
   vector<string> method_arguments;
   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
     string literal;
+    // b/144943748: CppNameOf FileDescriptor is unique_fd. Don't pass it by
+    // const reference but by value to make it easier for the user to keep
+    // it beyond the scope of the call. unique_fd is a thin wrapper for an
+    // int (fd) so passing by value is not expensive.
+    const bool nonCopyable = IsNonCopyableType(a->GetType(), typenames);
     if (for_declaration) {
       // Method declarations need typenames, pointers to out params, and variable
       // names that match the .aidl specification.
@@ -114,7 +119,7 @@
 
         // We pass in parameters that are not primitives by const reference.
         // Arrays of primitives are not primitives.
-        if (!(isPrimitive || isEnum) || a->GetType().IsArray()) {
+        if (!(isPrimitive || isEnum || nonCopyable) || a->GetType().IsArray()) {
           literal = "const " + literal + "&";
         }
       }
@@ -122,8 +127,14 @@
         literal += " " + a->GetName();
       }
     } else {
-      if (a->IsOut()) { literal = "&"; }
-      literal += BuildVarName(*a);
+      std::string varName = BuildVarName(*a);
+      if (a->IsOut()) {
+        literal = "&" + varName;
+      } else if (nonCopyable) {
+        literal = "std::move(" + varName + ")";
+      } else {
+        literal = varName;
+      }
     }
     method_arguments.push_back(literal);
   }
@@ -131,8 +142,10 @@
   if (method.GetType().GetName() != "void") {
     string literal;
     if (for_declaration) {
-      literal = StringPrintf("%s* %s", CppNameOf(method.GetType(), typenames).c_str(),
-                             type_name_only ? "" : kReturnVarName);
+      literal = CppNameOf(method.GetType(), typenames) + "*";
+      if (!type_name_only) {
+        literal += " " + string(kReturnVarName);
+      }
     } else {
       literal = string{"&"} + kReturnVarName;
     }
@@ -173,6 +186,19 @@
     }
     return unique_ptr<Declaration>(new LiteralDecl(code.str()));
   }
+  if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+    std::ostringstream code;
+    if (for_interface) {
+      code << "virtual ";
+    }
+    code << "std::string " << kGetInterfaceHash << "()";
+    if (for_interface) {
+      code << " = 0;\n";
+    } else {
+      code << " override;\n";
+    }
+    return unique_ptr<Declaration>(new LiteralDecl(code.str()));
+  }
   return nullptr;
 }
 
@@ -306,7 +332,11 @@
   // default implementation, if provided.
   vector<string> arg_names;
   for (const auto& a : method.GetArguments()) {
-    arg_names.emplace_back(a->GetName());
+    if (IsNonCopyableType(a->GetType(), typenames)) {
+      arg_names.emplace_back(StringPrintf("std::move(%s)", a->GetName().c_str()));
+    } else {
+      arg_names.emplace_back(a->GetName());
+    }
   }
   if (method.GetType().GetName() != "void") {
     arg_names.emplace_back(kReturnVarName);
@@ -416,6 +446,30 @@
          << "}\n";
     return unique_ptr<Declaration>(new LiteralDecl(code.str()));
   }
+  if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+    const string iface = ClassName(interface, ClassNames::INTERFACE);
+    const string proxy = ClassName(interface, ClassNames::CLIENT);
+    std::ostringstream code;
+    code << "std::string " << proxy << "::" << kGetInterfaceHash << "() {\n"
+         << "  std::lock_guard<std::mutex> lockGuard(cached_hash_mutex_);\n"
+         << "  if (cached_hash_ == \"-1\") {\n"
+         << "    ::android::Parcel data;\n"
+         << "    ::android::Parcel reply;\n"
+         << "    data.writeInterfaceToken(getInterfaceDescriptor());\n"
+         << "    ::android::status_t err = remote()->transact(" << GetTransactionIdFor(method)
+         << ", data, &reply);\n"
+         << "    if (err == ::android::OK) {\n"
+         << "      ::android::binder::Status _aidl_status;\n"
+         << "      err = _aidl_status.readFromParcel(reply);\n"
+         << "      if (err == ::android::OK && _aidl_status.isOk()) {\n"
+         << "        cached_hash_ = reply.readString8().c_str();\n"
+         << "      }\n"
+         << "    }\n"
+         << "  }\n"
+         << "  return cached_hash_;\n"
+         << "}\n";
+    return unique_ptr<Declaration>(new LiteralDecl(code.str()));
+  }
   return nullptr;
 }
 
@@ -605,6 +659,15 @@
     b->AddLiteral(code.str());
     return true;
   }
+  if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+    std::ostringstream code;
+    code << "_aidl_data.checkInterface(this);\n"
+         << "_aidl_reply->writeNoException();\n"
+         << "_aidl_reply->writeString8(android::String8("
+         << ClassName(interface, ClassNames::INTERFACE) << "::HASH.c_str()))";
+    b->AddLiteral(code.str());
+    return true;
+  }
   return false;
 }
 
@@ -702,6 +765,13 @@
          << "}\n";
     decls.emplace_back(new LiteralDecl(code.str()));
   }
+  if (!options.Hash().empty()) {
+    std::ostringstream code;
+    code << "std::string " << bn_name << "::" << kGetInterfaceHash << "() {\n"
+         << "  return " << ClassName(interface, ClassNames::INTERFACE) << "::HASH;\n"
+         << "}\n";
+    decls.emplace_back(new LiteralDecl(code.str()));
+  }
 
   if (options.GenLog()) {
     string code;
@@ -717,7 +787,8 @@
 }
 
 unique_ptr<Document> BuildInterfaceSource(const AidlTypenames& typenames,
-                                          const AidlInterface& interface, const Options& options) {
+                                          const AidlInterface& interface,
+                                          [[maybe_unused]] const Options& options) {
   vector<string> include_list{
       HeaderFile(interface, ClassNames::RAW, false),
       HeaderFile(interface, ClassNames::CLIENT, false),
@@ -731,9 +802,8 @@
   vector<unique_ptr<Declaration>> decls;
 
   unique_ptr<MacroDecl> meta_if{new MacroDecl{
-      "IMPLEMENT_META_INTERFACE",
-      ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
-                             '"' + fq_name + '"'}}}};
+      "DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE",
+      ArgList{vector<string>{ClassName(interface, ClassNames::BASE), '"' + fq_name + '"'}}}};
   decls.push_back(std::move(meta_if));
 
   for (const auto& constant : interface.GetConstantDeclarations()) {
@@ -751,39 +821,6 @@
     decls.push_back(std::move(getter));
   }
 
-  // Implement the default impl class.
-  // onAsBinder returns nullptr as this interface is not associated with a
-  // real binder.
-  const string default_impl(ClassName(interface, ClassNames::DEFAULT_IMPL));
-  decls.emplace_back(
-      new LiteralDecl(StringPrintf("::android::IBinder* %s::onAsBinder() {\n"
-                                   "  return nullptr;\n"
-                                   "}\n",
-                                   default_impl.c_str())));
-  // Each interface method by default returns UNKNOWN_TRANSACTION with is
-  // the same status that is returned by transact() when the method is
-  // not implemented in the server side. In other words, these default
-  // methods do nothing; they only exist to aid making a real default
-  // impl class without having to override all methods in an interface.
-  for (const auto& method : interface.GetMethods()) {
-    if (method->IsUserDefined()) {
-      std::ostringstream code;
-      code << "::android::binder::Status " << default_impl << "::" << method->GetName()
-           << BuildArgList(typenames, *method, true, true).ToString() << " {\n"
-           << "  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
-           << "}\n";
-      decls.emplace_back(new LiteralDecl(code.str()));
-    } else {
-      if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
-        std::ostringstream code;
-        code << "int32_t " << default_impl << "::" << kGetInterfaceVersion << "() {\n"
-             << "  return 0;\n"
-             << "}\n";
-        decls.emplace_back(new LiteralDecl(code.str()));
-      }
-    }
-  }
-
   return unique_ptr<Document>{new CppSource{
       include_list,
       NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
@@ -833,6 +870,10 @@
   if (options.Version() > 0) {
     privates.emplace_back(new LiteralDecl("int32_t cached_version_ = -1;\n"));
   }
+  if (!options.Hash().empty()) {
+    privates.emplace_back(new LiteralDecl("std::string cached_hash_ = \"-1\";\n"));
+    privates.emplace_back(new LiteralDecl("std::mutex cached_hash_mutex_;\n"));
+  }
 
   unique_ptr<ClassDecl> bp_class{new ClassDecl{
       bp_name,
@@ -874,6 +915,11 @@
     code << "int32_t " << kGetInterfaceVersion << "() final override;\n";
     publics.emplace_back(new LiteralDecl(code.str()));
   }
+  if (!options.Hash().empty()) {
+    std::ostringstream code;
+    code << "std::string " << kGetInterfaceHash << "();\n";
+    publics.emplace_back(new LiteralDecl(code.str()));
+  }
 
   if (options.GenLog()) {
     includes.emplace_back("chrono");      // for std::chrono::steady_clock
@@ -918,6 +964,12 @@
 
     if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
   }
+  if (!options.Hash().empty()) {
+    std::ostringstream code;
+    code << "const std::string HASH = \"" << options.Hash() << "\";\n";
+
+    if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
+  }
 
   std::vector<std::unique_ptr<Declaration>> string_constants;
   unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t", false}};
@@ -970,28 +1022,49 @@
     }
   }
 
-  vector<unique_ptr<Declaration>> decls;
-  decls.emplace_back(std::move(if_class));
-
-  // Base class for the default implementation.
-  vector<string> method_decls;
+  // Implement the default impl class.
+  vector<unique_ptr<Declaration>> method_decls;
+  // onAsBinder returns nullptr as this interface is not associated with a
+  // real binder.
+  method_decls.emplace_back(
+      new LiteralDecl("::android::IBinder* onAsBinder() override {\n"
+                      "  return nullptr;\n"
+                      "}\n"));
+  // Each interface method by default returns UNKNOWN_TRANSACTION with is
+  // the same status that is returned by transact() when the method is
+  // not implemented in the server side. In other words, these default
+  // methods do nothing; they only exist to aid making a real default
+  // impl class without having to override all methods in an interface.
   for (const auto& method : interface.GetMethods()) {
     if (method->IsUserDefined()) {
-      method_decls.emplace_back(BuildMethodDecl(*method, typenames, false)->ToString());
+      std::ostringstream code;
+      code << "::android::binder::Status " << method->GetName()
+           << BuildArgList(typenames, *method, true, true).ToString() << " override {\n"
+           << "  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
+           << "}\n";
+      method_decls.emplace_back(new LiteralDecl(code.str()));
     } else {
-      method_decls.emplace_back(
-          BuildMetaMethodDecl(*method, typenames, options, false)->ToString());
+      if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
+        std::ostringstream code;
+        code << "int32_t " << kGetInterfaceVersion << "() override {\n"
+             << "  return 0;\n"
+             << "}\n";
+        method_decls.emplace_back(new LiteralDecl(code.str()));
+      }
+      if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+        std::ostringstream code;
+        code << "std::string " << kGetInterfaceHash << "() override {\n"
+             << "  return \"\";\n"
+             << "}\n";
+        method_decls.emplace_back(new LiteralDecl(code.str()));
+      }
     }
   }
 
-  decls.emplace_back(new LiteralDecl(
-      android::base::StringPrintf("class %s : public %s {\n"
-                                  "public:\n"
-                                  "  ::android::IBinder* onAsBinder() override;\n"
-                                  "  %s\n"
-                                  "};\n",
-                                  ClassName(interface, ClassNames::DEFAULT_IMPL).c_str(),
-                                  i_name.c_str(), Join(method_decls, "  ").c_str())));
+  vector<unique_ptr<Declaration>> decls;
+  decls.emplace_back(std::move(if_class));
+  decls.emplace_back(new ClassDecl{
+      ClassName(interface, ClassNames::DEFAULT_IMPL), i_name, std::move(method_decls), {}});
 
   return unique_ptr<Document>{
       new CppHeader{BuildHeaderGuard(interface, ClassNames::INTERFACE),
@@ -1054,7 +1127,7 @@
   parcel_class->AddPublic(std::move(write));
 
   return unique_ptr<Document>{new CppHeader{
-      BuildHeaderGuard(parcel, ClassNames::BASE), vector<string>(includes.begin(), includes.end()),
+      BuildHeaderGuard(parcel, ClassNames::RAW), vector<string>(includes.begin(), includes.end()),
       NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage())}};
 }
 std::unique_ptr<Document> BuildParcelSource(const AidlTypenames& typenames,
@@ -1129,9 +1202,35 @@
                     NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
 }
 
+std::string GenerateEnumToString(const AidlTypenames& typenames,
+                                 const AidlEnumDeclaration& enum_decl) {
+  std::ostringstream code;
+  code << "static inline std::string toString(" << enum_decl.GetName() << " val) {\n";
+  code << "  switch(val) {\n";
+  std::set<std::string> unique_cases;
+  for (const auto& enumerator : enum_decl.GetEnumerators()) {
+    std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
+    // Only add a case if its value has not yet been used in the switch
+    // statement. C++ does not allow multiple cases with the same value, but
+    // enums does allow this. In this scenario, the first declared
+    // enumerator with the given value is printed.
+    if (unique_cases.count(c) == 0) {
+      unique_cases.insert(c);
+      code << "  case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
+      code << "    return \"" << enumerator->GetName() << "\";\n";
+    }
+  }
+  code << "  default:\n";
+  code << "    return std::to_string(static_cast<"
+       << CppNameOf(enum_decl.GetBackingType(), typenames) << ">(val));\n";
+  code << "  }\n";
+  code << "}\n";
+  return code.str();
+}
+
 std::unique_ptr<Document> BuildEnumHeader(const AidlTypenames& typenames,
                                           const AidlEnumDeclaration& enum_decl) {
-  unique_ptr<Enum> generated_enum{
+  std::unique_ptr<Enum> generated_enum{
       new Enum{enum_decl.GetName(), CppNameOf(enum_decl.GetBackingType(), typenames), true}};
   for (const auto& enumerator : enum_decl.GetEnumerators()) {
     generated_enum->AddValue(
@@ -1139,13 +1238,25 @@
         enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator));
   }
 
-  set<string> includes = {};
+  std::set<std::string> includes = {
+      "array",
+      "binder/Enums.h",
+      "string",
+  };
   AddHeaders(enum_decl.GetBackingType(), typenames, includes);
 
+  std::vector<std::unique_ptr<Declaration>> decls1;
+  decls1.push_back(std::move(generated_enum));
+  decls1.push_back(std::make_unique<LiteralDecl>(GenerateEnumToString(typenames, enum_decl)));
+
+  std::vector<std::unique_ptr<Declaration>> decls2;
+  decls2.push_back(std::make_unique<LiteralDecl>(GenerateEnumValues(enum_decl, {""})));
+
   return unique_ptr<Document>{
-      new CppHeader{BuildHeaderGuard(enum_decl, ClassNames::BASE),
+      new CppHeader{BuildHeaderGuard(enum_decl, ClassNames::RAW),
                     vector<string>(includes.begin(), includes.end()),
-                    NestInNamespaces(std::move(generated_enum), enum_decl.GetSplitPackage())}};
+                    Append(NestInNamespaces(std::move(decls1), enum_decl.GetSplitPackage()),
+                           NestInNamespaces(std::move(decls2), {"android", "internal"}))}};
 }
 
 bool WriteHeader(const Options& options, const AidlTypenames& typenames,
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index 3ec8b16..b5e39bd 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -76,7 +76,7 @@
   ::android::binder::Status NullableBinder(::android::sp<::foo::IFooType>* _aidl_return) override;
   ::android::binder::Status StringListMethod(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* output, ::std::vector<::android::String16>* _aidl_return) override;
   ::android::binder::Status BinderListMethod(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* output, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) override;
-  ::android::binder::Status TakesAFileDescriptor(const ::android::base::unique_fd& f, ::android::base::unique_fd* _aidl_return) override;
+  ::android::binder::Status TakesAFileDescriptor(::android::base::unique_fd f, ::android::base::unique_fd* _aidl_return) override;
   ::android::binder::Status TakesAFileDescriptorArray(const ::std::vector<::android::base::unique_fd>& f, ::std::vector<::android::base::unique_fd>* _aidl_return) override;
 };  // class BpComplexTypeInterface
 
@@ -325,7 +325,7 @@
   return _aidl_status;
 }
 
-::android::binder::Status BpComplexTypeInterface::TakesAFileDescriptor(const ::android::base::unique_fd& f, ::android::base::unique_fd* _aidl_return) {
+::android::binder::Status BpComplexTypeInterface::TakesAFileDescriptor(::android::base::unique_fd f, ::android::base::unique_fd* _aidl_return) {
   ::android::Parcel _aidl_data;
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
@@ -340,7 +340,7 @@
   }
   _aidl_ret_status = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 6 /* TakesAFileDescriptor */, _aidl_data, &_aidl_reply);
   if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IComplexTypeInterface::getDefaultImpl())) {
-     return IComplexTypeInterface::getDefaultImpl()->TakesAFileDescriptor(f, _aidl_return);
+     return IComplexTypeInterface::getDefaultImpl()->TakesAFileDescriptor(std::move(f), _aidl_return);
   }
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -646,7 +646,7 @@
   return _aidl_status;
 }
 
-::android::binder::Status BpComplexTypeInterface::TakesAFileDescriptor(const ::android::base::unique_fd& f, ::android::base::unique_fd* _aidl_return) {
+::android::binder::Status BpComplexTypeInterface::TakesAFileDescriptor(::android::base::unique_fd f, ::android::base::unique_fd* _aidl_return) {
   ::android::Parcel _aidl_data;
   ::android::Parcel _aidl_reply;
   ::android::status_t _aidl_ret_status = ::android::OK;
@@ -662,7 +662,7 @@
   }
   _aidl_ret_status = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 6 /* TakesAFileDescriptor */, _aidl_data, &_aidl_reply);
   if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IComplexTypeInterface::getDefaultImpl())) {
-     return IComplexTypeInterface::getDefaultImpl()->TakesAFileDescriptor(f, _aidl_return);
+     return IComplexTypeInterface::getDefaultImpl()->TakesAFileDescriptor(std::move(f), _aidl_return);
   }
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
@@ -945,7 +945,7 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
-    ::android::binder::Status _aidl_status(TakesAFileDescriptor(in_f, &_aidl_return));
+    ::android::binder::Status _aidl_status(TakesAFileDescriptor(std::move(in_f), &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
@@ -1211,7 +1211,7 @@
       break;
     }
     atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptor::cppServer");
-    ::android::binder::Status _aidl_status(TakesAFileDescriptor(in_f, &_aidl_return));
+    ::android::binder::Status _aidl_status(TakesAFileDescriptor(std::move(in_f), &_aidl_return));
     atrace_end(ATRACE_TAG_AIDL);
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -1302,23 +1302,40 @@
   virtual ::android::binder::Status NullableBinder(::android::sp<::foo::IFooType>* _aidl_return) = 0;
   virtual ::android::binder::Status StringListMethod(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* output, ::std::vector<::android::String16>* _aidl_return) = 0;
   virtual ::android::binder::Status BinderListMethod(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* output, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) = 0;
-  virtual ::android::binder::Status TakesAFileDescriptor(const ::android::base::unique_fd& f, ::android::base::unique_fd* _aidl_return) = 0;
+  virtual ::android::binder::Status TakesAFileDescriptor(::android::base::unique_fd f, ::android::base::unique_fd* _aidl_return) = 0;
   virtual ::android::binder::Status TakesAFileDescriptorArray(const ::std::vector<::android::base::unique_fd>& f, ::std::vector<::android::base::unique_fd>* _aidl_return) = 0;
 };  // class IComplexTypeInterface
 
 class IComplexTypeInterfaceDefault : public IComplexTypeInterface {
 public:
-  ::android::IBinder* onAsBinder() override;
-  ::android::binder::Status Send(const ::std::unique_ptr<::std::vector<int32_t>>& goes_in, ::std::vector<double>* goes_in_and_out, ::std::vector<bool>* goes_out, ::std::vector<int32_t>* _aidl_return) override;
-  ::android::binder::Status Piff(int32_t times) override;
-  ::android::binder::Status TakesABinder(const ::android::sp<::foo::IFooType>& f, ::android::sp<::foo::IFooType>* _aidl_return) override;
-  ::android::binder::Status NullableBinder(::android::sp<::foo::IFooType>* _aidl_return) override;
-  ::android::binder::Status StringListMethod(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* output, ::std::vector<::android::String16>* _aidl_return) override;
-  ::android::binder::Status BinderListMethod(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* output, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) override;
-  ::android::binder::Status TakesAFileDescriptor(const ::android::base::unique_fd& f, ::android::base::unique_fd* _aidl_return) override;
-  ::android::binder::Status TakesAFileDescriptorArray(const ::std::vector<::android::base::unique_fd>& f, ::std::vector<::android::base::unique_fd>* _aidl_return) override;
-
-};
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+  ::android::binder::Status Send(const ::std::unique_ptr<::std::vector<int32_t>>&, ::std::vector<double>*, ::std::vector<bool>*, ::std::vector<int32_t>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status Piff(int32_t) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status TakesABinder(const ::android::sp<::foo::IFooType>&, ::android::sp<::foo::IFooType>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status NullableBinder(::android::sp<::foo::IFooType>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status StringListMethod(const ::std::vector<::android::String16>&, ::std::vector<::android::String16>*, ::std::vector<::android::String16>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status BinderListMethod(const ::std::vector<::android::sp<::android::IBinder>>&, ::std::vector<::android::sp<::android::IBinder>>*, ::std::vector<::android::sp<::android::IBinder>>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status TakesAFileDescriptor(::android::base::unique_fd, ::android::base::unique_fd*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status TakesAFileDescriptorArray(const ::std::vector<::android::base::unique_fd>&, ::std::vector<::android::base::unique_fd>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+};  // class IComplexTypeInterfaceDefault
 
 }  // namespace os
 
@@ -1335,43 +1352,7 @@
 
 namespace os {
 
-IMPLEMENT_META_INTERFACE(ComplexTypeInterface, "android.os.IComplexTypeInterface")
-
-::android::IBinder* IComplexTypeInterfaceDefault::onAsBinder() {
-  return nullptr;
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::Send(const ::std::unique_ptr<::std::vector<int32_t>>&, ::std::vector<double>*, ::std::vector<bool>*, ::std::vector<int32_t>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::Piff(int32_t) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::TakesABinder(const ::android::sp<::foo::IFooType>&, ::android::sp<::foo::IFooType>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::NullableBinder(::android::sp<::foo::IFooType>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::StringListMethod(const ::std::vector<::android::String16>&, ::std::vector<::android::String16>*, ::std::vector<::android::String16>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::BinderListMethod(const ::std::vector<::android::sp<::android::IBinder>>&, ::std::vector<::android::sp<::android::IBinder>>*, ::std::vector<::android::sp<::android::IBinder>>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::TakesAFileDescriptor(const ::android::base::unique_fd&, ::android::base::unique_fd* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IComplexTypeInterfaceDefault::TakesAFileDescriptorArray(const ::std::vector<::android::base::unique_fd>&, ::std::vector<::android::base::unique_fd>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(ComplexTypeInterface, "android.os.IComplexTypeInterface")
 
 }  // namespace os
 
@@ -1380,31 +1361,103 @@
 
 const string kEnumAIDL = R"(package android.os;
 enum TestEnum {
-  FOO = 1,
-  BAR = 2,
+  ZERO,
+  ONE,
+  THREE = 3,
+  FOUR = 3 + 1,
+  FIVE,
+  SIX,
+  SEVEN,
+  EIGHT = 16 / 2,
+  NINE,
+  TEN,
 })";
 
+// clang-format off
 const char kExpectedEnumHeaderOutput[] =
     R"(#ifndef AIDL_GENERATED_ANDROID_OS_TEST_ENUM_H_
 #define AIDL_GENERATED_ANDROID_OS_TEST_ENUM_H_
 
+#include <array>
+#include <binder/Enums.h>
 #include <cstdint>
+#include <string>
 
 namespace android {
 
 namespace os {
 
 enum class TestEnum : int8_t {
-  FOO = 1,
-  BAR = 2,
+  ZERO = 0,
+  ONE = 1,
+  THREE = 3,
+  FOUR = 4,
+  FIVE = 5,
+  SIX = 6,
+  SEVEN = 7,
+  EIGHT = 8,
+  NINE = 9,
+  TEN = 10,
 };
 
+static inline std::string toString(TestEnum val) {
+  switch(val) {
+  case TestEnum::ZERO:
+    return "ZERO";
+  case TestEnum::ONE:
+    return "ONE";
+  case TestEnum::THREE:
+    return "THREE";
+  case TestEnum::FOUR:
+    return "FOUR";
+  case TestEnum::FIVE:
+    return "FIVE";
+  case TestEnum::SIX:
+    return "SIX";
+  case TestEnum::SEVEN:
+    return "SEVEN";
+  case TestEnum::EIGHT:
+    return "EIGHT";
+  case TestEnum::NINE:
+    return "NINE";
+  case TestEnum::TEN:
+    return "TEN";
+  default:
+    return std::to_string(static_cast<int8_t>(val));
+  }
+}
+
 }  // namespace os
 
 }  // namespace android
+namespace android {
+
+namespace internal {
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<::android::os::TestEnum, 10> enum_values<::android::os::TestEnum> = {
+  ::android::os::TestEnum::ZERO,
+  ::android::os::TestEnum::ONE,
+  ::android::os::TestEnum::THREE,
+  ::android::os::TestEnum::FOUR,
+  ::android::os::TestEnum::FIVE,
+  ::android::os::TestEnum::SIX,
+  ::android::os::TestEnum::SEVEN,
+  ::android::os::TestEnum::EIGHT,
+  ::android::os::TestEnum::NINE,
+  ::android::os::TestEnum::TEN,
+};
+#pragma clang diagnostic pop
+
+}  // namespace internal
+
+}  // namespace android
 
 #endif  // AIDL_GENERATED_ANDROID_OS_TEST_ENUM_H_
 )";
+// clang-format on
 
 const string kEnumWithBackingTypeAIDL = R"(package android.os;
 @Backing(type="long")
@@ -1413,11 +1466,15 @@
   BAR = 2,
 })";
 
+// clang-format off
 const char kExpectedEnumWithBackingTypeHeaderOutput[] =
     R"(#ifndef AIDL_GENERATED_ANDROID_OS_TEST_ENUM_H_
 #define AIDL_GENERATED_ANDROID_OS_TEST_ENUM_H_
 
+#include <array>
+#include <binder/Enums.h>
 #include <cstdint>
+#include <string>
 
 namespace android {
 
@@ -1428,12 +1485,40 @@
   BAR = 2L,
 };
 
+static inline std::string toString(TestEnum val) {
+  switch(val) {
+  case TestEnum::FOO:
+    return "FOO";
+  case TestEnum::BAR:
+    return "BAR";
+  default:
+    return std::to_string(static_cast<int64_t>(val));
+  }
+}
+
 }  // namespace os
 
 }  // namespace android
+namespace android {
+
+namespace internal {
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<::android::os::TestEnum, 2> enum_values<::android::os::TestEnum> = {
+  ::android::os::TestEnum::FOO,
+  ::android::os::TestEnum::BAR,
+};
+#pragma clang diagnostic pop
+
+}  // namespace internal
+
+}  // namespace android
 
 #endif  // AIDL_GENERATED_ANDROID_OS_TEST_ENUM_H_
 )";
+// clang-format on
 
 }  // namespace
 
diff --git a/generate_java.cpp b/generate_java.cpp
index ea23016..f87ce79 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -64,14 +64,6 @@
   return true;
 }
 
-bool generate_java_parcel_declaration(const std::string& filename, const IoDelegate& io_delegate) {
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-  *code_writer
-      << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
-
-  return true;
-}
-
 bool generate_java_enum_declaration(const std::string& filename,
                                     const AidlEnumDeclaration* enum_decl,
                                     const AidlTypenames& typenames, const IoDelegate& io_delegate) {
@@ -88,11 +80,6 @@
     return generate_java_parcel(filename, parcelable, typenames, io_delegate);
   }
 
-  if (const AidlParcelable* parcelable_decl = defined_type->AsParcelable();
-      parcelable_decl != nullptr) {
-    return generate_java_parcel_declaration(filename, io_delegate);
-  }
-
   if (const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
       enum_decl != nullptr) {
     return generate_java_enum_declaration(filename, enum_decl, typenames, io_delegate);
@@ -261,12 +248,12 @@
   code_writer->Write("package %s;\n", enum_decl->GetPackage().c_str());
   code_writer->Write("%s\n", enum_decl->GetComments().c_str());
   for (const std::string& annotation : generate_java_annotations(*enum_decl)) {
-    code_writer->Write(annotation.c_str());
+    code_writer->Write("%s", annotation.c_str());
   }
   code_writer->Write("public @interface %s {\n", enum_decl->GetName().c_str());
   code_writer->Indent();
   for (const auto& enumerator : enum_decl->GetEnumerators()) {
-    code_writer->Write(enumerator->GetComments().c_str());
+    code_writer->Write("%s", enumerator->GetComments().c_str());
     code_writer->Write(
         "public static final %s %s = %s;\n",
         JavaSignatureOf(enum_decl->GetBackingType(), typenames).c_str(),
@@ -277,17 +264,19 @@
   code_writer->Write("}\n");
 }
 
-std::string generate_java_annotation_parameters(const AidlAnnotation& a) {
+std::string dump_location(const AidlNode& method) {
+  return method.PrintLocation();
+}
+
+std::string generate_java_unsupportedappusage_parameters(const AidlAnnotation& a) {
   const std::map<std::string, std::string> params = a.AnnotationParams(ConstantValueDecorator);
-  if (params.empty()) {
-    return "";
-  }
   std::vector<string> parameters_decl;
   for (const auto& name_and_param : params) {
     const std::string& param_name = name_and_param.first;
     const std::string& param_value = name_and_param.second;
     parameters_decl.push_back(param_name + " = " + param_value);
   }
+  parameters_decl.push_back("overrideSourcePosition=\"" + dump_location(a) + "\"");
   return "(" + base::Join(parameters_decl, ", ") + ")";
 }
 
@@ -295,8 +284,8 @@
   std::vector<std::string> result;
   const AidlAnnotation* unsupported_app_usage = a.UnsupportedAppUsage();
   if (unsupported_app_usage != nullptr) {
-    result.emplace_back("@dalvik.annotation.compat.UnsupportedAppUsage" +
-                        generate_java_annotation_parameters(*unsupported_app_usage));
+    result.emplace_back("@android.compat.annotation.UnsupportedAppUsage" +
+                        generate_java_unsupportedappusage_parameters(*unsupported_app_usage));
   }
   if (a.IsSystemApi()) {
     result.emplace_back("@android.annotation.SystemApi");
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index b791241..296e023 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -129,6 +129,10 @@
       "interface. */";
   ctor->name = "Stub";
   ctor->statements = std::make_shared<StatementBlock>();
+  if (interfaceType->IsVintfStability()) {
+    auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
+    ctor->statements->Add(stability);
+  }
   auto attach = std::make_shared<MethodCall>(
       THIS_VALUE, "attachInterface",
       std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
@@ -332,6 +336,11 @@
     code << "private int mCachedVersion = -1;\n";
     this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
   }
+  if (!options.Hash().empty()) {
+    std::ostringstream code;
+    code << "private String mCachedHash = \"-1\";\n";
+    this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
+  }
 
   // IBinder asBinder()
   auto asBinder = std::make_shared<Method>();
@@ -781,6 +790,12 @@
            << "throws android.os.RemoteException;\n";
       decl = std::make_shared<LiteralClassElement>(code.str());
     }
+    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      std::ostringstream code;
+      code << "public String " << kGetInterfaceHash << "() "
+           << "throws android.os.RemoteException;\n";
+      decl = std::make_shared<LiteralClassElement>(code.str());
+    }
   }
   interface->elements.push_back(decl);
 
@@ -805,6 +820,16 @@
       c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
       stubClass->transact_switch->cases.push_back(c);
     }
+    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      auto c = std::make_shared<Case>(transactCodeName);
+      std::ostringstream code;
+      code << "data.enforceInterface(descriptor);\n"
+           << "reply.writeNoException();\n"
+           << "reply.writeString(" << kGetInterfaceHash << "());\n"
+           << "return true;\n";
+      c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
+      stubClass->transact_switch->cases.push_back(c);
+    }
   }
 
   // == the proxy method ===================================================
@@ -843,6 +868,35 @@
            << "}\n";
       proxy = std::make_shared<LiteralClassElement>(code.str());
     }
+    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      std::ostringstream code;
+      code << "@Override\n"
+           << "public synchronized String " << kGetInterfaceHash << "()"
+           << " throws "
+           << "android.os.RemoteException {\n"
+           << "  if (mCachedHash == \"-1\") {\n"
+           << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
+           << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
+           << "    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"
+           << "      mCachedHash = reply.readString();\n"
+           << "    } finally {\n"
+           << "      reply.recycle();\n"
+           << "      data.recycle();\n"
+           << "    }\n"
+           << "  }\n"
+           << "  return mCachedHash;\n"
+           << "}\n";
+      proxy = std::make_shared<LiteralClassElement>(code.str());
+    }
   }
   if (proxy != nullptr) {
     proxyClass->elements.push_back(proxy);
@@ -943,17 +997,25 @@
     if (m->IsUserDefined()) {
       default_class->elements.emplace_back(generate_default_impl_method(*m.get(), typenames));
     } else {
+      // These are called only when the remote side does not implement these
+      // methods, which is normally impossible, because these methods are
+      // automatically declared in the interface class and not implementing
+      // them on the remote side causes a compilation error. But if the remote
+      // side somehow managed to not implement it, that's an error and we
+      // report the case by returning an invalid value here.
       if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
-        // This is called only when the remote side is not implementing this
-        // method, which is impossible in normal case, because this method is
-        // automatically declared in the interface class and not implementing
-        // it in the remote side is causing compilation error. But if the remote
-        // side somehow managed to not implement it, that's an error and we
-        // report the case by returning -1 here.
         std::ostringstream code;
         code << "@Override\n"
              << "public int " << kGetInterfaceVersion << "() {\n"
-             << "  return -1;\n"
+             << "  return 0;\n"
+             << "}\n";
+        default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
+      }
+      if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+        std::ostringstream code;
+        code << "@Override\n"
+             << "public String " << kGetInterfaceHash << "() {\n"
+             << "  return \"\";\n"
              << "}\n";
         default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
       }
@@ -992,6 +1054,11 @@
          << "public static final int VERSION = " << options.Version() << ";\n";
     interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
   }
+  if (!options.Hash().empty()) {
+    std::ostringstream code;
+    code << "public static final String HASH = \"" << options.Hash() << "\";\n";
+    interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
+  }
 
   // the default impl class
   auto default_impl = generate_default_impl_class(*iface, typenames, options);
@@ -1016,7 +1083,11 @@
   // all the declared constants of the interface
   for (const auto& constant : iface->GetConstantDeclarations()) {
     const AidlConstantValue& value = constant->GetValue();
-
+    auto comment = constant->GetType().GetComments();
+    if (comment.length() != 0) {
+      auto code = StringPrintf("%s\n", comment.c_str());
+      interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
+    }
     switch (value.GetType()) {
       case AidlConstantValue::Type::STRING: {
         generate_string_constant(interface.get(), constant->GetName(),
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index 60c93d6..fd824bf 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -30,7 +30,10 @@
 static constexpr const char* kClazz = "_g_aidl_clazz";
 static constexpr const char* kDescriptor = "descriptor";
 static constexpr const char* kVersion = "version";
-static constexpr const char* kCacheVariable = "_aidl_cached_value";
+static constexpr const char* kHash = "hash";
+static constexpr const char* kCachedVersion = "_aidl_cached_version";
+static constexpr const char* kCachedHash = "_aidl_cached_hash";
+static constexpr const char* kCachedHashMutex = "_aidl_cached_hash_mutex";
 
 using namespace internals;
 using cpp::ClassNames;
@@ -170,7 +173,11 @@
 
 static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
                                    const AidlDefinedType& defined_type) {
-  out << "#include <android/binder_parcel_utils.h>\n";
+  out << "#include <cstdint>\n";
+  out << "#include <memory>\n";
+  out << "#include <optional>\n";
+  out << "#include <string>\n";
+  out << "#include <vector>\n";
   out << "#ifdef BINDER_STABILITY_SUPPORT\n";
   out << "#include <android/binder_stability.h>\n";
   out << "#endif  // BINDER_STABILITY_SUPPORT\n";
@@ -183,12 +190,12 @@
           << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
     } else if (other_defined_type.AsStructuredParcelable() != nullptr) {
       out << "#include <"
-          << NdkHeaderFile(other_defined_type, ClassNames::BASE, false /*use_os_sep*/) << ">\n";
+          << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
     } else if (other_defined_type.AsParcelable() != nullptr) {
       out << "#include \"" << other_defined_type.AsParcelable()->GetCppHeader() << "\"\n";
     } else if (other_defined_type.AsEnumDeclaration() != nullptr) {
       out << "#include <"
-          << NdkHeaderFile(other_defined_type, ClassNames::BASE, false /*use_os_sep*/) << ">\n";
+          << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
     } else {
       AIDL_FATAL(defined_type) << "Unrecognized type.";
     }
@@ -196,6 +203,8 @@
 }
 static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
                                    const AidlDefinedType& /*defined_type*/) {
+  out << "#include <android/binder_parcel_utils.h>\n";
+
   types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
     if (a_defined_type.AsInterface() != nullptr) {
       out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
@@ -282,7 +291,6 @@
 static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
                                            const AidlInterface& defined_type,
                                            const AidlMethod& method,
-                                           const std::optional<std::string> return_value_cached_to,
                                            const Options& options) {
   const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
 
@@ -291,10 +299,19 @@
   out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
   out << "::ndk::ScopedAStatus _aidl_status;\n";
 
-  if (return_value_cached_to) {
-    out << "if (" << *return_value_cached_to << " != -1) {\n";
+  if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+    out << "const std::lock_guard<std::mutex> lock(" << kCachedHashMutex << ");\n";
+    out << "if (" << kCachedHash << " != \"-1\") {\n";
     out.Indent();
-    out << "*_aidl_return = " << *return_value_cached_to << ";\n"
+    out << "*_aidl_return = " << kCachedHash << ";\n"
+        << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
+        << "return _aidl_status;\n";
+    out.Dedent();
+    out << "}\n";
+  } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
+    out << "if (" << kCachedVersion << " != -1) {\n";
+    out.Indent();
+    out << "*_aidl_return = " << kCachedVersion << ";\n"
         << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
         << "return _aidl_status;\n";
     out.Dedent();
@@ -364,8 +381,10 @@
     ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
     out << ";\n";
     StatusCheckGoto(out);
-    if (return_value_cached_to) {
-      out << *return_value_cached_to << " = *_aidl_return;\n";
+    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << kCachedHash << " = *_aidl_return;\n";
+    } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
+      out << kCachedVersion << " = *_aidl_return;\n";
     }
   }
   for (const AidlArgument* arg : method.GetOutArguments()) {
@@ -500,13 +519,7 @@
   }
   out << "\n";
   for (const auto& method : defined_type.GetMethods()) {
-    // Only getInterfaceVersion can use cache.
-    const bool cacheable = !method->IsUserDefined() && method->GetName() == kGetInterfaceVersion &&
-                           options.Version() > 0;
-    const auto return_value_cached_to =
-        cacheable ? std::make_optional<std::string>(kCacheVariable) : std::nullopt;
-    GenerateClientMethodDefinition(out, types, defined_type, *method, return_value_cached_to,
-                                   options);
+    GenerateClientMethodDefinition(out, types, defined_type, *method, options);
   }
 }
 void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
@@ -549,6 +562,14 @@
       out.Dedent();
       out << "}\n";
     }
+    if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << NdkMethodDecl(types, *method, clazz) << " {\n";
+      out.Indent();
+      out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
+      out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
+      out.Dedent();
+      out << "}\n";
+    }
   }
 }
 void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
@@ -644,6 +665,15 @@
         out.Dedent();
         out << "}\n";
       }
+      if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+        out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
+            << "std::string* _aidl_return) {\n";
+        out.Indent();
+        out << "*_aidl_return = \"\";\n";
+        out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
+        out.Dedent();
+        out << "}\n";
+      }
     }
   }
 
@@ -689,7 +719,12 @@
   }
 
   if (options.Version() > 0) {
-    out << "int32_t " << kCacheVariable << " = -1;\n";
+    out << "int32_t " << kCachedVersion << " = -1;\n";
+  }
+
+  if (!options.Hash().empty()) {
+    out << "std::string " << kCachedHash << " = \"-1\";\n";
+    out << "std::mutex " << kCachedHashMutex << ";\n";
   }
   if (options.GenLog()) {
     out << "static std::function<void(const Json::Value&)> logFunc;\n";
@@ -723,6 +758,8 @@
     }
     if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
       out << NdkMethodDecl(types, *method) << " final override;\n";
+    } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << NdkMethodDecl(types, *method) << " final override;\n";
     } else {
       AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
     }
@@ -771,6 +808,9 @@
     out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
         << ";\n";
   }
+  if (!options.Hash().empty()) {
+    out << "static inline const std::string " << kHash << " = \"" << options.Hash() << "\";\n";
+  }
   out << "\n";
   out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
   out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
@@ -803,6 +843,8 @@
       out << NdkMethodDecl(types, *method) << " override;\n";
     } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
       out << NdkMethodDecl(types, *method) << " override;\n";
+    } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << NdkMethodDecl(types, *method) << " override;\n";
     }
   }
   out << "::ndk::SpAIBinder asBinder() override;\n";
@@ -815,7 +857,7 @@
 void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
                           const AidlStructuredParcelable& defined_type,
                           const Options& /*options*/) {
-  const std::string clazz = ClassName(defined_type, ClassNames::BASE);
+  const std::string clazz = ClassName(defined_type, ClassNames::RAW);
 
   out << "#pragma once\n";
   out << "#include <android/binder_interface_utils.h>\n";
@@ -846,7 +888,7 @@
 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
                           const AidlStructuredParcelable& defined_type,
                           const Options& /*options*/) {
-  const std::string clazz = ClassName(defined_type, ClassNames::BASE);
+  const std::string clazz = ClassName(defined_type, ClassNames::RAW);
 
   out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
       << "\"\n";
@@ -860,22 +902,12 @@
 
   out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
   out.Indent();
-  out << "std::string _aidl_descriptor;\n";
-  out << "binder_status_t _aidl_ret_status;\n";
-
-  out << "int32_t _aidl_null;\n";
   out << "int32_t _aidl_parcelable_size;\n";
-  out << "int32_t _aidl_start_pos;\n";
-  out << "_aidl_ret_status = AParcel_readInt32(parcel, &_aidl_null);\n";
-  StatusCheckReturn(out);
-  out << "_aidl_start_pos = AParcel_getDataPosition(parcel);\n";
-  out << "_aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
+  out << "int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
+  out << "binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
   out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
   StatusCheckReturn(out);
 
-  // TODO(b/117281836)
-  out << "if (_aidl_null == 0) return STATUS_UNEXPECTED_NULL;\n\n";
-
   for (const auto& variable : defined_type.GetFields()) {
     out << "_aidl_ret_status = ";
     ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
@@ -895,9 +927,6 @@
   out.Indent();
   out << "binder_status_t _aidl_ret_status;\n";
 
-  // non-null
-  out << "_aidl_ret_status = AParcel_writeInt32(parcel, 1);\n";
-  StatusCheckReturn(out);
   out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
   out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
   StatusCheckReturn(out);
@@ -920,12 +949,41 @@
   LeaveNdkNamespace(out, defined_type);
 }
 
+std::string GenerateEnumToString(const AidlTypenames& typenames,
+                                 const AidlEnumDeclaration& enum_decl) {
+  std::ostringstream code;
+  code << "static inline std::string toString(" << enum_decl.GetName() << " val) {\n";
+  code << "  switch(val) {\n";
+  std::set<std::string> unique_cases;
+  for (const auto& enumerator : enum_decl.GetEnumerators()) {
+    std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
+    // Only add a case if its value has not yet been used in the switch
+    // statement. C++ does not allow multiple cases with the same value, but
+    // enums does allow this. In this scenario, the first declared
+    // enumerator with the given value is printed.
+    if (unique_cases.count(c) == 0) {
+      unique_cases.insert(c);
+      code << "  case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
+      code << "    return \"" << enumerator->GetName() << "\";\n";
+    }
+  }
+  code << "  default:\n";
+  code << "    return std::to_string(static_cast<"
+       << NdkNameOf(typenames, enum_decl.GetBackingType(), StorageMode::STACK) << ">(val));\n";
+  code << "  }\n";
+  code << "}\n";
+  return code.str();
+}
+
 void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
                         const AidlEnumDeclaration& enum_decl, const Options& /*options*/) {
   out << "#pragma once\n";
   out << "\n";
 
   GenerateHeaderIncludes(out, types, enum_decl);
+  // enum specific headers
+  out << "#include <array>\n";
+  out << "#include <android/binder_enums.h>\n";
 
   EnterNdkNamespace(out, enum_decl);
   out << "enum class " << enum_decl.GetName() << " : "
@@ -937,7 +995,15 @@
   }
   out.Dedent();
   out << "};\n";
+  out << "\n";
+  out << GenerateEnumToString(types, enum_decl);
   LeaveNdkNamespace(out, enum_decl);
+
+  out << "namespace ndk {\n";
+  out << "namespace internal {\n";
+  out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
+  out << "}  // namespace internal\n";
+  out << "}  // namespace android\n";
 }
 
 }  // namespace internals
diff --git a/import_resolver.cpp b/import_resolver.cpp
index 0500cf8..10cc4e4 100644
--- a/import_resolver.cpp
+++ b/import_resolver.cpp
@@ -74,13 +74,6 @@
 
   int num_found = found_paths.size();
   if (num_found == 0) {
-    // If not found from the import paths, try to find from the input files
-    relative_path.insert(0, 1, OS_PATH_SEPARATOR);
-    for (string input_file : input_files_) {
-      if (android::base::EndsWith(input_file, relative_path)) {
-        return input_file;
-      }
-    }
     return "";
   } else if (num_found == 1) {
     return found_paths.front();
diff --git a/main.cpp b/main.cpp
index 1199579..10b9274 100644
--- a/main.cpp
+++ b/main.cpp
@@ -15,26 +15,22 @@
  */
 
 #include "aidl.h"
-#include "aidl_apicheck.h"
+#include "aidl_checkapi.h"
 #include "io_delegate.h"
 #include "logging.h"
 #include "options.h"
 
 #include <iostream>
-#include <memory>
+
+#ifdef AIDL_CPP_BUILD
+constexpr Options::Language kDefaultLang = Options::Language::CPP;
+#else
+constexpr Options::Language kDefaultLang = Options::Language::JAVA;
+#endif
 
 using android::aidl::Options;
 
-int main(int argc, char* argv[]) {
-  android::base::InitLogging(argv);
-  LOG(DEBUG) << "aidl starting";
-  Options options(argc, argv, Options::Language::JAVA);
-  if (!options.Ok()) {
-    std::cerr << options.GetErrorMessage();
-    std::cerr << options.GetUsage();
-    return 1;
-  }
-
+int process_options(const Options& options) {
   android::aidl::IoDelegate io_delegate;
   switch (options.GetTask()) {
     case Options::Task::COMPILE:
@@ -52,3 +48,27 @@
       return 1;
   }
 }
+
+int main(int argc, char* argv[]) {
+  android::base::InitLogging(argv);
+  LOG(DEBUG) << "aidl starting";
+
+  Options options(argc, argv, kDefaultLang);
+  if (!options.Ok()) {
+    std::cerr << options.GetErrorMessage();
+    std::cerr << options.GetUsage();
+    return 1;
+  }
+
+  int ret = process_options(options);
+
+  // compiler invariants
+
+  // once AIDL_ERROR/AIDL_FATAL are used everywhere instead of std::cerr/LOG, we
+  // can make this assertion in both directions.
+  if (ret == 0) {
+    AIDL_FATAL_IF(AidlError::hadError(), "Compiler success, but error emitted");
+  }
+
+  return ret;
+}
diff --git a/main_cpp.cpp b/main_cpp.cpp
deleted file mode 100644
index 5cb778c..0000000
--- a/main_cpp.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "aidl.h"
-#include "io_delegate.h"
-#include "logging.h"
-#include "options.h"
-
-#include <iostream>
-
-using android::aidl::Options;
-
-int main(int argc, char* argv[]) {
-  android::base::InitLogging(argv);
-  LOG(DEBUG) << "aidl starting";
-
-  Options options(argc, argv, Options::Language::CPP);
-  if (!options.Ok()) {
-    std::cerr << options.GetErrorMessage();
-    std::cerr << options.GetUsage();
-    return 1;
-  }
-
-  android::aidl::IoDelegate io_delegate;
-  return android::aidl::compile_aidl(options, io_delegate);
-}
diff --git a/metadata/Android.bp b/metadata/Android.bp
new file mode 100644
index 0000000..245c366
--- /dev/null
+++ b/metadata/Android.bp
@@ -0,0 +1,31 @@
+// build time C++ available list of all AIDL interfaces in the tree
+cc_library {
+    name: "libaidlmetadata",
+    host_supported: true,
+    srcs: [":aidl_metadata_in_cpp"],
+    export_include_dirs: ["include"],
+
+    cflags: ["-O0"],
+}
+
+// private impl below
+
+cc_binary {
+    name: "aidl_metadata_parser",
+    host_supported: true,
+    srcs: ["parser.cpp"],
+    shared_libs: ["libjsoncpp"],
+    visibility: [":__subpackages__"],
+}
+
+cc_genrule {
+    name: "aidl_metadata_in_cpp",
+    host_supported: true,
+    cmd: "$(location aidl_metadata_parser) $(in) > $(genDir)/metadata.cpp",
+    srcs: [
+        ":aidl_metadata_json",
+    ],
+    tools: ["aidl_metadata_parser"],
+    visibility: [":__subpackages__"],
+    out: ["metadata.cpp"],
+}
diff --git a/metadata/include/aidl/metadata.h b/metadata/include/aidl/metadata.h
new file mode 100644
index 0000000..8a1caa2
--- /dev/null
+++ b/metadata/include/aidl/metadata.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+namespace android {
+
+struct AidlInterfaceMetadata {
+  // name of module defining package
+  std::string name;
+
+  // stability of interface (e.g. "vintf")
+  std::string stability;
+
+  // list of types e.g. android.hardware.foo::IFoo
+  std::vector<std::string> types;
+
+  static std::vector<AidlInterfaceMetadata> all();
+};
+
+}  // namespace android
diff --git a/metadata/parser.cpp b/metadata/parser.cpp
new file mode 100644
index 0000000..ba0aeb8
--- /dev/null
+++ b/metadata/parser.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fstream>
+#include <iostream>
+
+#include <json/json.h>
+
+int main(int argc, char** argv) {
+  if (argc != 2) {
+    std::cerr << "Usage: aidl_metadata_parser *.json" << std::endl;
+    return EXIT_FAILURE;
+  }
+  const std::string path = argv[1];
+
+  Json::Value root;
+  Json::Reader reader;
+
+  std::ifstream stream(path);
+  if (!reader.parse(stream, root)) {
+    std::cerr << "Failed to read interface metadata file: " << path << std::endl
+              << reader.getFormattedErrorMessages() << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  std::cout << "#include <aidl/metadata.h>" << std::endl;
+  std::cout << "namespace android {" << std::endl;
+  std::cout << "std::vector<AidlInterfaceMetadata> AidlInterfaceMetadata::all() {" << std::endl;
+  std::cout << "return std::vector<AidlInterfaceMetadata>{" << std::endl;
+  for (const Json::Value& entry : root) {
+    std::cout << "AidlInterfaceMetadata{" << std::endl;
+    // AIDL interface characters guaranteed to be accepted in C++ string
+    std::cout << "std::string(\"" << entry["name"].asString() << "\")," << std::endl;
+    std::cout << "std::string(\"" << entry["stability"].asString() << "\")," << std::endl;
+    std::cout << "std::vector<std::string>{" << std::endl;
+    for (const Json::Value& intf : entry["types"]) {
+      std::cout << "std::string(\"" << intf.asString() << "\")," << std::endl;
+    }
+    std::cout << "}," << std::endl;
+    std::cout << "}," << std::endl;
+  }
+  std::cout << "};" << std::endl;
+  std::cout << "}" << std::endl;
+  std::cout << "}  // namespace android" << std::endl;
+  return EXIT_SUCCESS;
+}
diff --git a/options.cpp b/options.cpp
index 8bd2887..b79c361 100644
--- a/options.cpp
+++ b/options.cpp
@@ -39,7 +39,7 @@
 string Options::GetUsage() const {
   std::ostringstream sstr;
   sstr << "usage:" << endl
-       << myname_ << " --lang={java|cpp} [OPTION]... INPUT..." << endl
+       << myname_ << " --lang={java|cpp|ndk} [OPTION]... INPUT..." << endl
        << "   Generate Java or C++ files for AIDL file(s)." << endl
        << endl
        << myname_ << " --preprocess OUTPUT INPUT..." << endl
@@ -109,6 +109,8 @@
        << "  -v VER, --version=VER" << endl
        << "          Set the version of the interface and parcelable to VER." << endl
        << "          VER must be an interger greater than 0." << endl
+       << "  --hash=HASH" << endl
+       << "          Set the interface hash to HASH." << endl
        << "  --log" << endl
        << "          Information about the transaction, e.g., method name, argument" << endl
        << "          values, execution time, etc., is provided via callback." << endl
@@ -188,6 +190,7 @@
         {"version", required_argument, 0, 'v'},
         {"log", no_argument, 0, 'L'},
         {"parcelable-to-string", no_argument, 0, 'P'},
+        {"hash", required_argument, 0, 'H'},
         {"help", no_argument, 0, 'e'},
         {0, 0, 0, 0},
     };
@@ -306,6 +309,9 @@
         }
         break;
       }
+      case 'H':
+        hash_ = Trim(optarg);
+        break;
       case 'L':
         gen_log_ = true;
         break;
diff --git a/options.h b/options.h
index 43334a7..73d33bb 100644
--- a/options.h
+++ b/options.h
@@ -121,6 +121,8 @@
 
   int Version() const { return version_; }
 
+  string Hash() const { return hash_; }
+
   bool GenLog() const { return gen_log_; }
 
   bool GenParcelableToString() const { return gen_parcelable_to_string_; }
@@ -161,6 +163,7 @@
   vector<string> input_files_;
   string output_file_;
   int version_ = 0;
+  string hash_ = "";
   bool gen_log_ = false;
   bool gen_parcelable_to_string_ = false;
   ErrorMessage error_message_;
diff --git a/tests/aidl_parser_fuzzer.cpp b/tests/aidl_parser_fuzzer.cpp
new file mode 100644
index 0000000..43da866
--- /dev/null
+++ b/tests/aidl_parser_fuzzer.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "aidl.h"
+#include "fake_io_delegate.h"
+#include "options.h"
+
+#include <iostream>
+
+#ifdef FUZZ_LOG
+constexpr bool kFuzzLog = true;
+#else
+constexpr bool kFuzzLog = false;
+#endif
+
+using android::aidl::test::FakeIoDelegate;
+
+void fuzz(const std::string& langOpt, const std::string& content) {
+  // TODO: fuzz multiple files
+  // TODO: fuzz arguments
+  FakeIoDelegate io;
+  io.SetFileContents("a/path/Foo.aidl", content);
+
+  std::vector<std::string> args;
+  args.emplace_back("aidl");
+  args.emplace_back("--lang=" + langOpt);
+  args.emplace_back("-b");
+  args.emplace_back("-I .");
+  args.emplace_back("-o out");
+  // corresponding items also in aidl_parser_fuzzer.dict
+  args.emplace_back("a/path/Foo.aidl");
+
+  if (kFuzzLog) {
+    std::cout << "lang: " << langOpt << " content: " << content << std::endl;
+  }
+
+  int ret = android::aidl::compile_aidl(Options::From(args), io);
+  if (ret != 0) return;
+
+  if (kFuzzLog) {
+    for (const std::string& f : io.ListOutputFiles()) {
+      std::string output;
+      if (io.GetWrittenContents(f, &output)) {
+        std::cout << "OUTPUT " << f << ": " << std::endl;
+        std::cout << output << std::endl;
+      }
+    }
+  }
+}
+
+void fuzz(uint8_t options, const std::string& content) {
+  // keeping a byte of options we can use for various flags in the future (do
+  // not remove or add unless absolutely necessary in order to preserve the
+  // corpus).
+  (void)options;
+
+  // Process for each backend.
+  //
+  // This is unfortunate because we are parsing multiple times, but we want to
+  // check generation of content for each backend. If output fails in one
+  // backend, it's likely to fail in another.
+  fuzz("ndk", content);
+  fuzz("cpp", content);
+  fuzz("java", content);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  if (size <= 1) return 0;  // no use
+
+  // b/145447540, large nested expressions sometimes hit the stack depth limit.
+  // Fuzzing things of this size don't provide any additional meaningful
+  // coverage. This is an approximate value which should allow us to explore all
+  // of the language w/o hitting a stack overflow.
+  if (size > 2000) return 0;
+
+  uint8_t options = *data;
+  data++;
+  size--;
+
+  std::string content(reinterpret_cast<const char*>(data), size);
+  fuzz(options, content);
+
+  return 0;
+}
diff --git a/tests/aidl_parser_fuzzer.dict b/tests/aidl_parser_fuzzer.dict
new file mode 100644
index 0000000..1f882a0
--- /dev/null
+++ b/tests/aidl_parser_fuzzer.dict
@@ -0,0 +1,62 @@
+# keywords
+" parcelable "
+" import "
+" package "
+" in "
+" out "
+" inout "
+" cpp_header "
+" const "
+" true "
+" false "
+" interface "
+" oneway "
+" enum "
+
+# types
+" void "
+" boolean "
+" byte "
+" char "
+" int "
+" long "
+" float "
+" double "
+" String "
+" List "
+" Map "
+" IBinder "
+" FileDescriptor "
+" CharSequence "
+" ParcelFileDescriptor "
+" java.util.List "
+" java.util.Map "
+" android.os.ParcelFileDescriptor "
+
+# annotations
+" @nullable "
+" @utf8InCpp "
+" @VintfStability "
+" @UnsupportedAppUsage "
+" @SystemApi "
+" @JavaOnlyStableParcelable "
+" @Backing "
+" expectedSignature "
+" implicitMember "
+" maxTargetSdk "
+" publicAlternatives "
+" trackingBug "
+" type "
+
+# ignorable imports
+" android.os.IInterface "
+" android.os.IBinder "
+" android.os.Parcelable "
+" android.os.Parcel "
+" android.content.Context "
+" java.lang.String "
+
+# specific to fuzzer
+" a.path "
+" Foo "
+
diff --git a/tests/aidl_test_client_file_descriptors.cpp b/tests/aidl_test_client_file_descriptors.cpp
index e2d59a9..6e51869 100644
--- a/tests/aidl_test_client_file_descriptors.cpp
+++ b/tests/aidl_test_client_file_descriptors.cpp
@@ -119,7 +119,7 @@
     return false;
   }
 
-  status = s->RepeatFileDescriptor(write_fd, &return_fd);
+  status = s->RepeatFileDescriptor(std::move(write_fd), &return_fd);
 
   if (!status.isOk()) {
     cerr << "Could not repeat file descriptors." << endl;
diff --git a/tests/aidl_test_client_primitives.cpp b/tests/aidl_test_client_primitives.cpp
index 2733800..beadf96 100644
--- a/tests/aidl_test_client_primitives.cpp
+++ b/tests/aidl_test_client_primitives.cpp
@@ -17,6 +17,7 @@
 #include "aidl_test_client_primitives.h"
 
 #include <iostream>
+#include <iterator>
 #include <vector>
 
 #include <utils/String16.h>
@@ -117,6 +118,9 @@
                     {String16{"f"}, String16{"a"}, String16{"b"}}) ||
       !ReverseArray(s, &ITestService::ReverseByteEnum,
                     {ByteEnum::FOO, ByteEnum::BAR, ByteEnum::BAR}) ||
+      !ReverseArray(s, &ITestService::ReverseByteEnum,
+                    {std::begin(::android::enum_range<ByteEnum>()),
+                     std::end(::android::enum_range<ByteEnum>())}) ||
       !ReverseArray(s, &ITestService::ReverseIntEnum, {IntEnum::FOO, IntEnum::BAR, IntEnum::BAR}) ||
       !ReverseArray(s, &ITestService::ReverseLongEnum,
                     {LongEnum::FOO, LongEnum::BAR, LongEnum::BAR})) {
diff --git a/tests/aidl_test_service.cpp b/tests/aidl_test_service.cpp
index 3b0deed..113d1f5 100644
--- a/tests/aidl_test_service.cpp
+++ b/tests/aidl_test_service.cpp
@@ -163,17 +163,17 @@
     return Status::ok();
   }
   Status RepeatByteEnum(ByteEnum token, ByteEnum* _aidl_return) override {
-    ALOGI("Repeating ByteEnum token %d", static_cast<int8_t>(token));
+    ALOGI("Repeating ByteEnum token %s", toString(token).c_str());
     *_aidl_return = token;
     return Status::ok();
   }
   Status RepeatIntEnum(IntEnum token, IntEnum* _aidl_return) override {
-    ALOGI("Repeating IntEnum token %d", static_cast<int8_t>(token));
+    ALOGI("Repeating IntEnum token %s", toString(token).c_str());
     *_aidl_return = token;
     return Status::ok();
   }
   Status RepeatLongEnum(LongEnum token, LongEnum* _aidl_return) override {
-    ALOGI("Repeating LongEnum token %d", static_cast<int8_t>(token));
+    ALOGI("Repeating LongEnum token %s", toString(token).c_str());
     *_aidl_return = token;
     return Status::ok();
   }
@@ -317,7 +317,7 @@
     return ReverseArray(input, repeated, _aidl_return);
   }
 
-  Status RepeatFileDescriptor(const unique_fd& read,
+  Status RepeatFileDescriptor(unique_fd read,
                               unique_fd* _aidl_return) override {
     ALOGE("Repeating file descriptor");
     *_aidl_return = unique_fd(dup(read.get()));
diff --git a/tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl b/tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl
deleted file mode 100644
index b3d2de6..0000000
--- a/tests/android/aidl/loggable/ILoggableInterfaceNdk.aidl
+++ /dev/null
@@ -1,14 +0,0 @@
-package android.aidl.loggable;
-
-interface ILoggableInterfaceNdk {
-    String[] LogThis(boolean boolValue, inout boolean[] boolArray,
-                   byte byteValue, inout byte[] byteArray,
-                   char charValue, inout char[] charArray,
-                   int intValue, inout int[] intArray,
-                   long longValue, inout long[] longArray,
-                   float floatValue, inout float[] floatArray,
-                   double doubleValue, inout double[] doubleArray,
-                   String stringValue, inout String[] stringArray,
-                   IBinder binderValue,
-                   inout ParcelFileDescriptor pfdValue);
-}
diff --git a/tests/android/aidl/tests/ByteEnum.aidl b/tests/android/aidl/tests/ByteEnum.aidl
index 31ca9e0..503ae8a 100644
--- a/tests/android/aidl/tests/ByteEnum.aidl
+++ b/tests/android/aidl/tests/ByteEnum.aidl
@@ -24,5 +24,6 @@
   // Comment about FOO.
   FOO = 1,
   BAR = 2,
+  BAZ,
 }
 
diff --git a/tests/android/aidl/tests/IntEnum.aidl b/tests/android/aidl/tests/IntEnum.aidl
index 5f10f58..d3769ef 100644
--- a/tests/android/aidl/tests/IntEnum.aidl
+++ b/tests/android/aidl/tests/IntEnum.aidl
@@ -20,5 +20,6 @@
 enum IntEnum {
   FOO = 1000,
   BAR = 2000,
+  BAZ,
 }
 
diff --git a/tests/android/aidl/tests/LongEnum.aidl b/tests/android/aidl/tests/LongEnum.aidl
index e7caa1b..9d7610b 100644
--- a/tests/android/aidl/tests/LongEnum.aidl
+++ b/tests/android/aidl/tests/LongEnum.aidl
@@ -20,5 +20,6 @@
 enum LongEnum {
   FOO = 100000000000,
   BAR = 200000000000,
+  BAZ,
 }
 
diff --git a/tests/android/aidl/tests/generic/Baz.aidl b/tests/android/aidl/tests/generic/Baz.aidl
new file mode 100644
index 0000000..2244d98
--- /dev/null
+++ b/tests/android/aidl/tests/generic/Baz.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests.generic;
+
+parcelable Baz {
+    int a;
+}
\ No newline at end of file
diff --git a/tests/android/aidl/tests/generic/IFaz.aidl b/tests/android/aidl/tests/generic/IFaz.aidl
new file mode 100644
index 0000000..127f3b7
--- /dev/null
+++ b/tests/android/aidl/tests/generic/IFaz.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests.generic;
+
+import android.aidl.tests.generic.Baz;
+import android.aidl.tests.generic.Pair;
+
+interface IFaz {
+    Pair<int, String> getPair();
+    Pair<Baz, Baz> getPair2();
+}
\ No newline at end of file
diff --git a/tests/android/aidl/tests/generic/Pair.aidl b/tests/android/aidl/tests/generic/Pair.aidl
new file mode 100644
index 0000000..69e5ed9
--- /dev/null
+++ b/tests/android/aidl/tests/generic/Pair.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests.generic;
+
+parcelable Pair<A, B>;
\ No newline at end of file
diff --git a/tests/android/aidl/tests/map/Bar.aidl b/tests/android/aidl/tests/map/Bar.aidl
new file mode 100644
index 0000000..cbd95ef
--- /dev/null
+++ b/tests/android/aidl/tests/map/Bar.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests.map;
+
+parcelable Bar {
+  int a;
+  String b;
+}
\ No newline at end of file
diff --git a/tests/android/aidl/tests/map/Foo.aidl b/tests/android/aidl/tests/map/Foo.aidl
new file mode 100644
index 0000000..4bc3e91
--- /dev/null
+++ b/tests/android/aidl/tests/map/Foo.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests.map;
+
+import android.aidl.tests.map.Bar;
+import android.aidl.tests.map.IEmpty;
+
+parcelable Foo {
+  Map<String, Bar> barMap;
+  Map<String, String> stringMap;
+  Map<String, IEmpty> interfaceMap;
+  Map<String, IBinder> ibinderMap;
+}
diff --git a/tests/android/aidl/tests/map/IEmpty.aidl b/tests/android/aidl/tests/map/IEmpty.aidl
new file mode 100644
index 0000000..c7f3f12
--- /dev/null
+++ b/tests/android/aidl/tests/map/IEmpty.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests.map;
+
+interface IEmpty {
+}
diff --git a/tests/corpus/char_seq_leak b/tests/corpus/char_seq_leak
new file mode 100644
index 0000000..688d6d8
--- /dev/null
+++ b/tests/corpus/char_seq_leak
@@ -0,0 +1 @@
+1enum F{U}parcelable e{CharSequence e;}
diff --git a/tests/corpus/double_include b/tests/corpus/double_include
new file mode 100644
index 0000000..e2e4a3d
--- /dev/null
+++ b/tests/corpus/double_include
@@ -0,0 +1 @@
+;import d;import d;
\ No newline at end of file
diff --git a/tests/corpus/map_leak b/tests/corpus/map_leak
new file mode 100644
index 0000000..11cc670
--- /dev/null
+++ b/tests/corpus/map_leak
@@ -0,0 +1 @@
+qparcelable a{Map e;}enum n{p}
diff --git a/tests/corpus/ndk_file_descriptor b/tests/corpus/ndk_file_descriptor
new file mode 100644
index 0000000..3769da0
--- /dev/null
+++ b/tests/corpus/ndk_file_descriptor
@@ -0,0 +1 @@
+&enum F{p}parcelable e{FileDescriptor e;}
\ No newline at end of file
diff --git a/tests/corpus/nongeneric_list b/tests/corpus/nongeneric_list
new file mode 100644
index 0000000..96e9e97
--- /dev/null
+++ b/tests/corpus/nongeneric_list
@@ -0,0 +1 @@
+²enum F{t}parcelable e{List e;}
\ No newline at end of file
diff --git a/tests/corpus/type_param_leak b/tests/corpus/type_param_leak
new file mode 100644
index 0000000..36eb684
--- /dev/null
+++ b/tests/corpus/type_param_leak
@@ -0,0 +1 @@
+;parcelable p<g
\ No newline at end of file
diff --git a/tests/corpus/utf8_non_string b/tests/corpus/utf8_non_string
new file mode 100644
index 0000000..f7a4e3a
--- /dev/null
+++ b/tests/corpus/utf8_non_string
@@ -0,0 +1 @@
+Uenum o{r}parcelable e{@utf8InCpp byte[]y;}
\ No newline at end of file
diff --git a/tests/end_to_end_tests.cpp b/tests/end_to_end_tests.cpp
index 601c76f..24458d6 100644
--- a/tests/end_to_end_tests.cpp
+++ b/tests/end_to_end_tests.cpp
@@ -170,7 +170,7 @@
   CheckFileContents(options.DependencyFile(), kExpectedJavaDepsOutput);
 }
 
-TEST_F(EndToEndTest, IExampleInterface_WithVersion) {
+TEST_F(EndToEndTest, IExampleInterface_WithVersionAndHash) {
   using namespace ::android::aidl::test_data::example_interface;
 
   vector<string> args = {
@@ -179,6 +179,7 @@
     "-I .",
     "-d an/arbitrary/path/to/dep.P",
     "--version=10",
+    "--hash=abcdefg",
     CanonicalNameToPath(kCanonicalName, ".aidl"),
     kJavaOutputPath};
   Options options = Options::From(args);
@@ -193,7 +194,7 @@
 
   // Check that we parse correctly.
   EXPECT_EQ(android::aidl::compile_aidl(options, io_delegate_), 0);
-  CheckFileContents(kJavaOutputPath, kExpectedJavaOutputWithVersion);
+  CheckFileContents(kJavaOutputPath, kExpectedJavaOutputWithVersionAndHash);
   CheckFileContents(options.DependencyFile(), kExpectedJavaDepsOutput);
 }
 
@@ -223,7 +224,7 @@
   CheckFileContents(options.DependencyFile(), kExpectedCppDepsOutput);
 }
 
-TEST_F(EndToEndTest, IPingResponderCpp_WithVersion) {
+TEST_F(EndToEndTest, IPingResponderCpp_WithVersionAndHash) {
   using namespace ::android::aidl::test_data::ping_responder;
 
   vector<string> args = {
@@ -231,6 +232,7 @@
     "-d deps.P",
     "-I .",
     "--version=10",
+    "--hash=abcdefg",
     CanonicalNameToPath(kCanonicalName, ".aidl"),
     kGenHeaderDir,
     kCppOutputPath};
@@ -242,10 +244,10 @@
 
   // Check that we parse and generate code correctly.
   EXPECT_EQ(android::aidl::compile_aidl(options, io_delegate_), 0);
-  CheckFileContents(kCppOutputPath, kExpectedCppOutputWithVersion);
-  CheckFileContents(kGenInterfaceHeaderPath, kExpectedIHeaderOutputWithVersion);
-  CheckFileContents(kGenClientHeaderPath, kExpectedBpHeaderOutputWithVersion);
-  CheckFileContents(kGenServerHeaderPath, kExpectedBnHeaderOutputWithVersion);
+  CheckFileContents(kCppOutputPath, kExpectedCppOutputWithVersionAndHash);
+  CheckFileContents(kGenInterfaceHeaderPath, kExpectedIHeaderOutputWithVersionAndHash);
+  CheckFileContents(kGenClientHeaderPath, kExpectedBpHeaderOutputWithVersionAndHash);
+  CheckFileContents(kGenServerHeaderPath, kExpectedBnHeaderOutputWithVersionAndHash);
   CheckFileContents(options.DependencyFile(), kExpectedCppDepsOutput);
 }
 
@@ -286,12 +288,13 @@
   CheckFileContents(kJavaOutputPath, kExpectedJavaOutput);
 }
 
-TEST_F(EndToEndTest, StringConstantsInCpp_WithVersion) {
+TEST_F(EndToEndTest, StringConstantsInCpp_WithVersionAndHash) {
   using namespace ::android::aidl::test_data::string_constants;
 
   vector<string> args = {
     "aidl-cpp",
     "--version=10",
+    "--hash=abcdefg",
     CanonicalNameToPath(kCanonicalName, ".aidl"),
     kGenHeaderDir,
     kCppOutputPath};
@@ -302,17 +305,18 @@
 
   // Check that we parse and generate code correctly.
   EXPECT_EQ(android::aidl::compile_aidl(options, io_delegate_), 0);
-  CheckFileContents(kCppOutputPath, kExpectedCppOutputWithVersion);
-  CheckFileContents(kGenInterfaceHeaderPath, kExpectedIHeaderOutputWithVersion);
+  CheckFileContents(kCppOutputPath, kExpectedCppOutputWithVersionAndHash);
+  CheckFileContents(kGenInterfaceHeaderPath, kExpectedIHeaderOutputWithVersionAndHash);
 }
 
-TEST_F(EndToEndTest, StringConstantsInJava_WithVersion) {
+TEST_F(EndToEndTest, StringConstantsInJava_WithVersionAndHash) {
   using namespace ::android::aidl::test_data::string_constants;
 
   vector<string> args = {
     "aidl",
     "-b",
     "--version=10",
+    "--hash=abcdefg",
     CanonicalNameToPath(kCanonicalName, ".aidl"),
     kJavaOutputPath};
   Options options = Options::From(args);
@@ -322,7 +326,7 @@
 
   // Check that we parse correctly.
   EXPECT_EQ(android::aidl::compile_aidl(options, io_delegate_), 0);
-  CheckFileContents(kJavaOutputPath, kExpectedJavaOutputWithVersion);
+  CheckFileContents(kJavaOutputPath, kExpectedJavaOutputWithVersionAndHash);
 }
 
 }  // namespace aidl
diff --git a/tests/fake_io_delegate.cpp b/tests/fake_io_delegate.cpp
index 682ea57..dc35c4d 100644
--- a/tests/fake_io_delegate.cpp
+++ b/tests/fake_io_delegate.cpp
@@ -151,6 +151,14 @@
   return true;
 }
 
+std::vector<std::string> FakeIoDelegate::ListOutputFiles() {
+  std::vector<std::string> out;
+  for (const auto& [file, contents] : written_file_contents_) {
+    out.push_back(file);
+  }
+  return out;
+}
+
 bool FakeIoDelegate::PathWasRemoved(const std::string& path) {
   if (removed_files_.count(path) > 0) {
     return true;
diff --git a/tests/fake_io_delegate.h b/tests/fake_io_delegate.h
index 68a9626..f077c0f 100644
--- a/tests/fake_io_delegate.h
+++ b/tests/fake_io_delegate.h
@@ -60,6 +60,7 @@
   // Returns true iff we've previously written to |path|.
   // When we return true, we'll set *contents to the written string.
   bool GetWrittenContents(const std::string& path, std::string* content);
+  std::vector<std::string> ListOutputFiles();
 
   bool PathWasRemoved(const std::string& path);
 
diff --git a/tests/java_app/src/android/aidl/tests/GenericTests.java b/tests/java_app/src/android/aidl/tests/GenericTests.java
new file mode 100644
index 0000000..85f09ab
--- /dev/null
+++ b/tests/java_app/src/android/aidl/tests/GenericTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests;
+
+import android.aidl.tests.generic.Baz;
+import android.aidl.tests.generic.IFaz;
+import android.aidl.tests.generic.Pair;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+class GenericTests {
+  private TestLogger mLog;
+
+  public GenericTests(TestLogger logger) { mLog = logger; }
+
+  public void checkGeneric() throws TestFailException {
+    mLog.log("Checking generic feature.");
+    IFaz.Stub ifaz = new IFaz.Stub() {
+      public Pair<Integer, String> getPair() {
+        Pair<Integer, String> ret = new Pair<Integer, String>();
+        ret.mFirst = 15;
+        ret.mSecond = "My";
+        return ret;
+      }
+      public Pair<Baz, Baz> getPair2() {
+        Pair<Baz, Baz> ret = new Pair<Baz, Baz>();
+        ret.mFirst = new Baz();
+        ret.mSecond = new Baz();
+        return ret;
+      }
+    };
+    try {
+      IFaz service = IFaz.Stub.asInterface(ifaz);
+      if (service.getPair().mFirst != 15) {
+        mLog.logAndThrow("mFirst must be 15, but it is " + service.getPair().mFirst);
+      }
+      if (!"My".equals(service.getPair().mSecond)) {
+        mLog.logAndThrow("mSecond must be \"My\", but it is " + service.getPair().mSecond);
+      }
+    } catch (RemoteException e) {
+      mLog.logAndThrow("This test is local, so the exception is not expected: " + e);
+    }
+  }
+
+  public void runTests() throws TestFailException { checkGeneric(); }
+}
diff --git a/tests/java_app/src/android/aidl/tests/MapTests.java b/tests/java_app/src/android/aidl/tests/MapTests.java
new file mode 100644
index 0000000..46d1657
--- /dev/null
+++ b/tests/java_app/src/android/aidl/tests/MapTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests;
+
+import android.aidl.tests.map.Bar;
+import android.aidl.tests.map.Foo;
+import android.aidl.tests.map.IEmpty;
+import android.os.IBinder;
+import android.os.Parcel;
+import java.util.HashMap;
+
+class MapTests {
+  private TestLogger mLog;
+
+  public MapTests(TestLogger logger) { mLog = logger; }
+
+  public void checkMap() throws TestFailException {
+    mLog.log("Checking if data in a Map object is transferred well.");
+    Parcel parcel = Parcel.obtain();
+    IEmpty intf = new IEmpty.Stub() {};
+    {
+      Foo foo = new Foo();
+      Bar bar = new Bar();
+      bar.a = 42;
+      bar.b = "Bar";
+      foo.barMap = new HashMap<>();
+      foo.barMap.put("Foo", bar);
+
+      foo.stringMap = new HashMap<>();
+      foo.stringMap.put("Foo", "Bar");
+
+      foo.interfaceMap = new HashMap<>();
+      foo.interfaceMap.put("Foo", intf);
+
+      foo.ibinderMap = new HashMap<>();
+      foo.ibinderMap.put("Foo", intf.asBinder());
+
+      foo.writeToParcel(parcel, 0);
+    }
+    parcel.setDataPosition(0);
+    {
+      Foo foo = new Foo();
+      foo.readFromParcel(parcel);
+      if (!foo.barMap.containsKey("Foo")) {
+        mLog.logAndThrow("Map foo.a must have the element of which key is \"Foo\"");
+      }
+      if (foo.barMap.size() != 1) {
+        mLog.logAndThrow("The size of map a is expected to be 1.");
+      }
+      Bar bar = foo.barMap.get("Foo");
+      if (bar.a != 42 || !"Bar".equals(bar.b)) {
+        mLog.logAndThrow("The content of bar is expected to be {a: 42, b: \"Bar\"}.");
+      }
+
+      if (foo.stringMap.size() != 1) {
+        mLog.logAndThrow("The size of map a is expected to be 1.");
+      }
+      String string = foo.stringMap.get("Foo");
+      if (!"Bar".equals(string)) {
+        mLog.logAndThrow("The content of string is expected to be \"Bar\".");
+      }
+
+      if (foo.interfaceMap.size() != 1) {
+        mLog.logAndThrow("The size of map a is expected to be 1.");
+      }
+
+      if (!intf.equals(foo.interfaceMap.get("Foo"))) {
+        mLog.logAndThrow("The content of service is expected to be same.");
+      }
+
+      if (foo.ibinderMap.size() != 1) {
+        mLog.logAndThrow("The size of map a is expected to be 1.");
+      }
+      IBinder ibinder = foo.ibinderMap.get("Foo");
+      if (!intf.asBinder().equals(ibinder)) {
+        mLog.logAndThrow("The content of IBinder is expected to be same.");
+      }
+    }
+  }
+
+  public void runTests() throws TestFailException { checkMap(); }
+}
diff --git a/tests/java_app/src/android/aidl/tests/TestServiceClient.java b/tests/java_app/src/android/aidl/tests/TestServiceClient.java
index ef5c651..01df091 100644
--- a/tests/java_app/src/android/aidl/tests/TestServiceClient.java
+++ b/tests/java_app/src/android/aidl/tests/TestServiceClient.java
@@ -972,6 +972,8 @@
           checkUtf8Strings(service);
           checkStructuredParcelable(service);
           new NullableTests(service, mLog).runTests();
+          new MapTests(mLog).runTests();
+          new GenericTests(mLog).runTests();
           checkDefaultImpl(service);
 
           mLog.log(mSuccessSentinel);
diff --git a/tests/java_app/src/android/aidl/tests/generic/Pair.java b/tests/java_app/src/android/aidl/tests/generic/Pair.java
new file mode 100644
index 0000000..a0631df
--- /dev/null
+++ b/tests/java_app/src/android/aidl/tests/generic/Pair.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests.generic;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class Pair<A, B> implements Parcelable {
+  public A mFirst;
+  public B mSecond;
+
+  public Pair() {}
+  public Pair(Parcel source) { readFromParcel(source); }
+
+  public int describeContents() { return 0; }
+
+  public void writeToParcel(Parcel dest, int flags) {
+    dest.writeValue(mFirst);
+    dest.writeValue(mSecond);
+  }
+
+  public void readFromParcel(Parcel source) {
+    mFirst = (A) source.readValue(null);
+    mSecond = (B) source.readValue(null);
+  }
+
+  public static final Parcelable.Creator<Pair> CREATOR = new Parcelable.Creator<Pair>() {
+    public Pair createFromParcel(Parcel source) { return new Pair(source); }
+
+    public Pair[] newArray(int size) { return new Pair[size]; }
+  };
+}
diff --git a/tests/lazy_test/Android.bp b/tests/lazy_test/Android.bp
new file mode 100644
index 0000000..47914ca
--- /dev/null
+++ b/tests/lazy_test/Android.bp
@@ -0,0 +1,26 @@
+cc_test {
+    name: "aidl_lazy_test",
+    srcs: ["main.cpp"],
+    test_suites: ["general-tests"],
+    require_root: true,
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libutils",
+        "libbinder",
+    ],
+}
+
+cc_binary {
+    name: "aidl_lazy_test_server",
+    srcs: ["server.cpp"],
+    init_rc: ["aidl_lazy_test_server.rc"],
+    system_ext_specific: true,
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/tests/lazy_test/README b/tests/lazy_test/README
new file mode 100644
index 0000000..e05f8f5
--- /dev/null
+++ b/tests/lazy_test/README
@@ -0,0 +1,66 @@
+aidl_lazy_test_server is a simple test service.
+
+Because it represents the bare minimum requirements for implementing a service, it also serves as
+an example of how to add a new service. The required files are as follows:
+
+============================================
+In this directory
+============================================
+--------------------------------------------
+server.cpp
+--------------------------------------------
+The implementation of the server. The only required function is main(), wherein the service must be
+instantiated and added (either to servicemanager as a standard service or to LazyServiceRegistrar
+to be a dynamic service). The server then joins the thread pool.
+
+--------------------------------------------
+aidl_lazy_test_server.rc
+--------------------------------------------
+This file is read by init, which later starts the service. The interface, oneshot, and disabled
+lines are only required for dynamic services.
+
+--------------------------------------------
+Android.bp
+--------------------------------------------
+A cc_binary entry will need to be added for the service with:
+name
+srcs - The source file(s), in this case just server.cpp
+init_rc - The .rc file
+shared_libs - Any shared libraries the source file depends on
+
+============================================
+In system/sepolicy
+============================================
+--------------------------------------------
+private/aidl_lazy_test_server.te
+--------------------------------------------
+Only two lines are required in this file.
+
+--------------------------------------------
+public/aidl_lazy_test_server.te
+--------------------------------------------
+The first two lines establish types for aidl_lazy_test_server and aidl_lazy_test_server_exec.
+binder_use and binder_call allow for basic use of this service.
+add_service allows the service to be registered. Note that an additional service type is required
+as the second argument to this function.
+
+--------------------------------------------
+private/compat/<number>/<number>.ignore.cil
+--------------------------------------------
+aidl_lazy_test_server and aidl_lazy_test_server_exec, and aidl_lazy_test_service need to be added
+to the new objects list.
+
+--------------------------------------------
+private/file_contexts
+--------------------------------------------
+A line is required to map aidl_lazy_test_server to aidl_lazy_test_server_exec.
+
+--------------------------------------------
+private/service_contexts
+--------------------------------------------
+Each interface for the service must be mapped to aidl_lazy_test_service here.
+
+--------------------------------------------
+public/service.te
+--------------------------------------------
+A line is required to define aidl_lazy_test_service.
diff --git a/tests/lazy_test/aidl_lazy_test_server.rc b/tests/lazy_test/aidl_lazy_test_server.rc
new file mode 100644
index 0000000..05c25b4
--- /dev/null
+++ b/tests/lazy_test/aidl_lazy_test_server.rc
@@ -0,0 +1,7 @@
+service aidl_lazy_test /system_ext/bin/aidl_lazy_test_server
+    interface aidl aidl_lazy_test_1
+    interface aidl aidl_lazy_test_2
+    user system
+    group system
+    oneshot
+    disabled
diff --git a/tests/lazy_test/main.cpp b/tests/lazy_test/main.cpp
new file mode 100644
index 0000000..178c2f7
--- /dev/null
+++ b/tests/lazy_test/main.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <numeric>
+#include <string>
+#include <thread>
+
+#include <unistd.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+
+using ::android::IBinder;
+using ::android::IPCThreadState;
+using ::android::IServiceManager;
+using ::android::sp;
+
+std::vector<android::String16> gServiceNames;
+
+sp<IBinder> waitForService(size_t inx) {
+  sp<IServiceManager> manager;
+  manager = android::defaultServiceManager();
+  EXPECT_TRUE(manager != nullptr);
+
+  return manager->waitForService(gServiceNames.at(inx));
+}
+
+class AidlLazyTest : public ::testing::Test {
+ protected:
+  sp<IServiceManager> manager;
+
+  void SetUp() override {
+    manager = android::defaultServiceManager();
+    ASSERT_NE(manager, nullptr);
+
+    for (size_t i = 0; i < gServiceNames.size(); i++) {
+      ASSERT_FALSE(isServiceRunning(i))
+          << "Service '" << android::String8(gServiceNames.at(i)) << "' is already running. "
+          << "Please ensure this is implemented as a lazy service, then kill all "
+          << "clients of this service and try again.";
+    }
+  }
+
+  static constexpr size_t SHUTDOWN_WAIT_TIME = 10;
+  void TearDown() override {
+    std::cout << "Waiting " << SHUTDOWN_WAIT_TIME << " seconds before checking that the "
+              << "service has shut down." << std::endl;
+    IPCThreadState::self()->flushCommands();
+    sleep(SHUTDOWN_WAIT_TIME);
+    for (size_t i = 0; i < gServiceNames.size(); i++) {
+      ASSERT_FALSE(isServiceRunning(i)) << "Service failed to shut down.";
+    }
+  }
+
+  bool isServiceRunning(size_t inx) {
+    auto services = manager->listServices();
+    for (size_t i = 0; i < services.size(); i++) {
+      if (services[i] == gServiceNames.at(inx)) return true;
+    }
+    return false;
+  }
+};
+
+static constexpr size_t NUM_IMMEDIATE_GETS = 100;
+TEST_F(AidlLazyTest, GetRelease) {
+  size_t nServices = gServiceNames.size();
+
+  for (size_t i = 0; i < nServices * NUM_IMMEDIATE_GETS; i++) {
+    IPCThreadState::self()->flushCommands();
+    sp<IBinder> service = waitForService(i % nServices);
+    ASSERT_NE(service.get(), nullptr);
+    EXPECT_TRUE(service->pingBinder() == android::NO_ERROR);
+  }
+}
+
+static std::vector<size_t> waitTimes(size_t numTimes, size_t maxWait) {
+  std::vector<size_t> times(numTimes);
+  for (size_t i = 0; i < numTimes; i++) {
+    times.at(i) = (size_t)(rand() % (maxWait + 1));
+  }
+  return times;
+}
+
+static void testWithTimes(const std::vector<size_t>& waitTimes, bool beforeGet) {
+  size_t nServices = gServiceNames.size();
+  for (size_t i = 0; i < waitTimes.size(); i++) {
+    IPCThreadState::self()->flushCommands();
+    if (beforeGet) {
+      std::cout << "Thread waiting " << waitTimes.at(i) << " while not holding service."
+                << std::endl;
+      sleep(waitTimes.at(i));
+    }
+
+    sp<IBinder> service = waitForService(i % nServices);
+
+    if (!beforeGet) {
+      std::cout << "Thread waiting " << waitTimes.at(i) << " while holding service." << std::endl;
+      sleep(waitTimes.at(i));
+    }
+
+    ASSERT_NE(service.get(), nullptr);
+    ASSERT_TRUE(service->pingBinder() == android::NO_ERROR);
+  }
+}
+
+static constexpr size_t NUM_TIMES_GET_RELEASE = 5;
+static constexpr size_t MAX_WAITING_DURATION = 10;
+static constexpr size_t NUM_CONCURRENT_THREADS = 3;
+static void testConcurrentThreadsWithDelays(bool delayBeforeGet) {
+  size_t nServices = gServiceNames.size();
+  std::vector<std::vector<size_t>> threadWaitTimes(NUM_CONCURRENT_THREADS);
+  int maxWait = 0;
+  for (size_t i = 0; i < threadWaitTimes.size(); i++) {
+    threadWaitTimes.at(i) = waitTimes(NUM_TIMES_GET_RELEASE * nServices, MAX_WAITING_DURATION);
+    int totalWait = std::accumulate(threadWaitTimes.at(i).begin(), threadWaitTimes.at(i).end(), 0);
+    maxWait = std::max(maxWait, totalWait);
+  }
+  std::cout << "Additional runtime expected from sleeps: " << maxWait << " second(s)." << std::endl;
+
+  std::vector<std::thread> threads(NUM_CONCURRENT_THREADS);
+  for (size_t i = 0; i < threads.size(); i++) {
+    threads.at(i) = std::thread(testWithTimes, threadWaitTimes.at(i), delayBeforeGet);
+  }
+
+  for (auto& thread : threads) {
+    thread.join();
+  }
+}
+
+TEST_F(AidlLazyTest, GetConcurrentWithWaitBefore) {
+  testConcurrentThreadsWithDelays(true);
+}
+
+TEST_F(AidlLazyTest, GetConcurrentWithWaitAfter) {
+  testConcurrentThreadsWithDelays(false);
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  srand(time(nullptr));
+
+  if (argc < 2) {
+    // If the user does not specify any service to test, default to these test interfaces
+    gServiceNames.push_back(android::String16("aidl_lazy_test_1"));
+    gServiceNames.push_back(android::String16("aidl_lazy_test_2"));
+  } else {
+    for (int i = 1; i < argc; i++) {
+      gServiceNames.push_back(android::String16(argv[i]));
+    }
+  }
+
+  android::ProcessState::self()->startThreadPool();
+
+  return RUN_ALL_TESTS();
+}
diff --git a/tests/lazy_test/server.cpp b/tests/lazy_test/server.cpp
new file mode 100644
index 0000000..f5fa9ed
--- /dev/null
+++ b/tests/lazy_test/server.cpp
@@ -0,0 +1,25 @@
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/LazyServiceRegistrar.h>
+#include <utils/Log.h>
+
+using android::BBinder;
+using android::IBinder;
+using android::IPCThreadState;
+using android::OK;
+using android::sp;
+using android::binder::LazyServiceRegistrar;
+
+int main() {
+  sp<IBinder> binder1 = new BBinder;
+  sp<IBinder> binder2 = new BBinder;
+
+  auto lazyRegistrar = LazyServiceRegistrar::getInstance();
+  LOG_ALWAYS_FATAL_IF(OK != lazyRegistrar.registerService(binder1, "aidl_lazy_test_1"), "");
+  LOG_ALWAYS_FATAL_IF(OK != lazyRegistrar.registerService(binder2, "aidl_lazy_test_2"), "");
+
+  IPCThreadState::self()->joinThreadPool();
+
+  return 1;
+}
diff --git a/tests/test_data.h b/tests/test_data.h
index b4be6ec..ad428b0 100644
--- a/tests/test_data.h
+++ b/tests/test_data.h
@@ -35,7 +35,7 @@
 extern const char kExpectedJavaOutputOutlining[];
 extern const char kExpectedJavaOutputWithTransactionNames[];
 extern const char kExpectedJavaOutputWithTrace[];
-extern const char kExpectedJavaOutputWithVersion[];
+extern const char kExpectedJavaOutputWithVersionAndHash[];
 
 }  // namespace example_interface
 
@@ -61,10 +61,10 @@
 extern const char kExpectedBpHeaderOutput[];
 extern const char kExpectedBnHeaderOutput[];
 
-extern const char kExpectedCppOutputWithVersion[];
-extern const char kExpectedIHeaderOutputWithVersion[];
-extern const char kExpectedBpHeaderOutputWithVersion[];
-extern const char kExpectedBnHeaderOutputWithVersion[];
+extern const char kExpectedCppOutputWithVersionAndHash[];
+extern const char kExpectedIHeaderOutputWithVersionAndHash[];
+extern const char kExpectedBpHeaderOutputWithVersionAndHash[];
+extern const char kExpectedBnHeaderOutputWithVersionAndHash[];
 
 }  // namespace ping_responder
 
@@ -76,7 +76,7 @@
 extern const char kJavaOutputPath[];
 extern const char kExpectedJavaOutput[];
 
-extern const char kExpectedJavaOutputWithVersion[];
+extern const char kExpectedJavaOutputWithVersionAndHash[];
 
 extern const char kCppOutputPath[];
 extern const char kGenHeaderDir[];
@@ -84,8 +84,8 @@
 extern const char kExpectedIHeaderOutput[];
 extern const char kExpectedCppOutput[];
 
-extern const char kExpectedIHeaderOutputWithVersion[];
-extern const char kExpectedCppOutputWithVersion[];
+extern const char kExpectedIHeaderOutputWithVersionAndHash[];
+extern const char kExpectedCppOutputWithVersionAndHash[];
 
 }  // namespace string_constants
 
diff --git a/tests/test_data_example_interface.cpp b/tests/test_data_example_interface.cpp
index 58a0426..7536306 100644
--- a/tests/test_data_example_interface.cpp
+++ b/tests/test_data_example_interface.cpp
@@ -105,15 +105,15 @@
 const char kExpectedJavaDepsOutput[] =
     R"(some/path/to/output.java : \
   android/test/IExampleInterface.aidl \
-  ./android/bar/IAuxInterface.aidl \
   ./android/foo/ExampleParcelable.aidl \
   ./android/test/CompoundParcelable.aidl \
+  ./android/bar/IAuxInterface.aidl \
   ./android/test/IAuxInterface2.aidl
 
 android/test/IExampleInterface.aidl :
-./android/bar/IAuxInterface.aidl :
 ./android/foo/ExampleParcelable.aidl :
 ./android/test/CompoundParcelable.aidl :
+./android/bar/IAuxInterface.aidl :
 ./android/test/IAuxInterface2.aidl :
 )";
 
@@ -122,7 +122,7 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.test;
-@dalvik.annotation.compat.UnsupportedAppUsage
+@android.compat.annotation.UnsupportedAppUsage(overrideSourcePosition="android/test/IExampleInterface.aidl:10:1:10:21")
 @android.annotation.SystemApi
 public interface IExampleInterface extends android.os.IInterface
 {
@@ -564,7 +564,7 @@
   public int getState() throws android.os.RemoteException;
   public java.lang.String getAddress() throws android.os.RemoteException;
   /* Test long comment */
-  @dalvik.annotation.compat.UnsupportedAppUsage
+  @android.compat.annotation.UnsupportedAppUsage(overrideSourcePosition="android/test/IExampleInterface.aidl:18:1:18:25")
   @android.annotation.SystemApi
   public android.foo.ExampleParcelable[] getParcelables() throws android.os.RemoteException;
   // Test short comment
@@ -584,7 +584,7 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.test;
-@dalvik.annotation.compat.UnsupportedAppUsage
+@android.compat.annotation.UnsupportedAppUsage(overrideSourcePosition="android/test/IExampleInterface.aidl:10:1:10:21")
 @android.annotation.SystemApi
 public interface IExampleInterface extends android.os.IInterface
 {
@@ -1078,7 +1078,7 @@
   public int getState() throws android.os.RemoteException;
   public java.lang.String getAddress() throws android.os.RemoteException;
   /* Test long comment */
-  @dalvik.annotation.compat.UnsupportedAppUsage
+  @android.compat.annotation.UnsupportedAppUsage(overrideSourcePosition="android/test/IExampleInterface.aidl:18:1:18:25")
   @android.annotation.SystemApi
   public android.foo.ExampleParcelable[] getParcelables() throws android.os.RemoteException;
   // Test short comment
@@ -1098,7 +1098,7 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.test;
-@dalvik.annotation.compat.UnsupportedAppUsage
+@android.compat.annotation.UnsupportedAppUsage(overrideSourcePosition="android/test/IExampleInterface.aidl:10:1:10:21")
 @android.annotation.SystemApi
 public interface IExampleInterface extends android.os.IInterface
 {
@@ -1620,7 +1620,7 @@
   public int getState() throws android.os.RemoteException;
   public java.lang.String getAddress() throws android.os.RemoteException;
   /* Test long comment */
-  @dalvik.annotation.compat.UnsupportedAppUsage
+  @android.compat.annotation.UnsupportedAppUsage(overrideSourcePosition="android/test/IExampleInterface.aidl:18:1:18:25")
   @android.annotation.SystemApi
   public android.foo.ExampleParcelable[] getParcelables() throws android.os.RemoteException;
   // Test short comment
@@ -2123,7 +2123,7 @@
 }
 )";
 
-const char kExpectedJavaOutputWithVersion[] =
+const char kExpectedJavaOutputWithVersionAndHash[] =
     R"(/*
  * This file is auto-generated.  DO NOT MODIFY.
  */
@@ -2137,6 +2137,7 @@
    * that the remote object is implementing.
    */
   public static final int VERSION = 10;
+  public static final String HASH = "abcdefg";
   /** Default implementation for IExampleInterface. */
   public static class Default implements android.test.IExampleInterface
   {
@@ -2182,7 +2183,11 @@
     }
     @Override
     public int getInterfaceVersion() {
-      return -1;
+      return 0;
+    }
+    @Override
+    public String getInterfaceHash() {
+      return "";
     }
     @Override
     public android.os.IBinder asBinder() {
@@ -2282,6 +2287,13 @@
           reply.writeInt(getInterfaceVersion());
           return true;
         }
+        case TRANSACTION_getInterfaceHash:
+        {
+          data.enforceInterface(descriptor);
+          reply.writeNoException();
+          reply.writeString(getInterfaceHash());
+          return true;
+        }
         default:
         {
           return super.onTransact(code, data, reply, flags);
@@ -2296,6 +2308,7 @@
         mRemote = remote;
       }
       private int mCachedVersion = -1;
+      private String mCachedHash = "-1";
       @Override public android.os.IBinder asBinder()
       {
         return mRemote;
@@ -2532,6 +2545,28 @@
         }
         return mCachedVersion;
       }
+      @Override
+      public synchronized String getInterfaceHash() throws android.os.RemoteException {
+        if (mCachedHash == "-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_getInterfaceHash, data, reply, 0);
+            if (!_status) {
+              if (getDefaultImpl() != null) {
+                return getDefaultImpl().getInterfaceHash();
+              }
+            }
+            reply.readException();
+            mCachedHash = reply.readString();
+          } finally {
+            reply.recycle();
+            data.recycle();
+          }
+        }
+        return mCachedHash;
+      }
       public static android.test.IExampleInterface sDefaultImpl;
     }
     static final int TRANSACTION_isEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
@@ -2624,6 +2659,7 @@
       return true;
     }
     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 boolean setDefaultImpl(android.test.IExampleInterface impl) {
       if (Stub.Proxy.sDefaultImpl == null && impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
@@ -2651,6 +2687,7 @@
   public int takesAnInterface(android.test.IAuxInterface2 arg) throws android.os.RemoteException;
   public int takesAParcelable(android.test.CompoundParcelable.Subclass1 arg, android.test.CompoundParcelable.Subclass2 arg2) throws android.os.RemoteException;
   public int getInterfaceVersion() throws android.os.RemoteException;
+  public String getInterfaceHash() throws android.os.RemoteException;
 }
 )";
 
diff --git a/tests/test_data_ping_responder.cpp b/tests/test_data_ping_responder.cpp
index 130a225..fdc2bd4 100644
--- a/tests/test_data_ping_responder.cpp
+++ b/tests/test_data_ping_responder.cpp
@@ -82,27 +82,7 @@
 
 namespace os {
 
-IMPLEMENT_META_INTERFACE(PingResponder, "android.os.IPingResponder")
-
-::android::IBinder* IPingResponderDefault::onAsBinder() {
-  return nullptr;
-}
-
-::android::binder::Status IPingResponderDefault::Ping(const ::android::String16&, ::android::String16* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IPingResponderDefault::NullablePing(const ::std::unique_ptr<::android::String16>&, ::std::unique_ptr<::android::String16>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IPingResponderDefault::Utf8Ping(const ::std::string&, ::std::string* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IPingResponderDefault::NullableUtf8Ping(const ::std::unique_ptr<::std::string>&, ::std::unique_ptr<::std::string>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(PingResponder, "android.os.IPingResponder")
 
 }  // namespace os
 
@@ -430,13 +410,22 @@
 
 class IPingResponderDefault : public IPingResponder {
 public:
-  ::android::IBinder* onAsBinder() override;
-  ::android::binder::Status Ping(const ::android::String16& input, ::android::String16* _aidl_return) override;
-  ::android::binder::Status NullablePing(const ::std::unique_ptr<::android::String16>& input, ::std::unique_ptr<::android::String16>* _aidl_return) override;
-  ::android::binder::Status Utf8Ping(const ::std::string& input, ::std::string* _aidl_return) override;
-  ::android::binder::Status NullableUtf8Ping(const ::std::unique_ptr<::std::string>& input, ::std::unique_ptr<::std::string>* _aidl_return) override;
-
-};
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+  ::android::binder::Status Ping(const ::android::String16&, ::android::String16*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status NullablePing(const ::std::unique_ptr<::android::String16>&, ::std::unique_ptr<::android::String16>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status Utf8Ping(const ::std::string&, ::std::string*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status NullableUtf8Ping(const ::std::unique_ptr<::std::string>&, ::std::unique_ptr<::std::string>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+};  // class IPingResponderDefault
 
 }  // namespace os
 
@@ -499,7 +488,7 @@
 #endif  // AIDL_GENERATED_ANDROID_OS_BN_PING_RESPONDER_H_
 )";
 
-const char kExpectedCppOutputWithVersion[] =
+const char kExpectedCppOutputWithVersionAndHash[] =
     R"(#include <android/os/IPingResponder.h>
 #include <android/os/BpPingResponder.h>
 
@@ -507,31 +496,7 @@
 
 namespace os {
 
-IMPLEMENT_META_INTERFACE(PingResponder, "android.os.IPingResponder")
-
-::android::IBinder* IPingResponderDefault::onAsBinder() {
-  return nullptr;
-}
-
-::android::binder::Status IPingResponderDefault::Ping(const ::android::String16&, ::android::String16* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IPingResponderDefault::NullablePing(const ::std::unique_ptr<::android::String16>&, ::std::unique_ptr<::android::String16>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IPingResponderDefault::Utf8Ping(const ::std::string&, ::std::string* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-::android::binder::Status IPingResponderDefault::NullableUtf8Ping(const ::std::unique_ptr<::std::string>&, ::std::unique_ptr<::std::string>* ) {
-  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
-}
-
-int32_t IPingResponderDefault::getInterfaceVersion() {
-  return 0;
-}
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(PingResponder, "android.os.IPingResponder")
 
 }  // namespace os
 
@@ -709,6 +674,24 @@
   return cached_version_;
 }
 
+std::string BpPingResponder::getInterfaceHash() {
+  std::lock_guard<std::mutex> lockGuard(cached_hash_mutex_);
+  if (cached_hash_ == "-1") {
+    ::android::Parcel data;
+    ::android::Parcel reply;
+    data.writeInterfaceToken(getInterfaceDescriptor());
+    ::android::status_t err = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 16777213 /* getInterfaceHash */, data, &reply);
+    if (err == ::android::OK) {
+      ::android::binder::Status _aidl_status;
+      err = _aidl_status.readFromParcel(reply);
+      if (err == ::android::OK && _aidl_status.isOk()) {
+        cached_hash_ = reply.readString8().c_str();
+      }
+    }
+  }
+  return cached_hash_;
+}
+
 }  // namespace os
 
 }  // namespace android
@@ -839,6 +822,13 @@
     _aidl_reply->writeInt32(IPingResponder::VERSION);
   }
   break;
+  case ::android::IBinder::FIRST_CALL_TRANSACTION + 16777213 /* getInterfaceHash */:
+  {
+    _aidl_data.checkInterface(this);
+    _aidl_reply->writeNoException();
+    _aidl_reply->writeString8(android::String8(IPingResponder::HASH.c_str()));
+  }
+  break;
   default:
   {
     _aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
@@ -855,13 +845,17 @@
   return IPingResponder::VERSION;
 }
 
+std::string BnPingResponder::getInterfaceHash() {
+  return IPingResponder::HASH;
+}
+
 }  // namespace os
 
 }  // namespace android
 )";
 
-const char kExpectedIHeaderOutputWithVersion[] =
-R"(#ifndef AIDL_GENERATED_ANDROID_OS_I_PING_RESPONDER_H_
+const char kExpectedIHeaderOutputWithVersionAndHash[] =
+    R"(#ifndef AIDL_GENERATED_ANDROID_OS_I_PING_RESPONDER_H_
 #define AIDL_GENERATED_ANDROID_OS_I_PING_RESPONDER_H_
 
 #include <binder/IBinder.h>
@@ -881,23 +875,39 @@
 public:
   DECLARE_META_INTERFACE(PingResponder)
   const int32_t VERSION = 10;
+  const std::string HASH = "abcdefg";
   virtual ::android::binder::Status Ping(const ::android::String16& input, ::android::String16* _aidl_return) = 0;
   virtual ::android::binder::Status NullablePing(const ::std::unique_ptr<::android::String16>& input, ::std::unique_ptr<::android::String16>* _aidl_return) = 0;
   virtual ::android::binder::Status Utf8Ping(const ::std::string& input, ::std::string* _aidl_return) = 0;
   virtual ::android::binder::Status NullableUtf8Ping(const ::std::unique_ptr<::std::string>& input, ::std::unique_ptr<::std::string>* _aidl_return) = 0;
   virtual int32_t getInterfaceVersion() = 0;
+  virtual std::string getInterfaceHash() = 0;
 };  // class IPingResponder
 
 class IPingResponderDefault : public IPingResponder {
 public:
-  ::android::IBinder* onAsBinder() override;
-  ::android::binder::Status Ping(const ::android::String16& input, ::android::String16* _aidl_return) override;
-  ::android::binder::Status NullablePing(const ::std::unique_ptr<::android::String16>& input, ::std::unique_ptr<::android::String16>* _aidl_return) override;
-  ::android::binder::Status Utf8Ping(const ::std::string& input, ::std::string* _aidl_return) override;
-  ::android::binder::Status NullableUtf8Ping(const ::std::unique_ptr<::std::string>& input, ::std::unique_ptr<::std::string>* _aidl_return) override;
-  int32_t getInterfaceVersion() override;
-
-};
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+  ::android::binder::Status Ping(const ::android::String16&, ::android::String16*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status NullablePing(const ::std::unique_ptr<::android::String16>&, ::std::unique_ptr<::android::String16>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status Utf8Ping(const ::std::string&, ::std::string*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status NullableUtf8Ping(const ::std::unique_ptr<::std::string>&, ::std::unique_ptr<::std::string>*) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  int32_t getInterfaceVersion() override {
+    return 0;
+  }
+  std::string getInterfaceHash() override {
+    return "";
+  }
+};  // class IPingResponderDefault
 
 }  // namespace os
 
@@ -906,7 +916,7 @@
 #endif  // AIDL_GENERATED_ANDROID_OS_I_PING_RESPONDER_H_
 )";
 
-const char kExpectedBpHeaderOutputWithVersion[] =
+const char kExpectedBpHeaderOutputWithVersionAndHash[] =
 R"(#ifndef AIDL_GENERATED_ANDROID_OS_BP_PING_RESPONDER_H_
 #define AIDL_GENERATED_ANDROID_OS_BP_PING_RESPONDER_H_
 
@@ -928,8 +938,11 @@
   ::android::binder::Status Utf8Ping(const ::std::string& input, ::std::string* _aidl_return) override;
   ::android::binder::Status NullableUtf8Ping(const ::std::unique_ptr<::std::string>& input, ::std::unique_ptr<::std::string>* _aidl_return) override;
   int32_t getInterfaceVersion() override;
+  std::string getInterfaceHash() override;
 private:
   int32_t cached_version_ = -1;
+  std::string cached_hash_ = "-1";
+  std::mutex cached_hash_mutex_;
 };  // class BpPingResponder
 
 }  // namespace os
@@ -939,7 +952,7 @@
 #endif  // AIDL_GENERATED_ANDROID_OS_BP_PING_RESPONDER_H_
 )";
 
-const char kExpectedBnHeaderOutputWithVersion[] =
+const char kExpectedBnHeaderOutputWithVersionAndHash[] =
     R"(#ifndef AIDL_GENERATED_ANDROID_OS_BN_PING_RESPONDER_H_
 #define AIDL_GENERATED_ANDROID_OS_BN_PING_RESPONDER_H_
 
@@ -955,6 +968,7 @@
   explicit BnPingResponder();
   ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
   int32_t getInterfaceVersion() final override;
+  std::string getInterfaceHash();
 };  // class BnPingResponder
 
 }  // namespace os
diff --git a/tests/test_data_string_constants.cpp b/tests/test_data_string_constants.cpp
index d7b4bb5..0bea929 100644
--- a/tests/test_data_string_constants.cpp
+++ b/tests/test_data_string_constants.cpp
@@ -147,9 +147,10 @@
 
 class IStringConstantsDefault : public IStringConstants {
 public:
-  ::android::IBinder* onAsBinder() override;
-  
-};
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+};  // class IStringConstantsDefault
 
 }  // namespace os
 
@@ -166,17 +167,13 @@
 
 namespace os {
 
-IMPLEMENT_META_INTERFACE(StringConstants, "android.os.IStringConstants")
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(StringConstants, "android.os.IStringConstants")
 
 const ::android::String16& IStringConstants::EXAMPLE_CONSTANT() {
   static const ::android::String16 value(::android::String16("foo"));
   return value;
 }
 
-::android::IBinder* IStringConstantsDefault::onAsBinder() {
-  return nullptr;
-}
-
 }  // namespace os
 
 }  // namespace android
@@ -228,7 +225,7 @@
 }  // namespace android
 )";
 
-const char kExpectedJavaOutputWithVersion[] =
+const char kExpectedJavaOutputWithVersionAndHash[] =
     R"(/*
  * This file is auto-generated.  DO NOT MODIFY.
  */
@@ -242,12 +239,17 @@
    * that the remote object is implementing.
    */
   public static final int VERSION = 10;
+  public static final String HASH = "abcdefg";
   /** Default implementation for IStringConstants. */
   public static class Default implements android.os.IStringConstants
   {
     @Override
     public int getInterfaceVersion() {
-      return -1;
+      return 0;
+    }
+    @Override
+    public String getInterfaceHash() {
+      return "";
     }
     @Override
     public android.os.IBinder asBinder() {
@@ -299,6 +301,13 @@
           reply.writeInt(getInterfaceVersion());
           return true;
         }
+        case TRANSACTION_getInterfaceHash:
+        {
+          data.enforceInterface(descriptor);
+          reply.writeNoException();
+          reply.writeString(getInterfaceHash());
+          return true;
+        }
         default:
         {
           return super.onTransact(code, data, reply, flags);
@@ -313,6 +322,7 @@
         mRemote = remote;
       }
       private int mCachedVersion = -1;
+      private String mCachedHash = "-1";
       @Override public android.os.IBinder asBinder()
       {
         return mRemote;
@@ -343,9 +353,32 @@
         }
         return mCachedVersion;
       }
+      @Override
+      public synchronized String getInterfaceHash() throws android.os.RemoteException {
+        if (mCachedHash == "-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_getInterfaceHash, data, reply, 0);
+            if (!_status) {
+              if (getDefaultImpl() != null) {
+                return getDefaultImpl().getInterfaceHash();
+              }
+            }
+            reply.readException();
+            mCachedHash = reply.readString();
+          } finally {
+            reply.recycle();
+            data.recycle();
+          }
+        }
+        return mCachedHash;
+      }
       public static android.os.IStringConstants sDefaultImpl;
     }
     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 boolean setDefaultImpl(android.os.IStringConstants impl) {
       if (Stub.Proxy.sDefaultImpl == null && impl != null) {
         Stub.Proxy.sDefaultImpl = impl;
@@ -359,11 +392,12 @@
   }
   public static final String EXAMPLE_CONSTANT = "foo";
   public int getInterfaceVersion() throws android.os.RemoteException;
+  public String getInterfaceHash() throws android.os.RemoteException;
 }
 )";
 
-const char kExpectedIHeaderOutputWithVersion[] =
-R"(#ifndef AIDL_GENERATED_ANDROID_OS_I_STRING_CONSTANTS_H_
+const char kExpectedIHeaderOutputWithVersionAndHash[] =
+    R"(#ifndef AIDL_GENERATED_ANDROID_OS_I_STRING_CONSTANTS_H_
 #define AIDL_GENERATED_ANDROID_OS_I_STRING_CONSTANTS_H_
 
 #include <binder/IBinder.h>
@@ -381,16 +415,24 @@
 public:
   DECLARE_META_INTERFACE(StringConstants)
   const int32_t VERSION = 10;
+  const std::string HASH = "abcdefg";
   static const ::android::String16& EXAMPLE_CONSTANT();
   virtual int32_t getInterfaceVersion() = 0;
+  virtual std::string getInterfaceHash() = 0;
 };  // class IStringConstants
 
 class IStringConstantsDefault : public IStringConstants {
 public:
-  ::android::IBinder* onAsBinder() override;
-  int32_t getInterfaceVersion() override;
-
-};
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+  int32_t getInterfaceVersion() override {
+    return 0;
+  }
+  std::string getInterfaceHash() override {
+    return "";
+  }
+};  // class IStringConstantsDefault
 
 }  // namespace os
 
@@ -399,7 +441,7 @@
 #endif  // AIDL_GENERATED_ANDROID_OS_I_STRING_CONSTANTS_H_
 )";
 
-const char kExpectedCppOutputWithVersion[] =
+const char kExpectedCppOutputWithVersionAndHash[] =
     R"(#include <android/os/IStringConstants.h>
 #include <android/os/BpStringConstants.h>
 
@@ -407,21 +449,13 @@
 
 namespace os {
 
-IMPLEMENT_META_INTERFACE(StringConstants, "android.os.IStringConstants")
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(StringConstants, "android.os.IStringConstants")
 
 const ::android::String16& IStringConstants::EXAMPLE_CONSTANT() {
   static const ::android::String16 value(::android::String16("foo"));
   return value;
 }
 
-::android::IBinder* IStringConstantsDefault::onAsBinder() {
-  return nullptr;
-}
-
-int32_t IStringConstantsDefault::getInterfaceVersion() {
-  return 0;
-}
-
 }  // namespace os
 
 }  // namespace android
@@ -454,6 +488,24 @@
   return cached_version_;
 }
 
+std::string BpStringConstants::getInterfaceHash() {
+  std::lock_guard<std::mutex> lockGuard(cached_hash_mutex_);
+  if (cached_hash_ == "-1") {
+    ::android::Parcel data;
+    ::android::Parcel reply;
+    data.writeInterfaceToken(getInterfaceDescriptor());
+    ::android::status_t err = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 16777213 /* getInterfaceHash */, data, &reply);
+    if (err == ::android::OK) {
+      ::android::binder::Status _aidl_status;
+      err = _aidl_status.readFromParcel(reply);
+      if (err == ::android::OK && _aidl_status.isOk()) {
+        cached_hash_ = reply.readString8().c_str();
+      }
+    }
+  }
+  return cached_hash_;
+}
+
 }  // namespace os
 
 }  // namespace android
@@ -480,6 +532,13 @@
     _aidl_reply->writeInt32(IStringConstants::VERSION);
   }
   break;
+  case ::android::IBinder::FIRST_CALL_TRANSACTION + 16777213 /* getInterfaceHash */:
+  {
+    _aidl_data.checkInterface(this);
+    _aidl_reply->writeNoException();
+    _aidl_reply->writeString8(android::String8(IStringConstants::HASH.c_str()));
+  }
+  break;
   default:
   {
     _aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
@@ -496,6 +555,10 @@
   return IStringConstants::VERSION;
 }
 
+std::string BnStringConstants::getInterfaceHash() {
+  return IStringConstants::HASH;
+}
+
 }  // namespace os
 
 }  // namespace android